@mhamz.01/easyflow-whiteboard 2.2.0 → 2.4.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;AAM9C,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;CAC/C;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,
|
|
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;AAM9C,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;CAC/C;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,2CAofzB"}
|
|
@@ -172,7 +172,6 @@ export default function CanvasOverlayLayer({ tasks, documents, onTasksUpdate, on
|
|
|
172
172
|
return e;
|
|
173
173
|
};
|
|
174
174
|
const handleDragStart = (itemId, e) => {
|
|
175
|
-
// Prevent browser scrolling while dragging
|
|
176
175
|
if (e.cancelable)
|
|
177
176
|
e.preventDefault();
|
|
178
177
|
const pointer = getPointerEvent(e);
|
|
@@ -184,33 +183,64 @@ export default function CanvasOverlayLayer({ tasks, documents, onTasksUpdate, on
|
|
|
184
183
|
itemsToDrag = [itemId];
|
|
185
184
|
setSelectedIds(new Set([itemId]));
|
|
186
185
|
}
|
|
186
|
+
// ── Read VPT first — single source of truth for coordinate space ──
|
|
187
|
+
const vpt = fabricCanvas?.current?.viewportTransform;
|
|
188
|
+
const liveZoom = vpt ? vpt[0] : 1;
|
|
189
|
+
const liveVpX = vpt ? vpt[4] : 0;
|
|
190
|
+
const liveVpY = vpt ? vpt[5] : 0;
|
|
191
|
+
// ── Snapshot world positions from DOM directly ──
|
|
192
|
+
// Avoids stale localTasks/localDocuments state by back-calculating
|
|
193
|
+
// world position from the actual rendered screen position of the element
|
|
187
194
|
const startPositions = new Map();
|
|
188
195
|
itemsToDrag.forEach((id) => {
|
|
189
|
-
const
|
|
190
|
-
if (
|
|
191
|
-
|
|
196
|
+
const el = document.querySelector(`[data-node-id="${id}"]`);
|
|
197
|
+
if (el) {
|
|
198
|
+
const rect = el.getBoundingClientRect();
|
|
199
|
+
// Back-calculate world coords from actual DOM position — always accurate
|
|
200
|
+
const worldX = (rect.left - liveVpX) / liveZoom;
|
|
201
|
+
const worldY = (rect.top - liveVpY) / liveZoom;
|
|
202
|
+
startPositions.set(id, { x: worldX, y: worldY });
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
// Fallback to state if DOM element not found
|
|
206
|
+
const pos = getItemPosition(id);
|
|
207
|
+
if (pos)
|
|
208
|
+
startPositions.set(id, pos);
|
|
209
|
+
}
|
|
192
210
|
});
|
|
193
211
|
const canvasObjectsStartPos = new Map();
|
|
194
212
|
selectedCanvasObjects.forEach((obj) => {
|
|
195
213
|
canvasObjectsStartPos.set(obj, { left: obj.left || 0, top: obj.top || 0 });
|
|
196
214
|
});
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
215
|
+
// ── Offset from pointer to node's top-left in screen space ──
|
|
216
|
+
const clickedEl = document.querySelector(`[data-node-id="${itemId}"]`);
|
|
217
|
+
let offsetX = 0;
|
|
218
|
+
let offsetY = 0;
|
|
219
|
+
if (clickedEl) {
|
|
220
|
+
const rect = clickedEl.getBoundingClientRect();
|
|
221
|
+
offsetX = pointer.clientX - rect.left;
|
|
222
|
+
offsetY = pointer.clientY - rect.top;
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
const clickedPos = getItemPosition(itemId);
|
|
226
|
+
if (!clickedPos)
|
|
227
|
+
return;
|
|
228
|
+
const screenX = clickedPos.x * liveZoom + liveVpX;
|
|
229
|
+
const screenY = clickedPos.y * liveZoom + liveVpY;
|
|
230
|
+
offsetX = pointer.clientX - screenX;
|
|
231
|
+
offsetY = pointer.clientY - screenY;
|
|
232
|
+
}
|
|
202
233
|
dragStateRef.current = {
|
|
203
234
|
isDragging: true,
|
|
204
235
|
itemIds: itemsToDrag,
|
|
205
236
|
startPositions,
|
|
206
237
|
canvasObjectsStartPos,
|
|
207
|
-
offsetX
|
|
208
|
-
offsetY
|
|
238
|
+
offsetX,
|
|
239
|
+
offsetY,
|
|
209
240
|
};
|
|
210
241
|
setDragging({ itemIds: itemsToDrag });
|
|
211
242
|
document.body.style.cursor = "grabbing";
|
|
212
243
|
document.body.style.userSelect = "none";
|
|
213
|
-
// Prevents mobile pull-to-refresh
|
|
214
244
|
document.body.style.touchAction = "none";
|
|
215
245
|
};
|
|
216
246
|
// ── Drag move (HTML Node side) ───────────────────────────────────────────────
|
|
@@ -220,7 +250,6 @@ export default function CanvasOverlayLayer({ tasks, documents, onTasksUpdate, on
|
|
|
220
250
|
const handleMove = (e) => {
|
|
221
251
|
if (!dragStateRef.current.isDragging)
|
|
222
252
|
return;
|
|
223
|
-
// Prevent mobile scrolling
|
|
224
253
|
if (e.cancelable)
|
|
225
254
|
e.preventDefault();
|
|
226
255
|
const pointer = getPointerEvent(e);
|
|
@@ -232,22 +261,27 @@ export default function CanvasOverlayLayer({ tasks, documents, onTasksUpdate, on
|
|
|
232
261
|
const firstStart = startPositions.get(firstId);
|
|
233
262
|
if (!firstStart)
|
|
234
263
|
return;
|
|
235
|
-
//
|
|
236
|
-
const
|
|
237
|
-
const
|
|
264
|
+
// ── Live VPT — no React state, no staleness ──
|
|
265
|
+
const vpt = fabricCanvas?.current?.viewportTransform;
|
|
266
|
+
const liveZoom = vpt ? vpt[0] : 1;
|
|
267
|
+
const liveVpX = vpt ? vpt[4] : 0;
|
|
268
|
+
const liveVpY = vpt ? vpt[5] : 0;
|
|
269
|
+
// pointer - offset = top-left of node in screen space
|
|
270
|
+
// subtract vpX, divide by zoom = world position
|
|
271
|
+
const newX = (pointer.clientX - offsetX - liveVpX) / liveZoom;
|
|
272
|
+
const newY = (pointer.clientY - offsetY - liveVpY) / liveZoom;
|
|
238
273
|
const deltaX = newX - firstStart.x;
|
|
239
274
|
const deltaY = newY - firstStart.y;
|
|
240
|
-
|
|
241
|
-
setLocalTasks((prev) => prev.map((t) => (itemIds.includes(t.id) ? {
|
|
275
|
+
setLocalTasks((prev) => prev.map((t) => itemIds.includes(t.id) ? {
|
|
242
276
|
...t,
|
|
243
|
-
x: (startPositions.get(t.id)?.x
|
|
244
|
-
y: (startPositions.get(t.id)?.y
|
|
245
|
-
} : t))
|
|
246
|
-
setLocalDocuments((prev) => prev.map((d) =>
|
|
277
|
+
x: (startPositions.get(t.id)?.x ?? t.x) + deltaX,
|
|
278
|
+
y: (startPositions.get(t.id)?.y ?? t.y) + deltaY,
|
|
279
|
+
} : t));
|
|
280
|
+
setLocalDocuments((prev) => prev.map((d) => itemIds.includes(d.id) ? {
|
|
247
281
|
...d,
|
|
248
|
-
x: (startPositions.get(d.id)?.x
|
|
249
|
-
y: (startPositions.get(d.id)?.y
|
|
250
|
-
} : d))
|
|
282
|
+
x: (startPositions.get(d.id)?.x ?? d.x) + deltaX,
|
|
283
|
+
y: (startPositions.get(d.id)?.y ?? d.y) + deltaY,
|
|
284
|
+
} : d));
|
|
251
285
|
if (fabricCanvas?.current) {
|
|
252
286
|
canvasObjectsStartPos.forEach((startPos, obj) => {
|
|
253
287
|
obj.set({
|
|
@@ -335,22 +369,15 @@ export default function CanvasOverlayLayer({ tasks, documents, onTasksUpdate, on
|
|
|
335
369
|
const renderItem = (id, x, y, children) => {
|
|
336
370
|
const screenX = x * canvasZoom;
|
|
337
371
|
const screenY = y * canvasZoom;
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
// You might want to pass 'isZooming' or 'isPanning' from your main canvas component here.
|
|
341
|
-
const isDragging = dragging?.itemIds.includes(id);
|
|
342
|
-
return (_jsx("div", { className: "pointer-events-auto absolute", style: {
|
|
372
|
+
const isDraggingItem = dragging?.itemIds.includes(id);
|
|
373
|
+
return (_jsx("div", { "data-node-id": id, className: "pointer-events-auto absolute", style: {
|
|
343
374
|
left: 0,
|
|
344
375
|
top: 0,
|
|
345
|
-
// 2. Use translate3d for GPU performance
|
|
346
376
|
transform: `translate3d(${screenX}px, ${screenY}px, 0) scale(${canvasZoom})`,
|
|
347
377
|
transformOrigin: "top left",
|
|
348
|
-
// 3. THE FIX: Remove transition entirely during any viewport change
|
|
349
|
-
// Any 'ease' during zoom causes the "shaking" behavior.
|
|
350
378
|
transition: "none",
|
|
351
|
-
// 4. Optimization
|
|
352
379
|
willChange: "transform",
|
|
353
|
-
zIndex:
|
|
380
|
+
zIndex: isDraggingItem ? 1000 : 1,
|
|
354
381
|
}, children: children }, id));
|
|
355
382
|
};
|
|
356
383
|
return (_jsx("div", { ref: overlayRef, className: "absolute inset-0 pointer-events-none", style: { zIndex: 50 }, onWheel: handleOverlayWheel, onClick: (e) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSelection.d.ts","sourceRoot":"","sources":["../../src/hooks/useSelection.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAQ,YAAY,EAAe,MAAM,QAAQ,CAAC;AAMjE,UAAU,iBAAiB;IACzB,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,eAAe,EAAE,CAAC,GAAG,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,KAAK,IAAI,CAAC;IAC1F,wBAAwB,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;IAC5D,YAAY,EAAE,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;CAC/C;AAED,eAAO,MAAM,YAAY,GAAI,wFAM1B,iBAAiB,
|
|
1
|
+
{"version":3,"file":"useSelection.d.ts","sourceRoot":"","sources":["../../src/hooks/useSelection.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAQ,YAAY,EAAe,MAAM,QAAQ,CAAC;AAMjE,UAAU,iBAAiB;IACzB,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,eAAe,EAAE,CAAC,GAAG,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,KAAK,IAAI,CAAC;IAC1F,wBAAwB,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;IAC5D,YAAY,EAAE,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;CAC/C;AAED,eAAO,MAAM,YAAY,GAAI,wFAM1B,iBAAiB,SAsJnB,CAAC"}
|
|
@@ -23,8 +23,6 @@ export const useSelection = ({ fabricCanvas, activeTool, setSelectionBox, setSel
|
|
|
23
23
|
if (activeToolRef.current !== "select" || e.target)
|
|
24
24
|
return;
|
|
25
25
|
isSelecting = true;
|
|
26
|
-
// Hide Fabric's native rubber-band rect — we draw our own
|
|
27
|
-
canvas.selection = false;
|
|
28
26
|
const p = canvas.getScenePoint(e.e);
|
|
29
27
|
selStart = { x: p.x, y: p.y };
|
|
30
28
|
selRect = new Rect({
|
|
@@ -32,11 +30,12 @@ export const useSelection = ({ fabricCanvas, activeTool, setSelectionBox, setSel
|
|
|
32
30
|
top: p.y,
|
|
33
31
|
width: 0,
|
|
34
32
|
height: 0,
|
|
35
|
-
fill: "
|
|
36
|
-
stroke: "
|
|
37
|
-
strokeWidth:
|
|
33
|
+
fill: "transparent",
|
|
34
|
+
stroke: "transparent",
|
|
35
|
+
strokeWidth: 0,
|
|
38
36
|
selectable: false,
|
|
39
37
|
evented: false,
|
|
38
|
+
visible: false, // ← hidden, pure coordinate tracker
|
|
40
39
|
excludeFromExport: true,
|
|
41
40
|
});
|
|
42
41
|
canvas.add(selRect);
|
|
@@ -56,7 +55,7 @@ export const useSelection = ({ fabricCanvas, activeTool, setSelectionBox, setSel
|
|
|
56
55
|
top: h < 0 ? p.y : selStart.y,
|
|
57
56
|
width: Math.abs(w),
|
|
58
57
|
height: Math.abs(h),
|
|
59
|
-
strokeWidth
|
|
58
|
+
// strokeWidth line removed
|
|
60
59
|
});
|
|
61
60
|
selRect.setCoords();
|
|
62
61
|
canvas.renderAll();
|
|
@@ -85,8 +84,6 @@ export const useSelection = ({ fabricCanvas, activeTool, setSelectionBox, setSel
|
|
|
85
84
|
canvas.renderAll();
|
|
86
85
|
selRect = null;
|
|
87
86
|
}
|
|
88
|
-
// Restore Fabric's native selection for object clicking
|
|
89
|
-
canvas.selection = true;
|
|
90
87
|
isSelecting = false;
|
|
91
88
|
setTimeout(() => setSelectionBox(null), 150);
|
|
92
89
|
};
|
|
@@ -135,7 +132,6 @@ export const useSelection = ({ fabricCanvas, activeTool, setSelectionBox, setSel
|
|
|
135
132
|
if (selRect) {
|
|
136
133
|
canvas.remove(selRect);
|
|
137
134
|
}
|
|
138
|
-
canvas.selection = true; // always restore on cleanup
|
|
139
135
|
};
|
|
140
136
|
// ── Stable deps only — effect registers once per canvas mount ──
|
|
141
137
|
}, [fabricCanvas, setSelectionBox, setSelectedCanvasObjects, setSelectedObjectType, setActiveTool, isDrawingRef]);
|