@mhamz.01/easyflow-whiteboard 2.79.0 → 2.81.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.
Files changed (31) hide show
  1. package/dist/components/node/custom-node-overlay-fix.d.ts +3 -0
  2. package/dist/components/node/custom-node-overlay-fix.d.ts.map +1 -0
  3. package/dist/components/node/custom-node-overlay-fix.js +198 -0
  4. package/dist/components/node/custom-node-overlay-layer.d.ts +0 -44
  5. package/dist/components/node/custom-node-overlay-layer.d.ts.map +1 -1
  6. package/dist/components/node/custom-node-overlay-layer.js +545 -458
  7. package/dist/components/node/hooks/useCanvasReady.d.ts +7 -0
  8. package/dist/components/node/hooks/useCanvasReady.d.ts.map +1 -0
  9. package/dist/components/node/hooks/useCanvasReady.js +21 -0
  10. package/dist/components/node/hooks/useKeyboardShortcuts.d.ts +12 -0
  11. package/dist/components/node/hooks/useKeyboardShortcuts.d.ts.map +1 -0
  12. package/dist/components/node/hooks/useKeyboardShortcuts.js +37 -0
  13. package/dist/components/node/hooks/useNodeDrag.d.ts +25 -0
  14. package/dist/components/node/hooks/useNodeDrag.d.ts.map +1 -0
  15. package/dist/components/node/hooks/useNodeDrag.js +119 -0
  16. package/dist/components/node/hooks/useNodeSync.d.ts +13 -0
  17. package/dist/components/node/hooks/useNodeSync.d.ts.map +1 -0
  18. package/dist/components/node/hooks/useNodeSync.js +56 -0
  19. package/dist/components/node/hooks/useSelectionBox.d.ts +20 -0
  20. package/dist/components/node/hooks/useSelectionBox.d.ts.map +1 -0
  21. package/dist/components/node/hooks/useSelectionBox.js +30 -0
  22. package/dist/components/node/hooks/useWheelZoom.d.ts +16 -0
  23. package/dist/components/node/hooks/useWheelZoom.d.ts.map +1 -0
  24. package/dist/components/node/hooks/useWheelZoom.js +76 -0
  25. package/dist/components/node/types/overlay-types.d.ts +67 -0
  26. package/dist/components/node/types/overlay-types.d.ts.map +1 -0
  27. package/dist/components/node/types/overlay-types.js +1 -0
  28. package/dist/components/whiteboard/whiteboard-test.d.ts +1 -1
  29. package/dist/components/whiteboard/whiteboard-test.d.ts.map +1 -1
  30. package/dist/components/whiteboard/whiteboard-test.js +2 -2
  31. package/package.json +1 -1
@@ -0,0 +1,3 @@
1
+ import { CanvasOverlayLayerProps } from "./types/overlay-types";
2
+ export default function CanvasOverlayLayer({ tasks, documents, onTasksUpdate, onDocumentsUpdate, canvasZoom, canvasViewport, selectionBox, selectedCanvasObjects, fabricCanvas, }: CanvasOverlayLayerProps): import("react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=custom-node-overlay-fix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-node-overlay-fix.d.ts","sourceRoot":"","sources":["../../../src/components/node/custom-node-overlay-fix.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAkB,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAQhF,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,2CA0SzB"}
@@ -0,0 +1,198 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState, useEffect, useRef, useCallback } from "react";
4
+ import TaskNode from "./custom-node";
5
+ import DocumentNode from "./document-node";
6
+ import { useWheelZoom } from "./hooks/useWheelZoom";
7
+ import { useNodeDrag } from "./hooks/useNodeDrag";
8
+ import { useSelectionBox } from "./hooks/useSelectionBox";
9
+ import { useKeyboardShortcuts } from "./hooks/useKeyboardShortcuts";
10
+ import { useCanvasReady } from "./hooks/useCanvasReady";
11
+ import { useNodeSync } from "./hooks/useNodeSync";
12
+ export default function CanvasOverlayLayer({ tasks, documents, onTasksUpdate, onDocumentsUpdate, canvasZoom = 1, canvasViewport = { x: 0, y: 0 }, selectionBox = null, selectedCanvasObjects = [], fabricCanvas, }) {
13
+ // ─── State Management ──────────────────────────────────────────────────
14
+ const [liveViewport, setLiveViewport] = useState(canvasViewport);
15
+ const [liveZoom, setLiveZoom] = useState(canvasZoom);
16
+ const [localTasks, setLocalTasks] = useState(tasks);
17
+ const [localDocuments, setLocalDocuments] = useState(documents);
18
+ const [selectedIds, setSelectedIds] = useState(new Set());
19
+ const [dragging, setDragging] = useState(null);
20
+ const overlayRef = useRef(null);
21
+ const dragStateRef = useRef(null);
22
+ // ─── Hooks ────────────────────────────────────────────────────────────
23
+ const canvasReady = useCanvasReady({ fabricCanvas });
24
+ const { handleOverlayWheel } = useWheelZoom({
25
+ overlayRef,
26
+ fabricCanvas,
27
+ canvasZoom,
28
+ canvasReady,
29
+ onViewportChange: useCallback((viewport, zoom) => {
30
+ setLiveViewport(viewport);
31
+ setLiveZoom(zoom);
32
+ }, []),
33
+ });
34
+ const { dragStateRef: dragRef, rafIdRef, getPointerEvent, getViewportTransform, handleDragStart: handleDragStartHook, handleDragMove: handleDragMoveHook, handleDragEnd: handleDragEndHook, } = useNodeDrag({
35
+ selectedIds,
36
+ fabricCanvas,
37
+ selectedCanvasObjects,
38
+ onDragStateChange: setDragging,
39
+ });
40
+ dragStateRef.current = dragRef.current;
41
+ useSelectionBox({
42
+ selectionBox,
43
+ localTasks,
44
+ localDocuments,
45
+ canvasZoom,
46
+ canvasViewport,
47
+ onSelectionChange: setSelectedIds,
48
+ });
49
+ useNodeSync({
50
+ tasks: localTasks,
51
+ documents: localDocuments,
52
+ selectedIds,
53
+ fabricCanvas,
54
+ onTasksUpdate,
55
+ onDocumentsUpdate,
56
+ });
57
+ useKeyboardShortcuts({
58
+ selectedIds,
59
+ localTasks,
60
+ localDocuments,
61
+ onSelectAll: () => setSelectedIds(new Set([...localTasks.map((t) => t.id), ...localDocuments.map((d) => d.id)])),
62
+ onClearSelection: () => setSelectedIds(new Set()),
63
+ onDeleteSelected: (tasks, docs) => {
64
+ setLocalTasks(tasks);
65
+ setLocalDocuments(docs);
66
+ setSelectedIds(new Set());
67
+ onTasksUpdate?.(tasks);
68
+ onDocumentsUpdate?.(docs);
69
+ },
70
+ });
71
+ // ─── Effects ──────────────────────────────────────────────────────────
72
+ useEffect(() => {
73
+ setLocalTasks(tasks);
74
+ }, [tasks]);
75
+ useEffect(() => {
76
+ setLocalDocuments(documents);
77
+ }, [documents]);
78
+ // ─── Handlers ─────────────────────────────────────────────────────────
79
+ const getItemPosition = useCallback((id) => {
80
+ const task = localTasks.find((t) => t.id === id);
81
+ if (task)
82
+ return { x: task.x, y: task.y };
83
+ const doc = localDocuments.find((d) => d.id === id);
84
+ if (doc)
85
+ return { x: doc.x, y: doc.y };
86
+ return undefined;
87
+ }, [localTasks, localDocuments]);
88
+ const handleDragStart = useCallback((itemId, e) => {
89
+ handleDragStartHook(itemId, getItemPosition, e);
90
+ }, [handleDragStartHook, getItemPosition]);
91
+ // ─── Drag Move Effect ─────────────────────────────────────────────────
92
+ useEffect(() => {
93
+ if (!dragging)
94
+ return;
95
+ const handleMove = (e) => {
96
+ if (!dragStateRef.current?.isDragging)
97
+ return;
98
+ if (e.cancelable)
99
+ e.preventDefault();
100
+ const pointer = getPointerEvent(e);
101
+ if (rafIdRef.current !== null)
102
+ cancelAnimationFrame(rafIdRef.current);
103
+ rafIdRef.current = requestAnimationFrame(() => {
104
+ const { itemIds, startPositions, canvasObjectsStartPos, offsetX, offsetY } = dragStateRef.current;
105
+ const canvas = fabricCanvas?.current;
106
+ if (!canvas)
107
+ return;
108
+ const { zoom: liveZoom, vpX: liveVpX, vpY: liveVpY } = getViewportTransform(canvas);
109
+ const currentWorldX = (pointer.clientX - liveVpX) / liveZoom;
110
+ const currentWorldY = (pointer.clientY - liveVpY) / liveZoom;
111
+ const deltaX = currentWorldX - offsetX;
112
+ const deltaY = currentWorldY - offsetY;
113
+ // Update HTML Nodes
114
+ setLocalTasks((prev) => prev.map((t) => itemIds.includes(t.id)
115
+ ? {
116
+ ...t,
117
+ x: (startPositions.get(t.id)?.x ?? t.x) + deltaX,
118
+ y: (startPositions.get(t.id)?.y ?? t.y) + deltaY,
119
+ }
120
+ : t));
121
+ setLocalDocuments((prev) => prev.map((d) => itemIds.includes(d.id)
122
+ ? {
123
+ ...d,
124
+ x: (startPositions.get(d.id)?.x ?? d.x) + deltaX,
125
+ y: (startPositions.get(d.id)?.y ?? d.y) + deltaY,
126
+ }
127
+ : d));
128
+ // Update Fabric Objects
129
+ canvasObjectsStartPos.forEach((startPos, obj) => {
130
+ obj.set({
131
+ left: startPos.left + deltaX,
132
+ top: startPos.top + deltaY,
133
+ });
134
+ obj.setCoords();
135
+ });
136
+ canvas.requestRenderAll();
137
+ });
138
+ };
139
+ const handleEnd = () => {
140
+ handleDragEndHook();
141
+ onTasksUpdate?.(localTasks);
142
+ onDocumentsUpdate?.(localDocuments);
143
+ };
144
+ window.addEventListener("mousemove", handleMove, { passive: false });
145
+ window.addEventListener("mouseup", handleEnd);
146
+ window.addEventListener("touchmove", handleMove, { passive: false });
147
+ window.addEventListener("touchend", handleEnd);
148
+ window.addEventListener("touchcancel", handleEnd);
149
+ return () => {
150
+ window.removeEventListener("mousemove", handleMove);
151
+ window.removeEventListener("mouseup", handleEnd);
152
+ window.removeEventListener("touchmove", handleMove);
153
+ window.removeEventListener("touchend", handleEnd);
154
+ window.removeEventListener("touchcancel", handleEnd);
155
+ };
156
+ }, [dragging, localTasks, localDocuments, fabricCanvas, getViewportTransform, getPointerEvent, handleDragEndHook, onTasksUpdate, onDocumentsUpdate]);
157
+ // ─── Selection Handlers ────────────────────────────────────────────────
158
+ const handleSelect = useCallback((id, e) => {
159
+ if (e?.shiftKey || e?.ctrlKey || e?.metaKey) {
160
+ setSelectedIds((prev) => {
161
+ const next = new Set(prev);
162
+ next.has(id) ? next.delete(id) : next.add(id);
163
+ return next;
164
+ });
165
+ }
166
+ else {
167
+ setSelectedIds(new Set([id]));
168
+ }
169
+ }, []);
170
+ const handleStatusChange = useCallback((taskId, newStatus) => {
171
+ const updated = localTasks.map((t) => t.id === taskId ? { ...t, status: newStatus } : t);
172
+ setLocalTasks(updated);
173
+ onTasksUpdate?.(updated);
174
+ }, [localTasks, onTasksUpdate]);
175
+ // ─── Render Helper ────────────────────────────────────────────────────
176
+ const renderItem = useCallback((id, x, y, children) => {
177
+ const screenX = x * canvasZoom;
178
+ const screenY = y * canvasZoom;
179
+ const isDragging = dragging?.itemIds.includes(id);
180
+ return (_jsx("div", { className: "pointer-events-auto absolute", style: {
181
+ left: 0,
182
+ top: 0,
183
+ transform: `translate3d(${screenX}px, ${screenY}px, 0) scale(${canvasZoom})`,
184
+ transformOrigin: "top left",
185
+ transition: "none",
186
+ willChange: "transform",
187
+ zIndex: isDragging ? 1000 : 1,
188
+ }, children: children }, id));
189
+ }, [canvasZoom, dragging]);
190
+ // ─── Render ───────────────────────────────────────────────────────────
191
+ return (_jsx("div", { ref: overlayRef, className: "absolute inset-0 pointer-events-none", style: { zIndex: 50 }, onWheel: handleOverlayWheel, onClick: (e) => {
192
+ if (e.target === e.currentTarget)
193
+ setSelectedIds(new Set());
194
+ }, children: _jsxs("div", { className: "absolute top-0 left-0 pointer-events-none", style: {
195
+ transform: `translate(${canvasViewport.x}px, ${canvasViewport.y}px)`,
196
+ transformOrigin: "top left",
197
+ }, 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 })))] }) }));
198
+ }
@@ -1,45 +1 @@
1
- import { FabricObject, Canvas } from "fabric";
2
- export interface Task {
3
- id: string;
4
- title: string;
5
- status: "todo" | "in-progress" | "done";
6
- x: number;
7
- y: number;
8
- assignee?: string;
9
- project?: string;
10
- priority?: "low" | "medium" | "high";
11
- dueDate?: string;
12
- }
13
- export interface Document {
14
- id: string;
15
- title: string;
16
- project: string;
17
- breadcrumb?: string[];
18
- preview: string;
19
- updatedAt?: string;
20
- x: number;
21
- y: number;
22
- }
23
- interface CanvasOverlayLayerProps {
24
- tasks: Task[];
25
- documents: Document[];
26
- onTasksUpdate?: (tasks: Task[]) => void;
27
- onDocumentsUpdate?: (documents: Document[]) => void;
28
- canvasZoom?: number;
29
- canvasViewport?: {
30
- x: number;
31
- y: number;
32
- };
33
- selectionBox?: {
34
- x1: number;
35
- y1: number;
36
- x2: number;
37
- y2: number;
38
- } | null;
39
- selectedCanvasObjects?: FabricObject[];
40
- fabricCanvas?: React.RefObject<Canvas | null>;
41
- canvasReady?: boolean;
42
- }
43
- export default function CanvasOverlayLayer({ tasks, documents, onTasksUpdate, onDocumentsUpdate, canvasZoom, canvasViewport, selectionBox, selectedCanvasObjects, fabricCanvas, }: CanvasOverlayLayerProps): import("react/jsx-runtime").JSX.Element;
44
- export {};
45
1
  //# sourceMappingURL=custom-node-overlay-layer.d.ts.map
@@ -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,2CA8kBzB"}
1
+ {"version":3,"file":"custom-node-overlay-layer.d.ts","sourceRoot":"","sources":["../../../src/components/node/custom-node-overlay-layer.tsx"],"names":[],"mappings":""}