@mhamz.01/easyflow-whiteboard 2.86.0 → 2.88.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"custom-node-overlay-layer.d.ts","sourceRoot":"","sources":["../../../src/components/node/custom-node-overlay-layer.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAS9C,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,MAAM,CAAC;IACxC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,UAAU,uBAAuB;IAC/B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACxC,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,YAAY,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACzE,qBAAqB,CAAC,EAAE,YAAY,EAAE,CAAC;IACvC,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC9C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAaD,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,EACzC,KAAK,EACL,SAAS,EACT,aAAa,EACb,iBAAiB,EACjB,UAAc,EACd,cAA+B,EAC/B,YAAmB,EACnB,qBAA0B,EAC1B,YAAY,GACb,EAAE,uBAAuB,2CAglBzB"}
1
+ {"version":3,"file":"custom-node-overlay-layer.d.ts","sourceRoot":"","sources":["../../../src/components/node/custom-node-overlay-layer.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAO9C,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,MAAM,CAAC;IACxC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,UAAU,uBAAuB;IAC/B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACxC,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,YAAY,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACzE,qBAAqB,CAAC,EAAE,YAAY,EAAE,CAAC;IACvC,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC9C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAaD,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,EACzC,KAAK,EACL,SAAS,EACT,aAAa,EACb,iBAAiB,EACjB,UAAc,EACd,cAA+B,EAC/B,YAAmB,EACnB,qBAA0B,EAC1B,YAAY,GACb,EAAE,uBAAuB,2CAomBzB"}
@@ -5,15 +5,12 @@ import TaskNode from "./custom-node";
5
5
  import DocumentNode from "./document-node";
6
6
  // ─── Component ────────────────────────────────────────────────────────────────
7
7
  export default function CanvasOverlayLayer({ tasks, documents, onTasksUpdate, onDocumentsUpdate, canvasZoom = 1, canvasViewport = { x: 0, y: 0 }, selectionBox = null, selectedCanvasObjects = [], fabricCanvas, }) {
8
+ const [liveVpt, setLiveVpt] = useState({ x: canvasViewport.x, y: canvasViewport.y, zoom: canvasZoom });
8
9
  const [localTasks, setLocalTasks] = useState(tasks);
9
10
  const [localDocuments, setLocalDocuments] = useState(documents);
10
11
  const [selectedIds, setSelectedIds] = useState(new Set());
11
12
  const [dragging, setDragging] = useState(null);
12
13
  const [canvasReady, setCanvasReady] = useState(false);
13
- const nodeClipboardRef = useRef({
14
- tasks: [],
15
- documents: [],
16
- });
17
14
  const dragStateRef = useRef({
18
15
  isDragging: false,
19
16
  itemIds: [],
@@ -166,6 +163,20 @@ export default function CanvasOverlayLayer({ tasks, documents, onTasksUpdate, on
166
163
  // change, creating a new closure each time. The second drag captured a stale
167
164
  // or empty selectedIds from the closure at re-registration time.
168
165
  }, [canvasZoom, fabricCanvas, canvasReady]);
166
+ // 2. Sync directly with Fabric's render heartbeat
167
+ useEffect(() => {
168
+ const canvas = fabricCanvas?.current;
169
+ if (!canvas)
170
+ return;
171
+ const sync = () => {
172
+ const vpt = canvas.viewportTransform;
173
+ if (vpt) {
174
+ setLiveVpt({ x: vpt[4], y: vpt[5], zoom: vpt[0] });
175
+ }
176
+ };
177
+ canvas.on("after:render", sync);
178
+ return () => { canvas.off("after:render", sync); };
179
+ }, [fabricCanvas, canvasReady]);
169
180
  // ── Helpers ─────────────────────────────────────────────────────────────────
170
181
  const getItemPosition = (id) => {
171
182
  const task = localTasks.find((t) => t.id === id);
@@ -428,17 +439,17 @@ export default function CanvasOverlayLayer({ tasks, documents, onTasksUpdate, on
428
439
  }, [localTasks, localDocuments, selectedIds, onTasksUpdate, onDocumentsUpdate]);
429
440
  // ── Render helper ────────────────────────────────────────────────────────────
430
441
  const renderItem = (id, x, y, children) => {
431
- const screenX = x * canvasZoom;
432
- const screenY = y * canvasZoom;
442
+ const screenX = x * liveVpt.zoom;
443
+ const screenY = y * liveVpt.zoom;
444
+ const isDragging = dragging?.itemIds.includes(id);
433
445
  // 1. Detect if the user is interacting with the canvas at all
434
446
  // 'dragging' is your existing state.
435
447
  // You might want to pass 'isZooming' or 'isPanning' from your main canvas component here.
436
- const isDragging = dragging?.itemIds.includes(id);
437
448
  return (_jsx("div", { className: "pointer-events-auto absolute", style: {
438
449
  left: 0,
439
450
  top: 0,
440
451
  // 2. Use translate3d for GPU performance
441
- transform: `translate3d(${screenX}px, ${screenY}px, 0) scale(${canvasZoom})`,
452
+ transform: `translate3d(${screenX}px, ${screenY}px, 0) scale(${liveVpt.zoom})`,
442
453
  transformOrigin: "top left",
443
454
  // 3. THE FIX: Remove transition entirely during any viewport change
444
455
  // Any 'ease' during zoom causes the "shaking" behavior.
@@ -452,7 +463,8 @@ export default function CanvasOverlayLayer({ tasks, documents, onTasksUpdate, on
452
463
  if (e.target === e.currentTarget)
453
464
  setSelectedIds(new Set());
454
465
  }, children: _jsxs("div", { className: "absolute top-0 left-0 pointer-events-none", style: {
455
- transform: `translate(${canvasViewport.x}px, ${canvasViewport.y}px)`,
466
+ transform: `translate3d(${liveVpt.x}px, ${liveVpt.y}px, 0)`,
456
467
  transformOrigin: "top left",
468
+ willChange: "transform",
457
469
  }, children: [localTasks.map((task) => renderItem(task.id, task.x, task.y, _jsx(TaskNode, { ...task, isSelected: selectedIds.has(task.id), onSelect: handleSelect, onDragStart: handleDragStart, onStatusChange: handleStatusChange, zoom: 1 }))), localDocuments.map((doc) => renderItem(doc.id, doc.x, doc.y, _jsx(DocumentNode, { ...doc, isSelected: selectedIds.has(doc.id), onSelect: handleSelect, onDragStart: handleDragStart })))] }) }));
458
470
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mhamz.01/easyflow-whiteboard",
3
- "version": "2.86.0",
3
+ "version": "2.88.0",
4
4
  "description": "A feature-rich whiteboard component built with Fabric.js and React",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",