@svgsketch/core 0.5.0 → 0.7.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.
package/dist/index.d.mts CHANGED
@@ -136,6 +136,32 @@ interface AnimationTrack {
136
136
  locked: boolean;
137
137
  /** SVG path data for motion-path animation (property should be 'pathMotion'). */
138
138
  motionPath?: string;
139
+ /**
140
+ * When set, the motion path was authored as a reference to another shape
141
+ * (SVG `<mpath href="#shapeId"/>`). `motionPath` still holds the resolved
142
+ * path data string (kept in sync with the referenced shape's geometry) so
143
+ * the runtime renderer doesn't need to dereference; the `mode` field
144
+ * controls how that data is interpreted and whether export can round-trip
145
+ * the reference as `<mpath>`.
146
+ *
147
+ * - `'trackShape'` — motionPath is displacement-relative to the animated
148
+ * element's center, so the overlay and playback render on top of the
149
+ * referenced shape's absolute canvas position ("follow this shape").
150
+ * Exports as inline `path=` because `<mpath>` would double-offset.
151
+ * - `'curveTemplate'` — motionPath is normalized so `M 0,0` is the
152
+ * animation's starting displacement ("trace this curve from wherever
153
+ * the element is"). Exports spec-correctly as `<mpath href>` since
154
+ * the referenced shape's `d` (normalized to origin) matches the stored
155
+ * motionPath byte-for-byte, enabling reuse across animations.
156
+ *
157
+ * Missing `mode` (legacy data) defaults to `'trackShape'` for back-compat.
158
+ *
159
+ * @see https://svgwg.org/specs/animations/#MPathElement
160
+ */
161
+ motionPathRef?: {
162
+ shapeId: string;
163
+ mode?: 'trackShape' | 'curveTemplate';
164
+ };
139
165
  /** Trigger to begin the animation (defaults to '0s'). */
140
166
  beginTrigger?: AnimationTrigger;
141
167
  /** Trigger to end the animation. */
@@ -165,6 +191,15 @@ interface AnimationTrack {
165
191
  * @default 'replace' (except transforms, which default to 'sum')
166
192
  */
167
193
  additive?: 'sum' | 'replace';
194
+ /**
195
+ * Scoping for this track.
196
+ * - Absent / 'document' — plays on the main document timeline (default).
197
+ * - `'marker:<markerId>'` — scoped to a marker definition's inner shapes.
198
+ * Only evaluated when the editor is isolation-editing that marker;
199
+ * exported as SMIL inside the `<marker>` element so it animates at
200
+ * every attached vertex.
201
+ */
202
+ scope?: string;
168
203
  }
169
204
  /**
170
205
  * The top-level animation timeline for a document.
@@ -197,6 +232,12 @@ interface SerializedAnimationTimeline {
197
232
  locked?: boolean;
198
233
  motionPath?: string;
199
234
  motionPathMatrix?: number[];
235
+ /** See `AnimationTrack.motionPathRef`. Persists the authoring reference to
236
+ * another shape's geometry so a round-trip re-emits `<mpath href>`. */
237
+ motionPathRef?: {
238
+ shapeId: string;
239
+ mode?: 'trackShape' | 'curveTemplate';
240
+ };
200
241
  beginTrigger?: AnimationTrigger;
201
242
  endTrigger?: AnimationTrigger;
202
243
  cycleDuration?: number;
@@ -209,6 +250,8 @@ interface SerializedAnimationTimeline {
209
250
  };
210
251
  motionRotate?: 'auto' | 'auto-reverse' | number;
211
252
  additive?: 'sum' | 'replace';
253
+ /** Scoping — see `AnimationTrack.scope`. */
254
+ scope?: string;
212
255
  /**
213
256
  * 6-element CSS matrix of the track's ancestor transform context, captured
214
257
  * at the time the animation was authored. Preserves visual fidelity when
@@ -302,6 +345,19 @@ interface Viewbox {
302
345
  width: number;
303
346
  height: number;
304
347
  }
348
+ /** Direction hint for connector routing tangents. */
349
+ type ConnectionDirection = 'n' | 's' | 'e' | 'w' | 'any';
350
+ /** A named anchor point on a shape where connectors can attach. */
351
+ interface ConnectionPoint {
352
+ /** Stable id — 'n','s','e','w','center' for derived; 'custom-<uuid>' for user-placed. */
353
+ id: string;
354
+ /** Location in canvas/workspace coordinates (post-transform). */
355
+ point: Point;
356
+ /** Tangent hint used by connector routing. */
357
+ direction: ConnectionDirection;
358
+ /** 'derived' anchors are computed from shape geometry; 'custom' are persisted overrides. */
359
+ kind: 'derived' | 'custom';
360
+ }
305
361
  type FillType = 'solid' | 'linear-gradient' | 'radial-gradient' | 'pattern' | 'none';
306
362
  type StrokeType = 'solid' | 'linear-gradient' | 'radial-gradient' | 'pattern' | 'none';
307
363
  type GradientSpreadMethod = 'pad' | 'repeat' | 'reflect';
@@ -344,6 +400,14 @@ interface LinearGradient {
344
400
  * element's bbox-normalised [0, 1] space. See `GradientUnits`.
345
401
  */
346
402
  gradientUnits?: GradientUnits;
403
+ /**
404
+ * Original `id` from the imported source SVG. Runtime `id` is always
405
+ * a fresh GUID (to keep editor uniqueness invariants), but `sourceId`
406
+ * is retained so export can restore human-friendly ids when there is
407
+ * no collision. Cleared whenever the gradient is mutated through the
408
+ * editor — at that point the source id no longer describes the data.
409
+ */
410
+ sourceId?: string;
347
411
  }
348
412
  interface RadialGradient {
349
413
  type: 'radial-gradient';
@@ -363,6 +427,8 @@ interface RadialGradient {
363
427
  * `r`/`ry` are in document user space. See `GradientUnits`.
364
428
  */
365
429
  gradientUnits?: GradientUnits;
430
+ /** See `LinearGradient.sourceId`. */
431
+ sourceId?: string;
366
432
  }
367
433
  /**
368
434
  * Per-pattern-type tuneable parameters.
@@ -444,6 +510,8 @@ interface PatternFill {
444
510
  y?: number;
445
511
  /** ID of the `CustomPatternDef` this fill was built from (if any). */
446
512
  customPatternId?: string;
513
+ /** See `LinearGradient.sourceId`. */
514
+ sourceId?: string;
447
515
  }
448
516
  type GradientDefinition = LinearGradient | RadialGradient | PatternFill;
449
517
  /** Style overrides for a single rich-text segment. */
@@ -495,7 +563,7 @@ interface CustomPatternDef {
495
563
  /** Tile height in userSpaceOnUse coordinates. */
496
564
  height: number;
497
565
  }
498
- type FilterType = 'drop-shadow' | 'inner-shadow' | 'gaussian-blur' | 'motion-blur' | 'point-light' | 'spot-light' | 'outline' | 'sharpen' | 'pixelate' | 'warp' | 'morphology' | 'contouring-discrete' | 'contouring-table' | 'round-edges' | 'grayscale' | 'channel-painter' | 'brightness' | 'contrast' | 'opacity' | 'invert' | 'hue-rotate' | 'saturate' | 'black-and-white' | 'sepia' | 'duotone' | 'xray' | 'noise' | 'emboss' | 'film-grain' | 'watercolor' | 'gouache' | 'ink-blot' | 'crumpled-plastic' | 'riddled' | 'glow' | 'inner-glow';
566
+ type FilterType = 'drop-shadow' | 'inner-shadow' | 'gaussian-blur' | 'motion-blur' | 'point-light' | 'spot-light' | 'diffuse-lighting' | 'specular-lighting' | 'outline' | 'sharpen' | 'pixelate' | 'warp' | 'morphology' | 'contouring-discrete' | 'contouring-table' | 'round-edges' | 'grayscale' | 'channel-painter' | 'brightness' | 'contrast' | 'opacity' | 'invert' | 'hue-rotate' | 'saturate' | 'black-and-white' | 'sepia' | 'duotone' | 'xray' | 'noise' | 'emboss' | 'film-grain' | 'watercolor' | 'gouache' | 'ink-blot' | 'crumpled-plastic' | 'riddled' | 'glow' | 'inner-glow' | 'raw-svg';
499
567
  type BlurQuality = 'normal' | 'high';
500
568
  interface BaseFilter {
501
569
  id: string;
@@ -558,6 +626,41 @@ interface SpotLightFilter extends BaseFilter {
558
626
  specularConstant: number;
559
627
  specularExponent: number;
560
628
  }
629
+ type LightSource = {
630
+ kind: 'point';
631
+ x: number;
632
+ y: number;
633
+ z: number;
634
+ } | {
635
+ kind: 'spot';
636
+ x: number;
637
+ y: number;
638
+ z: number;
639
+ pointsAtX: number;
640
+ pointsAtY: number;
641
+ pointsAtZ: number;
642
+ limitingConeAngle?: number;
643
+ specularExponent?: number;
644
+ } | {
645
+ kind: 'distant';
646
+ azimuth: number;
647
+ elevation: number;
648
+ };
649
+ interface DiffuseLightingFilter extends BaseFilter {
650
+ type: 'diffuse-lighting';
651
+ surfaceScale: number;
652
+ diffuseConstant: number;
653
+ color: string;
654
+ lightSource: LightSource;
655
+ }
656
+ interface SpecularLightingFilter extends BaseFilter {
657
+ type: 'specular-lighting';
658
+ surfaceScale: number;
659
+ specularConstant: number;
660
+ specularExponent: number;
661
+ color: string;
662
+ lightSource: LightSource;
663
+ }
561
664
  type OutlinePosition = 'outside' | 'center' | 'inside';
562
665
  interface OutlineFilter extends BaseFilter {
563
666
  type: 'outline';
@@ -706,7 +809,29 @@ interface InnerGlowFilter extends BaseFilter {
706
809
  radius: number;
707
810
  intensity: number;
708
811
  }
709
- type ShapeFilter = DropShadowFilter | InnerShadowFilter | GaussianBlurFilter | MotionBlurFilter | PointLightFilter | SpotLightFilter | OutlineFilter | SharpenFilter | PixelateFilter | WarpFilter | MorphologyFilter | ContouringDiscreteFilter | ContouringTableFilter | RoundEdgesFilter | GrayscaleFilter | ChannelPainterFilter | BrightnessFilter | ContrastFilter | OpacityFilter | InvertFilter | HueRotateFilter | SaturateFilter | BlackAndWhiteFilter | SepiaFilter | DuotoneFilter | XrayFilter | NoiseFilter | EmbossFilter | FilmGrainFilter | WatercolorFilter | GouacheFilter | InkBlotFilter | CrumpledPlasticFilter | RiddledFilter | GlowFilter | InnerGlowFilter;
812
+ /**
813
+ * Passthrough for `<filter>` definitions the editor doesn't model as a preset.
814
+ * The parser serialises the element's inner markup and authored region
815
+ * attributes verbatim; the filter manager re-emits them on render. Absent
816
+ * attributes stay `undefined` so the UA applies the SVG spec initial values
817
+ * (filterUnits=objectBoundingBox, primitiveUnits=userSpaceOnUse, filter region
818
+ * -10% -10% 120% 120%, color-interpolation-filters=linearRGB).
819
+ */
820
+ interface RawSvgFilter extends BaseFilter {
821
+ type: 'raw-svg';
822
+ svgContent: string;
823
+ x?: string;
824
+ y?: string;
825
+ width?: string;
826
+ height?: string;
827
+ filterUnits?: 'userSpaceOnUse' | 'objectBoundingBox';
828
+ primitiveUnits?: 'userSpaceOnUse' | 'objectBoundingBox';
829
+ colorInterpolationFilters?: 'auto' | 'sRGB' | 'linearRGB';
830
+ floodColor?: string;
831
+ floodOpacity?: string;
832
+ lightingColor?: string;
833
+ }
834
+ type ShapeFilter = DropShadowFilter | InnerShadowFilter | GaussianBlurFilter | MotionBlurFilter | PointLightFilter | SpotLightFilter | DiffuseLightingFilter | SpecularLightingFilter | OutlineFilter | SharpenFilter | PixelateFilter | WarpFilter | MorphologyFilter | ContouringDiscreteFilter | ContouringTableFilter | RoundEdgesFilter | GrayscaleFilter | ChannelPainterFilter | BrightnessFilter | ContrastFilter | OpacityFilter | InvertFilter | HueRotateFilter | SaturateFilter | BlackAndWhiteFilter | SepiaFilter | DuotoneFilter | XrayFilter | NoiseFilter | EmbossFilter | FilmGrainFilter | WatercolorFilter | GouacheFilter | InkBlotFilter | CrumpledPlasticFilter | RiddledFilter | GlowFilter | InnerGlowFilter | RawSvgFilter;
710
835
  type SegmentCurveType = 'LINEAR' | 'CUBIC' | 'QUADRATIC' | 'ARC';
711
836
  interface SplinePoint {
712
837
  x: number;
@@ -737,6 +862,30 @@ interface ShapeMetadata {
737
862
  linkUrl: string;
738
863
  linkTarget: LinkTarget;
739
864
  customData: Record<string, string>;
865
+ /**
866
+ * Lossless carrier for any `<metadata>` elements that appeared as children
867
+ * of this shape's SVG element. Stored as a serialized string containing
868
+ * one or more complete `<metadata ...>...</metadata>` blocks in document
869
+ * order. Preserves element-level attributes (id, lang, class, style,
870
+ * xml:space), arbitrary child elements from any namespace, character data,
871
+ * mixed content, and multiple sibling blocks.
872
+ *
873
+ * Spec: SVG 2 §5.8 — content model is "Any elements or character data",
874
+ * and the element may appear on any container or graphical element.
875
+ */
876
+ rawMetadata?: string;
877
+ /**
878
+ * Lossless carrier for the inner XML of the `<desc>` element when it
879
+ * contains foreign XML (per SVG 2 §5.7 — the spec example shows
880
+ * `<myfoo:…>` elements inside `<desc>`). Populated only when `<desc>`
881
+ * has non-text children; plain-prose desc uses `description` alone.
882
+ *
883
+ * Emit rule: if the textContent of `rawDescription` still equals the
884
+ * current `description` value, emit the raw (foreign XML round-trips).
885
+ * If `description` has been edited and the textual views diverge, emit
886
+ * plain text from `description` (user intent takes precedence).
887
+ */
888
+ rawDescription?: string;
740
889
  }
741
890
  /**
742
891
  * Provider attribution metadata for an image shape sourced from a third-party
@@ -775,6 +924,107 @@ interface DocumentMetadata {
775
924
  licenseUrl: string;
776
925
  language: string;
777
926
  customMetadata: Record<string, string>;
927
+ /**
928
+ * Lossless carrier for any `<metadata>` elements that appeared as direct
929
+ * children of the root `<svg>`. Stored as a serialized string containing
930
+ * one or more complete `<metadata ...>...</metadata>` blocks in document
931
+ * order. Preserves element-level attributes, arbitrary child elements
932
+ * from any namespace (RDF, XMP, Inkscape, custom), character data and
933
+ * mixed content, and multiple sibling blocks.
934
+ *
935
+ * Typed fields above (`author`, `keywords`, `license`, `licenseUrl`,
936
+ * `customMetadata`) are a structured view over a designated managed
937
+ * `<rdf:Description>` inside this carrier. On export the managed
938
+ * description is spliced into the preserved raw; foreign siblings and
939
+ * non-RDF content survive untouched.
940
+ *
941
+ * Spec: SVG 2 §5.8.
942
+ */
943
+ rawMetadata?: string;
944
+ /**
945
+ * Lossless carrier for the inner XML of the document-level `<desc>`
946
+ * element when it contains foreign XML (SVG 2 §5.7). Mirrors
947
+ * `ShapeMetadata.rawDescription`; see there for the emit rule.
948
+ */
949
+ rawDescription?: string;
950
+ /**
951
+ * Decimal precision for coordinate values when the document is
952
+ * serialized — file save, cloud sync, undo capture, and SVG export.
953
+ * Stored on the document so collaborators stay consistent and
954
+ * round-trips are deterministic.
955
+ *
956
+ * Range 0-12. Defaults to 3 (sub-pixel precision adequate for screen
957
+ * rendering; matches SVGO's `floatPrecision` and Adobe Illustrator's
958
+ * SVG export defaults). Set higher (6-8) when authoring assets for
959
+ * high-fidelity interchange. Values above 8 carry no practical benefit
960
+ * at the coordinate ranges typical of SVG documents.
961
+ *
962
+ * Imported SVGs are NOT rounded on the way in; the first edit or save
963
+ * conforms them to this precision.
964
+ */
965
+ coordinatePrecision?: number;
966
+ }
967
+ /**
968
+ * A document-level `<script>` element. Scripts are stored as inert data
969
+ * alongside document metadata — never executed inside the editor — and
970
+ * re-emitted on export.
971
+ *
972
+ * Spec reference: SVG 2 §15.9 (The `<script>` element).
973
+ */
974
+ interface DocumentScript {
975
+ /** Internal id (guid) used for list keying inside the editor. */
976
+ id: string;
977
+ /** Preserved `id` attribute from the source SVG, if any. */
978
+ svgId?: string;
979
+ /** Whether this script has inline body text or an external href. */
980
+ source: 'inline' | 'external';
981
+ /** Script body for inline scripts. Empty for external. */
982
+ content: string;
983
+ /** URL for external scripts. */
984
+ href?: string;
985
+ /** MIME type. Defaults to 'application/ecmascript' per SVG 2. */
986
+ type: string;
987
+ /** CORS setting. */
988
+ crossorigin?: 'anonymous' | 'use-credentials';
989
+ /** async attribute (SVG 2 aligns with HTML). */
990
+ async?: boolean;
991
+ /** defer attribute (SVG 2 aligns with HTML). */
992
+ defer?: boolean;
993
+ /** Unknown/extra attributes preserved for round-trip fidelity. */
994
+ customAttrs?: Record<string, string>;
995
+ }
996
+ /**
997
+ * A document-level `<style>` block captured from the imported SVG and
998
+ * re-emitted verbatim on export.
999
+ *
1000
+ * Styles with `preserved: true` are opaque CSS blobs the editor refuses
1001
+ * to reinterpret because their matched elements live inside `<defs>`
1002
+ * subtrees (mask / clipPath / symbol / pattern) that never become canvas
1003
+ * shapes. Keeping them intact is the only way to round-trip author CSS
1004
+ * that drives mask-interior animations (e.g. `stroke-dashoffset` flow on
1005
+ * `<use>` elements inside a `<mask>`).
1006
+ *
1007
+ * Spec reference: SVG 2 §16 (The `<style>` element).
1008
+ */
1009
+ interface DocumentStyle {
1010
+ /** Internal id (guid) used for list keying inside the editor. */
1011
+ id: string;
1012
+ /** Preserved `id` attribute from the source SVG, if any. */
1013
+ svgId?: string;
1014
+ /** Raw CSS source — `@keyframes`, rules, `@media`, etc. */
1015
+ css: string;
1016
+ /** `type` attribute. Defaults to `text/css`. */
1017
+ type?: string;
1018
+ /** `media` attribute, if specified. */
1019
+ media?: string;
1020
+ /**
1021
+ * When true, this block was captured verbatim during import because
1022
+ * the editor cannot safely reinterpret its effect. Must be emitted
1023
+ * as-is on export.
1024
+ */
1025
+ preserved: boolean;
1026
+ /** Unknown/extra attributes preserved for round-trip fidelity. */
1027
+ customAttrs?: Record<string, string>;
778
1028
  }
779
1029
  /** Type of a template variable's value. */
780
1030
  type TemplateVariableType = 'string' | 'color' | 'number';
@@ -844,253 +1094,11 @@ interface Measurement {
844
1094
  }
845
1095
 
846
1096
  /**
847
- * Typed property interfaces for every node type in the scene graph.
848
- *
849
- * This is the **single source of truth** for shape property types across
850
- * the entire SVGSketch stack (editor, API worker, server renderer, etc.).
1097
+ * @svgsketch/core Serialized document types.
851
1098
  *
852
- * Each shape type declares the exact set of properties it owns.
853
- * These interfaces drive:
854
- * - Compile-time type safety on `SceneNode.get()` / `.set()` calls
855
- * - The `NodeTypePropsMap` lookup used by `SceneNode.create()`
856
- * - Schema defaults and validators in the editor's `node-schema.ts`
857
- * - Serialization format for the `.svgs` document format
858
- */
859
-
860
- interface CommonNodeProps {
861
- fillColor: string;
862
- borderColor: string;
863
- borderWidth: number;
864
- opacity: number;
865
- fillOpacity: number;
866
- strokeOpacity: number;
867
- rotation: number;
868
- skewX: number;
869
- skewY: number;
870
- customPivot: Point | null;
871
- locked: boolean;
872
- visible: boolean;
873
- fillType: string;
874
- fillGradient: unknown | null;
875
- strokeType: string;
876
- strokeGradient: unknown | null;
877
- fillRule: 'nonzero' | 'evenodd';
878
- strokeLinejoin: 'miter' | 'round' | 'bevel';
879
- strokeLinecap: 'butt' | 'round' | 'square';
880
- strokeMiterlimit: number;
881
- lineStyle: string;
882
- dashLength: number;
883
- gapLength: number;
884
- dashOffset: number;
885
- strokeDasharray: string | null;
886
- filters: unknown[];
887
- metadata: unknown | null;
888
- cssClipPath: string | null;
889
- cssMaskProperties: Record<string, string> | null;
890
- groupId: string | null;
891
- }
892
- type CornerShapeValue = 'round' | 'notch' | 'bevel' | 'scoop';
893
- interface RectangleNodeProps extends CommonNodeProps {
894
- x: number;
895
- y: number;
896
- width: number;
897
- height: number;
898
- cornerRadius: number;
899
- cornerShape: CornerShapeValue;
900
- cornerMode: 'uniform' | 'non-uniform';
901
- cornerRadiusTL: number;
902
- cornerRadiusTR: number;
903
- cornerRadiusBL: number;
904
- cornerRadiusBR: number;
905
- cornerShapeTL: CornerShapeValue;
906
- cornerShapeTR: CornerShapeValue;
907
- cornerShapeBL: CornerShapeValue;
908
- cornerShapeBR: CornerShapeValue;
909
- }
910
- type SquareNodeProps = RectangleNodeProps;
911
- interface CircleNodeProps extends CommonNodeProps {
912
- x: number;
913
- y: number;
914
- radius: number;
915
- }
916
- interface EllipseNodeProps extends CommonNodeProps {
917
- x: number;
918
- y: number;
919
- rx: number;
920
- ry: number;
921
- }
922
- type LineEndpointValue = 'none' | 'arrow' | 'open-arrow' | 'circle' | 'diamond' | 'square';
923
- interface LineNodeProps extends CommonNodeProps {
924
- x1: number;
925
- y1: number;
926
- x2: number;
927
- y2: number;
928
- startEndpoint: LineEndpointValue;
929
- endEndpoint: LineEndpointValue;
930
- }
931
- interface TextNodeProps extends CommonNodeProps {
932
- x: number;
933
- y: number;
934
- width: number;
935
- height: number;
936
- textX: number;
937
- textY: number;
938
- fontSize: number;
939
- text: string;
940
- fontFamily: string;
941
- fontWeight: string;
942
- fontStyle: string;
943
- textDecoration: Record<string, boolean>;
944
- textTransform: string;
945
- baselineShift: string;
946
- dominantBaseline: string;
947
- writingMode: string;
948
- textAnchor: string;
949
- letterSpacing: number;
950
- wordSpacing: number;
951
- lineHeight: number;
952
- inlineSize: number;
953
- overflowWrap: string;
954
- whiteSpace: string;
955
- textDirection: string;
956
- unicodeBidi: string;
957
- scaleX: number;
958
- scaleY: number;
959
- scaleAnchor: Point | null;
960
- useRichText: boolean;
961
- richTextData: unknown | null;
962
- charOffsets: {
963
- x: number;
964
- y: number;
965
- rotate: number;
966
- }[] | null;
967
- fontVariationSettings: Record<string, number>;
968
- isTextPath: boolean;
969
- textPathPoints: unknown[] | null;
970
- textPathStartOffset: number;
971
- textPathSide: 'left' | 'right';
972
- shapeInsideRef: string | null;
973
- shapePadding: number;
974
- }
975
- interface ImageNodeProps extends CommonNodeProps {
976
- x: number;
977
- y: number;
978
- width: number;
979
- height: number;
980
- href: string;
981
- originalWidth: number;
982
- originalHeight: number;
983
- preserveAspectRatio: boolean;
984
- imageOpacity: number;
985
- }
986
- interface SplineNodeProps extends CommonNodeProps {
987
- x: number;
988
- y: number;
989
- width: number;
990
- height: number;
991
- splinePoints: unknown[];
992
- splineArcParams: unknown[];
993
- splineControlBounds: {
994
- x: number;
995
- y: number;
996
- width: number;
997
- height: number;
998
- } | null;
999
- startEndpoint: LineEndpointValue;
1000
- endEndpoint: LineEndpointValue;
1001
- }
1002
- interface PolylineNodeProps extends CommonNodeProps {
1003
- x: number;
1004
- y: number;
1005
- width: number;
1006
- height: number;
1007
- polylinePoints: Point[];
1008
- polylineClosed: boolean;
1009
- }
1010
- interface PolygonBaseNodeProps extends CommonNodeProps {
1011
- cx: number;
1012
- cy: number;
1013
- radius: number;
1014
- cornerRadius: number;
1015
- shiftAngle: number;
1016
- }
1017
- interface TriangleNodeProps extends PolygonBaseNodeProps {
1018
- sides: 3;
1019
- }
1020
- interface NGonNodeProps extends PolygonBaseNodeProps {
1021
- sides: number;
1022
- }
1023
- interface StarNodeProps extends PolygonBaseNodeProps {
1024
- arms: number;
1025
- innerRadiusPercent: number;
1026
- }
1027
- interface CrossNodeProps extends PolygonBaseNodeProps {
1028
- armWidthPercent: number;
1029
- }
1030
- interface RingNodeProps extends PolygonBaseNodeProps {
1031
- innerRadiusPercent: number;
1032
- }
1033
- interface SpiralNodeProps extends PolygonBaseNodeProps {
1034
- turns: number;
1035
- thicknessPercent: number;
1036
- spiralDirection: number;
1037
- }
1038
- interface GearNodeProps extends PolygonBaseNodeProps {
1039
- teeth: number;
1040
- toothDepthPercent: number;
1041
- holeRadiusPercent: number;
1042
- }
1043
- interface ArrowNodeProps extends PolygonBaseNodeProps {
1044
- headWidthPercent: number;
1045
- headLengthPercent: number;
1046
- shaftWidthPercent: number;
1047
- }
1048
- interface SymbolInstanceNodeProps extends CommonNodeProps {
1049
- x: number;
1050
- y: number;
1051
- width: number;
1052
- height: number;
1053
- symbolId: string;
1054
- }
1055
- interface GroupNodeProps {
1056
- groupId: string | null;
1057
- }
1058
- type DocumentNodeProps = Record<string, never>;
1059
- /**
1060
- * Maps each node type string to its typed property interface.
1061
- * Used by `SceneNode.create()` for compile-time type safety.
1062
- */
1063
- interface NodeTypePropsMap {
1064
- rectangle: RectangleNodeProps;
1065
- square: SquareNodeProps;
1066
- circle: CircleNodeProps;
1067
- ellipse: EllipseNodeProps;
1068
- line: LineNodeProps;
1069
- text: TextNodeProps;
1070
- image: ImageNodeProps;
1071
- spline: SplineNodeProps;
1072
- polyline: PolylineNodeProps;
1073
- triangle: TriangleNodeProps;
1074
- ngon: NGonNodeProps;
1075
- star: StarNodeProps;
1076
- cross: CrossNodeProps;
1077
- ring: RingNodeProps;
1078
- spiral: SpiralNodeProps;
1079
- gear: GearNodeProps;
1080
- arrow: ArrowNodeProps;
1081
- 'symbol-instance': SymbolInstanceNodeProps;
1082
- group: GroupNodeProps;
1083
- document: DocumentNodeProps;
1084
- }
1085
- /** Union of all node prop types. */
1086
- type AnyNodeProps = RectangleNodeProps | SquareNodeProps | CircleNodeProps | EllipseNodeProps | LineNodeProps | TextNodeProps | ImageNodeProps | SplineNodeProps | PolylineNodeProps | TriangleNodeProps | NGonNodeProps | StarNodeProps | CrossNodeProps | RingNodeProps | SpiralNodeProps | GearNodeProps | ArrowNodeProps | SymbolInstanceNodeProps | GroupNodeProps | DocumentNodeProps;
1087
-
1088
- /**
1089
- * @svgsketch/core — Serialized document types.
1090
- *
1091
- * These types define the .svgs document format. SerializedShape and
1092
- * HistorySnapshot are the canonical data structures for persisting
1093
- * SVGSketch documents.
1099
+ * These types define the .svgs document format. SerializedShape and
1100
+ * HistorySnapshot are the canonical data structures for persisting
1101
+ * SVGSketch documents.
1094
1102
  */
1095
1103
 
1096
1104
  interface SerializedShape {
@@ -1106,6 +1114,16 @@ interface SerializedShape {
1106
1114
  rx?: number;
1107
1115
  ry?: number;
1108
1116
  cornerRadius?: number;
1117
+ cornerShape?: 'round' | 'notch' | 'bevel' | 'scoop';
1118
+ cornerMode?: 'uniform' | 'non-uniform';
1119
+ cornerRadiusTL?: number;
1120
+ cornerRadiusTR?: number;
1121
+ cornerRadiusBL?: number;
1122
+ cornerRadiusBR?: number;
1123
+ cornerShapeTL?: 'round' | 'notch' | 'bevel' | 'scoop';
1124
+ cornerShapeTR?: 'round' | 'notch' | 'bevel' | 'scoop';
1125
+ cornerShapeBL?: 'round' | 'notch' | 'bevel' | 'scoop';
1126
+ cornerShapeBR?: 'round' | 'notch' | 'bevel' | 'scoop';
1109
1127
  fontSize?: number;
1110
1128
  text?: string;
1111
1129
  fontFamily?: string;
@@ -1139,6 +1157,8 @@ interface SerializedShape {
1139
1157
  x: number;
1140
1158
  dy: number;
1141
1159
  }[];
1160
+ textLength?: number;
1161
+ lengthAdjust?: 'spacing' | 'spacingAndGlyphs';
1142
1162
  /**
1143
1163
  * Whether this text element uses the rich-text model (styled runs with
1144
1164
  * per-character formatting) versus the plain-text model. When true,
@@ -1161,6 +1181,15 @@ interface SerializedShape {
1161
1181
  borderColor?: string;
1162
1182
  borderWidth?: number | string;
1163
1183
  strokeOpacity?: number;
1184
+ /** CSS `paint-order` (SVG 2). Canonical SVG token string, e.g.
1185
+ * 'stroke fill markers'. Omitted when equivalent to default 'normal'. */
1186
+ paintOrder?: string;
1187
+ /** Marker id applied as `marker-start` (rendered `url(#id)` in SVG). */
1188
+ markerStart?: string;
1189
+ /** Marker id applied as `marker-mid`. */
1190
+ markerMid?: string;
1191
+ /** Marker id applied as `marker-end`. */
1192
+ markerEnd?: string;
1164
1193
  cx?: number;
1165
1194
  cy?: number;
1166
1195
  sides?: number;
@@ -1212,11 +1241,69 @@ interface SerializedShape {
1212
1241
  * overrides the SVG visibility attribute.
1213
1242
  */
1214
1243
  visibility?: 'visible' | 'hidden' | 'collapse';
1244
+ /**
1245
+ * Structural role of the shape in the exported SVG.
1246
+ * - `'normal'` / absent — rendered inline in document order (default).
1247
+ * - `'motionOnly'` — emitted inside `<defs>` as an `<mpath>` reference
1248
+ * target; not rendered. Used for `<path>` elements imported from
1249
+ * `<defs>` that serve only as animateMotion paths.
1250
+ * @see https://svgwg.org/specs/animations/#MPathElement
1251
+ */
1252
+ displayMode?: 'normal' | 'motionOnly';
1215
1253
  fillType?: FillType;
1254
+ /**
1255
+ * @deprecated from v2 for linear/radial kinds — canonical storage is a
1256
+ * `LinearGradientLibraryDef` / `RadialGradientLibraryDef` keyed by
1257
+ * `fillLibraryId`. Still used for `PatternFill` until Phase 3 promotes
1258
+ * patterns, and retained as a runtime shadow copy of the library def so
1259
+ * legacy readers keep working through the transition.
1260
+ */
1216
1261
  fillGradient?: LinearGradient | RadialGradient | PatternFill;
1262
+ /**
1263
+ * Reference into the unified library (v2+). When `fillType` is
1264
+ * `'linear-gradient'` or `'radial-gradient'`, `fillLibraryId` points at
1265
+ * the canonical `LinearGradientLibraryDef` / `RadialGradientLibraryDef`.
1266
+ * For `'pattern'` this field is unused in v2 (patterns still live on
1267
+ * `fillGradient`) and will be populated in Phase 3. For `'solid'` /
1268
+ * `'none'` this field is ignored.
1269
+ */
1270
+ fillLibraryId?: string;
1217
1271
  strokeType?: StrokeType;
1272
+ /** @deprecated see `fillGradient`. */
1218
1273
  strokeGradient?: LinearGradient | RadialGradient | PatternFill;
1274
+ /** See `fillLibraryId`. */
1275
+ strokeLibraryId?: string;
1276
+ /**
1277
+ * @deprecated from v2 — canonical storage is a `FilterLibraryDef` keyed
1278
+ * by entries in `filterLibraryIds`. Retained as a runtime shadow copy of
1279
+ * the library def so legacy readers and the editor's filter-manager keep
1280
+ * working through the transition.
1281
+ */
1219
1282
  filters?: ShapeFilter[];
1283
+ /**
1284
+ * Ordered list of library filter-def ids applied to this shape. On
1285
+ * export each id emits `url(#id)`; the `filter` CSS property chains the
1286
+ * list serially (CSS Filter Effects §Filter Property). Today the list
1287
+ * always has length 0 or 1 — the editor wraps a shape's primitive chain
1288
+ * in a single compound `FilterLibraryDef`. Future phases may split
1289
+ * independent filter chains into multiple library entries.
1290
+ */
1291
+ filterLibraryIds?: string[];
1292
+ /** @deprecated v2 — scope fields live on `FilterLibraryDef` from Phase 4 on. */
1293
+ filterColorInterpolation?: 'auto' | 'sRGB' | 'linearRGB';
1294
+ /** @deprecated v2 — see `filterColorInterpolation`. */
1295
+ filterUnits?: 'userSpaceOnUse' | 'objectBoundingBox';
1296
+ /** @deprecated v2 — see `filterColorInterpolation`. */
1297
+ primitiveUnits?: 'userSpaceOnUse' | 'objectBoundingBox';
1298
+ /** @deprecated v2 — lives on `FilterLibraryDef` from Phase 4 on. */
1299
+ filterX?: string;
1300
+ /** @deprecated v2 — see `filterX`. */
1301
+ filterY?: string;
1302
+ /** @deprecated v2 — see `filterX`. */
1303
+ filterWidth?: string;
1304
+ /** @deprecated v2 — see `filterX`. */
1305
+ filterHeight?: string;
1306
+ rawTransform?: string;
1220
1307
  splinePoints?: SplinePoint[];
1221
1308
  splineCurveType?: SplineCurveType;
1222
1309
  splineClosed?: boolean;
@@ -1229,6 +1316,40 @@ interface SerializedShape {
1229
1316
  originalHeight?: number;
1230
1317
  preserveAspectRatio?: boolean;
1231
1318
  imageOpacity?: number;
1319
+ mediaKind?: 'audio' | 'video';
1320
+ mediaMimeType?: string;
1321
+ naturalDuration?: number;
1322
+ begin?: number;
1323
+ trimStart?: number;
1324
+ trimEnd?: number;
1325
+ volume?: number;
1326
+ muted?: boolean;
1327
+ loop?: boolean;
1328
+ playbackRate?: number;
1329
+ mediaOpacity?: number;
1330
+ /** Auto-generated volume ramp length at clip start (seconds). */
1331
+ fadeInDuration?: number;
1332
+ /** Auto-generated volume ramp length at clip end (seconds). */
1333
+ fadeOutDuration?: number;
1334
+ /** First-frame thumbnail (data URI or /api/image-assets URL). Video only. */
1335
+ posterHref?: string;
1336
+ /** Crop rectangle in source pixels. Video only. */
1337
+ sourceRect?: {
1338
+ x: number;
1339
+ y: number;
1340
+ width: number;
1341
+ height: number;
1342
+ };
1343
+ /**
1344
+ * BCP 47 language tag matched against the user agent's language
1345
+ * preferences via SVG's `systemLanguage` conditional-processing
1346
+ * attribute. Meaningful when a `<switch>` wraps multiple
1347
+ * localized media alternatives — the UA picks the foreignObject
1348
+ * whose language matches. No editor UI yet; preserved on
1349
+ * import/export for forward compatibility with translated
1350
+ * soundtracks / captioned video versions.
1351
+ */
1352
+ systemLanguage?: string;
1232
1353
  shapeInsideRef?: string;
1233
1354
  shapePadding?: number;
1234
1355
  isTextPath?: boolean;
@@ -1261,6 +1382,21 @@ interface SerializedShape {
1261
1382
  * variant (`def.shapes`). Only meaningful on `symbol-instance` shapes.
1262
1383
  */
1263
1384
  variantKey?: string;
1385
+ /**
1386
+ * Id of the canvas shape this `shape-reference` (Linked Copy) targets.
1387
+ * A Linked Copy renders as a live clone of another top-level shape and
1388
+ * exports to `<use href="#targetShapeId">` per SVG 2 §5.5. Only
1389
+ * meaningful on shapes of type `shape-reference`.
1390
+ */
1391
+ targetShapeId?: string;
1392
+ /**
1393
+ * For `shape-reference` shapes: x/y offset from the source's reference
1394
+ * point. Maps to the `x`/`y` on the exported `<use>` per SVG 2 §5.5.2
1395
+ * (an additional translate applied to the use element), so the instance
1396
+ * tracks the source's position natively.
1397
+ */
1398
+ offsetX?: number;
1399
+ offsetY?: number;
1264
1400
  /**
1265
1401
  * Map of geometry-property name → CSS custom-property name (without
1266
1402
  * the leading `--`) the property is bound to.
@@ -1276,6 +1412,40 @@ interface SerializedShape {
1276
1412
  * when serialized to standalone SVG.
1277
1413
  */
1278
1414
  bindings?: Record<string, string>;
1415
+ /** User-placed custom connection anchors. Derived anchors are not persisted. */
1416
+ connectionPoints?: ConnectionPoint[];
1417
+ /** Connector shape: reference to the source shape + anchor it attaches to. */
1418
+ sourceRef?: {
1419
+ shapeId: string;
1420
+ anchorId: string;
1421
+ } | null;
1422
+ /** Connector shape: reference to the target shape + anchor it attaches to. */
1423
+ targetRef?: {
1424
+ shapeId: string;
1425
+ anchorId: string;
1426
+ } | null;
1427
+ /** Connector shape: cached absolute source point (recomputed when source moves). */
1428
+ sourcePoint?: Point;
1429
+ /** Connector shape: cached absolute target point. */
1430
+ targetPoint?: Point;
1431
+ /** Connector shape: interior waypoints for orthogonal routing. */
1432
+ waypoints?: Point[];
1433
+ /** Connector shape: path routing algorithm. */
1434
+ routingMode?: 'straight' | 'orthogonal' | 'rounded-ortho' | 'curved';
1435
+ /** Connector shape: in-path label (double-click to edit). */
1436
+ label?: string;
1437
+ /** Connector shape: label position along the path (0–1). */
1438
+ labelPosition?: number;
1439
+ /** Connector shape: perpendicular offset of the label. */
1440
+ labelOffset?: number;
1441
+ /** Connector shape: stroke style to Mermaid edge mapping. */
1442
+ mermaidEdgeStyle?: 'solid' | 'thick' | 'dotted';
1443
+ /** Parallelogram/trapezoid slant amount as a % of width. */
1444
+ slantPercent?: number;
1445
+ /** Trapezoid top width as a % of the bottom width (0–100). */
1446
+ topWidthPercent?: number;
1447
+ /** Document shape: wave amplitude as a % of height. */
1448
+ waveAmplitudePercent?: number;
1279
1449
  };
1280
1450
  }
1281
1451
  type SerializedViewbox = Viewbox;
@@ -1300,7 +1470,7 @@ type SerializedViewbox = Viewbox;
1300
1470
  * (version - 1) snapshots into the new format.
1301
1471
  * c. Register it in the migrateSnapshot() chain.
1302
1472
  */
1303
- declare const CURRENT_SCHEMA_VERSION = 1;
1473
+ declare const CURRENT_SCHEMA_VERSION = 2;
1304
1474
  interface HistorySnapshot {
1305
1475
  /**
1306
1476
  * Schema version — written on save, read on load to trigger migrations.
@@ -1317,164 +1487,577 @@ interface HistorySnapshot {
1317
1487
  clipMaskGroups?: SerializedClipMaskGroup[];
1318
1488
  /** Document-level metadata (title, description, author, etc.) */
1319
1489
  documentMetadata?: DocumentMetadata;
1490
+ /** Document-level `<script>` elements (SVG 2 §15.9). */
1491
+ documentScripts?: DocumentScript[];
1492
+ /**
1493
+ * Document-level `<style>` blocks captured from the source SVG and
1494
+ * re-emitted verbatim on export. Used for CSS whose effect targets
1495
+ * def-scoped content (mask / clipPath / symbol interiors) that the
1496
+ * editor cannot translate into AnimationTracks.
1497
+ */
1498
+ documentStyles?: DocumentStyle[];
1320
1499
  /** Template variable definitions with defaults. */
1321
1500
  templateVariables?: TemplateVariable[];
1322
1501
  /** Animation timeline (tracks, keyframes, easing). */
1323
1502
  animationTimeline?: SerializedAnimationTimeline;
1324
- /** User-defined custom patterns stored in the document. */
1503
+ /**
1504
+ * Unified library of reusable `<defs>` content. Authoritative from v2 onward
1505
+ * for symbols and markers (and, as later phases land, gradients, patterns,
1506
+ * and filters too). Built-in markers are reconstituted at load time by
1507
+ * MarkerManager and are NOT persisted here — only user-authored defs are.
1508
+ */
1509
+ library?: LibraryDef[];
1510
+ /** @deprecated v2 — use `library`. Read-only: v1 docs migrate into `library`. */
1325
1511
  customPatterns?: CustomPatternDef[];
1326
- /** Symbol definitions (reusable component templates). */
1512
+ /** @deprecated v2 use `library`. Read-only: v1 docs migrate into `library`. */
1327
1513
  symbols?: SerializedSymbolDef[];
1514
+ /** @deprecated v2 — use `library`. Read-only: v1 docs migrate into `library`. */
1515
+ markers?: SerializedMarkerDef[];
1516
+ }
1517
+ /**
1518
+ * A variant axis on a component symbol. Each axis has a name (e.g.
1519
+ * `state`, `size`, `theme`) and an ordered list of allowed values
1520
+ * (e.g. `[default, hover, pressed]`). The default value is always
1521
+ * the first entry in `values`.
1522
+ */
1523
+ interface SerializedVariantAxis {
1524
+ name: string;
1525
+ values: string[];
1526
+ }
1527
+ /**
1528
+ * A reusable symbol definition. Contains the shapes that make up the
1529
+ * symbol template, plus metadata for the symbols panel.
1530
+ *
1531
+ * **Variants:** when `variantAxes` is present, the symbol carries
1532
+ * multiple alternative shape arrays keyed by variant combination
1533
+ * (e.g. `state=hover,size=md`). The base `shapes` field is always
1534
+ * the **default variant** — the combination where every axis is at
1535
+ * its first value. Other variants live in `variants[variantKey]`.
1536
+ * Variant resolution falls back to `shapes` whenever `variantKey`
1537
+ * is missing or empty.
1538
+ */
1539
+ type SerializedSymbolDef = SymbolLibraryDef;
1540
+ /**
1541
+ * A reusable `<marker>` definition (SVG 2 §11.6). Markers are vertex-attached
1542
+ * graphics — arrowheads, vertex dots, decorations — referenced via
1543
+ * `marker-start` / `marker-mid` / `marker-end` attributes on stroked shapes.
1544
+ *
1545
+ * The browser handles per-vertex positioning, scaling (via `markerUnits`),
1546
+ * and orientation (via `orient`, including tangent-aware `auto` mode on
1547
+ * curved paths). MarkerManager only maintains the DOM `<defs>` entries in
1548
+ * sync with this serialized state.
1549
+ *
1550
+ * Simpler than `SerializedSymbolDef` — markers have no variants, no instance
1551
+ * overrides, and no placed instances (they attach via attribute references).
1552
+ */
1553
+ type SerializedMarkerDef = MarkerLibraryDef;
1554
+ interface SerializedGroup {
1555
+ id: string;
1556
+ parentId: string | null;
1557
+ /** CSS transform-origin value (e.g. "50px 50px") for group animations */
1558
+ transformOrigin?: string;
1559
+ /**
1560
+ * Zero-based position of this group among its parent container's
1561
+ * children (including both sibling groups and sibling shape nodes).
1562
+ * Used during restoration to correctly interleave groups and shapes
1563
+ * so that SVG document order (painting order) is preserved.
1564
+ */
1565
+ siblingIndex?: number;
1566
+ /** Plugin that owns this group (e.g. 'svgsketch-charts') */
1567
+ pluginId?: string;
1568
+ /** Serialized plugin-specific state (JSON string) */
1569
+ pluginData?: string;
1570
+ /** Additional custom data-* attributes set by plugins */
1571
+ attributes?: Record<string, string>;
1572
+ fill?: string;
1573
+ fillOpacity?: string;
1574
+ strokeOpacity?: string;
1575
+ opacity?: string;
1576
+ filter?: string;
1577
+ cssFilter?: string;
1578
+ mixBlendMode?: string;
1579
+ clipPath?: string;
1580
+ mask?: string;
1581
+ /**
1582
+ * Lossless carrier for any `<metadata>` elements that appeared as
1583
+ * children of this group's source `<g>` element. Same semantics as
1584
+ * `ShapeMetadata.rawMetadata` / `DocumentMetadata.rawMetadata` — see
1585
+ * SVG 2 §5.8 (`<metadata>` can appear on any container).
1586
+ */
1587
+ rawMetadata?: string;
1588
+ }
1589
+ /** Serialized clip or mask group */
1590
+ interface SerializedClipMaskGroup {
1591
+ id: string;
1592
+ type: 'clip' | 'mask';
1593
+ /**
1594
+ * @deprecated Use `clipShapeIds` instead. Kept for backward compatibility
1595
+ * when reading older documents that used a single clip/mask shape.
1596
+ */
1597
+ clipShapeId?: string;
1598
+ /** IDs of shape(s) that form the clip/mask definition. */
1599
+ clipShapeIds: string[];
1600
+ /** IDs of the content shapes being clipped/masked. */
1601
+ contentShapeIds: string[];
1602
+ parentId: string | null;
1603
+ /**
1604
+ * Position of the clip/mask group among its parent container's children,
1605
+ * so that SVG document order (painting order) is preserved across
1606
+ * save / restore.
1607
+ */
1608
+ siblingIndex?: number;
1609
+ /**
1610
+ * Coordinate system for the `<mask>` bounds (`x`, `y`, `width`, `height`).
1611
+ * @see CSS Masking Module §9.1 — `maskUnits`
1612
+ * @default 'objectBoundingBox'
1613
+ */
1614
+ maskUnits?: 'userSpaceOnUse' | 'objectBoundingBox';
1615
+ /**
1616
+ * Coordinate system for the **contents** of a `<mask>`.
1617
+ * @see CSS Masking Module §9.1 — `maskContentUnits`
1618
+ * @default 'userSpaceOnUse'
1619
+ */
1620
+ maskContentUnits?: 'userSpaceOnUse' | 'objectBoundingBox';
1621
+ /**
1622
+ * Coordinate system for the contents of a `<clipPath>`.
1623
+ * @see CSS Masking Module §6.1 — `clipPathUnits`
1624
+ * @default 'userSpaceOnUse'
1625
+ */
1626
+ clipPathUnits?: 'userSpaceOnUse' | 'objectBoundingBox';
1627
+ /**
1628
+ * Explicit mask bounds (`x`, `y`, `width`, `height`).
1629
+ * When omitted the browser defaults apply (−10% / 120%).
1630
+ */
1631
+ maskBounds?: {
1632
+ x: string;
1633
+ y: string;
1634
+ width: string;
1635
+ height: string;
1636
+ };
1637
+ /**
1638
+ * Whether the mask uses luminance or alpha channel.
1639
+ * @see CSS Masking Module §9.2 — `mask-type`
1640
+ * @default 'luminance'
1641
+ */
1642
+ maskType?: 'luminance' | 'alpha';
1643
+ /**
1644
+ * Raw SVG markup for imported mask/clip definitions that cannot be
1645
+ * decomposed into editor `Shape` objects (e.g. multi-element masks
1646
+ * with gradients, patterns, or nested groups). When present the
1647
+ * editor preserves the original `<mask>` / `<clipPath>` verbatim
1648
+ * and `clipShapeIds` may be empty.
1649
+ */
1650
+ rawDefinition?: string;
1651
+ }
1652
+
1653
+ /**
1654
+ * @svgsketch/core — Library (defs) types.
1655
+ *
1656
+ * A `LibraryDef` is any reusable element that lives in an SVG `<defs>` and is
1657
+ * referenced from shapes via `url(#id)`. The library is the authoritative store
1658
+ * for these definitions; shapes carry only ID references.
1659
+ *
1660
+ * Kinds covered here:
1661
+ * - symbol (SVG 2 §5.5, referenced by `<use href="#id">`)
1662
+ * - marker (SVG 2 §13.7, referenced by `marker-start/-mid/-end`)
1663
+ * - linear-gradient / radial-gradient (SVG 2 §14, referenced by fill/stroke)
1664
+ * - pattern (SVG 2 §14.3, referenced by fill/stroke)
1665
+ * - filter (CSS Filter Effects §Filter Property, referenced by `filter`)
1666
+ *
1667
+ * ClipPath, mask, and <style> are deliberately out of scope for this pass.
1668
+ */
1669
+
1670
+ /** Discriminator for the `LibraryDef` union. */
1671
+ type LibraryKind = 'symbol' | 'marker' | 'linear-gradient' | 'radial-gradient' | 'pattern' | 'filter';
1672
+ /**
1673
+ * Common fields shared by every kind of library def. ID prefix convention:
1674
+ * sym- / mkr- / grd- / pat- / flt-
1675
+ */
1676
+ interface LibraryDefBase {
1677
+ /** Unique identifier, prefixed by kind (see convention above). */
1678
+ id: string;
1679
+ /** Kind discriminator — required on every def. */
1680
+ kind: LibraryKind;
1681
+ /** Human-readable name shown in the library panel. */
1682
+ name: string;
1683
+ /** Base64 data-URI thumbnail, rendered by the kind's thumbnail generator. */
1684
+ thumbnail?: string;
1685
+ /**
1686
+ * Editor-shipped seed that isn't deletable, renamable, or user-editable
1687
+ * (today: built-in markers). Only set when the kind actually has built-ins.
1688
+ */
1689
+ builtIn?: boolean;
1690
+ /**
1691
+ * Original id from the imported source SVG. Runtime `id` is always a fresh
1692
+ * GUID; `sourceId` lets export restore human-friendly ids when uncontested.
1693
+ */
1694
+ sourceId?: string;
1695
+ }
1696
+ /**
1697
+ * Reusable component template. Shapes inside are edited via symbol isolation
1698
+ * mode and placed onto the canvas as `SymbolInstance` shapes (which emit as
1699
+ * `<use href="#id">` on export — SVG 2 §5.5).
1700
+ */
1701
+ interface SymbolLibraryDef extends LibraryDefBase {
1702
+ kind: 'symbol';
1703
+ viewBox: string;
1704
+ /**
1705
+ * Default variant shapes. When `variantAxes` is present this represents the
1706
+ * variant where every axis is at its first value.
1707
+ */
1708
+ shapes: SerializedShape[];
1709
+ groups?: SerializedGroup[];
1710
+ /**
1711
+ * Ordered list of variant axes. The order is stable so variant keys can be
1712
+ * canonicalized as `axis1=val1,axis2=val2`.
1713
+ */
1714
+ variantAxes?: SerializedVariantAxis[];
1715
+ /** Non-default variant shape arrays keyed by canonical axis combination. */
1716
+ variants?: Record<string, SerializedShape[]>;
1717
+ /** Per-variant thumbnails keyed by canonical variant string. */
1718
+ variantThumbnails?: Record<string, string>;
1719
+ }
1720
+ /**
1721
+ * Vertex-attached graphic (arrowheads, dots, decorations). Referenced via
1722
+ * `marker-start` / `marker-mid` / `marker-end` on stroked shapes — SVG 2
1723
+ * §13.7.2 specifies each attribute accepts a single `<marker-ref>`.
1724
+ */
1725
+ interface MarkerLibraryDef extends LibraryDefBase {
1726
+ kind: 'marker';
1727
+ viewBox: string;
1728
+ /** X reference point — where the marker's tip aligns with the host vertex. */
1729
+ refX: number;
1730
+ refY: number;
1731
+ markerWidth: number;
1732
+ markerHeight: number;
1733
+ /**
1734
+ * `strokeWidth` scales with the host's stroke; `userSpaceOnUse` renders at
1735
+ * fixed size regardless of stroke.
1736
+ */
1737
+ markerUnits: 'strokeWidth' | 'userSpaceOnUse';
1738
+ /**
1739
+ * `auto` rotates to match path tangent; `auto-start-reverse` reverses the
1740
+ * start marker; a number is a fixed rotation in degrees.
1741
+ */
1742
+ orient: 'auto' | 'auto-start-reverse' | number;
1743
+ /**
1744
+ * Inner geometry (authoritative for user markers). Built-ins render from
1745
+ * the descriptor registry and carry `shapes: []`.
1746
+ */
1747
+ shapes: SerializedShape[];
1748
+ groups?: SerializedGroup[];
1749
+ /**
1750
+ * Animation tracks scoped to the marker's inner shapes. Emitted as SMIL
1751
+ * `<animate>` children of the exported `<marker>`.
1752
+ */
1753
+ animations?: SerializedAnimationTimeline['tracks'];
1754
+ }
1755
+ /**
1756
+ * Linear gradient def (SVG 2 §14.6). Referenced via `fill="url(#id)"` or
1757
+ * `stroke="url(#id)"`. Inner geometry is the existing `LinearGradient` shape,
1758
+ * minus the fields that live on `LibraryDefBase` (`id`, `sourceId`).
1759
+ */
1760
+ interface LinearGradientLibraryDef extends LibraryDefBase {
1761
+ kind: 'linear-gradient';
1762
+ gradient: Omit<LinearGradient, 'id' | 'sourceId'>;
1763
+ }
1764
+ /** Radial gradient def (SVG 2 §14.7). See `LinearGradientLibraryDef`. */
1765
+ interface RadialGradientLibraryDef extends LibraryDefBase {
1766
+ kind: 'radial-gradient';
1767
+ gradient: Omit<RadialGradient, 'id' | 'sourceId'>;
1768
+ }
1769
+ /**
1770
+ * Pattern def (SVG 2 §14.3). Subsumes today's `CustomPatternDef` (user-created
1771
+ * reusable tiles) and the per-shape `PatternFill` — both collapse into one
1772
+ * persisted representation keyed by `LibraryDefBase.id`.
1773
+ *
1774
+ * `customPatternId` is stripped because once the pattern IS the library entry,
1775
+ * the back-reference is redundant.
1776
+ */
1777
+ interface PatternLibraryDef extends LibraryDefBase {
1778
+ kind: 'pattern';
1779
+ pattern: Omit<PatternFill, 'id' | 'sourceId' | 'customPatternId'>;
1780
+ }
1781
+ /**
1782
+ * Filter def (CSS Filter Effects). Referenced via `filter="url(#id)"`. When a
1783
+ * shape chains multiple filters, the CSS `filter` property accepts a
1784
+ * space-separated list (`<filter-value-list>`) and composes them serially —
1785
+ * each url()'s input is the previous url()'s output.
1786
+ *
1787
+ * Filter region and unit attributes live on `<filter>` itself (per the spec),
1788
+ * so they move here from the per-shape state.
1789
+ */
1790
+ interface FilterLibraryDef extends LibraryDefBase {
1791
+ kind: 'filter';
1792
+ /** Ordered primitive chain (same editable model used per-shape today). */
1793
+ filters: ShapeFilter[];
1794
+ colorInterpolation?: 'auto' | 'sRGB' | 'linearRGB';
1795
+ filterUnits?: 'userSpaceOnUse' | 'objectBoundingBox';
1796
+ primitiveUnits?: 'userSpaceOnUse' | 'objectBoundingBox';
1797
+ x?: string;
1798
+ y?: string;
1799
+ width?: string;
1800
+ height?: string;
1801
+ }
1802
+ /** Discriminated union over `kind`. */
1803
+ type LibraryDef = SymbolLibraryDef | MarkerLibraryDef | LinearGradientLibraryDef | RadialGradientLibraryDef | PatternLibraryDef | FilterLibraryDef;
1804
+ /**
1805
+ * Narrow helper — picks the library-def type for a given kind. Useful for
1806
+ * `getByKind('symbol')` return types.
1807
+ */
1808
+ type LibraryDefOfKind<K extends LibraryKind> = Extract<LibraryDef, {
1809
+ kind: K;
1810
+ }>;
1811
+
1812
+ /**
1813
+ * Typed property interfaces for every node type in the scene graph.
1814
+ *
1815
+ * This is the **single source of truth** for shape property types across
1816
+ * the entire SVGSketch stack (editor, API worker, server renderer, etc.).
1817
+ *
1818
+ * Each shape type declares the exact set of properties it owns.
1819
+ * These interfaces drive:
1820
+ * - Compile-time type safety on `SceneNode.get()` / `.set()` calls
1821
+ * - The `NodeTypePropsMap` lookup used by `SceneNode.create()`
1822
+ * - Schema defaults and validators in the editor's `node-schema.ts`
1823
+ * - Serialization format for the `.svgs` document format
1824
+ */
1825
+
1826
+ interface CommonNodeProps {
1827
+ fillColor: string;
1828
+ borderColor: string;
1829
+ borderWidth: number;
1830
+ opacity: number;
1831
+ fillOpacity: number;
1832
+ strokeOpacity: number;
1833
+ rotation: number;
1834
+ skewX: number;
1835
+ skewY: number;
1836
+ customPivot: Point | null;
1837
+ locked: boolean;
1838
+ visible: boolean;
1839
+ fillType: string;
1840
+ fillGradient: unknown | null;
1841
+ strokeType: string;
1842
+ strokeGradient: unknown | null;
1843
+ fillRule: 'nonzero' | 'evenodd';
1844
+ strokeLinejoin: 'miter' | 'round' | 'bevel';
1845
+ strokeLinecap: 'butt' | 'round' | 'square';
1846
+ strokeMiterlimit: number;
1847
+ lineStyle: string;
1848
+ dashLength: number;
1849
+ gapLength: number;
1850
+ dashOffset: number;
1851
+ strokeDasharray: string | null;
1852
+ filters: unknown[];
1853
+ filterColorInterpolation: 'auto' | 'sRGB' | 'linearRGB' | null;
1854
+ filterUnits: 'userSpaceOnUse' | 'objectBoundingBox' | null;
1855
+ primitiveUnits: 'userSpaceOnUse' | 'objectBoundingBox' | null;
1856
+ filterX: string | null;
1857
+ filterY: string | null;
1858
+ filterWidth: string | null;
1859
+ filterHeight: string | null;
1860
+ rawTransform: string | null;
1861
+ metadata: unknown | null;
1862
+ cssClipPath: string | null;
1863
+ cssMaskProperties: Record<string, string> | null;
1864
+ groupId: string | null;
1865
+ }
1866
+ type CornerShapeValue = 'round' | 'notch' | 'bevel' | 'scoop';
1867
+ interface RectangleNodeProps extends CommonNodeProps {
1868
+ x: number;
1869
+ y: number;
1870
+ width: number;
1871
+ height: number;
1872
+ cornerRadius: number;
1873
+ cornerShape: CornerShapeValue;
1874
+ cornerMode: 'uniform' | 'non-uniform';
1875
+ cornerRadiusTL: number;
1876
+ cornerRadiusTR: number;
1877
+ cornerRadiusBL: number;
1878
+ cornerRadiusBR: number;
1879
+ cornerShapeTL: CornerShapeValue;
1880
+ cornerShapeTR: CornerShapeValue;
1881
+ cornerShapeBL: CornerShapeValue;
1882
+ cornerShapeBR: CornerShapeValue;
1883
+ }
1884
+ type SquareNodeProps = RectangleNodeProps;
1885
+ interface CircleNodeProps extends CommonNodeProps {
1886
+ x: number;
1887
+ y: number;
1888
+ radius: number;
1889
+ }
1890
+ interface EllipseNodeProps extends CommonNodeProps {
1891
+ x: number;
1892
+ y: number;
1893
+ rx: number;
1894
+ ry: number;
1895
+ }
1896
+ type LineEndpointValue = 'none' | 'arrow' | 'open-arrow' | 'circle' | 'diamond' | 'square';
1897
+ interface LineNodeProps extends CommonNodeProps {
1898
+ x1: number;
1899
+ y1: number;
1900
+ x2: number;
1901
+ y2: number;
1902
+ startEndpoint: LineEndpointValue;
1903
+ endEndpoint: LineEndpointValue;
1904
+ }
1905
+ interface TextNodeProps extends CommonNodeProps {
1906
+ x: number;
1907
+ y: number;
1908
+ width: number;
1909
+ height: number;
1910
+ textX: number;
1911
+ textY: number;
1912
+ fontSize: number;
1913
+ text: string;
1914
+ fontFamily: string;
1915
+ fontWeight: string;
1916
+ fontStyle: string;
1917
+ textDecoration: Record<string, boolean>;
1918
+ textTransform: string;
1919
+ baselineShift: string;
1920
+ dominantBaseline: string;
1921
+ writingMode: string;
1922
+ textAnchor: string;
1923
+ letterSpacing: number;
1924
+ wordSpacing: number;
1925
+ lineHeight: number;
1926
+ inlineSize: number;
1927
+ overflowWrap: string;
1928
+ whiteSpace: string;
1929
+ textDirection: string;
1930
+ unicodeBidi: string;
1931
+ scaleX: number;
1932
+ scaleY: number;
1933
+ scaleAnchor: Point | null;
1934
+ useRichText: boolean;
1935
+ richTextData: unknown | null;
1936
+ charOffsets: {
1937
+ x: number;
1938
+ y: number;
1939
+ rotate: number;
1940
+ }[] | null;
1941
+ fontVariationSettings: Record<string, number>;
1942
+ isTextPath: boolean;
1943
+ textPathPoints: unknown[] | null;
1944
+ textPathStartOffset: number;
1945
+ textPathSide: 'left' | 'right';
1946
+ shapeInsideRef: string | null;
1947
+ shapePadding: number;
1948
+ }
1949
+ interface ImageNodeProps extends CommonNodeProps {
1950
+ x: number;
1951
+ y: number;
1952
+ width: number;
1953
+ height: number;
1954
+ href: string;
1955
+ originalWidth: number;
1956
+ originalHeight: number;
1957
+ preserveAspectRatio: boolean;
1958
+ imageOpacity: number;
1959
+ }
1960
+ interface SplineNodeProps extends CommonNodeProps {
1961
+ x: number;
1962
+ y: number;
1963
+ width: number;
1964
+ height: number;
1965
+ splinePoints: unknown[];
1966
+ splineArcParams: unknown[];
1967
+ splineControlBounds: {
1968
+ x: number;
1969
+ y: number;
1970
+ width: number;
1971
+ height: number;
1972
+ } | null;
1973
+ startEndpoint: LineEndpointValue;
1974
+ endEndpoint: LineEndpointValue;
1975
+ }
1976
+ interface PolylineNodeProps extends CommonNodeProps {
1977
+ x: number;
1978
+ y: number;
1979
+ width: number;
1980
+ height: number;
1981
+ polylinePoints: Point[];
1982
+ polylineClosed: boolean;
1983
+ }
1984
+ interface PolygonBaseNodeProps extends CommonNodeProps {
1985
+ cx: number;
1986
+ cy: number;
1987
+ radius: number;
1988
+ cornerRadius: number;
1989
+ shiftAngle: number;
1990
+ }
1991
+ interface TriangleNodeProps extends PolygonBaseNodeProps {
1992
+ sides: 3;
1993
+ }
1994
+ interface NGonNodeProps extends PolygonBaseNodeProps {
1995
+ sides: number;
1996
+ }
1997
+ interface StarNodeProps extends PolygonBaseNodeProps {
1998
+ arms: number;
1999
+ innerRadiusPercent: number;
2000
+ }
2001
+ interface CrossNodeProps extends PolygonBaseNodeProps {
2002
+ armWidthPercent: number;
2003
+ }
2004
+ interface RingNodeProps extends PolygonBaseNodeProps {
2005
+ innerRadiusPercent: number;
1328
2006
  }
1329
- /**
1330
- * A variant axis on a component symbol. Each axis has a name (e.g.
1331
- * `state`, `size`, `theme`) and an ordered list of allowed values
1332
- * (e.g. `[default, hover, pressed]`). The default value is always
1333
- * the first entry in `values`.
1334
- */
1335
- interface SerializedVariantAxis {
1336
- name: string;
1337
- values: string[];
2007
+ interface SpiralNodeProps extends PolygonBaseNodeProps {
2008
+ turns: number;
2009
+ thicknessPercent: number;
2010
+ spiralDirection: number;
1338
2011
  }
1339
- /**
1340
- * A reusable symbol definition. Contains the shapes that make up the
1341
- * symbol template, plus metadata for the symbols panel.
1342
- *
1343
- * **Variants:** when `variantAxes` is present, the symbol carries
1344
- * multiple alternative shape arrays keyed by variant combination
1345
- * (e.g. `state=hover,size=md`). The base `shapes` field is always
1346
- * the **default variant** — the combination where every axis is at
1347
- * its first value. Other variants live in `variants[variantKey]`.
1348
- * Variant resolution falls back to `shapes` whenever `variantKey`
1349
- * is missing or empty.
1350
- */
1351
- interface SerializedSymbolDef {
1352
- /** Unique identifier for this symbol definition. */
1353
- id: string;
1354
- /** Human-readable name shown in the symbols panel. */
1355
- name: string;
1356
- /** SVG viewBox string ("minX minY width height"). */
1357
- viewBox: string;
1358
- /**
1359
- * Default variant shapes. When `variantAxes` is present, this represents
1360
- * the variant where every axis is at its first value.
1361
- */
1362
- shapes: SerializedShape[];
1363
- /** Groups within the symbol. */
1364
- groups?: SerializedGroup[];
1365
- /** Base64 data-URI thumbnail for the symbols panel. */
1366
- thumbnail?: string;
1367
- /**
1368
- * Ordered list of variant axes available on this symbol. The order is
1369
- * stable so that variant keys can be canonicalized as
1370
- * `axis1=val1,axis2=val2`.
1371
- */
1372
- variantAxes?: SerializedVariantAxis[];
1373
- /**
1374
- * Non-default variant shape arrays keyed by canonical axis combination
1375
- * string (e.g. `state=hover,size=md`). Missing keys fall back to the
1376
- * base `shapes` array.
1377
- */
1378
- variants?: Record<string, SerializedShape[]>;
1379
- /**
1380
- * Per-variant thumbnails as base64 data URIs, keyed by canonical
1381
- * variant combination string. The empty string `""` keys the default
1382
- * variant (which also lives in `thumbnail` for backwards compatibility).
1383
- * Used by the variant matrix view to show real previews of each cell.
1384
- */
1385
- variantThumbnails?: Record<string, string>;
2012
+ interface GearNodeProps extends PolygonBaseNodeProps {
2013
+ teeth: number;
2014
+ toothDepthPercent: number;
2015
+ holeRadiusPercent: number;
1386
2016
  }
1387
- interface SerializedGroup {
1388
- id: string;
1389
- parentId: string | null;
1390
- /** CSS transform-origin value (e.g. "50px 50px") for group animations */
1391
- transformOrigin?: string;
1392
- /**
1393
- * Zero-based position of this group among its parent container's
1394
- * children (including both sibling groups and sibling shape nodes).
1395
- * Used during restoration to correctly interleave groups and shapes
1396
- * so that SVG document order (painting order) is preserved.
1397
- */
1398
- siblingIndex?: number;
1399
- /** Plugin that owns this group (e.g. 'svgsketch-charts') */
1400
- pluginId?: string;
1401
- /** Serialized plugin-specific state (JSON string) */
1402
- pluginData?: string;
1403
- /** Additional custom data-* attributes set by plugins */
1404
- attributes?: Record<string, string>;
1405
- fill?: string;
1406
- fillOpacity?: string;
1407
- strokeOpacity?: string;
1408
- opacity?: string;
1409
- filter?: string;
1410
- cssFilter?: string;
1411
- mixBlendMode?: string;
1412
- clipPath?: string;
1413
- mask?: string;
2017
+ interface ArrowNodeProps extends PolygonBaseNodeProps {
2018
+ headWidthPercent: number;
2019
+ headLengthPercent: number;
2020
+ shaftWidthPercent: number;
1414
2021
  }
1415
- /** Serialized clip or mask group */
1416
- interface SerializedClipMaskGroup {
1417
- id: string;
1418
- type: 'clip' | 'mask';
1419
- /**
1420
- * @deprecated Use `clipShapeIds` instead. Kept for backward compatibility
1421
- * when reading older documents that used a single clip/mask shape.
1422
- */
1423
- clipShapeId?: string;
1424
- /** IDs of shape(s) that form the clip/mask definition. */
1425
- clipShapeIds: string[];
1426
- /** IDs of the content shapes being clipped/masked. */
1427
- contentShapeIds: string[];
1428
- parentId: string | null;
1429
- /**
1430
- * Position of the clip/mask group among its parent container's children,
1431
- * so that SVG document order (painting order) is preserved across
1432
- * save / restore.
1433
- */
1434
- siblingIndex?: number;
1435
- /**
1436
- * Coordinate system for the `<mask>` bounds (`x`, `y`, `width`, `height`).
1437
- * @see CSS Masking Module §9.1 — `maskUnits`
1438
- * @default 'objectBoundingBox'
1439
- */
1440
- maskUnits?: 'userSpaceOnUse' | 'objectBoundingBox';
1441
- /**
1442
- * Coordinate system for the **contents** of a `<mask>`.
1443
- * @see CSS Masking Module §9.1 — `maskContentUnits`
1444
- * @default 'userSpaceOnUse'
1445
- */
1446
- maskContentUnits?: 'userSpaceOnUse' | 'objectBoundingBox';
1447
- /**
1448
- * Coordinate system for the contents of a `<clipPath>`.
1449
- * @see CSS Masking Module §6.1 — `clipPathUnits`
1450
- * @default 'userSpaceOnUse'
1451
- */
1452
- clipPathUnits?: 'userSpaceOnUse' | 'objectBoundingBox';
1453
- /**
1454
- * Explicit mask bounds (`x`, `y`, `width`, `height`).
1455
- * When omitted the browser defaults apply (−10% / 120%).
1456
- */
1457
- maskBounds?: {
1458
- x: string;
1459
- y: string;
1460
- width: string;
1461
- height: string;
1462
- };
1463
- /**
1464
- * Whether the mask uses luminance or alpha channel.
1465
- * @see CSS Masking Module §9.2 — `mask-type`
1466
- * @default 'luminance'
1467
- */
1468
- maskType?: 'luminance' | 'alpha';
1469
- /**
1470
- * Raw SVG markup for imported mask/clip definitions that cannot be
1471
- * decomposed into editor `Shape` objects (e.g. multi-element masks
1472
- * with gradients, patterns, or nested groups). When present the
1473
- * editor preserves the original `<mask>` / `<clipPath>` verbatim
1474
- * and `clipShapeIds` may be empty.
1475
- */
1476
- rawDefinition?: string;
2022
+ interface SymbolInstanceNodeProps extends CommonNodeProps {
2023
+ x: number;
2024
+ y: number;
2025
+ width: number;
2026
+ height: number;
2027
+ symbolId: string;
2028
+ }
2029
+ interface GroupNodeProps {
2030
+ groupId: string | null;
2031
+ }
2032
+ type DocumentNodeProps = Record<string, never>;
2033
+ /**
2034
+ * Maps each node type string to its typed property interface.
2035
+ * Used by `SceneNode.create()` for compile-time type safety.
2036
+ */
2037
+ interface NodeTypePropsMap {
2038
+ rectangle: RectangleNodeProps;
2039
+ square: SquareNodeProps;
2040
+ circle: CircleNodeProps;
2041
+ ellipse: EllipseNodeProps;
2042
+ line: LineNodeProps;
2043
+ text: TextNodeProps;
2044
+ image: ImageNodeProps;
2045
+ spline: SplineNodeProps;
2046
+ polyline: PolylineNodeProps;
2047
+ triangle: TriangleNodeProps;
2048
+ ngon: NGonNodeProps;
2049
+ star: StarNodeProps;
2050
+ cross: CrossNodeProps;
2051
+ ring: RingNodeProps;
2052
+ spiral: SpiralNodeProps;
2053
+ gear: GearNodeProps;
2054
+ arrow: ArrowNodeProps;
2055
+ 'symbol-instance': SymbolInstanceNodeProps;
2056
+ group: GroupNodeProps;
2057
+ document: DocumentNodeProps;
1477
2058
  }
2059
+ /** Union of all node prop types. */
2060
+ type AnyNodeProps = RectangleNodeProps | SquareNodeProps | CircleNodeProps | EllipseNodeProps | LineNodeProps | TextNodeProps | ImageNodeProps | SplineNodeProps | PolylineNodeProps | TriangleNodeProps | NGonNodeProps | StarNodeProps | CrossNodeProps | RingNodeProps | SpiralNodeProps | GearNodeProps | ArrowNodeProps | SymbolInstanceNodeProps | GroupNodeProps | DocumentNodeProps;
1478
2061
 
1479
2062
  /**
1480
2063
  * @svgsketch/core — Schema migrations.
@@ -1511,17 +2094,6 @@ interface SerializedClipMaskGroup {
1511
2094
  * It must return the transformed snapshot (typically the same object).
1512
2095
  */
1513
2096
  type Migration = (snapshot: HistorySnapshot) => HistorySnapshot;
1514
- /**
1515
- * Registry of schema migrations, keyed by **source** version.
1516
- *
1517
- * Entry `N: fn` means "`fn` transforms a version-N snapshot into a
1518
- * version-(N+1) snapshot." The dispatcher in {@link migrateSnapshot}
1519
- * walks this registry from the snapshot's current version up to
1520
- * {@link CURRENT_SCHEMA_VERSION}.
1521
- *
1522
- * This object is exported so tests (and diagnostic tooling) can read
1523
- * the registered migrations, but it should not be mutated at runtime.
1524
- */
1525
2097
  declare const MIGRATIONS: Readonly<Record<number, Migration>>;
1526
2098
  /**
1527
2099
  * Migrate a snapshot from any older schema version to the current version.
@@ -1777,6 +2349,65 @@ declare function extractVariables(snapshot: HistorySnapshot): ExtractedVariables
1777
2349
  */
1778
2350
  declare function parseVariableArgs(args: string[]): VariableMap;
1779
2351
 
2352
+ /**
2353
+ * @svgsketch/core — Coordinate precision utilities.
2354
+ *
2355
+ * Pure rounding utilities used at every state-capture boundary in the
2356
+ * editor (per-shape command capture, full snapshot capture, SVG export)
2357
+ * to enforce a configurable decimal precision on persisted/exported
2358
+ * coordinate values.
2359
+ *
2360
+ * Rounding fires only on the way OUT of the document model (save, export,
2361
+ * undo capture). Imports are never rounded — see DocumentMetadata's
2362
+ * `coordinatePrecision` field for the policy.
2363
+ *
2364
+ * Industry context: Adobe Illustrator, Inkscape, Affinity Designer, and
2365
+ * SVGO all expose a precision control. Default 3 decimals matches SVGO
2366
+ * and Illustrator.
2367
+ */
2368
+
2369
+ /** Default precision when DocumentMetadata.coordinatePrecision is unset. */
2370
+ declare const DEFAULT_COORDINATE_PRECISION = 3;
2371
+ /**
2372
+ * Maximum precision we accept. Above 12 the rounding becomes a no-op for
2373
+ * practical SVG coordinate ranges (float64 has ~15-17 significant digits).
2374
+ */
2375
+ declare const MAX_COORDINATE_PRECISION = 12;
2376
+ /**
2377
+ * Resolve an optional precision value to a concrete one. Clamps to the
2378
+ * supported range and substitutes the default for `undefined` / `null` /
2379
+ * non-finite inputs.
2380
+ */
2381
+ declare function getEffectivePrecision(p: number | undefined | null): number;
2382
+ /**
2383
+ * Round a single number to N decimal places. Non-finite inputs (NaN,
2384
+ * Infinity) pass through unchanged so we never poison data with NaN.
2385
+ */
2386
+ declare function roundCoord(value: number, precision: number): number;
2387
+ /**
2388
+ * Round every numeric token in a string in place. Does not touch any
2389
+ * non-numeric content (operators, commands, whitespace).
2390
+ */
2391
+ declare function roundNumberString(s: string, precision: number): string;
2392
+ /**
2393
+ * Round all coordinate-bearing numeric fields in a SerializedShape's
2394
+ * state. Returns a new object — input is not mutated.
2395
+ *
2396
+ * `id` and `type` are passed through unchanged.
2397
+ */
2398
+ declare function roundSerializedShape(shape: SerializedShape, precision: number): SerializedShape;
2399
+ /**
2400
+ * Round all coordinate-bearing fields in a complete HistorySnapshot.
2401
+ * Used at the snapshot-level capture boundary (file save, cloud sync).
2402
+ *
2403
+ * Returns a new snapshot with shapes, viewboxes, guides, measurements,
2404
+ * and the animation timeline rounded. Document metadata (titles, IDs,
2405
+ * etc.) and structural fields (groups, clipMaskGroups, scripts, symbols)
2406
+ * pass through with their numeric leaves rounded but their structure
2407
+ * preserved.
2408
+ */
2409
+ declare function roundSnapshot(snapshot: HistorySnapshot, precision: number): HistorySnapshot;
2410
+
1780
2411
  /**
1781
2412
  * Document-level SVG renderer.
1782
2413
  *
@@ -1842,14 +2473,25 @@ declare function renderFilterPrimitivesForType(filter: ShapeFilter, input: strin
1842
2473
  /**
1843
2474
  * Generate `<filter>` definition strings for all shapes that have filters.
1844
2475
  *
2476
+ * Phase 4: filters are library-first. Each distinct `filterLibraryIds`
2477
+ * entry emits exactly one `<filter>` in the output — two shapes sharing
2478
+ * the same library filter id produce one `<filter>`, not two. Falls back
2479
+ * to the legacy `filter-${shape.id}` id when a shape has inline filters
2480
+ * but no library ids set (shapes that haven't re-serialized since the
2481
+ * migration, or callers working against an in-memory object).
2482
+ *
1845
2483
  * @returns Concatenated `<filter>` elements to include in `<defs>`.
1846
2484
  */
1847
2485
  declare function renderFilterDefs(shapes: SerializedShape[]): string;
1848
2486
  /**
1849
2487
  * Get the `filter="url(#...)"` attribute value for a shape, or empty string
1850
2488
  * if the shape has no enabled filters.
2489
+ *
2490
+ * Phase 4: reads from `filterLibraryIds` when set, joining multiple ids as
2491
+ * a space-separated `<filter-value-list>` (CSS Filter Effects §Filter
2492
+ * Property). Falls back to the legacy shape-derived id for unmigrated input.
1851
2493
  */
1852
- declare function filterAttr(shapeId: string, filters: ShapeFilter[] | undefined): string;
2494
+ declare function filterAttr(shapeId: string, filters: ShapeFilter[] | undefined, filterLibraryIds?: string[]): string;
1853
2495
 
1854
2496
  /**
1855
2497
  * Shape renderers — convert SerializedShape → SVG element string.
@@ -1869,6 +2511,31 @@ declare function renderImage(shape: SerializedShape): string;
1869
2511
  declare function renderPolygonShape(shape: SerializedShape): string;
1870
2512
  /** Render any SerializedShape to an SVG element string. */
1871
2513
  declare function renderShape(shape: SerializedShape): string;
2514
+ /**
2515
+ * Walk shapes to find referenced marker ids. Returns two sets:
2516
+ * - `ids`: raw marker ids from `state.markerStart` / `markerMid` /
2517
+ * `markerEnd` — can be built-in ids (`mkr-builtin-arrow`,
2518
+ * `line-marker-arrow`) or user marker ids.
2519
+ * - `legacyEndpoints`: endpoint names from `state.startEndpoint` /
2520
+ * `endEndpoint` (e.g. `'arrow'`, `'circle'`). Lines emit these as a
2521
+ * shortcut to built-in markers without explicit `marker-*` attrs.
2522
+ */
2523
+ interface MarkerReferenceSets {
2524
+ ids: Set<string>;
2525
+ legacyEndpoints: Set<string>;
2526
+ }
2527
+ /**
2528
+ * Emit only built-in marker `<marker>` definitions referenced by a shape
2529
+ * collection. Split out of `renderMarkerDefs` so the library-first
2530
+ * pipeline can compose built-in handling with
2531
+ * `renderReferencedLibraryDefs` (which covers user-authored markers via
2532
+ * `snapshot.library`).
2533
+ *
2534
+ * Takes a pre-collected `MarkerReferenceSets` so callers can avoid walking
2535
+ * shapes twice when they need both the reference sets and the built-in
2536
+ * defs.
2537
+ */
2538
+ declare function renderBuiltinMarkerDefs(referenced: MarkerReferenceSets | SerializedShape[]): string;
1872
2539
 
1873
2540
  /**
1874
2541
  * Pure geometry functions for computing shape vertices and paths.
@@ -2051,6 +2718,7 @@ declare function generatePatternSvgContent(patternType: string, scale: number, c
2051
2718
  *
2052
2719
  * @packageDocumentation
2053
2720
  */
2721
+
2054
2722
  interface MarkerDescriptor {
2055
2723
  /** Marker element id (e.g., 'line-marker-arrow'). */
2056
2724
  id: string;
@@ -2075,6 +2743,22 @@ declare const MARKER_HEIGHT = 6;
2075
2743
  * `markerUnits="strokeWidth"`, and `orient="auto-start-reverse"`.
2076
2744
  */
2077
2745
  declare function getMarkerDescriptors(): MarkerDescriptor[];
2746
+ /**
2747
+ * Maps the legacy marker ids (used by line endpoint shape state) to the new
2748
+ * first-class MarkerManager ids. The legacy ids remain valid references in
2749
+ * the DOM — built-ins are emitted under BOTH ids to preserve backwards
2750
+ * compat with saved docs that reference `url(#line-marker-arrow)`.
2751
+ */
2752
+ declare const BUILTIN_MARKER_ID_MAP: Record<string, string>;
2753
+ /**
2754
+ * Return `SerializedMarkerDef`s for the built-in line endpoint markers.
2755
+ *
2756
+ * Built-ins carry `shapes: []` — their geometry is rendered by the editor
2757
+ * directly from the descriptor registry rather than from `SerializedShape`s.
2758
+ * This keeps descriptor → shape conversion out of v1 scope. Consequence:
2759
+ * built-ins are non-editable (the markers panel disables Edit on them).
2760
+ */
2761
+ declare function getBuiltInMarkerDefs(): SerializedMarkerDef[];
2078
2762
 
2079
2763
  /**
2080
2764
  * SMIL animation renderer — converts SerializedAnimationTimeline
@@ -2100,6 +2784,95 @@ declare function getMarkerDescriptors(): MarkerDescriptor[];
2100
2784
  */
2101
2785
  declare function renderAnimationElements(timeline: SerializedAnimationTimeline): Map<string, string[]>;
2102
2786
 
2787
+ /**
2788
+ * Library renderers — convert `LibraryDef` entries into SVG `<defs>` strings.
2789
+ *
2790
+ * This is the headless/string-based renderer for library defs. The editor's
2791
+ * live `<defs>` rendering is handled by the kind-specific managers
2792
+ * (SymbolManager, MarkerManager, GradientManager, FilterManager) writing D3
2793
+ * DOM nodes; this module is the equivalent path for the CLI/SDK export pipe.
2794
+ *
2795
+ * Implementations delegate to the existing per-shape renderers where
2796
+ * possible — library defs carry the same render-affecting data as the
2797
+ * inline payloads those renderers were built for, with `LibraryDefBase`
2798
+ * metadata (id, name, thumbnail) peeled off at the outer call.
2799
+ *
2800
+ * @packageDocumentation
2801
+ */
2802
+
2803
+ /**
2804
+ * Deterministic emission order for `<defs>` contents. Put paint servers
2805
+ * (gradients, patterns) and filters **before** symbols/markers so that when a
2806
+ * symbol or marker's inner shapes reference a library paint or filter by
2807
+ * `url(#id)`, the forward reference resolves in parsers that do a single
2808
+ * forward pass.
2809
+ *
2810
+ * This matches the plan's export ordering rule: symbols and markers can
2811
+ * reference any other library kind, but not vice versa.
2812
+ */
2813
+ declare const LIBRARY_EMIT_ORDER: readonly LibraryKind[];
2814
+ /** Top-level dispatch. Picks the right kind-renderer for a library def. */
2815
+ declare function renderLibraryDef(def: LibraryDef): string;
2816
+ declare function renderSymbolLibraryDef(def: SymbolLibraryDef): string;
2817
+ declare function renderMarkerLibraryDef(def: MarkerLibraryDef): string;
2818
+ declare function renderLinearGradientLibraryDef(def: LinearGradientLibraryDef): string;
2819
+ declare function renderRadialGradientLibraryDef(def: RadialGradientLibraryDef): string;
2820
+ declare function renderPatternLibraryDef(def: PatternLibraryDef): string;
2821
+ declare function renderFilterLibraryDef(def: FilterLibraryDef): string;
2822
+ /**
2823
+ * Render every library def as a single `<defs>`-body string, in the
2824
+ * canonical order defined by `LIBRARY_EMIT_ORDER`. Useful for callers that
2825
+ * want to emit the entire library regardless of which defs are actually
2826
+ * referenced — the editor's export finalizer uses a reference-walker
2827
+ * instead, but standalone SVG producers (e.g. CLI fixture generation) may
2828
+ * prefer this unconditional emission.
2829
+ */
2830
+ declare function renderLibraryDefs(defs: readonly LibraryDef[]): string;
2831
+ /**
2832
+ * Collect every library-def id referenced by a shape collection. Covers
2833
+ * all the ways a shape points at a library entry:
2834
+ *
2835
+ * - `fillLibraryId` / `strokeLibraryId` (gradient / pattern paint servers)
2836
+ * - `filterLibraryIds[]` (filter chain)
2837
+ * - `markerStart` / `markerMid` / `markerEnd` (vertex markers)
2838
+ * - `symbolId` (symbol instances)
2839
+ *
2840
+ * Ids for built-in markers (e.g. `mkr-builtin-arrow`, `line-marker-arrow`)
2841
+ * are included in the result — callers that emit built-ins from the
2842
+ * descriptor registry should still look here for the reference signal.
2843
+ *
2844
+ * Does NOT include `url(#...)` strings parsed out of inline fill/stroke
2845
+ * CSS text — the library-first pipeline assumes shapes set `fillLibraryId`
2846
+ * explicitly when they reference a library def.
2847
+ */
2848
+ declare function collectReferencedLibraryIds(shapes: readonly SerializedShape[]): Set<string>;
2849
+ /**
2850
+ * Library-first `<defs>` emission: walks shapes and emits one `<defs>`
2851
+ * entry per unique paint-server / filter / user-marker referenced by the
2852
+ * scene. Built-in markers (which live in the descriptor registry, not
2853
+ * `snapshot.library`) are NOT emitted by this function — callers should
2854
+ * compose with `renderBuiltinMarkerDefs` or similar.
2855
+ *
2856
+ * Two input sources are merged, with library-first precedence:
2857
+ *
2858
+ * 1. **Library refs**: shapes set `fillLibraryId`, `strokeLibraryId`,
2859
+ * `filterLibraryIds`, `markerStart/Mid/End`, or `symbolId` pointing
2860
+ * into `library`. The library entry is authoritative for the def.
2861
+ * 2. **Legacy inline payloads**: shapes with `fillGradient` /
2862
+ * `strokeGradient` / `filters[]` but NO matching library ref. A
2863
+ * transient library def is synthesized from the inline data on the
2864
+ * fly so renders remain correct for snapshots that bypass the
2865
+ * migrator (e.g. older tests, hand-built snapshots via the SDK).
2866
+ *
2867
+ * Dedup is by emitted id. A shape that has both a library ref AND an
2868
+ * inline payload with the same id emits the library entry once.
2869
+ *
2870
+ * Defs are emitted in `LIBRARY_EMIT_ORDER` so cross-kind references
2871
+ * (e.g. a `<symbol>` whose inner shapes reference a gradient) resolve
2872
+ * during single-pass parsing.
2873
+ */
2874
+ declare function renderReferencedLibraryDefs(shapes: readonly SerializedShape[], library: readonly LibraryDef[]): string;
2875
+
2103
2876
  /**
2104
2877
  * Code generation dispatcher — routes to format-specific generators.
2105
2878
  */
@@ -2401,6 +3174,26 @@ declare abstract class ShapeBuilder<T extends ShapeBuilder<T>> {
2401
3174
  locked(value?: boolean): T;
2402
3175
  /** Set visibility. */
2403
3176
  visible(value?: boolean): T;
3177
+ /**
3178
+ * Set the shape's structural role in the exported SVG.
3179
+ *
3180
+ * - `'normal'` (default) — rendered inline in document order.
3181
+ * - `'motionOnly'` — emitted inside `<defs>` as an `<mpath>` reference
3182
+ * target and NOT rendered. Pair with `Track.motionPathRef(shapeId,
3183
+ * 'curveTemplate')` so the animation's `<mpath>` resolves to this
3184
+ * shape's origin-normalized `d`. The exporter automatically
3185
+ * translates the shape's `d` so its first moveto is at `M 0,0`,
3186
+ * the canonical "curve template" form that lets multiple animations
3187
+ * share one motion-path `<defs>` entry.
3188
+ *
3189
+ * @see https://svgwg.org/specs/animations/#MPathElement
3190
+ */
3191
+ displayMode(mode: 'normal' | 'motionOnly'): T;
3192
+ /**
3193
+ * Convenience alias for `.displayMode('motionOnly')` — marks this shape
3194
+ * as an `<mpath>` reference target (not rendered; placed in `<defs>`).
3195
+ */
3196
+ motionOnly(): T;
2404
3197
  /** Set a solid fill color. */
2405
3198
  fill(color: string, opacity?: number): T;
2406
3199
  /** Set fill to none (transparent). */
@@ -2930,6 +3723,42 @@ declare class Track {
2930
3723
  locked(): Track;
2931
3724
  /** Set an SVG path for motion-path animation. */
2932
3725
  motionPath(path: string): Track;
3726
+ /**
3727
+ * Link this motion-path track to another shape's geometry as an
3728
+ * `<mpath href="#shapeId"/>` reference. The track's `motionPath` is
3729
+ * expected to have been set (or will be) to the referenced shape's
3730
+ * path data — the two fields together model SVG Animations §19.2
3731
+ * semantics where `<mpath>` supersedes inline `path=` on export.
3732
+ *
3733
+ * The `mode` controls how the reference is interpreted:
3734
+ * - `'trackShape'` (default) — the motion path is displacement-
3735
+ * relative to the animated element's center, so playback and
3736
+ * editor overlay render on top of the referenced shape's absolute
3737
+ * position. Exports as inline `path=` (spec-correct).
3738
+ * - `'curveTemplate'` — the motion path's first point is `M 0,0`,
3739
+ * matching how `<mpath>` semantics want a reusable curve-template.
3740
+ * Exports as `<mpath href="#shapeId"/>` pointing at a `<defs>` path
3741
+ * with the same origin-normalized `d` — reusable across animations.
3742
+ *
3743
+ * Pair with `.motionPath(d)` where `d` is in the form the mode expects:
3744
+ * absolute-minus-element-center for trackShape, origin-normalized for
3745
+ * curveTemplate.
3746
+ *
3747
+ * @example
3748
+ * ```ts
3749
+ * const curve = new Spline(...).id('curve');
3750
+ * doc.add(curve);
3751
+ *
3752
+ * const track = new Track('rect-1', 'pathMotion')
3753
+ * .motionPath('M0,0 C 50,-100 150,-100 200,0') // origin-normalized
3754
+ * .motionPathRef('curve', 'curveTemplate') // emits <mpath href="#curve"/>
3755
+ * .keyframe(0, 0)
3756
+ * .keyframe(3, 1);
3757
+ * ```
3758
+ *
3759
+ * @see https://svgwg.org/specs/animations/#MPathElement
3760
+ */
3761
+ motionPathRef(shapeId: string, mode?: 'trackShape' | 'curveTemplate'): Track;
2933
3762
  /**
2934
3763
  * Set the begin trigger for this track.
2935
3764
  *
@@ -3349,4 +4178,4 @@ declare class Document {
3349
4178
  private _ensureMetadata;
3350
4179
  }
3351
4180
 
3352
- export { type AnimatablePropertyDescriptor, type AnimationKeyframe, type AnimationTimeline, type AnimationTrack, type AnimationTrigger, type AnimationTriggerType, type AnyNodeProps, type ArcParams$1 as ArcParams, type AriaRole, Arrow, type ArrowNodeProps, type BaseFilter, type BlackAndWhiteFilter, type BlurQuality, type BrightnessFilter, CURRENT_SCHEMA_VERSION, type ChannelPainterFilter, Circle, type CircleNodeProps, type CodeFormat, type CodegenOptions, type CommonNodeProps, type ContouringDiscreteFilter, type ContouringTableFilter, type ContrastFilter, type CornerShapeValue, type CreateDocumentOptions, type CreateShapeOptions, Cross, type CrossNodeProps, type CrumpledPlasticFilter, type CustomPatternDef, type CycleBehavior, Document, type DocumentMetadata, type DocumentNodeProps, type DocumentOptions, type DropShadowFilter, type DuotoneFilter, EASING_CURVES, EVENT_TRIGGER_OPTIONS, EasingType, Ellipse, type EllipseNodeProps, type EmbossFilter, type ExtractedVariables, type FillType, type FilmGrainFilter, type FilterType, type GaussianBlurFilter, Gear, type GearNodeProps, type GlowFilter, type GouacheFilter, type GradientDefinition, type GradientSpreadMethod, type GradientStop, type GradientUnits, type GrayscaleFilter, type GroupNodeProps, type Guide, type HistorySnapshot, type HueRotateFilter, type ImageAttribution, type ImageNodeProps, ImageShape, type InkBlotFilter, type InnerGlowFilter, type InnerShadowFilter, type InvertFilter, type LicenseType, Line, type LineEndpointValue, type LineNodeProps, type LinearEasingPoint, type LinearGradient, LinearGradientBuilder, type LinkTarget, MARKER_HEIGHT, MARKER_VIEWBOX, MARKER_WIDTH, MIGRATIONS, type MarkerDescriptor, type Measurement, type Migration, type MorphologyFilter, type MorphologyOperator, type MotionBlurFilter, NGon, type NGonNodeProps, type NodeTypePropsMap, type NoiseFilter, type OpacityFilter, type OutlineFilter, type OutlinePosition, type ParseOptions, PatternBuilder, type PatternElement, type PatternFill, type PatternParams, type PatternSvgContentResult, type PatternType, type PixelateFilter, type Point, type PointLightFilter, type PolygonBaseNodeProps, Polyline, type PolylineNodeProps, type RadialGradient, RadialGradientBuilder, Rectangle, type RectangleNodeProps, type RenderOptions, type RichTextData, type RichTextLine, type RichTextSegment, type RichTextSegmentStyle, type RiddledFilter, Ring, type RingNodeProps, type RoundEdgesFilter, type SaturateFilter, type SegmentCurveType, type SepiaFilter, type SerializedAnimationTimeline, type SerializedClipMaskGroup, type SerializedGroup, type SerializedShape, type SerializedSymbolDef, type SerializedVariantAxis, type SerializedViewbox, ShapeBuilder, type ShapeFilter, type ShapeMetadata, type SharpenFilter, Spiral, type SpiralNodeProps, Spline, SplineCurveType, type SplineNodeProps, type SplinePoint, SplinePointType, type SpotLightFilter, Square, type SquareNodeProps, Star, type StarNodeProps, type StepPosition, type StepsParams, type StringifyOptions, type StrokeType, type SymbolInstanceNodeProps, type TemplateVariable, type TemplateVariableSource, type TemplateVariableType, Text, type TextNodeProps, Timeline, Track, Triangle, type TriangleNodeProps, type ValidationError, type ValidationResult, type VariableMap, type Viewbox, type WarpFilter, type WarpType, type WatercolorFilter, type XrayFilter, computeArrowVertices, computeCloudPath, computeCrossVertices, computeDashArray, computeGearPath, computeGearVertices, computeHeartPath, computeLightningVertices, computePolygonVertices, computeRectanglePath, computeRingPath, computeSpeechBubbleVertices, computeSpiralPath, computeSplinePath, computeStarVertices, createDocument, createShape, createViewbox, escXml, extractVariables, filterAttr, generateCode, generateCssCode, generateD3Code, generateId, generatePatternSvgContent, generateReactCode, generateSvgCode, generateVueCode, getEasingCubicBezier, getMarkerDescriptors, getPatternElements, linearGradient, migrateSnapshot, parseDocument, parseVariableArgs, pattern, radialGradient, renderAnimationElements, renderCircle, renderEllipse, renderFilterDefs, renderFilterPrimitivesForType, renderImage, renderLine, renderPolygonShape, renderPolyline, renderRectangle, renderShape, renderSpline, renderText, renderToSvg, stringifyDocument, substituteString, substituteVariables, validateSnapshot, verticesToPath };
4181
+ export { type AnimatablePropertyDescriptor, type AnimationKeyframe, type AnimationTimeline, type AnimationTrack, type AnimationTrigger, type AnimationTriggerType, type AnyNodeProps, type ArcParams$1 as ArcParams, type AriaRole, Arrow, type ArrowNodeProps, BUILTIN_MARKER_ID_MAP, type BaseFilter, type BlackAndWhiteFilter, type BlurQuality, type BrightnessFilter, CURRENT_SCHEMA_VERSION, type ChannelPainterFilter, Circle, type CircleNodeProps, type CodeFormat, type CodegenOptions, type CommonNodeProps, type ConnectionDirection, type ConnectionPoint, type ContouringDiscreteFilter, type ContouringTableFilter, type ContrastFilter, type CornerShapeValue, type CreateDocumentOptions, type CreateShapeOptions, Cross, type CrossNodeProps, type CrumpledPlasticFilter, type CustomPatternDef, type CycleBehavior, DEFAULT_COORDINATE_PRECISION, type DiffuseLightingFilter, Document, type DocumentMetadata, type DocumentNodeProps, type DocumentOptions, type DocumentScript, type DocumentStyle, type DropShadowFilter, type DuotoneFilter, EASING_CURVES, EVENT_TRIGGER_OPTIONS, EasingType, Ellipse, type EllipseNodeProps, type EmbossFilter, type ExtractedVariables, type FillType, type FilmGrainFilter, type FilterLibraryDef, type FilterType, type GaussianBlurFilter, Gear, type GearNodeProps, type GlowFilter, type GouacheFilter, type GradientDefinition, type GradientSpreadMethod, type GradientStop, type GradientUnits, type GrayscaleFilter, type GroupNodeProps, type Guide, type HistorySnapshot, type HueRotateFilter, type ImageAttribution, type ImageNodeProps, ImageShape, type InkBlotFilter, type InnerGlowFilter, type InnerShadowFilter, type InvertFilter, LIBRARY_EMIT_ORDER, type LibraryDef, type LibraryDefBase, type LibraryDefOfKind, type LibraryKind, type LicenseType, type LightSource, Line, type LineEndpointValue, type LineNodeProps, type LinearEasingPoint, type LinearGradient, LinearGradientBuilder, type LinearGradientLibraryDef, type LinkTarget, MARKER_HEIGHT, MARKER_VIEWBOX, MARKER_WIDTH, MAX_COORDINATE_PRECISION, MIGRATIONS, type MarkerDescriptor, type MarkerLibraryDef, type Measurement, type Migration, type MorphologyFilter, type MorphologyOperator, type MotionBlurFilter, NGon, type NGonNodeProps, type NodeTypePropsMap, type NoiseFilter, type OpacityFilter, type OutlineFilter, type OutlinePosition, type ParseOptions, PatternBuilder, type PatternElement, type PatternFill, type PatternLibraryDef, type PatternParams, type PatternSvgContentResult, type PatternType, type PixelateFilter, type Point, type PointLightFilter, type PolygonBaseNodeProps, Polyline, type PolylineNodeProps, type RadialGradient, RadialGradientBuilder, type RadialGradientLibraryDef, type RawSvgFilter, Rectangle, type RectangleNodeProps, type RenderOptions, type RichTextData, type RichTextLine, type RichTextSegment, type RichTextSegmentStyle, type RiddledFilter, Ring, type RingNodeProps, type RoundEdgesFilter, type SaturateFilter, type SegmentCurveType, type SepiaFilter, type SerializedAnimationTimeline, type SerializedClipMaskGroup, type SerializedGroup, type SerializedMarkerDef, type SerializedShape, type SerializedSymbolDef, type SerializedVariantAxis, type SerializedViewbox, ShapeBuilder, type ShapeFilter, type ShapeMetadata, type SharpenFilter, type SpecularLightingFilter, Spiral, type SpiralNodeProps, Spline, SplineCurveType, type SplineNodeProps, type SplinePoint, SplinePointType, type SpotLightFilter, Square, type SquareNodeProps, Star, type StarNodeProps, type StepPosition, type StepsParams, type StringifyOptions, type StrokeType, type SymbolInstanceNodeProps, type SymbolLibraryDef, type TemplateVariable, type TemplateVariableSource, type TemplateVariableType, Text, type TextNodeProps, Timeline, Track, Triangle, type TriangleNodeProps, type ValidationError, type ValidationResult, type VariableMap, type Viewbox, type WarpFilter, type WarpType, type WatercolorFilter, type XrayFilter, collectReferencedLibraryIds, computeArrowVertices, computeCloudPath, computeCrossVertices, computeDashArray, computeGearPath, computeGearVertices, computeHeartPath, computeLightningVertices, computePolygonVertices, computeRectanglePath, computeRingPath, computeSpeechBubbleVertices, computeSpiralPath, computeSplinePath, computeStarVertices, createDocument, createShape, createViewbox, escXml, extractVariables, filterAttr, generateCode, generateCssCode, generateD3Code, generateId, generatePatternSvgContent, generateReactCode, generateSvgCode, generateVueCode, getBuiltInMarkerDefs, getEasingCubicBezier, getEffectivePrecision, getMarkerDescriptors, getPatternElements, linearGradient, migrateSnapshot, parseDocument, parseVariableArgs, pattern, radialGradient, renderAnimationElements, renderBuiltinMarkerDefs, renderCircle, renderEllipse, renderFilterDefs, renderFilterLibraryDef, renderFilterPrimitivesForType, renderImage, renderLibraryDef, renderLibraryDefs, renderLine, renderLinearGradientLibraryDef, renderMarkerLibraryDef, renderPatternLibraryDef, renderPolygonShape, renderPolyline, renderRadialGradientLibraryDef, renderRectangle, renderReferencedLibraryDefs, renderShape, renderSpline, renderSymbolLibraryDef, renderText, renderToSvg, roundCoord, roundNumberString, roundSerializedShape, roundSnapshot, stringifyDocument, substituteString, substituteVariables, validateSnapshot, verticesToPath };