@mhamz.01/easyflow-whiteboard 2.48.0 → 2.51.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.
@@ -38,6 +38,7 @@ interface CanvasOverlayLayerProps {
38
38
  } | null;
39
39
  selectedCanvasObjects?: FabricObject[];
40
40
  fabricCanvas?: React.RefObject<Canvas | null>;
41
+ canvasReady?: boolean;
41
42
  }
42
43
  export default function CanvasOverlayLayer({ tasks, documents, onTasksUpdate, onDocumentsUpdate, canvasZoom, canvasViewport, selectionBox, selectedCanvasObjects, fabricCanvas, }: CanvasOverlayLayerProps): import("react/jsx-runtime").JSX.Element;
43
44
  export {};
@@ -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;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,2CA6hBzB"}
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,2CA2jBzB"}
@@ -9,6 +9,7 @@ export default function CanvasOverlayLayer({ tasks, documents, onTasksUpdate, on
9
9
  const [localDocuments, setLocalDocuments] = useState(documents);
10
10
  const [selectedIds, setSelectedIds] = useState(new Set());
11
11
  const [dragging, setDragging] = useState(null);
12
+ const [canvasReady, setCanvasReady] = useState(false);
12
13
  const dragStateRef = useRef({
13
14
  isDragging: false,
14
15
  itemIds: [],
@@ -24,6 +25,23 @@ export default function CanvasOverlayLayer({ tasks, documents, onTasksUpdate, on
24
25
  // ── Sync props → local state ────────────────────────────────────────────────
25
26
  useEffect(() => { setLocalTasks(tasks); }, [tasks]);
26
27
  useEffect(() => { setLocalDocuments(documents); }, [documents]);
28
+ // effect — polls until fabricCanvas.current is available:
29
+ useEffect(() => {
30
+ if (canvasReady)
31
+ return;
32
+ if (fabricCanvas?.current) {
33
+ setCanvasReady(true);
34
+ return;
35
+ }
36
+ // Poll every 50ms until canvas is ready (only needed on first load)
37
+ const interval = setInterval(() => {
38
+ if (fabricCanvas?.current) {
39
+ setCanvasReady(true);
40
+ clearInterval(interval);
41
+ }
42
+ }, 50);
43
+ return () => clearInterval(interval);
44
+ }, [fabricCanvas, canvasReady]);
27
45
  // ── Event Forwarding (Fixes Zooming on Nodes) ───────────────────────────────
28
46
  const handleOverlayWheel = (e) => {
29
47
  if (e.ctrlKey || e.metaKey || e.shiftKey) {
@@ -84,7 +102,7 @@ export default function CanvasOverlayLayer({ tasks, documents, onTasksUpdate, on
84
102
  return () => {
85
103
  overlayEl.removeEventListener("wheel", handleGlobalWheel);
86
104
  };
87
- }, [fabricCanvas, canvasZoom]); // Re-bind when zoom changes to keep closure fresh
105
+ }, [fabricCanvas, canvasZoom, canvasReady]); // Re-bind when zoom changes to keep closure fresh
88
106
  // ── Fabric → Overlay Sync (Fixes Dragging from Fabric area) ──────────────────
89
107
  useEffect(() => {
90
108
  const canvas = fabricCanvas?.current;
@@ -115,26 +133,35 @@ export default function CanvasOverlayLayer({ tasks, documents, onTasksUpdate, on
115
133
  setSelectedIds(new Set());
116
134
  return;
117
135
  }
118
- // ── Read from ref not stale closure ──
119
- const activeObject = canvas.getActiveObject(); // the group/selection box
120
- const activeObjects = canvas.getActiveObjects(); // individual objects inside it
121
- const isTargetAlreadySelected = activeObjects.includes(target) || // clicked an individual selected object
122
- activeObject === target; // clicked the selection box itself
123
- if (!isTargetAlreadySelected) {
136
+ // At zoom=1 with identity VPT, getActiveObject() can return null before
137
+ // Fabric updates _activeObject. Use e.transform as the primary check —
138
+ // it is populated by Fabric's hit-test regardless of zoom level.
139
+ const transformTarget = e.transform?.target;
140
+ const activeObject = canvas.getActiveObject();
141
+ const activeObjects = canvas.getActiveObjects();
142
+ const isPartOfActiveSelection = transformTarget === target || // most reliable — direct from event
143
+ activeObject === target || // selection box group
144
+ activeObjects.includes(target); // individual object in multi-select
145
+ if (!isPartOfActiveSelection) {
124
146
  setSelectedIds(new Set());
125
147
  }
126
148
  };
149
+ const handleSelectionCleared = () => {
150
+ setSelectedIds(new Set());
151
+ };
127
152
  canvas.on("object:moving", handleObjectMoving);
128
153
  canvas.on("mouse:down", handleMouseDown);
154
+ canvas.on("selection:cleared", handleSelectionCleared);
129
155
  return () => {
130
156
  canvas.off("object:moving", handleObjectMoving);
131
157
  canvas.off("mouse:down", handleMouseDown);
158
+ canvas.off("selection:cleared", handleSelectionCleared);
132
159
  };
133
160
  // ── selectedIds REMOVED from deps — read via selectedIdsRef instead ──────
134
161
  // Having selectedIds here caused the effect to re-register on every selection
135
162
  // change, creating a new closure each time. The second drag captured a stale
136
163
  // or empty selectedIds from the closure at re-registration time.
137
- }, [canvasZoom, fabricCanvas]);
164
+ }, [canvasZoom, fabricCanvas, canvasReady]);
138
165
  // ── Helpers ─────────────────────────────────────────────────────────────────
139
166
  const getItemPosition = (id) => {
140
167
  const task = localTasks.find((t) => t.id === id);
@@ -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,mCAAmC,CAAC;AAkBlE,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;AAID,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,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;AAID,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EACvC,WAAW,EACX,MAAM,EACN,cAAc,GACf,EAAE,qBAAqB,2CAkPvB"}
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,mCAAmC,CAAC;AAkBlE,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;AAID,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,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;AAID,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EACvC,WAAW,EACX,MAAM,EACN,cAAc,GACf,EAAE,qBAAqB,2CAqPvB"}
@@ -44,6 +44,7 @@ export default function FabricWhiteboard({ initialData, onSave, saveDebounceMs,
44
44
  const pushHistory = useWhiteboardStore((state) => state.pushHistory);
45
45
  // State
46
46
  const [tasks, setTasks] = useState([]);
47
+ const [canvasReady, setCanvasReady] = useState(false);
47
48
  const [documents, setDocuments] = useState([]);
48
49
  const [canvasZoom, setCanvasZoom] = useState(1);
49
50
  const [canvasViewport, setCanvasViewport] = useState({ x: 0, y: 0 });
@@ -63,6 +64,7 @@ export default function FabricWhiteboard({ initialData, onSave, saveDebounceMs,
63
64
  setTasks,
64
65
  setDocuments,
65
66
  initialData,
67
+ onReady: () => setCanvasReady(true),
66
68
  });
67
69
  // CHANGE 3: Pass onSave and saveDebounceMs to usePersistence (replaces localStorage.setItem)
68
70
  usePersistence({
@@ -194,5 +196,5 @@ export default function FabricWhiteboard({ initialData, onSave, saveDebounceMs,
194
196
  backgroundImage: `radial-gradient(circle, rgba(255,255,255,0.2) 1.2px, transparent 1.2px)`,
195
197
  backgroundSize: "40px 40px",
196
198
  zIndex: 0,
197
- } }), _jsx("canvas", { ref: canvasRef, className: "absolute inset-0", style: { zIndex: 1 } }), _jsx(CanvasOverlayLayer, { tasks: tasks, documents: documents, onTasksUpdate: setTasks, onDocumentsUpdate: setDocuments, canvasZoom: canvasZoom, canvasViewport: canvasViewport, selectionBox: selectionBox, selectedCanvasObjects: selectedCanvasObjects, fabricCanvas: fabricCanvasRef }), _jsxs("div", { className: "absolute inset-0 pointer-events-none", style: { zIndex: 100 }, children: [_jsx("div", { className: "pointer-events-auto", children: _jsx(WhiteboardToolbar, { fabricCanvas: fabricCanvasRef, isRestoringRef: isRestoringRef, onAddTask: handleAddTaskFromDropdown, onAddDocument: handleAddDocumentFromDropdown }) }), _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 }) })] })] }) }));
199
+ } }), _jsx("canvas", { ref: canvasRef, className: "absolute inset-0", style: { zIndex: 1 } }), _jsx(CanvasOverlayLayer, { tasks: tasks, documents: documents, onTasksUpdate: setTasks, onDocumentsUpdate: setDocuments, canvasZoom: canvasZoom, canvasViewport: canvasViewport, selectionBox: selectionBox, selectedCanvasObjects: selectedCanvasObjects, fabricCanvas: fabricCanvasRef, canvasReady: canvasReady }), _jsxs("div", { className: "absolute inset-0 pointer-events-none", style: { zIndex: 100 }, children: [_jsx("div", { className: "pointer-events-auto", children: _jsx(WhiteboardToolbar, { fabricCanvas: fabricCanvasRef, isRestoringRef: isRestoringRef, onAddTask: handleAddTaskFromDropdown, onAddDocument: handleAddDocumentFromDropdown }) }), _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 }) })] })] }) }));
198
200
  }
@@ -15,7 +15,8 @@ interface UseCanvasInitProps {
15
15
  setTasks: (tasks: any[]) => void;
16
16
  setDocuments: (docs: any[]) => void;
17
17
  initialData?: WhiteboardInitialData;
18
+ onReady?: () => void;
18
19
  }
19
- export declare const useCanvasInit: ({ canvasRef, fabricCanvasRef, activeTool, suppressHistoryRef, isRestoringRef, pushHistory, setTasks, setDocuments, initialData, }: UseCanvasInitProps) => void;
20
+ export declare const useCanvasInit: ({ canvasRef, fabricCanvasRef, activeTool, suppressHistoryRef, isRestoringRef, pushHistory, setTasks, setDocuments, initialData, onReady, }: UseCanvasInitProps) => void;
20
21
  export {};
21
22
  //# sourceMappingURL=useCanvasInit.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useCanvasInit.d.ts","sourceRoot":"","sources":["../../src/hooks/useCanvasInit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,SAAS,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAKhC,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAK,MAAM,CAAC;IACnB,KAAK,CAAC,EAAM,GAAG,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC;CACnB;AAED,UAAU,kBAAkB;IAC1B,SAAS,EAAW,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IACxD,eAAe,EAAK,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,UAAU,EAAU,MAAM,CAAC;IAC3B,kBAAkB,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IACvC,cAAc,EAAM,SAAS,CAAC,OAAO,CAAC,CAAC;IACvC,WAAW,EAAS,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,QAAQ,EAAY,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IAC3C,YAAY,EAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAQ,qBAAqB,CAAC;CAC3C;AAID,eAAO,MAAM,aAAa,GAAI,mIAU3B,kBAAkB,SAuHpB,CAAC"}
1
+ {"version":3,"file":"useCanvasInit.d.ts","sourceRoot":"","sources":["../../src/hooks/useCanvasInit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,SAAS,EAAY,MAAM,OAAO,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAKhC,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAK,MAAM,CAAC;IACnB,KAAK,CAAC,EAAM,GAAG,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC;CACnB;AAED,UAAU,kBAAkB;IAC1B,SAAS,EAAW,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IACxD,eAAe,EAAK,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,UAAU,EAAU,MAAM,CAAC;IAC3B,kBAAkB,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IACvC,cAAc,EAAM,SAAS,CAAC,OAAO,CAAC,CAAC;IACvC,WAAW,EAAS,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,QAAQ,EAAY,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IAC3C,YAAY,EAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAQ,qBAAqB,CAAC;IAC1C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAID,eAAO,MAAM,aAAa,GAAI,4IAW3B,kBAAkB,SA0HpB,CAAC"}
@@ -2,7 +2,7 @@ import { useEffect } from "react";
2
2
  import { Canvas } from "fabric";
3
3
  import { initializeFabricCanvas, addWelcomeContent } from "../lib/fabric-utils";
4
4
  // ─── Hook ─────────────────────────────────────────────────────────────────────
5
- export const useCanvasInit = ({ canvasRef, fabricCanvasRef, activeTool, suppressHistoryRef, isRestoringRef, pushHistory, setTasks, setDocuments, initialData, }) => {
5
+ export const useCanvasInit = ({ canvasRef, fabricCanvasRef, activeTool, suppressHistoryRef, isRestoringRef, pushHistory, setTasks, setDocuments, initialData, onReady, }) => {
6
6
  useEffect(() => {
7
7
  if (!canvasRef.current || fabricCanvasRef.current)
8
8
  return;
@@ -68,6 +68,7 @@ export const useCanvasInit = ({ canvasRef, fabricCanvasRef, activeTool, suppress
68
68
  }
69
69
  }
70
70
  isRestoringRef.current = false;
71
+ onReady?.();
71
72
  }
72
73
  else {
73
74
  if (!disposed) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mhamz.01/easyflow-whiteboard",
3
- "version": "2.48.0",
3
+ "version": "2.51.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",