@pixerate/editor 0.22.0 → 0.23.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 (83) hide show
  1. package/README.md +80 -2
  2. package/THIRD_PARTY_NOTICES.md +88 -0
  3. package/dist/agent/index.cjs +83 -108
  4. package/dist/agent/index.cjs.map +1 -1
  5. package/dist/agent/index.d.cts +69 -211
  6. package/dist/agent/index.d.ts +69 -211
  7. package/dist/agent/index.js +76 -101
  8. package/dist/agent/index.js.map +1 -1
  9. package/dist/arrangeShortcuts-B8O3f8-P.d.cts +184 -0
  10. package/dist/arrangeShortcuts-sLlD2rSX.d.ts +184 -0
  11. package/dist/canvas/index.cjs +879 -83
  12. package/dist/canvas/index.cjs.map +1 -1
  13. package/dist/canvas/index.d.cts +291 -186
  14. package/dist/canvas/index.d.ts +291 -186
  15. package/dist/canvas/index.js +865 -69
  16. package/dist/canvas/index.js.map +1 -1
  17. package/dist/chunk-26BVFKHU.cjs +453 -0
  18. package/dist/chunk-26BVFKHU.cjs.map +1 -0
  19. package/dist/chunk-2H7ZHPEJ.js +762 -0
  20. package/dist/chunk-2H7ZHPEJ.js.map +1 -0
  21. package/dist/chunk-7DWMJCAT.js +453 -0
  22. package/dist/chunk-7DWMJCAT.js.map +1 -0
  23. package/dist/chunk-ARRTP33I.js +101 -0
  24. package/dist/chunk-ARRTP33I.js.map +1 -0
  25. package/dist/chunk-CPOKFNBG.cjs +101 -0
  26. package/dist/chunk-CPOKFNBG.cjs.map +1 -0
  27. package/dist/chunk-G2I4QJOT.cjs +762 -0
  28. package/dist/chunk-G2I4QJOT.cjs.map +1 -0
  29. package/dist/{chunk-RU52I7QO.js → chunk-K3R5NG2D.js} +147 -42
  30. package/dist/chunk-K3R5NG2D.js.map +1 -0
  31. package/dist/{chunk-DENSCKFC.js → chunk-QBJ22YZR.js} +423 -30
  32. package/dist/chunk-QBJ22YZR.js.map +1 -0
  33. package/dist/{chunk-SAZRENEZ.cjs → chunk-RIKBJLS2.cjs} +424 -31
  34. package/dist/chunk-RIKBJLS2.cjs.map +1 -0
  35. package/dist/{chunk-6M3BCTBD.cjs → chunk-XDMXXC4Z.cjs} +230 -125
  36. package/dist/chunk-XDMXXC4Z.cjs.map +1 -0
  37. package/dist/commands/index.cjs +860 -0
  38. package/dist/commands/index.cjs.map +1 -0
  39. package/dist/commands/index.d.cts +592 -0
  40. package/dist/commands/index.d.ts +592 -0
  41. package/dist/commands/index.js +860 -0
  42. package/dist/commands/index.js.map +1 -0
  43. package/dist/{controller-B7GIybc4.d.cts → controller-pePCJLT1.d.cts} +78 -5
  44. package/dist/{controller-B7GIybc4.d.ts → controller-pePCJLT1.d.ts} +78 -5
  45. package/dist/history/index.cjs +12 -2
  46. package/dist/history/index.cjs.map +1 -1
  47. package/dist/history/index.d.cts +211 -7
  48. package/dist/history/index.d.ts +211 -7
  49. package/dist/history/index.js +13 -3
  50. package/dist/image-editor/index.cjs +418 -13
  51. package/dist/image-editor/index.cjs.map +1 -1
  52. package/dist/image-editor/index.d.cts +154 -3
  53. package/dist/image-editor/index.d.ts +154 -3
  54. package/dist/image-editor/index.js +417 -12
  55. package/dist/image-editor/index.js.map +1 -1
  56. package/dist/index.cjs +34 -76
  57. package/dist/index.cjs.map +1 -1
  58. package/dist/index.d.cts +5 -42
  59. package/dist/index.d.ts +5 -42
  60. package/dist/index.js +27 -69
  61. package/dist/index.js.map +1 -1
  62. package/dist/registry-D5-R90p0.d.cts +209 -0
  63. package/dist/registry-D5-R90p0.d.ts +209 -0
  64. package/dist/spreadsheet/index.cjs +19 -3
  65. package/dist/spreadsheet/index.cjs.map +1 -1
  66. package/dist/spreadsheet/index.d.cts +67 -9
  67. package/dist/spreadsheet/index.d.ts +67 -9
  68. package/dist/spreadsheet/index.js +18 -2
  69. package/dist/{types-CJ4U-HHI.d.cts → types-DX4Mh4SL.d.cts} +1 -1
  70. package/dist/{types-CJ4U-HHI.d.ts → types-DX4Mh4SL.d.ts} +1 -1
  71. package/dist/types-GT5a5YAX.d.cts +86 -0
  72. package/dist/types-GT5a5YAX.d.ts +86 -0
  73. package/package.json +8 -2
  74. package/dist/chunk-2TWGLC5K.cjs +0 -262
  75. package/dist/chunk-2TWGLC5K.cjs.map +0 -1
  76. package/dist/chunk-6M3BCTBD.cjs.map +0 -1
  77. package/dist/chunk-DENSCKFC.js.map +0 -1
  78. package/dist/chunk-KAADNAPF.js +0 -262
  79. package/dist/chunk-KAADNAPF.js.map +0 -1
  80. package/dist/chunk-RU52I7QO.js.map +0 -1
  81. package/dist/chunk-SAZRENEZ.cjs.map +0 -1
  82. package/dist/types-BZgcDsC5.d.cts +0 -42
  83. package/dist/types-BZgcDsC5.d.ts +0 -42
@@ -1,6 +1,8 @@
1
- import { R as Rect, C as CanvasNode, X as XYPosition, a as CanvasEdge, I as IncrementalLayoutOptions, S as Side, b as CanvasLayoutOptions, P as PlaceBesideOptions, T as TrajectoryFunction, F as FanOutTrajectoryOptions, N as NodeTransition, c as CanvasNodeStyle, d as ReflowDisplacementOptions, D as DirectionalDisplacementOptions, e as CanvasClipboardPayload, f as Position, g as Point } from '../types-CJ4U-HHI.js';
2
- export { h as CanvasDockingCallbacks, i as CollapseNodeOptions, j as DisplacementDirection, k as DockStrategy, E as ExplodeNodeOptions, l as ExplosionSnapshot, G as GraphDifferences, m as TrajectoryPoint } from '../types-CJ4U-HHI.js';
3
- import { C as Command } from '../types-BZgcDsC5.js';
1
+ import { R as Rect, C as CanvasNode, X as XYPosition, b as CanvasEdge, I as IncrementalLayoutOptions, S as Side, c as CanvasLayoutOptions, P as PlaceBesideOptions, T as TrajectoryFunction, F as FanOutTrajectoryOptions, N as NodeTransition, a as CanvasNodeStyle, d as ReflowDisplacementOptions, D as DirectionalDisplacementOptions, e as CanvasClipboardPayload, f as Position, g as Point } from '../types-DX4Mh4SL.js';
2
+ export { h as CanvasDockingCallbacks, i as CollapseNodeOptions, j as DisplacementDirection, k as DockStrategy, E as ExplodeNodeOptions, l as ExplosionSnapshot, G as GraphDifferences, m as TrajectoryPoint } from '../types-DX4Mh4SL.js';
3
+ import { b as CanvasNodeUpdate, N as NodeRectOptions, A as AlignEdge, c as AlignNodesOptions, D as DistributeAxis, a as DistributeMode, d as DistributeNodesOptions, S as SizeDimension, M as MatchSizeOptions, Z as ZOrderOperation, C as CanvasArrangeAction } from '../arrangeShortcuts-sLlD2rSX.js';
4
+ export { e as ArrangeShortcutBinding, f as DEFAULT_ARRANGE_SHORTCUTS, L as LOCKED_DATA_KEY, g as LOCKED_PREVIOUS_FLAGS_KEY, h as alignNodes, i as applyNodeUpdates, j as createNodeLookup, k as distributeNodes, l as getAbsolutePosition, m as getNodeRect, n as getNodeSize, o as invertNodeUpdates, p as isLocked, q as lockNodes, r as matchArrangeShortcut, s as matchSize, t as readStyleSize, u as reorderNodes, v as toggleLockNodes, w as unlockNodes, x as withStyleSize } from '../arrangeShortcuts-sLlD2rSX.js';
5
+ import { C as Command } from '../types-GT5a5YAX.js';
4
6
 
5
7
  declare const DEFAULT_NODE_WIDTH = 200;
6
8
  declare const DEFAULT_NODE_HEIGHT = 60;
@@ -328,172 +330,30 @@ declare function blendLayout<TNode extends CanvasNode = CanvasNode>(from: TNode[
328
330
  */
329
331
  declare function connectedOnly<TNode extends CanvasNode = CanvasNode, TEdge extends CanvasEdge = CanvasEdge>(nodes: TNode[], edges: TEdge[]): TNode[];
330
332
 
331
- /**
332
- * Edge (or centre line) used by `alignNodes`.
333
- * `center` aligns horizontal centres (a vertical line); `middle` aligns vertical centres.
334
- */
335
- type AlignEdge = 'left' | 'center' | 'right' | 'top' | 'middle' | 'bottom';
336
- /** Axis used by `distributeNodes`. `both` distributes horizontally and vertically. */
337
- type DistributeAxis = 'horizontal' | 'vertical' | 'both';
338
- /**
339
- * `gaps` leaves equal space between neighbouring nodes, `centres` spaces their centres equally.
340
- */
341
- type DistributeMode = 'gaps' | 'centres';
342
- /** Dimension(s) copied by `matchSize`. */
343
- type SizeDimension = 'width' | 'height' | 'both';
344
- /**
345
- * Partial node change produced by the arrange helpers. `position` is in the node's own
346
- * coordinate space (relative to its `parentId` parent when it has one).
347
- */
348
- interface CanvasNodeUpdate {
349
- id: string;
350
- position?: XYPosition;
351
- width?: number;
352
- height?: number;
353
- zIndex?: number;
354
- }
355
- interface NodeRectOptions {
356
- /** Width used when a node has no measured, explicit or style size and estimation is off. */
357
- defaultWidth?: number;
358
- /** Height used when a node has no measured, explicit or style size and estimation is off. */
359
- defaultHeight?: number;
360
- /** Estimate unmeasured node sizes from their label via `estimateNodeSize` (default `true`). */
361
- estimate?: boolean;
362
- }
363
- /** Data key marking a node as locked. See `lockNodes`. */
364
- declare const LOCKED_DATA_KEY = "locked";
365
- /** Data key holding the interaction flags a node had before it was locked. */
366
- declare const LOCKED_PREVIOUS_FLAGS_KEY = "lockedPrevious";
367
- /**
368
- * Reads a pixel `width` / `height` from a node style, which may be a CSS string (SvelteFlow)
369
- * or a style object (React Flow). Non-pixel values (`%`, `auto`, ...) are ignored.
370
- */
371
- declare function readStyleSize(style: CanvasNodeStyle | undefined | null): {
372
- width?: number;
373
- height?: number;
374
- };
375
- /**
376
- * Returns `style` with its pixel `width` / `height` replaced, keeping its representation
377
- * (string or object). Only dimensions already present in the style are rewritten, because
378
- * xyflow applies the node's own `width` / `height` props otherwise.
379
- */
380
- declare function withStyleSize(style: CanvasNodeStyle | undefined | null, size: {
381
- width?: number;
382
- height?: number;
383
- }): CanvasNodeStyle | undefined;
384
- /**
385
- * Resolves a node's size: measured DOM size, then explicit `width` / `height`, then a pixel
386
- * size in `style`, then a label-based estimate (or the defaults when `estimate` is `false`).
387
- */
388
- declare function getNodeSize(node: CanvasNode, options?: NodeRectOptions): {
389
- width: number;
390
- height: number;
391
- };
392
- /**
393
- * Absolute (flow-space) position of a node, following its `parentId` chain.
394
- * Cycles and missing parents are tolerated.
395
- */
396
- declare function getAbsolutePosition(node: CanvasNode, lookup: ReadonlyMap<string, CanvasNode>): XYPosition;
397
- /** Builds an id lookup for a node array. */
398
- declare function createNodeLookup<TNode extends CanvasNode>(nodes: TNode[]): Map<string, TNode>;
399
- /** Absolute flow-space rectangle of a node. */
400
- declare function getNodeRect(node: CanvasNode, lookup?: ReadonlyMap<string, CanvasNode>, options?: NodeRectOptions): Rect;
401
- /**
402
- * Whether a node has been locked with `lockNodes`.
403
- */
404
- declare function isLocked(node: CanvasNode | undefined | null): boolean;
405
- /**
406
- * Locks nodes: marks `data.locked = true` and sets `draggable: false` and `deletable: false`
407
- * so both SvelteFlow and React Flow stop dragging and deleting them. Nodes stay `selectable`
408
- * so they can be unlocked again. The previous flags are kept in `data.lockedPrevious` and
409
- * restored by `unlockNodes`. Returns a new array; untouched nodes keep their identity.
410
- */
411
- declare function lockNodes<TNode extends CanvasNode>(nodes: TNode[], ids: Iterable<string>): TNode[];
412
- /**
413
- * Reverses `lockNodes`, restoring the `draggable` / `deletable` flags the node had before.
414
- */
415
- declare function unlockNodes<TNode extends CanvasNode>(nodes: TNode[], ids: Iterable<string>): TNode[];
416
- /** Locks the given nodes if any of them is unlocked, otherwise unlocks them all. */
417
- declare function toggleLockNodes<TNode extends CanvasNode>(nodes: TNode[], ids: Iterable<string>): TNode[];
418
- interface AlignNodesOptions extends NodeRectOptions {
419
- /**
420
- * What to align to: the selection bounding box (default) or a fixed rectangle.
421
- * Locked nodes never move but still count towards the selection bounds, so they act as anchors.
422
- */
423
- to?: 'selection' | Rect;
424
- }
425
- /**
426
- * Aligns nodes to a shared edge or centre line of their bounding box (Freeform's
427
- * Align Left / Center / Right / Top / Middle / Bottom). Needs at least two nodes unless
428
- * `options.to` is a rectangle. Locked nodes are not moved.
429
- */
430
- declare function alignNodes(nodes: CanvasNode[], ids: Iterable<string>, edge: AlignEdge, options?: AlignNodesOptions): CanvasNodeUpdate[];
431
- interface DistributeNodesOptions extends NodeRectOptions {
432
- /** Explicit gap between neighbours for `gaps` mode. Default: spread evenly between the outer nodes. */
433
- gap?: number;
434
- }
435
- /**
436
- * Distributes nodes along an axis (Freeform's Distribute Horizontally / Vertically / Evenly).
437
- * The outermost nodes stay put and the others are spaced with equal gaps (`gaps`, default)
438
- * or equally spaced centres (`centres`). Needs at least three nodes (two with an explicit
439
- * `gap`). Locked nodes keep their place in the order but are not moved.
440
- */
441
- declare function distributeNodes(nodes: CanvasNode[], ids: Iterable<string>, axis: DistributeAxis, mode?: DistributeMode, options?: DistributeNodesOptions): CanvasNodeUpdate[];
442
- interface MatchSizeOptions extends NodeRectOptions {
443
- /**
444
- * Size source: the `largest` (default) or `smallest` node, the `first` id given,
445
- * or a specific node id.
446
- */
447
- reference?: 'largest' | 'smallest' | 'first' | {
448
- id: string;
449
- };
450
- /** Keep each node's centre in place instead of its top-left corner (default `false`). */
451
- keepCentre?: boolean;
452
- }
453
- /**
454
- * Makes nodes the same width, height or both (Freeform's Make Same Size). Returns size
455
- * updates (plus position updates with `keepCentre`). Locked nodes are not resized but can
456
- * be the reference.
457
- */
458
- declare function matchSize(nodes: CanvasNode[], ids: Iterable<string>, dimension: SizeDimension, options?: MatchSizeOptions): CanvasNodeUpdate[];
459
- /** Z-order operation. */
460
- type ZOrderOperation = 'bringForward' | 'sendBackward' | 'bringToFront' | 'sendToBack';
461
- /**
462
- * Restacks nodes (Bring Forward / Send Backward / Bring to Front / Send to Back).
463
- *
464
- * Both SvelteFlow and React Flow stack nodes by `zIndex` (missing = 0) and, for equal
465
- * `zIndex`, by array order. This computes that effective order for the siblings that share
466
- * the targets' parent, applies the operation, and returns `zIndex` updates assigning each
467
- * sibling its new rank. The array order is left alone, because xyflow requires parents to
468
- * precede their children. Locked nodes are not restacked. "Forward" moves past the next
469
- * sibling the node overlaps, falling back to the next sibling when nothing overlaps.
470
- */
471
- declare function reorderNodes(nodes: CanvasNode[], ids: Iterable<string>, operation: ZOrderOperation, options?: NodeRectOptions): CanvasNodeUpdate[];
472
- /**
473
- * Applies `CanvasNodeUpdate`s to a node array, returning a new array. Unchanged nodes keep
474
- * their identity. Size updates set `width` / `height` and rewrite pixel sizes already present
475
- * in `style` (string or object). An existing `measured` size is updated too, so geometry
476
- * helpers see the new size before xyflow re-measures the node.
477
- */
478
- declare function applyNodeUpdates<TNode extends CanvasNode>(nodes: TNode[], updates: CanvasNodeUpdate[]): TNode[];
479
- /**
480
- * Inverse of a set of updates against the current nodes, for undo. Restores the previous
481
- * position / size / zIndex of every node an update touches.
482
- */
483
- declare function invertNodeUpdates(nodes: CanvasNode[], updates: CanvasNodeUpdate[]): CanvasNodeUpdate[];
484
-
485
333
  /**
486
334
  * A guide line to render while dragging, in flow coordinates.
487
335
  * `edge` and `centre` guides are alignment lines; `spacing` guides mark equal gaps.
336
+ * `measure` lines (with a distance `label`) and dashed `extension` lines come from the
337
+ * distance measuring helpers (`measureBetween`, `measureSelection`).
488
338
  */
489
339
  interface GuideLine {
490
340
  orientation: 'vertical' | 'horizontal';
491
- kind: 'edge' | 'centre' | 'spacing';
341
+ kind: 'edge' | 'centre' | 'spacing' | 'measure' | 'extension';
492
342
  x1: number;
493
343
  y1: number;
494
344
  x2: number;
495
345
  y2: number;
346
+ /** Text drawn at the middle of the line (measuring distances). */
347
+ label?: string;
496
348
  }
349
+ /**
350
+ * Snaps `value` to a grid with the given `spacing` and `origin`. A spacing of 0 or less
351
+ * (or a non-finite one) leaves the value unchanged.
352
+ *
353
+ * Ported from vectorcraft-main/crates/geom/src/snap.rs (MIT OR Apache-2.0, © ArtCraft Team
354
+ * and contributors). See THIRD_PARTY_NOTICES.md.
355
+ */
356
+ declare function snapToGrid(value: number, spacing: number, origin?: number): number;
497
357
  interface SnapGuidesOptions {
498
358
  /** Current viewport zoom; the threshold is in screen pixels and divided by it (default 1). */
499
359
  zoom?: number;
@@ -505,6 +365,13 @@ interface SnapGuidesOptions {
505
365
  centres?: boolean;
506
366
  /** Snap to equal spacing between neighbouring shapes in the same row / column (default `true`). */
507
367
  spacing?: boolean;
368
+ /**
369
+ * Grid spacing in flow units (default 0, off). An axis that does not snap to a shape snaps
370
+ * its top-left (drag) or moving edge (resize) to the grid; grid snaps draw no guides.
371
+ */
372
+ gridSize?: number;
373
+ /** Grid origin in flow units (default `{ x: 0, y: 0 }`). */
374
+ gridOrigin?: XYPosition;
508
375
  }
509
376
  interface SnapResult {
510
377
  /** Snapped top-left of the moving rectangle. */
@@ -513,6 +380,7 @@ interface SnapResult {
513
380
  offset: XYPosition;
514
381
  /** Guide segments to draw for the snap that was applied. */
515
382
  guides: GuideLine[];
383
+ /** Whether x snapped to a shape (grid snaps do not count). */
516
384
  snappedX: boolean;
517
385
  snappedY: boolean;
518
386
  }
@@ -738,33 +606,6 @@ declare function fitViewportToNodes(nodes: CanvasNode[], size: {
738
606
  height: number;
739
607
  }, ids?: Iterable<string>, options?: FitViewportOptions & NodeRectOptions): CanvasViewport | null;
740
608
 
741
- /**
742
- * Canvas arrangement actions that have keyboard shortcuts.
743
- */
744
- type CanvasArrangeAction = 'alignLeft' | 'alignCenter' | 'alignRight' | 'alignTop' | 'alignMiddle' | 'alignBottom' | 'distributeHorizontal' | 'distributeVertical' | 'lock' | 'unlock' | 'bringForward' | 'sendBackward' | 'bringToFront' | 'sendToBack' | 'nextScene' | 'previousScene';
745
- interface ArrangeShortcutBinding {
746
- action: CanvasArrangeAction;
747
- /** `KeyboardEvent.code` (layout- and Option-independent, e.g. `KeyA`, `BracketRight`). */
748
- code: string;
749
- mod?: boolean;
750
- alt?: boolean;
751
- shift?: boolean;
752
- /** Human readable label, e.g. for menus. `Mod` is ⌘ on macOS and Ctrl elsewhere. */
753
- label: string;
754
- }
755
- /**
756
- * Default bindings. Align/distribute follow Figma (Option/Alt + letter), layer order follows
757
- * the common `Mod+]` / `Mod+[` convention, lock follows Keynote/Freeform (`Mod+L`,
758
- * `Mod+Alt+L` to unlock) and scenes step with PageDown / PageUp.
759
- */
760
- declare const DEFAULT_ARRANGE_SHORTCUTS: readonly ArrangeShortcutBinding[];
761
- /**
762
- * Resolves a keydown event to an arrange action, or `null`. Events from text inputs,
763
- * textareas, selects, contenteditable and ProseMirror are ignored (see `isEventFromTextInput`).
764
- * `Mod` is ⌘ or Ctrl.
765
- */
766
- declare function matchArrangeShortcut(event: KeyboardEvent, bindings?: readonly ArrangeShortcutBinding[]): CanvasArrangeAction | null;
767
-
768
609
  /**
769
610
  * Polygon boolean operations (union, intersection, difference, xor and divide) on
770
611
  * multi-polygons with holes.
@@ -1040,6 +881,16 @@ interface PolygonToPathOptions {
1040
881
  x: number;
1041
882
  y: number;
1042
883
  };
884
+ /**
885
+ * `'lines'` (default) writes every ring as `M`/`L`/`Z`. `'fit'` fits cubic Béziers to each
886
+ * ring (`fitPathData`), so flattened curves come back as smooth `C` curves while sharp
887
+ * corners (turning more than `cornerAngleDeg`) and straight edges stay as they are.
888
+ */
889
+ curves?: 'lines' | 'fit';
890
+ /** Curve-fitting tolerance in path units for `curves: 'fit'` (default 0.25). */
891
+ curveTolerance?: number;
892
+ /** Corner threshold in degrees for `curves: 'fit'` (default 30). */
893
+ cornerAngleDeg?: number;
1043
894
  }
1044
895
  /**
1045
896
  * Converts a multi-polygon (or a list of rings) to SVG path data using `M`/`L`/`Z`. Holes
@@ -1103,6 +954,16 @@ interface CombineShapeNodesOptions extends ShapeNodePolygonOptions {
1103
954
  precision?: number;
1104
955
  /** Ramer–Douglas–Peucker simplification tolerance for the result (default 0, off). */
1105
956
  simplify?: number;
957
+ /**
958
+ * How the result's outline is written: `'fit'` (default) fits smooth cubic curves to the
959
+ * flattened result, so booleans of curved shapes stay curved (sharp corners and straight
960
+ * edges are kept); `'lines'` writes the polygon as straight segments.
961
+ */
962
+ curves?: 'lines' | 'fit';
963
+ /** Curve-fitting tolerance in flow units for `curves: 'fit'` (default: `tolerance`, 0.25). */
964
+ curveTolerance?: number;
965
+ /** Corner threshold in degrees for `curves: 'fit'` (default 30). */
966
+ cornerAngleDeg?: number;
1106
967
  /** Point-merge tolerance passed to the boolean engine. */
1107
968
  epsilon?: number;
1108
969
  /** Select the new nodes (default `true`). */
@@ -1169,6 +1030,76 @@ declare function revertShapeCombination<TNode extends CanvasNode>(nodes: TNode[]
1169
1030
  nodes: TNode[];
1170
1031
  }, previous: TNode[]): TNode[];
1171
1032
 
1033
+ /** A resize handle, named like xyflow's `ControlPosition`. */
1034
+ type ResizeHandle = 'top-left' | 'top' | 'top-right' | 'right' | 'bottom-right' | 'bottom' | 'bottom-left' | 'left';
1035
+ declare const RESIZE_HANDLES: readonly ResizeHandle[];
1036
+ /** Which edge of each axis a handle moves: -1 the start (left / top), 1 the end, 0 none. */
1037
+ declare function resizeHandleAxes(handle: ResizeHandle): {
1038
+ x: -1 | 0 | 1;
1039
+ y: -1 | 0 | 1;
1040
+ };
1041
+ /**
1042
+ * The handle a resize from `start` to `next` was made with, from the edges that moved, or
1043
+ * `null` when no edge moved.
1044
+ */
1045
+ declare function inferResizeHandle(start: Rect, next: Rect, eps?: number): ResizeHandle | null;
1046
+ interface SnapResizeOptions extends Omit<SnapGuidesOptions, 'spacing'> {
1047
+ /**
1048
+ * Keep the input box's aspect ratio. A corner snaps whichever axis is closer to a target
1049
+ * and the other follows; a side scales the other axis about its centre.
1050
+ */
1051
+ keepAspectRatio?: boolean;
1052
+ /** Smallest width a snap may leave (default: anything above 0). */
1053
+ minWidth?: number;
1054
+ /** Smallest height a snap may leave (default: anything above 0). */
1055
+ minHeight?: number;
1056
+ }
1057
+ interface SnapResizeResult {
1058
+ /** The snapped box. */
1059
+ rect: Rect;
1060
+ /** Guide segments for the shape snaps that were applied (grid snaps draw none). */
1061
+ guides: GuideLine[];
1062
+ /** Whether the moving x edge snapped to a shape. */
1063
+ snappedX: boolean;
1064
+ /** Whether the moving y edge snapped to a shape. */
1065
+ snappedY: boolean;
1066
+ /** Whether `rect` differs from the input. */
1067
+ changed: boolean;
1068
+ }
1069
+ /**
1070
+ * Snaps a resize of the axis-aligned box `rect` made with `handle` against `targets`. The
1071
+ * opposite edge (side handles) or corner (corner handles) stays fixed:
1072
+ *
1073
+ * - A **side** handle snaps its one moving edge to the nearest target edge or centre within
1074
+ * `threshold` screen pixels.
1075
+ * - A **corner** handle snaps x and y independently (unless `keepAspectRatio`).
1076
+ * - A snap that would collapse or flip the box (or go below `minWidth` / `minHeight`) is
1077
+ * rejected; the next nearest target is tried, else the edge stays where it was dragged.
1078
+ * - With `gridSize`, an axis without a shape snap snaps its moving edge to the grid.
1079
+ *
1080
+ * Returns the snapped box and the guides to draw (same shape as drag snapping).
1081
+ */
1082
+ declare function snapResize(rect: Rect, handle: ResizeHandle, targets: Rect[] | GuideIndex, options?: SnapResizeOptions): SnapResizeResult;
1083
+ interface SnapNodeResizeOptions extends SnapResizeOptions, NodeRectOptions {
1084
+ /** Index from `createNodeGuideIndex(nodes, [id])`, reused across resize frames. */
1085
+ index?: GuideIndex;
1086
+ }
1087
+ interface SnapNodeResizeResult extends SnapResizeResult {
1088
+ /** Position / size update for the node (parent-relative position), or none. */
1089
+ updates: CanvasNodeUpdate[];
1090
+ }
1091
+ /**
1092
+ * Snaps a node that is being resized. `rect` is the node's proposed absolute box (e.g. from
1093
+ * a resize event) and `handle` the handle being dragged. Locked nodes are never snapped.
1094
+ * The node itself and its descendants are not snap targets.
1095
+ */
1096
+ declare function snapNodeResize(nodes: CanvasNode[], id: string, rect: Rect, handle: ResizeHandle, options?: SnapNodeResizeOptions): SnapNodeResizeResult;
1097
+ /**
1098
+ * Absolute box of a node while it is being resized: flow libraries write the new size to
1099
+ * `width` / `height` before the DOM is re-measured, so those win over `measured` here.
1100
+ */
1101
+ declare function getResizingNodeRect(node: CanvasNode, lookup: ReadonlyMap<string, CanvasNode>, options?: NodeRectOptions): Rect;
1102
+
1172
1103
  /** Minimal history surface (`HistoryManager` satisfies it). */
1173
1104
  interface ArrangeHistoryTarget {
1174
1105
  execute(command: Command): void;
@@ -1186,6 +1117,14 @@ interface CanvasArrangeControllerOptions<TNode extends CanvasNode = CanvasNode>
1186
1117
  guides?: Omit<SnapGuidesOptions, 'zoom'>;
1187
1118
  /** Turns drag snapping off while keeping the arrange actions (default `true`). */
1188
1119
  snapping?: boolean;
1120
+ /** Turns resize snapping off (default: follows `snapping`). */
1121
+ resizeSnapping?: boolean;
1122
+ /** Resize options passed to `snapResize` (`keepAspectRatio`, `minWidth`, `minHeight`). */
1123
+ resize?: {
1124
+ keepAspectRatio?: boolean;
1125
+ minWidth?: number;
1126
+ minHeight?: number;
1127
+ };
1189
1128
  /** Size resolution for unmeasured nodes. */
1190
1129
  rectOptions?: NodeRectOptions;
1191
1130
  /** Called whenever the guide segments change (set while dragging, cleared on drop). */
@@ -1256,6 +1195,31 @@ declare function createCanvasArrangeController<TNode extends CanvasNode = Canvas
1256
1195
  * A batch without a dragging position change ends the drag and clears the guides.
1257
1196
  */
1258
1197
  snapPositionChanges<TChange extends PositionChangeLike>(changes: TChange[]): TChange[];
1198
+ /**
1199
+ * Starts resize snapping for node `id`: records its box (to tell which handle is
1200
+ * dragged) and caches the snap targets. Optional: `resize` starts lazily.
1201
+ */
1202
+ beginResize(id: string): void;
1203
+ /**
1204
+ * Snaps node `id` as currently sized in `getNodes()` (call it after the flow wrote the
1205
+ * new size, e.g. SvelteFlow's `NodeResizer` `onResize`, deferred by a microtask) and
1206
+ * writes the snapped box back through `setNodes` (not recorded in history). `handle`
1207
+ * defaults to the one inferred from the edges that moved since `beginResize`. A locked
1208
+ * node is restored to its starting box.
1209
+ */
1210
+ resize(id: string, handle?: ResizeHandle): SnapNodeResizeResult | null;
1211
+ /**
1212
+ * Ends resize snapping: clears guides and re-applies the last snapped box if the flow
1213
+ * wrote the raw pointer size afterwards.
1214
+ */
1215
+ endResize(): void;
1216
+ /**
1217
+ * React Flow style: snaps the `dimensions` (and matching `position`) changes a
1218
+ * `NodeResizer` emits in an `onNodesChange` batch and updates `guides`. The resize-end
1219
+ * change (`resizing: false`) carries the raw pointer size, so the last snapped size is
1220
+ * kept. Resize changes of locked nodes are dropped. Returns the (possibly new) changes.
1221
+ */
1222
+ snapResizeChanges<TChange extends PositionChangeLike>(changes: TChange[]): TChange[];
1259
1223
  /**
1260
1224
  * Clears guides and the cached snap targets. Call it from the flow's drag-stop
1261
1225
  * handler: flow libraries write the raw pointer position when a drag ends, so the
@@ -1265,4 +1229,145 @@ declare function createCanvasArrangeController<TNode extends CanvasNode = Canvas
1265
1229
  };
1266
1230
  type CanvasArrangeController<TNode extends CanvasNode = CanvasNode> = ReturnType<typeof createCanvasArrangeController<TNode>>;
1267
1231
 
1268
- export { type AlignEdge, type AlignNodesOptions, type ArrangeHistoryTarget, type ArrangeShortcutBinding, CONNECTION_LINE_TYPES, type CanvasArrangeAction, type CanvasArrangeController, type CanvasArrangeControllerOptions, CanvasClipboardPayload, type CanvasConnectionLineType, CanvasEdge, type CanvasHeightOptions, CanvasLayoutOptions, CanvasNode, CanvasNodeStyle, type CanvasNodeUpdate, type CanvasScene, type CanvasScenesOptions, type CanvasScenesState, CanvasScenesStore, type CanvasViewport, type Clock, type CombineShapeNodesOptions, type CombineShapeNodesRefusal, type CombineShapeNodesResult, type ConnectorSnap, type ConnectorSnapOptions, type ConnectorSnapTarget, DEFAULT_ARRANGE_SHORTCUTS, DEFAULT_NODE_HEIGHT, DEFAULT_NODE_WIDTH, DEFAULT_PLACEMENT_GAP, DirectionalDisplacementOptions, type DistributeAxis, type DistributeMode, type DistributeNodesOptions, type EllipseShape, FanOutTrajectoryOptions, type FitViewportOptions, type FlattenOptions, type GuideIndex, type GuideLine, IncrementalLayoutOptions, LOCKED_DATA_KEY, LOCKED_PREVIOUS_FLAGS_KEY, ManualClock, type MatchSizeOptions, type MultiNodeTransitionOptions, type MultiPolygon, type NodeRectOptions, NodeTransition, type PathCommand, type PathShape, PlaceBesideOptions, Point, type PolygonBooleanOperation, type PolygonBooleanOptions, type PolygonFillRule, type PolygonInput, type PolygonOperand, type PolygonPiece, type PolygonRing, type PolygonToPathOptions, type PolygonWithHoles, Position, type PositionChangeLike, Rect, type RectShape, ReflowDisplacementOptions, type RegularPolygonShape, SHAPE_DATA_KEY, SHAPE_KINDS, SHAPE_NODE_TYPE, SHAPE_OPERATIONS, type SerializedCanvasScenes, type ShapeDescription, type ShapeKind, type ShapeNodePolygonOptions, type ShapeOperation, type ShapePaint, type ShapeRenderData, type ShapeSize, Side, type SizeDimension, type SnapGuidesOptions, type SnapNodeDragOptions, type SnapNodeDragResult, type SnapResult, type StarShape, StreamingLayoutManager, type StreamingLayoutManagerOptions, TrajectoryFunction, XYPosition, type ZOrderOperation, alignNodes, applyNodeUpdates, applyShapeCombination, blendLayout, boundsOf, calculateDagreReflowDisplacement, calculateDirectionalDisplacement, canCombineShapeNodes, canvasHeight, centerNodes, centre, collectDescendantIds, combineShapeNodes, computeNodesBoundingBox, computeSnapGuides, connectedOnly, createBezierTrajectory, createCanvasArrangeController, createCanvasScenesStore, createFanOutTrajectory, createGuideIndex, createNodeGuideIndex, createNodeLookup, defaultEasing, distributeNodes, dividePolygons, ensureLayout, estimateCanvasHeight, estimateNodeSize, findConnectorSnap, fitViewportToNodes, fitViewportToRect, flattenSvgPath, flowSide, formatNumber, getAbsolutePosition, getCenteredNodePosition, getLayoutedNodes, getNodeRect, getNodeShape, getNodeSize, getShapeRenderData, getShapeSvg, handlePoint, intersectPolygons, invertNodeUpdates, isEventFromTextInput, isLocked, isShapeDescription, isShapeNode, isValidCanvasEdge, isValidCanvasNode, isValidCanvasScene, isValidUrl, layoutBounds, linearPositionTrajectory, linearTrajectory, lockNodes, matchArrangeShortcut, matchSize, multiPolygonArea, multiPolygonBounds, nearestHandlePositions, oppositePosition, overlaps, pageHidden, parseCanvasClipboardData, parseCanvasScenes, parseSvgPath, placeBeside, pointInMultiPolygon, pointInRings, polygonArea, polygonBoolean, polygonToSvgPath, positionToSide, readStyleSize, realClock, remapPastedNodes, reorderNodes, repositionNodesTo, revertShapeCombination, ringSignedArea, runMultiNodeTransition, serializeCanvasNodes, shapeNodeToPolygon, shapeToPolygon, sideToPosition, simplifyRing, snapNodeDrag, subtractPolygons, toggleLockNodes, unionPolygons, unlockNodes, withStyleOpacity, withStyleSize, xorPolygons };
1232
+ /**
1233
+ * A measuring line in flow coordinates. `measure` lines carry a `label` (the distance);
1234
+ * `extension` lines are dashed, unlabelled lines that carry a gap over to the measured box
1235
+ * when the gap line passes beside it.
1236
+ */
1237
+ interface MeasureGuide extends GuideLine {
1238
+ kind: 'measure' | 'extension';
1239
+ /** The distance as shown on the label (`measure` lines only). */
1240
+ label?: string;
1241
+ }
1242
+ /** A distance as shown on a label: absolute value, up to two decimals, no trailing zeros. */
1243
+ declare function measureLabel(distance: number): string;
1244
+ /**
1245
+ * Distance lines from box `a` (the selection) to box `b` (the hovered shape):
1246
+ *
1247
+ * - **One inside the other**: from the inner box to each edge of the outer one, along the
1248
+ * inner box's centre lines (the same lines either way round).
1249
+ * - **Overlapping**: between the matching edges (left to left, right to right, ...).
1250
+ * - **Apart**: the horizontal and/or vertical gap, across the shared rows / columns, or from
1251
+ * the middle of `a` with a dashed `extension` line to `b` when the gap line passes beside it.
1252
+ * Touching boxes have no gap to draw.
1253
+ */
1254
+ declare function measureBetween(a: Rect, b: Rect): MeasureGuide[];
1255
+ /**
1256
+ * Distance lines from box `a` to an infinite guide line (`vertical` at x = `at`, otherwise
1257
+ * horizontal at y = `at`): to the nearer side, or to both sides when the line crosses the box.
1258
+ */
1259
+ declare function measureToLine(a: Rect, orientation: 'vertical' | 'horizontal', at: number): MeasureGuide[];
1260
+ interface MeasureSelectionResult {
1261
+ /** Measuring lines in flow coordinates. */
1262
+ guides: MeasureGuide[];
1263
+ /** The box measured to (to outline), or `null` when nothing is measured. */
1264
+ target: Rect | null;
1265
+ /** The selection's bounding box, or `null` without a selection. */
1266
+ selection: Rect | null;
1267
+ }
1268
+ interface MeasureSelectionOptions extends NodeRectOptions {
1269
+ }
1270
+ /**
1271
+ * Alt-hover measuring on canvas nodes: from the bounding box of `selectedIds` (absolute,
1272
+ * union of several nodes) to the hovered node. Hovering the selection itself, or nothing
1273
+ * (`hoveredId` null), measures to the selection's parent (`parentId`) when it has one;
1274
+ * a top-level selection then measures nothing. Hidden nodes are ignored.
1275
+ */
1276
+ declare function measureSelection(nodes: CanvasNode[], selectedIds: Iterable<string>, hoveredId: string | null | undefined, options?: MeasureSelectionOptions): MeasureSelectionResult;
1277
+ /**
1278
+ * Whether the measuring modifier (Alt / Option) is held after a keyboard or pointer event.
1279
+ * `keyup` of Alt releases it; `keydown` of Alt or any event with `altKey` holds it.
1280
+ */
1281
+ declare function isMeasureModifierHeld(event: {
1282
+ type?: string;
1283
+ key?: string;
1284
+ altKey?: boolean;
1285
+ } | null | undefined): boolean;
1286
+
1287
+ /**
1288
+ * Least-squares cubic Bézier fitting of point sequences (Schneider-style: fit one cubic with
1289
+ * fixed end tangents, reparameterise with Newton steps, split at the worst point), with
1290
+ * corner preservation by a turning-angle test.
1291
+ *
1292
+ * Portions ported from vectorcraft-main/crates/pathops/src/fit.rs and
1293
+ * vectorcraft-main/crates/pathops/src/edit.rs (MIT OR Apache-2.0, © ArtCraft Team and
1294
+ * contributors). See THIRD_PARTY_NOTICES.md.
1295
+ */
1296
+
1297
+ /** One cubic Bézier segment. */
1298
+ interface CubicSegment {
1299
+ p0: Point;
1300
+ p1: Point;
1301
+ p2: Point;
1302
+ p3: Point;
1303
+ }
1304
+ interface FitCubicsOptions {
1305
+ /**
1306
+ * Vertices where the polyline turns by more than this many degrees stay sharp corners
1307
+ * (default 30). Use 180 to smooth through every vertex.
1308
+ */
1309
+ cornerAngleDeg?: number;
1310
+ /** Treat the points as a closed ring (the last point connects back to the first). */
1311
+ closed?: boolean;
1312
+ }
1313
+ /** Evaluates a cubic segment at `t` ∈ [0, 1]. */
1314
+ declare function cubicPointAt(c: CubicSegment, t: number): Point;
1315
+ /**
1316
+ * Fits a G1-continuous chain of cubics through `points` (an open run) with the unit
1317
+ * tangents `t0` (leaving the first point) and `t1` (arriving at the last point, forward);
1318
+ * both are estimated from the end points when omitted. Every point lies within `tolerance`
1319
+ * of the curve at its fitted parameter.
1320
+ */
1321
+ declare function fitCubicRun(points: readonly Point[], tolerance: number, t0?: Point, t1?: Point): CubicSegment[];
1322
+ /**
1323
+ * Fits cubic Bézier segments to a polyline (`closed` for a ring), keeping vertices that turn
1324
+ * by more than `cornerAngleDeg` (default 30°) as sharp corners. Each stretch between corners
1325
+ * is fitted Schneider-style so that every input point is within `tolerance` of the result.
1326
+ *
1327
+ * Returns the segments in order (consecutive segments share end points; a closed result ends
1328
+ * where it starts). Fewer than two distinct points give an empty array.
1329
+ */
1330
+ declare function fitCubics(points: readonly Point[], tolerance: number, options?: FitCubicsOptions): CubicSegment[];
1331
+ /** Whether a cubic is (within `tol`) the straight line from `p0` to `p3`. */
1332
+ declare function isStraightCubic(c: CubicSegment, tol: number): boolean;
1333
+ interface FitPathDataOptions extends FitCubicsOptions {
1334
+ /** Fitting tolerance in path units (default 0.5). */
1335
+ tolerance?: number;
1336
+ /** Decimal places (default 3). */
1337
+ precision?: number;
1338
+ /** Added to every point before formatting. */
1339
+ offset?: {
1340
+ x: number;
1341
+ y: number;
1342
+ };
1343
+ /**
1344
+ * Keep the original polyline when fitting would need more segments than it has edges
1345
+ * (default `true`), so fitting never makes a path heavier.
1346
+ */
1347
+ noWorse?: boolean;
1348
+ }
1349
+ /** SVG `d` for fitted segments (`L` for straight ones, `C` otherwise). */
1350
+ declare function cubicsToPathData(segments: readonly CubicSegment[], options?: {
1351
+ precision?: number;
1352
+ offset?: {
1353
+ x: number;
1354
+ y: number;
1355
+ };
1356
+ closed?: boolean;
1357
+ straightTolerance?: number;
1358
+ }): string;
1359
+ /**
1360
+ * Fits smooth curves to a polygon ring (closed by default) and returns SVG path data with
1361
+ * `C` curves for smooth stretches, `L` lines for straight ones and sharp corners kept.
1362
+ * Use it for boolean results of curved shapes or to smooth freehand strokes
1363
+ * (`{ closed: false }`, see `fitFreehandPath`).
1364
+ */
1365
+ declare function fitPathData(ring: readonly Point[], options?: FitPathDataOptions): string;
1366
+ /**
1367
+ * Smooths a freehand stroke (pointer samples) into an open SVG path of cubic curves.
1368
+ * `tolerance` is the largest distance (in the points' units) a sample may be from the
1369
+ * curve (default 1); sharp turns above `cornerAngleDeg` (default 30) stay corners.
1370
+ */
1371
+ declare function fitFreehandPath(points: readonly Point[], options?: Omit<FitPathDataOptions, 'closed'>): string;
1372
+
1373
+ export { AlignEdge, AlignNodesOptions, type ArrangeHistoryTarget, CONNECTION_LINE_TYPES, CanvasArrangeAction, type CanvasArrangeController, type CanvasArrangeControllerOptions, CanvasClipboardPayload, type CanvasConnectionLineType, CanvasEdge, type CanvasHeightOptions, CanvasLayoutOptions, CanvasNode, CanvasNodeStyle, CanvasNodeUpdate, type CanvasScene, type CanvasScenesOptions, type CanvasScenesState, CanvasScenesStore, type CanvasViewport, type Clock, type CombineShapeNodesOptions, type CombineShapeNodesRefusal, type CombineShapeNodesResult, type ConnectorSnap, type ConnectorSnapOptions, type ConnectorSnapTarget, type CubicSegment, DEFAULT_NODE_HEIGHT, DEFAULT_NODE_WIDTH, DEFAULT_PLACEMENT_GAP, DirectionalDisplacementOptions, DistributeAxis, DistributeMode, DistributeNodesOptions, type EllipseShape, FanOutTrajectoryOptions, type FitCubicsOptions, type FitPathDataOptions, type FitViewportOptions, type FlattenOptions, type GuideIndex, type GuideLine, IncrementalLayoutOptions, ManualClock, MatchSizeOptions, type MeasureGuide, type MeasureSelectionOptions, type MeasureSelectionResult, type MultiNodeTransitionOptions, type MultiPolygon, NodeRectOptions, NodeTransition, type PathCommand, type PathShape, PlaceBesideOptions, Point, type PolygonBooleanOperation, type PolygonBooleanOptions, type PolygonFillRule, type PolygonInput, type PolygonOperand, type PolygonPiece, type PolygonRing, type PolygonToPathOptions, type PolygonWithHoles, Position, type PositionChangeLike, RESIZE_HANDLES, Rect, type RectShape, ReflowDisplacementOptions, type RegularPolygonShape, type ResizeHandle, SHAPE_DATA_KEY, SHAPE_KINDS, SHAPE_NODE_TYPE, SHAPE_OPERATIONS, type SerializedCanvasScenes, type ShapeDescription, type ShapeKind, type ShapeNodePolygonOptions, type ShapeOperation, type ShapePaint, type ShapeRenderData, type ShapeSize, Side, SizeDimension, type SnapGuidesOptions, type SnapNodeDragOptions, type SnapNodeDragResult, type SnapNodeResizeOptions, type SnapNodeResizeResult, type SnapResizeOptions, type SnapResizeResult, type SnapResult, type StarShape, StreamingLayoutManager, type StreamingLayoutManagerOptions, TrajectoryFunction, XYPosition, ZOrderOperation, applyShapeCombination, blendLayout, boundsOf, calculateDagreReflowDisplacement, calculateDirectionalDisplacement, canCombineShapeNodes, canvasHeight, centerNodes, centre, collectDescendantIds, combineShapeNodes, computeNodesBoundingBox, computeSnapGuides, connectedOnly, createBezierTrajectory, createCanvasArrangeController, createCanvasScenesStore, createFanOutTrajectory, createGuideIndex, createNodeGuideIndex, cubicPointAt, cubicsToPathData, defaultEasing, dividePolygons, ensureLayout, estimateCanvasHeight, estimateNodeSize, findConnectorSnap, fitCubicRun, fitCubics, fitFreehandPath, fitPathData, fitViewportToNodes, fitViewportToRect, flattenSvgPath, flowSide, formatNumber, getCenteredNodePosition, getLayoutedNodes, getNodeShape, getResizingNodeRect, getShapeRenderData, getShapeSvg, handlePoint, inferResizeHandle, intersectPolygons, isEventFromTextInput, isMeasureModifierHeld, isShapeDescription, isShapeNode, isStraightCubic, isValidCanvasEdge, isValidCanvasNode, isValidCanvasScene, isValidUrl, layoutBounds, linearPositionTrajectory, linearTrajectory, measureBetween, measureLabel, measureSelection, measureToLine, multiPolygonArea, multiPolygonBounds, nearestHandlePositions, oppositePosition, overlaps, pageHidden, parseCanvasClipboardData, parseCanvasScenes, parseSvgPath, placeBeside, pointInMultiPolygon, pointInRings, polygonArea, polygonBoolean, polygonToSvgPath, positionToSide, realClock, remapPastedNodes, repositionNodesTo, resizeHandleAxes, revertShapeCombination, ringSignedArea, runMultiNodeTransition, serializeCanvasNodes, shapeNodeToPolygon, shapeToPolygon, sideToPosition, simplifyRing, snapNodeDrag, snapNodeResize, snapResize, snapToGrid, subtractPolygons, unionPolygons, withStyleOpacity, xorPolygons };