@mhamz.01/easyflow-whiteboard 2.154.0 → 2.156.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":"AAEA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAI9C,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;IACtB,qBAAqB,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,MAAM,IAAI,CAAC,CAAC;CAC5D;;AAaD,wBAktBG"}
1
+ {"version":3,"file":"custom-node-overlay-layer.d.ts","sourceRoot":"","sources":["../../../src/components/node/custom-node-overlay-layer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAK9C,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;IACtB,qBAAqB,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,MAAM,IAAI,CAAC,CAAC;CAC5D;;AAaD,wBA+tBG"}
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import React, { useState, useEffect, useRef } from "react";
4
4
  import TaskNode from "./custom-node";
5
5
  import DocumentNode from "./document-node";
6
+ import { util } from "fabric";
6
7
  // ─── Component ────────────────────────────────────────────────────────────────
7
8
  export default React.memo(function CanvasOverlayLayer({ tasks, documents, onTasksUpdate, onDocumentsUpdate, canvasZoom = 1, canvasViewport = { x: 0, y: 0 }, selectionBox = null, selectedCanvasObjects = [], fabricCanvas, canvasReady: canvasReadyProp = false, clearHtmlSelectionRef, }) {
8
9
  const [localTasks, setLocalTasks] = useState(tasks);
@@ -308,28 +309,30 @@ export default React.memo(function CanvasOverlayLayer({ tasks, documents, onTask
308
309
  if (pos)
309
310
  startPositions.set(id, pos);
310
311
  });
312
+ // In handleDragStart — replace the activeSelection branch:
311
313
  const liveActiveObjects = canvas.getActiveObjects();
312
314
  const activeSelection = canvas.getActiveObject();
313
315
  const canvasObjectsStartPos = new Map();
314
- liveActiveObjects.forEach((obj) => {
315
- // If objects are grouped in an activeSelection, their left/top is relative
316
- // to the group center. We need their true world position instead.
317
- if (activeSelection && activeSelection.type === "activeSelection") {
318
- // Calculate the object's true world position from its transform matrix
316
+ if (activeSelection && activeSelection.type === "activeSelection" && liveActiveObjects.length > 1) {
317
+ // Snapshot each child's TRUE canvas-absolute position via its transform matrix,
318
+ // not its group-relative left/top. This avoids drift caused by activeSelection's
319
+ // internal bounding-box recalculation during the drag.
320
+ liveActiveObjects.forEach((obj) => {
319
321
  const matrix = obj.calcTransformMatrix();
320
322
  canvasObjectsStartPos.set(obj, {
321
- left: matrix[4], // translateX from world transform
322
- top: matrix[5], // translateY from world transform
323
+ left: matrix[4],
324
+ top: matrix[5],
323
325
  });
324
- }
325
- else {
326
- // Single object — left/top IS world position
326
+ });
327
+ }
328
+ else {
329
+ liveActiveObjects.forEach((obj) => {
327
330
  canvasObjectsStartPos.set(obj, {
328
331
  left: obj.left || 0,
329
332
  top: obj.top || 0,
330
333
  });
331
- }
332
- });
334
+ });
335
+ }
333
336
  // 10. Commit to the ref for the requestAnimationFrame loop
334
337
  dragStateRef.current = {
335
338
  isDragging: true,
@@ -405,19 +408,26 @@ export default React.memo(function CanvasOverlayLayer({ tasks, documents, onTask
405
408
  y: (startPositions.get(d.id)?.y ?? d.y) + deltaY,
406
409
  }
407
410
  : d));
408
- // 7. Sync Fabric Objects (Imperative update for performance)
409
- canvasObjectsStartPos.forEach((startPos, obj) => {
410
- obj.set({
411
- left: startPos.left + deltaX,
412
- top: startPos.top + deltaY,
413
- });
414
- obj.setCoords(); // Required for selection/intersection accuracy
415
- });
416
411
  const activeObj = canvas.getActiveObject();
417
- if (activeObj && activeObj.type === "activeSelection") {
418
- activeObj.setCoords();
412
+ const isGroup = activeObj && activeObj.type === "activeSelection" && canvasObjectsStartPos.size > 1;
413
+ // Precompute the group's inverse matrix ONCE per frame, not per child
414
+ let groupInverseMatrix = null;
415
+ if (isGroup) {
416
+ const groupMatrix = activeObj.calcOwnMatrix();
417
+ groupInverseMatrix = util.invertTransform(groupMatrix);
419
418
  }
420
- // 8. Single render call for all Fabric changes
419
+ canvasObjectsStartPos.forEach((startPos, obj) => {
420
+ const targetAbsoluteLeft = startPos.left + deltaX;
421
+ const targetAbsoluteTop = startPos.top + deltaY;
422
+ if (isGroup && groupInverseMatrix) {
423
+ const localPoint = util.transformPoint({ x: targetAbsoluteLeft, y: targetAbsoluteTop }, groupInverseMatrix);
424
+ obj.set({ left: localPoint.x, top: localPoint.y });
425
+ }
426
+ else {
427
+ obj.set({ left: targetAbsoluteLeft, top: targetAbsoluteTop });
428
+ }
429
+ obj.setCoords();
430
+ });
421
431
  canvas.requestRenderAll();
422
432
  });
423
433
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mhamz.01/easyflow-whiteboard",
3
- "version": "2.154.0",
3
+ "version": "2.156.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",