@jeevandev/flow-canvas 0.1.2 → 0.1.4

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/index.d.ts CHANGED
@@ -2,9 +2,173 @@ import { default as default_2 } from 'react';
2
2
  import { JSX } from 'react/jsx-runtime';
3
3
  import { ReactNode } from 'react';
4
4
  import { StoreApi } from 'zustand';
5
+ import { TemporalState } from 'zundo';
6
+ import { UseBoundStore } from 'zustand';
5
7
  import { WritableDraft } from 'immer';
6
8
 
7
- export declare const Canvas: ({ children, grid, background, className, style, canvasStyle }: CanvasProps) => JSX.Element;
9
+ /**
10
+ * Hidden accessibility instructions for screen readers
11
+ * Provides context for keyboard navigation and interactions
12
+ */
13
+ export declare const AccessibilityInstructions: () => JSX.Element;
14
+
15
+ export declare interface Asset {
16
+ id: string;
17
+ name: string;
18
+ type: 'image' | 'icon' | 'shape' | 'text' | 'component';
19
+ url: string;
20
+ thumbnail?: string;
21
+ category?: string;
22
+ tags?: string[];
23
+ metadata?: {
24
+ width?: number;
25
+ height?: number;
26
+ format?: string;
27
+ size?: number;
28
+ author?: string;
29
+ createdAt?: number;
30
+ };
31
+ }
32
+
33
+ export declare interface AssetCategory {
34
+ id: string;
35
+ name: string;
36
+ icon?: string;
37
+ }
38
+
39
+ declare class AssetLibrary {
40
+ private assets;
41
+ private categories;
42
+ private storageKey;
43
+ /**
44
+ * Load assets from localStorage
45
+ */
46
+ loadAssets(): void;
47
+ /**
48
+ * Save assets to localStorage
49
+ */
50
+ saveAssets(): void;
51
+ /**
52
+ * Add or update an asset
53
+ */
54
+ addAsset(asset: Asset): void;
55
+ /**
56
+ * Get asset by ID
57
+ */
58
+ getAsset(id: string): Asset | undefined;
59
+ /**
60
+ * Get all assets
61
+ */
62
+ getAllAssets(): Asset[];
63
+ /**
64
+ * Get assets by type
65
+ */
66
+ getAssetsByType(type: Asset['type']): Asset[];
67
+ /**
68
+ * Get assets by category
69
+ */
70
+ getAssetsByCategory(category: string): Asset[];
71
+ /**
72
+ * Search assets
73
+ */
74
+ searchAssets(query: string): Asset[];
75
+ /**
76
+ * Delete an asset
77
+ */
78
+ deleteAsset(id: string): boolean;
79
+ /**
80
+ * Add category
81
+ */
82
+ addCategory(category: AssetCategory): void;
83
+ /**
84
+ * Get all categories
85
+ */
86
+ getAllCategories(): AssetCategory[];
87
+ /**
88
+ * Delete category
89
+ */
90
+ deleteCategory(id: string): boolean;
91
+ /**
92
+ * Create asset from URL (for images)
93
+ */
94
+ createAssetFromUrl(url: string, options: {
95
+ name: string;
96
+ type: Asset['type'];
97
+ category?: string;
98
+ tags?: string[];
99
+ }): Promise<Asset>;
100
+ }
101
+
102
+ export declare const assetLibrary: AssetLibrary;
103
+
104
+ declare interface AutoSaveOptions {
105
+ enabled?: boolean;
106
+ interval?: number;
107
+ storageKey?: string;
108
+ onSave?: (state: EditorState_2) => void | Promise<void>;
109
+ onError?: (error: Error) => void;
110
+ }
111
+
112
+ /**
113
+ * Calculate total bounds of all nodes (for scroll container sizing)
114
+ */
115
+ export declare function calculateTotalBounds(nodes: EditorNode_2[]): {
116
+ minX: number;
117
+ minY: number;
118
+ maxX: number;
119
+ maxY: number;
120
+ width: number;
121
+ height: number;
122
+ };
123
+
124
+ export declare class Camera {
125
+ x: number;
126
+ y: number;
127
+ zoom: number;
128
+ constructor(x?: number, y?: number, zoom?: number);
129
+ /**
130
+ * Pan camera by delta
131
+ */
132
+ pan(dx: number, dy: number): void;
133
+ /**
134
+ * Zoom camera at point
135
+ */
136
+ zoomAt(factor: number, centerX: number, centerY: number): void;
137
+ /**
138
+ * Convert screen coordinates to world coordinates
139
+ */
140
+ screenToWorld(screenX: number, screenY: number): {
141
+ x: number;
142
+ y: number;
143
+ };
144
+ /**
145
+ * Convert world coordinates to screen coordinates
146
+ */
147
+ worldToScreen(worldX: number, worldY: number): {
148
+ x: number;
149
+ y: number;
150
+ };
151
+ /**
152
+ * Get camera state
153
+ */
154
+ getState(): CameraState;
155
+ /**
156
+ * Set camera state
157
+ */
158
+ setState(state: Partial<CameraState>): void;
159
+ }
160
+
161
+ /**
162
+ * Camera Domain Model
163
+ * Represents viewport/camera state
164
+ */
165
+ export declare interface CameraState {
166
+ x: number;
167
+ y: number;
168
+ zoom: number;
169
+ }
170
+
171
+ export declare const Canvas: ({ children, grid, background, className, style, canvasStyle, nodeTypes, }: CanvasProps) => JSX.Element;
8
172
 
9
173
  declare interface CanvasProps {
10
174
  children?: ReactNode;
@@ -13,28 +177,20 @@ declare interface CanvasProps {
13
177
  className?: string;
14
178
  style?: React.CSSProperties;
15
179
  canvasStyle?: React.CSSProperties;
180
+ nodeTypes?: NodeTypesRegistry;
16
181
  }
17
182
 
18
- export declare const DefaultNode: ({ data, ...props }: {
183
+ export declare const DemoNodeContent: ({ data }: {
19
184
  data: any;
20
- } & React.HTMLAttributes<HTMLDivElement>) => JSX.Element;
21
-
22
- export declare interface Edge {
23
- id: string;
24
- source: string;
25
- target: string;
26
- sourceHandle?: string;
27
- targetHandle?: string;
28
- type?: string;
29
- data?: Record<string, any>;
30
- style?: React.CSSProperties;
31
- animated?: boolean;
32
- }
185
+ }) => JSX.Element;
33
186
 
34
- export declare const Editor: ({ children, initialNodes, initialEdges, nodes, config, className, style, onChange }: EditorProps & {
35
- nodes?: EditorNode[];
187
+ export declare const Editor: ({ children, initialNodes, nodes, config, className, style, onChange, }: EditorProps & {
188
+ nodes?: EditorNode_2[];
36
189
  }) => JSX.Element;
37
190
 
191
+ /**
192
+ * Editor Configuration
193
+ */
38
194
  export declare interface EditorConfig {
39
195
  width?: number;
40
196
  height?: number;
@@ -49,13 +205,42 @@ export declare interface EditorConfig {
49
205
  minZoom?: number;
50
206
  maxZoom?: number;
51
207
  viewOnly?: boolean;
52
- connectionMode?: 'loose' | 'strict';
53
- snapToHandle?: boolean;
208
+ pageWidth?: number;
209
+ pageHeight?: number;
210
+ pageGap?: number;
211
+ }
212
+
213
+ declare interface EditorConfig_2 {
214
+ width?: number;
215
+ height?: number;
216
+ showGrid?: boolean;
217
+ gridSize?: number;
218
+ gridColor?: string;
219
+ snapGuide?: boolean;
220
+ snapping?: boolean;
221
+ pan?: boolean;
222
+ zoom?: boolean;
223
+ isLimited?: boolean;
224
+ minZoom?: number;
225
+ maxZoom?: number;
226
+ viewOnly?: boolean;
227
+ pageWidth?: number;
228
+ pageHeight?: number;
229
+ pageGap?: number;
54
230
  rotation?: boolean;
55
231
  rotationSnap?: number;
56
232
  rotationSpeed?: number;
233
+ viewportCulling?: boolean;
234
+ virtualization?: {
235
+ enabled?: boolean;
236
+ threshold?: number;
237
+ overscan?: number;
238
+ };
57
239
  }
58
240
 
241
+ /**
242
+ * Editor Node Definition
243
+ */
59
244
  export declare interface EditorNode {
60
245
  id: string;
61
246
  x: number;
@@ -63,20 +248,39 @@ export declare interface EditorNode {
63
248
  width: number;
64
249
  height: number;
65
250
  rotation?: number;
251
+ pageId?: string;
252
+ draggable?: boolean;
253
+ resizable?: boolean;
254
+ rotatable?: boolean;
255
+ type?: string;
256
+ data?: Record<string, unknown>;
257
+ className?: string;
258
+ style?: default_2.CSSProperties;
259
+ customCss?: string;
260
+ showDragHandle?: boolean;
261
+ doubleClickToEdit?: boolean;
262
+ rotationSnap?: number;
263
+ selectable?: boolean;
264
+ parentId?: string;
265
+ locked?: boolean;
266
+ }
267
+
268
+ declare interface EditorNode_2 {
269
+ id: string;
270
+ x: number;
271
+ y: number;
272
+ width: number;
273
+ height: number;
274
+ rotation?: number;
275
+ pageId?: string;
66
276
  draggable?: boolean;
67
277
  resizable?: boolean;
68
278
  rotatable?: boolean;
279
+ parentId?: string;
69
280
  type?: string;
70
281
  data?: Record<string, any>;
71
- handles?: Record<string, {
72
- id: string;
73
- type: 'source' | 'target';
74
- position: 'top' | 'right' | 'bottom' | 'left';
75
- x: number;
76
- y: number;
77
- width: number;
78
- height: number;
79
- }>;
282
+ zIndex?: number;
283
+ locked?: boolean;
80
284
  className?: string;
81
285
  style?: React.CSSProperties;
82
286
  customCss?: string;
@@ -84,68 +288,92 @@ export declare interface EditorNode {
84
288
  }
85
289
 
86
290
  export declare interface EditorProps {
87
- children?: ReactNode;
88
- initialNodes?: EditorNode[];
89
- initialEdges?: Edge[];
90
- config?: EditorConfig;
291
+ children: React.ReactNode;
292
+ initialNodes?: EditorNode_2[];
293
+ config?: EditorConfig_2;
91
294
  className?: string;
92
295
  style?: React.CSSProperties;
93
- onChange?: (state: EditorState) => void;
296
+ onChange?: (state: EditorState_2) => void;
94
297
  }
95
298
 
299
+ /**
300
+ * Editor State
301
+ */
96
302
  export declare interface EditorState {
97
303
  nodes: Record<string, EditorNode>;
98
- edges: Record<string, Edge>;
304
+ pages: Record<string, Page>;
305
+ pageOrder: string[];
99
306
  selectedIds: string[];
100
- config: EditorConfig;
307
+ editingGroupId: string | null;
101
308
  camera: {
102
309
  x: number;
103
310
  y: number;
104
311
  zoom: number;
105
312
  };
106
- dimensions: {
107
- width: number;
108
- height: number;
109
- };
110
- connectionState: {
111
- nodeId: string | null;
112
- handleId: string | null;
113
- handleType: 'source' | 'target' | null;
114
- position: {
115
- x: number;
116
- y: number;
117
- } | null;
118
- isValid: boolean;
119
- };
120
- startConnection: (nodeId: string, handleId: string, handleType: 'source' | 'target', position: {
121
- x: number;
122
- y: number;
123
- }) => void;
124
- updateConnection: (position: {
125
- x: number;
126
- y: number;
127
- }) => void;
128
- endConnection: () => void;
129
- setNodes: (nodes: EditorNode[]) => void;
313
+ config: EditorConfig;
314
+ dragTargetPageId: string | null;
130
315
  addNode: (node: EditorNode) => void;
131
- updateNode: (id: string, node: Partial<EditorNode>) => void;
132
- registerHandle: (nodeId: string, handleId: string, handle: {
133
- type: 'source' | 'target';
134
- position: 'top' | 'right' | 'bottom' | 'left';
316
+ updateNode: (id: string, updates: Partial<EditorNode>) => void;
317
+ deleteNode: (id: string) => void;
318
+ selectNode: (id: string, multi?: boolean) => void;
319
+ deselectNode: (id: string) => void;
320
+ clearSelection: () => void;
321
+ setCamera: (camera: Partial<EditorState["camera"]>) => void;
322
+ setConfig: (config: Partial<EditorConfig>) => void;
323
+ setDragTargetPage: (pageId: string | null) => void;
324
+ addPage: (page: Page) => void;
325
+ updatePage: (id: string, updates: Partial<Page>) => void;
326
+ deletePage: (id: string) => void;
327
+ reorderPages: (pageOrder: string[]) => void;
328
+ nudgeSelected: (dx: number, dy: number) => void;
329
+ rotateSelected: (angle: number) => void;
330
+ rotateSelectedBy: (deltaAngle: number) => void;
331
+ duplicateSelected: () => void;
332
+ deleteSelected: () => void;
333
+ moveSelectedToPage: (pageId: string) => void;
334
+ checkAutoReparent: () => void;
335
+ setDimensions: (width: number, height: number) => void;
336
+ panCamera: (dx: number, dy: number) => void;
337
+ zoomCamera: (factor: number, cx: number, cy: number) => void;
338
+ setActivePage: (pageId: string) => void;
339
+ }
340
+
341
+ declare interface EditorState_2 {
342
+ pages: Record<string, Page_2>;
343
+ pageOrder: string[];
344
+ dragTargetPageId: string | null;
345
+ activePageId: string | null;
346
+ nodes: Record<string, EditorNode_2>;
347
+ selectedIds: string[];
348
+ config: EditorConfig_2;
349
+ camera: {
135
350
  x: number;
136
351
  y: number;
352
+ zoom: number;
353
+ };
354
+ editingGroupId: string | null;
355
+ clipboard: {
356
+ nodes: EditorNode_2[];
357
+ copyCount: number;
358
+ };
359
+ dimensions: {
137
360
  width: number;
138
361
  height: number;
139
- }) => void;
362
+ };
363
+ setNodes: (nodes: EditorNode_2[]) => void;
364
+ addNode: (node: EditorNode_2) => void;
365
+ updateNode: (id: string, node: Partial<EditorNode_2>) => void;
140
366
  removeNode: (id: string) => void;
141
- setEdges: (edges: Edge[]) => void;
142
- addEdge: (edge: Edge) => void;
143
- removeEdge: (id: string) => void;
144
367
  selectNode: (id: string, multi?: boolean) => void;
368
+ selectAll: () => void;
145
369
  deselectAll: () => void;
146
370
  deleteSelected: () => void;
147
371
  duplicateSelected: () => void;
148
- setConfig: (config: Partial<EditorConfig>) => void;
372
+ setEditingGroup: (groupId: string | null) => void;
373
+ copy: () => void;
374
+ paste: () => void;
375
+ cut: () => void;
376
+ setConfig: (config: Partial<EditorConfig_2>) => void;
149
377
  panCamera: (dx: number, dy: number) => void;
150
378
  zoomCamera: (factor: number, cx: number, cy: number) => void;
151
379
  setCamera: (x: number, y: number, zoom: number) => void;
@@ -153,33 +381,376 @@ export declare interface EditorState {
153
381
  nudgeSelected: (dx: number, dy: number) => void;
154
382
  resizeNode: (id: string, x: number, y: number, w: number, h: number) => void;
155
383
  rotateNode: (id: string, angle: number) => void;
384
+ rotateSelected: (angle: number) => void;
385
+ rotateSelectedBy: (deltaAngle: number) => void;
386
+ resizeSelected: (scaleX: number, scaleY: number, pivotX: number, pivotY: number, initialNodes: Record<string, {
387
+ x: number;
388
+ y: number;
389
+ w: number;
390
+ h: number;
391
+ }>) => void;
392
+ resizeSelectedLocal: (scaleX: number, scaleY: number, pivot: {
393
+ x: number;
394
+ y: number;
395
+ }, boxRotation: number, initialNodes: Record<string, {
396
+ x: number;
397
+ y: number;
398
+ w: number;
399
+ h: number;
400
+ r: number;
401
+ cx: number;
402
+ cy: number;
403
+ }>, canvasOrigin: {
404
+ x: number;
405
+ y: number;
406
+ }) => void;
407
+ moveSelectedToPage: (pageId: string) => void;
408
+ checkAutoReparent: () => void;
409
+ groupSelected: () => void;
410
+ ungroupSelected: () => void;
411
+ bringForward: () => void;
412
+ sendBackward: () => void;
413
+ bringToFront: () => void;
414
+ sendToBack: () => void;
415
+ alignLeft: () => void;
416
+ alignRight: () => void;
417
+ alignTop: () => void;
418
+ alignBottom: () => void;
419
+ alignCenterH: () => void;
420
+ alignCenterV: () => void;
421
+ distributeH: () => void;
422
+ distributeV: () => void;
423
+ toggleLock: () => void;
424
+ lockSelected: () => void;
425
+ unlockSelected: () => void;
426
+ addPage: (page?: Partial<Page_2>) => string;
427
+ removePage: (id: string) => void;
428
+ updatePage: (id: string, updates: Partial<Page_2>) => void;
429
+ setDragTargetPage: (pageId: string | null) => void;
430
+ setActivePage: (pageId: string) => void;
431
+ }
432
+
433
+ declare class Element_2 {
434
+ id: string;
435
+ bounds: ElementBounds;
436
+ rotation: number;
437
+ pageId?: string;
438
+ parentId?: string;
439
+ type?: string;
440
+ data?: Record<string, any>;
441
+ constructor(id: string, bounds: ElementBounds, rotation?: number, pageId?: string, parentId?: string, type?: string, data?: Record<string, any>);
442
+ /**
443
+ * Get element center point
444
+ */
445
+ getCenter(): {
446
+ x: number;
447
+ y: number;
448
+ };
449
+ /**
450
+ * Get element bounds including rotation
451
+ */
452
+ getRotatedBounds(): ElementBounds;
453
+ /**
454
+ * Check if point is inside element bounds
455
+ */
456
+ containsPoint(x: number, y: number): boolean;
457
+ /**
458
+ * Get element transform
459
+ */
460
+ getTransform(): ElementTransform;
461
+ /**
462
+ * Apply transform to element
463
+ */
464
+ applyTransform(transform: Partial<ElementTransform>): void;
465
+ }
466
+ export { Element_2 as Element }
467
+
468
+ /**
469
+ * Element Domain Model
470
+ * Pure domain logic for canvas elements
471
+ */
472
+ export declare interface ElementBounds {
473
+ x: number;
474
+ y: number;
475
+ width: number;
476
+ height: number;
477
+ }
478
+
479
+ export declare interface ElementTransform {
480
+ position: {
481
+ x: number;
482
+ y: number;
483
+ };
484
+ size: {
485
+ width: number;
486
+ height: number;
487
+ };
488
+ rotation: number;
156
489
  }
157
490
 
158
491
  export declare const ElementWrapper: default_2.MemoExoticComponent<({ id, children, className, style, draggable, resizable, rotatable, selectable, rotationSnap, showDragHandle, doubleClickToEdit, ...props }: Props) => JSX.Element | null>;
159
492
 
160
- export declare const Handle: ({ type, id, position, className, style, ...props }: HandleProps) => JSX.Element;
493
+ declare class ErrorReporter {
494
+ private config;
495
+ private initialized;
496
+ constructor();
497
+ init(config?: Partial<ErrorReportingConfig>): void;
498
+ private initSentry;
499
+ captureException(error: Error, context?: Record<string, unknown>): void;
500
+ captureMessage(message: string, level?: 'info' | 'warning' | 'error', context?: Record<string, unknown>): void;
501
+ setUser(user: {
502
+ id: string;
503
+ email?: string;
504
+ username?: string;
505
+ }): void;
506
+ clearUser(): void;
507
+ }
508
+
509
+ export declare const errorReporter: ErrorReporter;
161
510
 
162
- declare interface HandleProps extends default_2.HTMLAttributes<HTMLDivElement> {
163
- type: 'source' | 'target';
164
- id?: string;
165
- position?: 'top' | 'right' | 'bottom' | 'left';
511
+ /**
512
+ * Error reporting utility
513
+ * Supports integration with error reporting services (Sentry, etc.)
514
+ */
515
+ declare interface ErrorReportingConfig {
516
+ enabled: boolean;
517
+ dsn?: string;
518
+ environment?: string;
519
+ release?: string;
166
520
  }
167
521
 
168
- export declare const InputNode: ({ data, ...props }: {
169
- data: any;
170
- } & React.HTMLAttributes<HTMLDivElement>) => JSX.Element;
522
+ /**
523
+ * Calculate spawn position for a new element
524
+ * Places element at the center of the specified page (or first page)
525
+ *
526
+ * @param store - Editor store instance (with getState method)
527
+ * @param elementSize - Size of the element to spawn (default: { width: 200, height: 150 })
528
+ * @param pageId - Optional specific page ID (defaults to first page)
529
+ * @returns Position with x, y coordinates and pageId
530
+ */
531
+ export declare function getSpawnPosition(store: {
532
+ getState: () => EditorState_2;
533
+ }, elementSize?: {
534
+ width: number;
535
+ height: number;
536
+ }, pageId?: string): {
537
+ x: number;
538
+ y: number;
539
+ pageId: string;
540
+ };
541
+
542
+ /**
543
+ * Get cells that intersect with viewport
544
+ */
545
+ export declare function getVisibleCells(grid: Map<string, EditorNode_2[]>, viewport: {
546
+ x: number;
547
+ y: number;
548
+ width: number;
549
+ height: number;
550
+ }, cellSize?: number): EditorNode_2[];
551
+
552
+ /**
553
+ * Get visible nodes only (for rendering)
554
+ */
555
+ export declare function getVisibleNodes(virtualized: VirtualizedItem[]): EditorNode_2[];
556
+
557
+ export declare class GroupService {
558
+ /**
559
+ * Get all direct children of a group
560
+ */
561
+ static getChildren(groupId: string, nodes: Record<string, EditorNode>): EditorNode[];
562
+ /**
563
+ * Get all descendants of a group (recursive)
564
+ */
565
+ static getDescendants(groupId: string, nodes: Record<string, EditorNode>): EditorNode[];
566
+ /**
567
+ * Calculate bounding box from a set of nodes (children)
568
+ * Returns relative coordinates (min values can be negative)
569
+ */
570
+ static calculateBounds(children: EditorNode[]): {
571
+ x: number;
572
+ y: number;
573
+ width: number;
574
+ height: number;
575
+ };
576
+ /**
577
+ * Find which group to enter when double-clicking on a nested element
578
+ */
579
+ static findTargetGroupToEnter(clickedId: string, editingGroupId: string | null, nodes: Record<string, EditorNode>): string | null;
580
+ /**
581
+ * Find the ancestor of a node that is a direct child of the editing group
582
+ */
583
+ static findAncestorInEditScope(elementId: string, editingGroupId: string, nodes: Record<string, EditorNode>): string | null;
584
+ }
585
+
586
+ declare interface LogEntry {
587
+ level: LogLevel;
588
+ message: string;
589
+ timestamp: number;
590
+ data?: unknown;
591
+ error?: Error;
592
+ }
593
+
594
+ declare class Logger {
595
+ private isDevelopment;
596
+ private logHistory;
597
+ private maxHistorySize;
598
+ constructor();
599
+ private log;
600
+ private reportError;
601
+ debug(message: string, ...args: unknown[]): void;
602
+ info(message: string, ...args: unknown[]): void;
603
+ warn(message: string, ...args: unknown[]): void;
604
+ error(message: string, error?: Error, ...args: unknown[]): void;
605
+ getHistory(): LogEntry[];
606
+ clearHistory(): void;
607
+ }
608
+
609
+ export declare const logger: Logger;
171
610
 
172
- export declare const NodeLayer: ({ nodeTypes }: NodeLayerProps) => JSX.Element;
611
+ /**
612
+ * Logger utility for production-ready logging
613
+ * Handles different log levels and environment-based filtering
614
+ */
615
+ declare type LogLevel = 'debug' | 'info' | 'warn' | 'error';
616
+
617
+ /**
618
+ * Type for node component
619
+ */
620
+ export declare type NodeComponent = default_2.ComponentType<NodeComponentProps>;
621
+
622
+ /**
623
+ * Props for custom node components
624
+ */
625
+ export declare interface NodeComponentProps {
626
+ id: string;
627
+ data?: Record<string, unknown>;
628
+ style?: default_2.CSSProperties;
629
+ className?: string;
630
+ nodeTypes?: Record<string, default_2.ComponentType<NodeComponentProps>>;
631
+ }
632
+
633
+ export declare const NodeLayer: ({ nodeTypes, pageId }: NodeLayerProps) => JSX.Element;
173
634
 
174
635
  declare interface NodeLayerProps {
175
- nodeTypes?: Record<string, default_2.ComponentType<any>>;
636
+ nodeTypes?: NodeTypesRegistry;
637
+ pageId?: string;
176
638
  }
177
639
 
178
- export declare const OutputNode: ({ data, ...props }: {
179
- data: any;
180
- } & React.HTMLAttributes<HTMLDivElement>) => JSX.Element;
640
+ /**
641
+ * Type for node types registry
642
+ */
643
+ export declare type NodeTypesRegistry = Record<string, NodeComponent>;
181
644
 
182
- declare interface Props extends Omit<default_2.HTMLAttributes<HTMLDivElement>, 'id' | 'style' | 'onDrag'> {
645
+ /**
646
+ * Optimize node list for virtualization
647
+ * Groups nearby nodes for batch processing
648
+ */
649
+ export declare function optimizeForVirtualization(nodes: EditorNode_2[], cellSize?: number): Map<string, EditorNode_2[]>;
650
+
651
+ export declare interface Page {
652
+ id: string;
653
+ width: number;
654
+ height: number;
655
+ backgroundColor?: string;
656
+ name?: string;
657
+ }
658
+
659
+ declare interface Page_2 {
660
+ id: string;
661
+ width: number;
662
+ height: number;
663
+ backgroundColor?: string;
664
+ name?: string;
665
+ }
666
+
667
+ /**
668
+ * Page Domain Model
669
+ * Pure domain logic for canvas pages
670
+ */
671
+ export declare interface PageDimensions {
672
+ width: number;
673
+ height: number;
674
+ }
675
+
676
+ export declare class PageService {
677
+ /**
678
+ * Get the page that contains a given absolute position
679
+ */
680
+ static getPageAtPosition(absoluteY: number, pages: Record<string, Page>, pageOrder: string[], pageGap?: number): string | null;
681
+ /**
682
+ * Calculate the cumulative offset (top position) of a page
683
+ */
684
+ static calculatePageOffset(targetPageId: string, pages: Record<string, Page>, pageOrder: string[], pageGap?: number): number;
685
+ /**
686
+ * Check if an element is fully within page bounds
687
+ */
688
+ static isWithinPageBounds(element: EditorNode, page: Page): boolean;
689
+ /**
690
+ * Check if an element is partially within page bounds
691
+ */
692
+ static isPartiallyWithinPageBounds(element: EditorNode, page: Page): boolean;
693
+ /**
694
+ * Constrain element position to stay within page bounds
695
+ */
696
+ static constrainToPageBounds(position: Position, size: {
697
+ width: number;
698
+ height: number;
699
+ }, page: Page): Position;
700
+ /**
701
+ * Convert element position from one page to another
702
+ */
703
+ static convertPositionBetweenPages(elementPos: Position, fromPageId: string, toPageId: string, pages: Record<string, Page>, pageOrder: string[], pageGap?: number): Position;
704
+ /**
705
+ * Get total height of all pages including gaps
706
+ */
707
+ static getTotalHeight(pages: Record<string, Page>, pageOrder: string[], pageGap?: number): number;
708
+ /**
709
+ * Get the widest page width
710
+ */
711
+ static getMaxWidth(pages: Record<string, Page>): number;
712
+ /**
713
+ * Find which page an element belongs to based on its center point
714
+ */
715
+ static getPageByElementCenter(element: EditorNode, pages: Record<string, Page>, pageOrder: string[], pageGap?: number): string | null;
716
+ }
717
+
718
+ /**
719
+ * Performance monitoring utilities
720
+ * Tracks render times, operation durations, and performance metrics
721
+ */
722
+ declare interface PerformanceMetric {
723
+ name: string;
724
+ duration: number;
725
+ timestamp: number;
726
+ metadata?: Record<string, unknown>;
727
+ }
728
+
729
+ declare class PerformanceMonitor {
730
+ private metrics;
731
+ private maxMetrics;
732
+ private enabled;
733
+ measure<T>(name: string, fn: () => T, metadata?: Record<string, unknown>): T;
734
+ measureAsync<T>(name: string, fn: () => Promise<T>, metadata?: Record<string, unknown>): Promise<T>;
735
+ recordMetric(name: string, duration: number, metadata?: Record<string, unknown>): void;
736
+ getMetrics(): PerformanceMetric[];
737
+ getAverageDuration(name: string): number;
738
+ clearMetrics(): void;
739
+ enable(): void;
740
+ disable(): void;
741
+ }
742
+
743
+ export declare const performanceMonitor: PerformanceMonitor;
744
+
745
+ /**
746
+ * Geometric type definitions
747
+ */
748
+ export declare interface Position {
749
+ x: number;
750
+ y: number;
751
+ }
752
+
753
+ declare interface Props extends Omit<default_2.HTMLAttributes<HTMLDivElement>, "id" | "style" | "onDrag"> {
183
754
  id: string;
184
755
  children: ReactNode;
185
756
  className?: string;
@@ -193,22 +764,235 @@ declare interface Props extends Omit<default_2.HTMLAttributes<HTMLDivElement>, '
193
764
  doubleClickToEdit?: boolean;
194
765
  }
195
766
 
196
- declare interface Props_2 {
767
+ export declare interface Size {
768
+ width: number;
769
+ height: number;
770
+ }
771
+
772
+ declare interface SnapLine {
197
773
  id: string;
198
- children: ReactNode;
199
- className?: string;
200
- style?: default_2.CSSProperties;
201
- draggable?: boolean;
202
- selectable?: boolean;
774
+ type: "vertical" | "horizontal";
775
+ position: number;
776
+ pageId: string;
203
777
  }
204
778
 
205
- export declare const useEditor: <T>(selector: (state: EditorState) => T) => T;
779
+ export declare class SnapService {
780
+ /**
781
+ * Find all potential snap lines for an element
782
+ */
783
+ static findSnapLines(element: EditorNode, allNodes: Record<string, EditorNode>, threshold?: number): SnapLine[];
784
+ /**
785
+ * Apply snap adjustments to a position
786
+ */
787
+ static applySnap(position: Position, size: {
788
+ width: number;
789
+ height: number;
790
+ }, snapLines: SnapLine[], threshold?: number): Position;
791
+ /**
792
+ * Get active snap lines that should be displayed
793
+ */
794
+ static getActiveSnapLines(element: EditorNode, allNodes: Record<string, EditorNode>, threshold?: number): SnapLine[];
795
+ }
206
796
 
207
- export declare const useEditorStoreApi: () => Omit<StoreApi<EditorState>, "setState"> & {
208
- setState(nextStateOrUpdater: EditorState | Partial<EditorState> | ((state: WritableDraft<EditorState>) => void), shouldReplace?: false): void;
209
- setState(nextStateOrUpdater: EditorState | ((state: WritableDraft<EditorState>) => void), shouldReplace: true): void;
797
+ /**
798
+ * StyleInjector component that collects and injects custom CSS from all nodes
799
+ * Place this inside your Editor component to enable customCss support
800
+ */
801
+ export declare const StyleInjector: () => JSX.Element | null;
802
+
803
+ export declare interface Template {
804
+ id: string;
805
+ name: string;
806
+ description?: string;
807
+ thumbnail?: string;
808
+ category?: string;
809
+ nodes: EditorNode_2[];
810
+ pages: Page_2[];
811
+ pageOrder: string[];
812
+ metadata?: {
813
+ author?: string;
814
+ version?: string;
815
+ tags?: string[];
816
+ createdAt?: number;
817
+ updatedAt?: number;
818
+ };
819
+ }
820
+
821
+ declare class TemplateManager {
822
+ private templates;
823
+ private storageKey;
824
+ /**
825
+ * Load templates from localStorage
826
+ */
827
+ loadTemplates(): void;
828
+ /**
829
+ * Save templates to localStorage
830
+ */
831
+ saveTemplates(): void;
832
+ /**
833
+ * Add or update a template
834
+ */
835
+ saveTemplate(template: Template): void;
836
+ /**
837
+ * Get a template by ID
838
+ */
839
+ getTemplate(id: string): Template | undefined;
840
+ /**
841
+ * Get all templates
842
+ */
843
+ getAllTemplates(): Template[];
844
+ /**
845
+ * Get templates by category
846
+ */
847
+ getTemplatesByCategory(category: string): Template[];
848
+ /**
849
+ * Delete a template
850
+ */
851
+ deleteTemplate(id: string): boolean;
852
+ /**
853
+ * Create template from current editor state
854
+ */
855
+ createTemplateFromState(name: string, state: {
856
+ nodes: Record<string, EditorNode_2>;
857
+ pages: Record<string, Page_2>;
858
+ pageOrder: string[];
859
+ }, options?: {
860
+ description?: string;
861
+ category?: string;
862
+ thumbnail?: string;
863
+ }): Template;
864
+ /**
865
+ * Apply template to editor state
866
+ */
867
+ applyTemplate(templateId: string): Template | null;
868
+ }
869
+
870
+ export declare const templateManager: TemplateManager;
871
+
872
+ export declare class TransformService {
873
+ /**
874
+ * Calculate new position after drag movement
875
+ */
876
+ static calculateDragPosition(currentPos: Position, movement: [number, number], zoom: number, constraints?: {
877
+ minX?: number;
878
+ minY?: number;
879
+ maxX?: number;
880
+ maxY?: number;
881
+ }): Position;
882
+ /**
883
+ * Calculate new size after resize
884
+ */
885
+ static calculateResize(currentPos: Position, currentSize: Size, movement: [number, number], handle: string, zoom: number, rotation?: number, constraints?: {
886
+ minWidth?: number;
887
+ minHeight?: number;
888
+ maxWidth?: number;
889
+ maxHeight?: number;
890
+ aspectRatio?: number;
891
+ }): {
892
+ position: Position;
893
+ size: Size;
894
+ };
895
+ /**
896
+ * Apply resize based on handle position
897
+ */
898
+ private static applyHandleResize;
899
+ /**
900
+ * Calculate new rotation angle
901
+ */
902
+ static calculateRotation(elementCenter: Position, mousePos: Position, snapAngle?: number): number;
903
+ /**
904
+ * Calculate element's center point
905
+ */
906
+ static getElementCenter(pos: Position, size: Size): Position;
907
+ /**
908
+ * Calculate bounding box for rotated element
909
+ */
910
+ static getRotatedBounds(pos: Position, size: Size, rotation: number): {
911
+ x: number;
912
+ y: number;
913
+ width: number;
914
+ height: number;
915
+ };
916
+ }
917
+
918
+ /**
919
+ * Hook for auto-saving editor state
920
+ * Saves state to localStorage and/or calls custom save handler
921
+ */
922
+ export declare function useAutoSave(options?: AutoSaveOptions): {
923
+ manualSave: () => void;
924
+ loadSavedState: () => EditorState_2 | null;
925
+ clearSavedState: () => void;
926
+ lastSaveTime: number;
927
+ };
928
+
929
+ export declare const useEditor: <T>(selector: (state: EditorState_2) => T) => T;
930
+
931
+ export declare const useEditorStoreApi: () => UseBoundStore<Omit<Omit<Omit<StoreApi<EditorState_2>, "temporal"> & {
932
+ temporal: StoreApi<TemporalState<EditorState_2>>;
933
+ }, "setState" | "devtools"> & {
934
+ setState(partial: EditorState_2 | Partial<EditorState_2> | ((state: EditorState_2) => EditorState_2 | Partial<EditorState_2>), replace?: false | undefined, action?: (string | {
935
+ [x: string]: unknown;
936
+ [x: number]: unknown;
937
+ [x: symbol]: unknown;
938
+ type: string;
939
+ }) | undefined): void;
940
+ setState(state: EditorState_2 | ((state: EditorState_2) => EditorState_2), replace: true, action?: (string | {
941
+ [x: string]: unknown;
942
+ [x: number]: unknown;
943
+ [x: symbol]: unknown;
944
+ type: string;
945
+ }) | undefined): void;
946
+ devtools: {
947
+ cleanup: () => void;
210
948
  };
949
+ }, "setState"> & {
950
+ setState(nextStateOrUpdater: EditorState_2 | Partial<EditorState_2> | ((state: WritableDraft<EditorState_2>) => void), shouldReplace?: false, action?: (string | {
951
+ [x: string]: unknown;
952
+ [x: number]: unknown;
953
+ [x: symbol]: unknown;
954
+ type: string;
955
+ }) | undefined): void;
956
+ setState(nextStateOrUpdater: EditorState_2 | ((state: WritableDraft<EditorState_2>) => void), shouldReplace: true, action?: (string | {
957
+ [x: string]: unknown;
958
+ [x: number]: unknown;
959
+ [x: symbol]: unknown;
960
+ type: string;
961
+ }) | undefined): void;
962
+ }>;
963
+
964
+ export declare interface VirtualizationConfig {
965
+ enabled: boolean;
966
+ threshold: number;
967
+ overscan: number;
968
+ itemHeight?: number;
969
+ }
970
+
971
+ export declare interface VirtualizedItem {
972
+ node: EditorNode_2;
973
+ index: number;
974
+ isVisible: boolean;
975
+ }
211
976
 
212
- export declare const WorkflowNodeWrapper: default_2.MemoExoticComponent<({ id, children, className, style, draggable, selectable, }: Props_2) => JSX.Element | null>;
977
+ /**
978
+ * VirtualizedNodeLayer - Advanced virtualization for very large datasets
979
+ * Uses intersection observer and grid-based culling for optimal performance
980
+ */
981
+ export declare const VirtualizedNodeLayer: ({ nodeTypes, pageId }: VirtualizedNodeLayerProps) => JSX.Element;
982
+
983
+ declare interface VirtualizedNodeLayerProps {
984
+ nodeTypes?: NodeTypesRegistry;
985
+ pageId?: string;
986
+ }
987
+
988
+ /**
989
+ * Calculate which nodes should be rendered based on viewport
990
+ */
991
+ export declare function virtualizeNodes(nodes: EditorNode_2[], viewport: {
992
+ x: number;
993
+ y: number;
994
+ width: number;
995
+ height: number;
996
+ }, config?: VirtualizationConfig): VirtualizedItem[];
213
997
 
214
998
  export { }