mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-12 04:37:44 +02:00
[eric] windows 1.1.62: cursor and popups follow target on windows via store-driven style.transform
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "openswarm",
|
||||
"version": "1.1.61",
|
||||
"version": "1.1.62",
|
||||
"description": "OpenSwarm — AI Agent Orchestrator",
|
||||
"author": "openswarm-ai",
|
||||
"main": "main.js",
|
||||
|
||||
@@ -24,11 +24,29 @@ const stripFramerProps = (props: any) => {
|
||||
return out;
|
||||
};
|
||||
|
||||
// Components that drive position via `animate={{ x, y }}` (ACPopup, ACMultiChoice, etc.) would otherwise lose their layout when the animate prop is stripped, because they have no fallback style.transform. We salvage the latest numeric x/y from animate and apply them as a transform so the div lands in the right place; no animation, just static placement.
|
||||
const motionShim: any = new Proxy({}, {
|
||||
get: (_target, tag: string) => {
|
||||
return React.forwardRef((props: any, ref: any) =>
|
||||
React.createElement(tag, { ...stripFramerProps(props), ref })
|
||||
);
|
||||
return React.forwardRef((props: any, ref: any) => {
|
||||
let translate = '';
|
||||
const a = props.animate;
|
||||
if (a && typeof a === 'object' && !Array.isArray(a)) {
|
||||
const ax = typeof a.x === 'number' ? a.x : null;
|
||||
const ay = typeof a.y === 'number' ? a.y : null;
|
||||
if (ax !== null || ay !== null) {
|
||||
translate = `translate(${ax ?? 0}px, ${ay ?? 0}px)`;
|
||||
}
|
||||
}
|
||||
const stripped = stripFramerProps(props);
|
||||
if (translate) {
|
||||
const existing = stripped.style && stripped.style.transform;
|
||||
stripped.style = {
|
||||
...(stripped.style || {}),
|
||||
transform: existing ? `${existing} ${translate}` : translate,
|
||||
};
|
||||
}
|
||||
return React.createElement(tag, { ...stripped, ref });
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import React, {
|
||||
import { createPortal } from 'react-dom';
|
||||
import { motion, useAnimationControls, AnimatePresence } from '../_motionWin';
|
||||
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
import { cursorStore } from './cursorStore';
|
||||
import { cursorStore, useCursorPosition } from './cursorStore';
|
||||
import { resolveSelector } from '../selectors';
|
||||
import ACPopup from './ACPopup';
|
||||
import ACMultiChoice from './ACMultiChoice';
|
||||
@@ -53,9 +53,13 @@ interface MultiChoiceState {
|
||||
// Snappy 260/26 spring; calm comes from popup cadence + 3s dwell, not cursor delay.
|
||||
const SPRING = { type: 'spring' as const, stiffness: 260, damping: 26 };
|
||||
|
||||
// On Windows the motionWin shim strips Framer Motion's animate prop, so controls.set({x,y}) never moves the wrapper. We bypass by reading the same store the popups read and applying style.transform directly; Mac is unaffected since Framer's own transform writes win the cascade.
|
||||
const IS_WIN = typeof navigator !== 'undefined' && navigator.userAgent.includes('Windows');
|
||||
|
||||
const AgenticCursor = forwardRef<AgenticCursorHandle>((_props, ref) => {
|
||||
const c = useClaudeTokens();
|
||||
const controls = useAnimationControls();
|
||||
const storePos = useCursorPosition();
|
||||
const posRef = useRef({ x: 0, y: 0 });
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [popup, setPopup] = useState<PopupState | null>(null);
|
||||
@@ -255,6 +259,7 @@ const AgenticCursor = forwardRef<AgenticCursorHandle>((_props, ref) => {
|
||||
zIndex: 10500,
|
||||
pointerEvents: 'none',
|
||||
transformOrigin: 'top left',
|
||||
...(IS_WIN ? { transform: `translate(${storePos.x}px, ${storePos.y}px)` } : null),
|
||||
}}
|
||||
>
|
||||
{visible && (
|
||||
|
||||
Reference in New Issue
Block a user