@mhamz.01/easyflow-whiteboard 2.171.0 → 2.173.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.
- package/dist/components/node/hooks/useNodeDrag.d.ts +3 -2
- package/dist/components/node/hooks/useNodeDrag.d.ts.map +1 -1
- package/dist/components/node/hooks/useNodeDrag.js +29 -15
- package/dist/components/whiteboard/whiteboard-test.d.ts.map +1 -1
- package/dist/components/whiteboard/whiteboard-test.js +20 -1
- package/package.json +1 -1
|
@@ -21,8 +21,9 @@ interface UseNodeDragProps {
|
|
|
21
21
|
* during a drag stays correct without extra state dependencies.
|
|
22
22
|
* - startPositions + anchor-offset approach prevents the "jump on drag start"
|
|
23
23
|
* bug that occurs when using raw mouse coords.
|
|
24
|
-
* -
|
|
25
|
-
*
|
|
24
|
+
* - Fabric object positions are read via queueMicrotask (after discardActiveObject)
|
|
25
|
+
* so they are always in ground-truth world coords, immune to Fabric v6's
|
|
26
|
+
* matrix-decomposition vs matrix-multiplication divergence.
|
|
26
27
|
*/
|
|
27
28
|
export declare function useNodeDrag({ selectedIdsRef, dragSelectedIdsRef, localTasksRef, localDocumentsRef, fabricCanvas, setLocalTasks, setLocalDocuments, onTasksUpdate, onDocumentsUpdate, }: UseNodeDragProps): {
|
|
28
29
|
dragging: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useNodeDrag.d.ts","sourceRoot":"","sources":["../../../../src/components/node/hooks/useNodeDrag.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,QAAQ,EACR,cAAc,EACd,UAAU,IAAI,eAAe,EAC7B,UAAU,IAAI,eAAe,EAC9B,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAA4B,MAAM,wBAAwB,CAAC;AAEvF,UAAU,gBAAgB;IACxB,cAAc,EAAE,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9C,kBAAkB,EAAE,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAClD,aAAa,EAAE,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC;IACxC,iBAAiB,EAAE,gBAAgB,CAAC,QAAQ,EAAE,CAAC,CAAC;IAChD,YAAY,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACxC,aAAa,EAAE,QAAQ,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAChD,iBAAiB,EAAE,QAAQ,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IACxD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACxC,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;CACrD;AAcD
|
|
1
|
+
{"version":3,"file":"useNodeDrag.d.ts","sourceRoot":"","sources":["../../../../src/components/node/hooks/useNodeDrag.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,QAAQ,EACR,cAAc,EACd,UAAU,IAAI,eAAe,EAC7B,UAAU,IAAI,eAAe,EAC9B,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAA4B,MAAM,wBAAwB,CAAC;AAEvF,UAAU,gBAAgB;IACxB,cAAc,EAAE,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9C,kBAAkB,EAAE,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAClD,aAAa,EAAE,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC;IACxC,iBAAiB,EAAE,gBAAgB,CAAC,QAAQ,EAAE,CAAC,CAAC;IAChD,YAAY,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACxC,aAAa,EAAE,QAAQ,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAChD,iBAAiB,EAAE,QAAQ,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IACxD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACxC,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;CACrD;AAcD;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,EAC1B,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,iBAAiB,GAClB,EAAE,gBAAgB;;iBACmC,MAAM,EAAE;;0BAcrD,MAAM,KAAG;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS;8BAWzC,MAAM,KAAK,eAAe,GAAG,eAAe;EAgLxD"}
|
|
@@ -17,8 +17,9 @@ function readPointer(e) {
|
|
|
17
17
|
* during a drag stays correct without extra state dependencies.
|
|
18
18
|
* - startPositions + anchor-offset approach prevents the "jump on drag start"
|
|
19
19
|
* bug that occurs when using raw mouse coords.
|
|
20
|
-
* -
|
|
21
|
-
*
|
|
20
|
+
* - Fabric object positions are read via queueMicrotask (after discardActiveObject)
|
|
21
|
+
* so they are always in ground-truth world coords, immune to Fabric v6's
|
|
22
|
+
* matrix-decomposition vs matrix-multiplication divergence.
|
|
22
23
|
*/
|
|
23
24
|
export function useNodeDrag({ selectedIdsRef, dragSelectedIdsRef, localTasksRef, localDocumentsRef, fabricCanvas, setLocalTasks, setLocalDocuments, onTasksUpdate, onDocumentsUpdate, }) {
|
|
24
25
|
const [dragging, setDragging] = useState(null);
|
|
@@ -72,21 +73,34 @@ export function useNodeDrag({ selectedIdsRef, dragSelectedIdsRef, localTasksRef,
|
|
|
72
73
|
if (pos)
|
|
73
74
|
startPositions.set(id, pos);
|
|
74
75
|
});
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
//
|
|
76
|
+
// Capture Fabric object references NOW (before handleSelect fires
|
|
77
|
+
// discardActiveObject), but read their actual left/top positions via a
|
|
78
|
+
// queueMicrotask that runs AFTER discardActiveObject() has restored every
|
|
79
|
+
// object to true world coordinates, yet BEFORE any requestAnimationFrame
|
|
80
|
+
// callback (where handleMove runs).
|
|
81
|
+
//
|
|
82
|
+
// Why not calcTransformMatrix() here?
|
|
83
|
+
// In Fabric v6 the matrix-multiplication path (calcTransformMatrix) and
|
|
84
|
+
// the matrix-decomposition path (ActiveSelection.destroy) are independent
|
|
85
|
+
// algorithms. They can diverge when objects carry scale, strokeUniform, or
|
|
86
|
+
// accumulated float rounding — causing a visible position jump on frame 1.
|
|
87
|
+
// Reading obj.left/top after discard is the ground-truth value: no
|
|
88
|
+
// prediction, no mismatch.
|
|
78
89
|
const liveActiveObjects = canvas.getActiveObjects();
|
|
79
|
-
const activeSelection = canvas.getActiveObject();
|
|
80
90
|
const canvasObjectsStartPos = new Map();
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
91
|
+
const objectsToSync = [...liveActiveObjects];
|
|
92
|
+
if (objectsToSync.length > 0) {
|
|
93
|
+
queueMicrotask(() => {
|
|
94
|
+
if (!dragStateRef.current.isDragging)
|
|
95
|
+
return;
|
|
96
|
+
objectsToSync.forEach((obj) => {
|
|
97
|
+
dragStateRef.current.canvasObjectsStartPos.set(obj, {
|
|
98
|
+
left: obj.left || 0,
|
|
99
|
+
top: obj.top || 0,
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
}
|
|
90
104
|
dragStateRef.current = {
|
|
91
105
|
isDragging: true,
|
|
92
106
|
itemIds: itemsToDrag,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whiteboard-test.d.ts","sourceRoot":"","sources":["../../../src/components/whiteboard/whiteboard-test.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAkB5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGxD,YAAY,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACvE,YAAY,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAIxE,UAAU,IAAI;IACZ,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,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,qBAAqB;IAC7B,WAAW,CAAC,EAAE;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;QACf,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;KACxB,CAAC;IACF,cAAc,CAAC,EAAE,YAAY,EAAE,CAAC;IAChC,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACxC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,GAAG,EAAE,CAAC;QACb,SAAS,EAAE,GAAG,EAAE,CAAC;KAClB,KAAK,IAAI,CAAC;IACX,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAoHD,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EACvC,WAAW,EACX,MAAM,EACN,cAAc,EACd,cAAmB,EACnB,kBAAuB,EACvB,aAAqB,GACtB,EAAE,qBAAqB,
|
|
1
|
+
{"version":3,"file":"whiteboard-test.d.ts","sourceRoot":"","sources":["../../../src/components/whiteboard/whiteboard-test.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAkB5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGxD,YAAY,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACvE,YAAY,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAIxE,UAAU,IAAI;IACZ,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,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,qBAAqB;IAC7B,WAAW,CAAC,EAAE;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;QACf,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;KACxB,CAAC;IACF,cAAc,CAAC,EAAE,YAAY,EAAE,CAAC;IAChC,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACxC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,GAAG,EAAE,CAAC;QACb,SAAS,EAAE,GAAG,EAAE,CAAC;KAClB,KAAK,IAAI,CAAC;IACX,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAoHD,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EACvC,WAAW,EACX,MAAM,EACN,cAAc,EACd,cAAmB,EACnB,kBAAuB,EACvB,aAAqB,GACtB,EAAE,qBAAqB,2CAkTvB"}
|
|
@@ -93,6 +93,25 @@ export default function FabricWhiteboard({ initialData, onSave, saveDebounceMs,
|
|
|
93
93
|
const [documents, setDocuments] = useState([]);
|
|
94
94
|
const [selectionBox, setSelectionBox] = useState(null);
|
|
95
95
|
const [selectedCanvasObjects, setSelectedCanvasObjects] = useState([]);
|
|
96
|
+
const [canvasZoom, setCanvasZoom] = useState(1);
|
|
97
|
+
// Track live zoom for the ZoomControls display. Only triggers a re-render
|
|
98
|
+
// when the zoom value actually changes, so panning doesn't cause extra renders.
|
|
99
|
+
React.useEffect(() => {
|
|
100
|
+
const canvas = fabricCanvasRef.current;
|
|
101
|
+
if (!canvas || !canvasReady)
|
|
102
|
+
return;
|
|
103
|
+
let lastZoom = canvas.viewportTransform?.[0] ?? 1;
|
|
104
|
+
const syncZoom = () => {
|
|
105
|
+
const z = canvas.viewportTransform?.[0];
|
|
106
|
+
if (z !== undefined && z !== lastZoom) {
|
|
107
|
+
lastZoom = z;
|
|
108
|
+
setCanvasZoom(z);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
canvas.on("after:render", syncZoom);
|
|
112
|
+
syncZoom(); // initialise immediately
|
|
113
|
+
return () => { canvas.off("after:render", syncZoom); };
|
|
114
|
+
}, [canvasReady]);
|
|
96
115
|
const MIN_ZOOM = 0.1;
|
|
97
116
|
const MAX_ZOOM = 5;
|
|
98
117
|
const ZOOM_STEP = 0.1;
|
|
@@ -272,5 +291,5 @@ export default function FabricWhiteboard({ initialData, onSave, saveDebounceMs,
|
|
|
272
291
|
backgroundImage: `radial-gradient(circle, rgba(255,255,255,0.2) 1.2px, transparent 1.2px)`,
|
|
273
292
|
backgroundSize: "40px 40px",
|
|
274
293
|
zIndex: 0,
|
|
275
|
-
} }), _jsx("canvas", { ref: canvasRef, className: "absolute inset-0", style: { zIndex: 1 } }), _jsx(MemoizedOverlayWrapper, { tasks: tasks, documents: documents, canvasReady: canvasReady, fabricCanvasRef: fabricCanvasRef, onTasksUpdate: setTasks, onDocumentsUpdate: setDocuments, selectionBox: selectionBox, selectedCanvasObjects: selectedCanvasObjects, clearHtmlSelectionRef: clearHtmlSelectionRef }), _jsxs("div", { className: "absolute inset-0 pointer-events-none", style: { zIndex: 100 }, children: [_jsx("div", { className: "pointer-events-auto", children: _jsx(MemoizedToolbarWrapper, { canvasReady: canvasReady, fabricCanvasRef: fabricCanvasRef, isRestoringRef: isRestoringRef, onAddTask: handleAddTaskFromDropdown, onAddDocument: handleAddDocumentFromDropdown, availableDocuments: availableDocuments, availableTasks: availableTasks, isLoadingData: isLoadingData }) }), _jsx("div", { className: "pointer-events-auto", children: _jsx(ToolOptionsPanel, { fabricCanvas: fabricCanvasRef }) }), _jsx("div", { className: "pointer-events-auto", children: _jsx(ZoomControls, { zoom:
|
|
294
|
+
} }), _jsx("canvas", { ref: canvasRef, className: "absolute inset-0", style: { zIndex: 1 } }), _jsx(MemoizedOverlayWrapper, { tasks: tasks, documents: documents, canvasReady: canvasReady, fabricCanvasRef: fabricCanvasRef, onTasksUpdate: setTasks, onDocumentsUpdate: setDocuments, selectionBox: selectionBox, selectedCanvasObjects: selectedCanvasObjects, clearHtmlSelectionRef: clearHtmlSelectionRef }), _jsxs("div", { className: "absolute inset-0 pointer-events-none", style: { zIndex: 100 }, children: [_jsx("div", { className: "pointer-events-auto", children: _jsx(MemoizedToolbarWrapper, { canvasReady: canvasReady, fabricCanvasRef: fabricCanvasRef, isRestoringRef: isRestoringRef, onAddTask: handleAddTaskFromDropdown, onAddDocument: handleAddDocumentFromDropdown, availableDocuments: availableDocuments, availableTasks: availableTasks, isLoadingData: isLoadingData }) }), _jsx("div", { className: "pointer-events-auto", children: _jsx(ToolOptionsPanel, { fabricCanvas: fabricCanvasRef }) }), _jsx("div", { className: "pointer-events-auto", children: _jsx(ZoomControls, { zoom: canvasZoom, onZoomIn: handleZoomIn, onZoomOut: handleZoomOut, onResetZoom: handleResetZoom }) })] })] }) }));
|
|
276
295
|
}
|