@svgsketch/core 0.5.0 → 0.6.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
@@ -165,6 +165,15 @@ interface AnimationTrack {
165
165
  * @default 'replace' (except transforms, which default to 'sum')
166
166
  */
167
167
  additive?: 'sum' | 'replace';
168
+ /**
169
+ * Scoping for this track.
170
+ * - Absent / 'document' — plays on the main document timeline (default).
171
+ * - `'marker:<markerId>'` — scoped to a marker definition's inner shapes.
172
+ * Only evaluated when the editor is isolation-editing that marker;
173
+ * exported as SMIL inside the `<marker>` element so it animates at
174
+ * every attached vertex.
175
+ */
176
+ scope?: string;
168
177
  }
169
178
  /**
170
179
  * The top-level animation timeline for a document.
@@ -209,6 +218,8 @@ interface SerializedAnimationTimeline {
209
218
  };
210
219
  motionRotate?: 'auto' | 'auto-reverse' | number;
211
220
  additive?: 'sum' | 'replace';
221
+ /** Scoping — see `AnimationTrack.scope`. */
222
+ scope?: string;
212
223
  /**
213
224
  * 6-element CSS matrix of the track's ancestor transform context, captured
214
225
  * at the time the animation was authored. Preserves visual fidelity when
@@ -302,6 +313,19 @@ interface Viewbox {
302
313
  width: number;
303
314
  height: number;
304
315
  }
316
+ /** Direction hint for connector routing tangents. */
317
+ type ConnectionDirection = 'n' | 's' | 'e' | 'w' | 'any';
318
+ /** A named anchor point on a shape where connectors can attach. */
319
+ interface ConnectionPoint {
320
+ /** Stable id — 'n','s','e','w','center' for derived; 'custom-<uuid>' for user-placed. */
321
+ id: string;
322
+ /** Location in canvas/workspace coordinates (post-transform). */
323
+ point: Point;
324
+ /** Tangent hint used by connector routing. */
325
+ direction: ConnectionDirection;
326
+ /** 'derived' anchors are computed from shape geometry; 'custom' are persisted overrides. */
327
+ kind: 'derived' | 'custom';
328
+ }
305
329
  type FillType = 'solid' | 'linear-gradient' | 'radial-gradient' | 'pattern' | 'none';
306
330
  type StrokeType = 'solid' | 'linear-gradient' | 'radial-gradient' | 'pattern' | 'none';
307
331
  type GradientSpreadMethod = 'pad' | 'repeat' | 'reflect';
@@ -344,6 +368,14 @@ interface LinearGradient {
344
368
  * element's bbox-normalised [0, 1] space. See `GradientUnits`.
345
369
  */
346
370
  gradientUnits?: GradientUnits;
371
+ /**
372
+ * Original `id` from the imported source SVG. Runtime `id` is always
373
+ * a fresh GUID (to keep editor uniqueness invariants), but `sourceId`
374
+ * is retained so export can restore human-friendly ids when there is
375
+ * no collision. Cleared whenever the gradient is mutated through the
376
+ * editor — at that point the source id no longer describes the data.
377
+ */
378
+ sourceId?: string;
347
379
  }
348
380
  interface RadialGradient {
349
381
  type: 'radial-gradient';
@@ -363,6 +395,8 @@ interface RadialGradient {
363
395
  * `r`/`ry` are in document user space. See `GradientUnits`.
364
396
  */
365
397
  gradientUnits?: GradientUnits;
398
+ /** See `LinearGradient.sourceId`. */
399
+ sourceId?: string;
366
400
  }
367
401
  /**
368
402
  * Per-pattern-type tuneable parameters.
@@ -444,6 +478,8 @@ interface PatternFill {
444
478
  y?: number;
445
479
  /** ID of the `CustomPatternDef` this fill was built from (if any). */
446
480
  customPatternId?: string;
481
+ /** See `LinearGradient.sourceId`. */
482
+ sourceId?: string;
447
483
  }
448
484
  type GradientDefinition = LinearGradient | RadialGradient | PatternFill;
449
485
  /** Style overrides for a single rich-text segment. */
@@ -495,7 +531,7 @@ interface CustomPatternDef {
495
531
  /** Tile height in userSpaceOnUse coordinates. */
496
532
  height: number;
497
533
  }
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';
534
+ 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
535
  type BlurQuality = 'normal' | 'high';
500
536
  interface BaseFilter {
501
537
  id: string;
@@ -558,6 +594,41 @@ interface SpotLightFilter extends BaseFilter {
558
594
  specularConstant: number;
559
595
  specularExponent: number;
560
596
  }
597
+ type LightSource = {
598
+ kind: 'point';
599
+ x: number;
600
+ y: number;
601
+ z: number;
602
+ } | {
603
+ kind: 'spot';
604
+ x: number;
605
+ y: number;
606
+ z: number;
607
+ pointsAtX: number;
608
+ pointsAtY: number;
609
+ pointsAtZ: number;
610
+ limitingConeAngle?: number;
611
+ specularExponent?: number;
612
+ } | {
613
+ kind: 'distant';
614
+ azimuth: number;
615
+ elevation: number;
616
+ };
617
+ interface DiffuseLightingFilter extends BaseFilter {
618
+ type: 'diffuse-lighting';
619
+ surfaceScale: number;
620
+ diffuseConstant: number;
621
+ color: string;
622
+ lightSource: LightSource;
623
+ }
624
+ interface SpecularLightingFilter extends BaseFilter {
625
+ type: 'specular-lighting';
626
+ surfaceScale: number;
627
+ specularConstant: number;
628
+ specularExponent: number;
629
+ color: string;
630
+ lightSource: LightSource;
631
+ }
561
632
  type OutlinePosition = 'outside' | 'center' | 'inside';
562
633
  interface OutlineFilter extends BaseFilter {
563
634
  type: 'outline';
@@ -706,7 +777,29 @@ interface InnerGlowFilter extends BaseFilter {
706
777
  radius: number;
707
778
  intensity: number;
708
779
  }
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;
780
+ /**
781
+ * Passthrough for `<filter>` definitions the editor doesn't model as a preset.
782
+ * The parser serialises the element's inner markup and authored region
783
+ * attributes verbatim; the filter manager re-emits them on render. Absent
784
+ * attributes stay `undefined` so the UA applies the SVG spec initial values
785
+ * (filterUnits=objectBoundingBox, primitiveUnits=userSpaceOnUse, filter region
786
+ * -10% -10% 120% 120%, color-interpolation-filters=linearRGB).
787
+ */
788
+ interface RawSvgFilter extends BaseFilter {
789
+ type: 'raw-svg';
790
+ svgContent: string;
791
+ x?: string;
792
+ y?: string;
793
+ width?: string;
794
+ height?: string;
795
+ filterUnits?: 'userSpaceOnUse' | 'objectBoundingBox';
796
+ primitiveUnits?: 'userSpaceOnUse' | 'objectBoundingBox';
797
+ colorInterpolationFilters?: 'auto' | 'sRGB' | 'linearRGB';
798
+ floodColor?: string;
799
+ floodOpacity?: string;
800
+ lightingColor?: string;
801
+ }
802
+ 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
803
  type SegmentCurveType = 'LINEAR' | 'CUBIC' | 'QUADRATIC' | 'ARC';
711
804
  interface SplinePoint {
712
805
  x: number;
@@ -775,6 +868,84 @@ interface DocumentMetadata {
775
868
  licenseUrl: string;
776
869
  language: string;
777
870
  customMetadata: Record<string, string>;
871
+ /**
872
+ * Decimal precision for coordinate values when the document is
873
+ * serialized — file save, cloud sync, undo capture, and SVG export.
874
+ * Stored on the document so collaborators stay consistent and
875
+ * round-trips are deterministic.
876
+ *
877
+ * Range 0-12. Defaults to 3 (sub-pixel precision adequate for screen
878
+ * rendering; matches SVGO's `floatPrecision` and Adobe Illustrator's
879
+ * SVG export defaults). Set higher (6-8) when authoring assets for
880
+ * high-fidelity interchange. Values above 8 carry no practical benefit
881
+ * at the coordinate ranges typical of SVG documents.
882
+ *
883
+ * Imported SVGs are NOT rounded on the way in; the first edit or save
884
+ * conforms them to this precision.
885
+ */
886
+ coordinatePrecision?: number;
887
+ }
888
+ /**
889
+ * A document-level `<script>` element. Scripts are stored as inert data
890
+ * alongside document metadata — never executed inside the editor — and
891
+ * re-emitted on export.
892
+ *
893
+ * Spec reference: SVG 2 §15.9 (The `<script>` element).
894
+ */
895
+ interface DocumentScript {
896
+ /** Internal id (guid) used for list keying inside the editor. */
897
+ id: string;
898
+ /** Preserved `id` attribute from the source SVG, if any. */
899
+ svgId?: string;
900
+ /** Whether this script has inline body text or an external href. */
901
+ source: 'inline' | 'external';
902
+ /** Script body for inline scripts. Empty for external. */
903
+ content: string;
904
+ /** URL for external scripts. */
905
+ href?: string;
906
+ /** MIME type. Defaults to 'application/ecmascript' per SVG 2. */
907
+ type: string;
908
+ /** CORS setting. */
909
+ crossorigin?: 'anonymous' | 'use-credentials';
910
+ /** async attribute (SVG 2 aligns with HTML). */
911
+ async?: boolean;
912
+ /** defer attribute (SVG 2 aligns with HTML). */
913
+ defer?: boolean;
914
+ /** Unknown/extra attributes preserved for round-trip fidelity. */
915
+ customAttrs?: Record<string, string>;
916
+ }
917
+ /**
918
+ * A document-level `<style>` block captured from the imported SVG and
919
+ * re-emitted verbatim on export.
920
+ *
921
+ * Styles with `preserved: true` are opaque CSS blobs the editor refuses
922
+ * to reinterpret because their matched elements live inside `<defs>`
923
+ * subtrees (mask / clipPath / symbol / pattern) that never become canvas
924
+ * shapes. Keeping them intact is the only way to round-trip author CSS
925
+ * that drives mask-interior animations (e.g. `stroke-dashoffset` flow on
926
+ * `<use>` elements inside a `<mask>`).
927
+ *
928
+ * Spec reference: SVG 2 §16 (The `<style>` element).
929
+ */
930
+ interface DocumentStyle {
931
+ /** Internal id (guid) used for list keying inside the editor. */
932
+ id: string;
933
+ /** Preserved `id` attribute from the source SVG, if any. */
934
+ svgId?: string;
935
+ /** Raw CSS source — `@keyframes`, rules, `@media`, etc. */
936
+ css: string;
937
+ /** `type` attribute. Defaults to `text/css`. */
938
+ type?: string;
939
+ /** `media` attribute, if specified. */
940
+ media?: string;
941
+ /**
942
+ * When true, this block was captured verbatim during import because
943
+ * the editor cannot safely reinterpret its effect. Must be emitted
944
+ * as-is on export.
945
+ */
946
+ preserved: boolean;
947
+ /** Unknown/extra attributes preserved for round-trip fidelity. */
948
+ customAttrs?: Record<string, string>;
778
949
  }
779
950
  /** Type of a template variable's value. */
780
951
  type TemplateVariableType = 'string' | 'color' | 'number';
@@ -884,6 +1055,14 @@ interface CommonNodeProps {
884
1055
  dashOffset: number;
885
1056
  strokeDasharray: string | null;
886
1057
  filters: unknown[];
1058
+ filterColorInterpolation: 'auto' | 'sRGB' | 'linearRGB' | null;
1059
+ filterUnits: 'userSpaceOnUse' | 'objectBoundingBox' | null;
1060
+ primitiveUnits: 'userSpaceOnUse' | 'objectBoundingBox' | null;
1061
+ filterX: string | null;
1062
+ filterY: string | null;
1063
+ filterWidth: string | null;
1064
+ filterHeight: string | null;
1065
+ rawTransform: string | null;
887
1066
  metadata: unknown | null;
888
1067
  cssClipPath: string | null;
889
1068
  cssMaskProperties: Record<string, string> | null;
@@ -1106,6 +1285,16 @@ interface SerializedShape {
1106
1285
  rx?: number;
1107
1286
  ry?: number;
1108
1287
  cornerRadius?: number;
1288
+ cornerShape?: 'round' | 'notch' | 'bevel' | 'scoop';
1289
+ cornerMode?: 'uniform' | 'non-uniform';
1290
+ cornerRadiusTL?: number;
1291
+ cornerRadiusTR?: number;
1292
+ cornerRadiusBL?: number;
1293
+ cornerRadiusBR?: number;
1294
+ cornerShapeTL?: 'round' | 'notch' | 'bevel' | 'scoop';
1295
+ cornerShapeTR?: 'round' | 'notch' | 'bevel' | 'scoop';
1296
+ cornerShapeBL?: 'round' | 'notch' | 'bevel' | 'scoop';
1297
+ cornerShapeBR?: 'round' | 'notch' | 'bevel' | 'scoop';
1109
1298
  fontSize?: number;
1110
1299
  text?: string;
1111
1300
  fontFamily?: string;
@@ -1139,6 +1328,8 @@ interface SerializedShape {
1139
1328
  x: number;
1140
1329
  dy: number;
1141
1330
  }[];
1331
+ textLength?: number;
1332
+ lengthAdjust?: 'spacing' | 'spacingAndGlyphs';
1142
1333
  /**
1143
1334
  * Whether this text element uses the rich-text model (styled runs with
1144
1335
  * per-character formatting) versus the plain-text model. When true,
@@ -1161,6 +1352,15 @@ interface SerializedShape {
1161
1352
  borderColor?: string;
1162
1353
  borderWidth?: number | string;
1163
1354
  strokeOpacity?: number;
1355
+ /** CSS `paint-order` (SVG 2). Canonical SVG token string, e.g.
1356
+ * 'stroke fill markers'. Omitted when equivalent to default 'normal'. */
1357
+ paintOrder?: string;
1358
+ /** Marker id applied as `marker-start` (rendered `url(#id)` in SVG). */
1359
+ markerStart?: string;
1360
+ /** Marker id applied as `marker-mid`. */
1361
+ markerMid?: string;
1362
+ /** Marker id applied as `marker-end`. */
1363
+ markerEnd?: string;
1164
1364
  cx?: number;
1165
1365
  cy?: number;
1166
1366
  sides?: number;
@@ -1217,6 +1417,14 @@ interface SerializedShape {
1217
1417
  strokeType?: StrokeType;
1218
1418
  strokeGradient?: LinearGradient | RadialGradient | PatternFill;
1219
1419
  filters?: ShapeFilter[];
1420
+ filterColorInterpolation?: 'auto' | 'sRGB' | 'linearRGB';
1421
+ filterUnits?: 'userSpaceOnUse' | 'objectBoundingBox';
1422
+ primitiveUnits?: 'userSpaceOnUse' | 'objectBoundingBox';
1423
+ filterX?: string;
1424
+ filterY?: string;
1425
+ filterWidth?: string;
1426
+ filterHeight?: string;
1427
+ rawTransform?: string;
1220
1428
  splinePoints?: SplinePoint[];
1221
1429
  splineCurveType?: SplineCurveType;
1222
1430
  splineClosed?: boolean;
@@ -1229,6 +1437,40 @@ interface SerializedShape {
1229
1437
  originalHeight?: number;
1230
1438
  preserveAspectRatio?: boolean;
1231
1439
  imageOpacity?: number;
1440
+ mediaKind?: 'audio' | 'video';
1441
+ mediaMimeType?: string;
1442
+ naturalDuration?: number;
1443
+ begin?: number;
1444
+ trimStart?: number;
1445
+ trimEnd?: number;
1446
+ volume?: number;
1447
+ muted?: boolean;
1448
+ loop?: boolean;
1449
+ playbackRate?: number;
1450
+ mediaOpacity?: number;
1451
+ /** Auto-generated volume ramp length at clip start (seconds). */
1452
+ fadeInDuration?: number;
1453
+ /** Auto-generated volume ramp length at clip end (seconds). */
1454
+ fadeOutDuration?: number;
1455
+ /** First-frame thumbnail (data URI or /api/image-assets URL). Video only. */
1456
+ posterHref?: string;
1457
+ /** Crop rectangle in source pixels. Video only. */
1458
+ sourceRect?: {
1459
+ x: number;
1460
+ y: number;
1461
+ width: number;
1462
+ height: number;
1463
+ };
1464
+ /**
1465
+ * BCP 47 language tag matched against the user agent's language
1466
+ * preferences via SVG's `systemLanguage` conditional-processing
1467
+ * attribute. Meaningful when a `<switch>` wraps multiple
1468
+ * localized media alternatives — the UA picks the foreignObject
1469
+ * whose language matches. No editor UI yet; preserved on
1470
+ * import/export for forward compatibility with translated
1471
+ * soundtracks / captioned video versions.
1472
+ */
1473
+ systemLanguage?: string;
1232
1474
  shapeInsideRef?: string;
1233
1475
  shapePadding?: number;
1234
1476
  isTextPath?: boolean;
@@ -1276,6 +1518,40 @@ interface SerializedShape {
1276
1518
  * when serialized to standalone SVG.
1277
1519
  */
1278
1520
  bindings?: Record<string, string>;
1521
+ /** User-placed custom connection anchors. Derived anchors are not persisted. */
1522
+ connectionPoints?: ConnectionPoint[];
1523
+ /** Connector shape: reference to the source shape + anchor it attaches to. */
1524
+ sourceRef?: {
1525
+ shapeId: string;
1526
+ anchorId: string;
1527
+ } | null;
1528
+ /** Connector shape: reference to the target shape + anchor it attaches to. */
1529
+ targetRef?: {
1530
+ shapeId: string;
1531
+ anchorId: string;
1532
+ } | null;
1533
+ /** Connector shape: cached absolute source point (recomputed when source moves). */
1534
+ sourcePoint?: Point;
1535
+ /** Connector shape: cached absolute target point. */
1536
+ targetPoint?: Point;
1537
+ /** Connector shape: interior waypoints for orthogonal routing. */
1538
+ waypoints?: Point[];
1539
+ /** Connector shape: path routing algorithm. */
1540
+ routingMode?: 'straight' | 'orthogonal' | 'rounded-ortho' | 'curved';
1541
+ /** Connector shape: in-path label (double-click to edit). */
1542
+ label?: string;
1543
+ /** Connector shape: label position along the path (0–1). */
1544
+ labelPosition?: number;
1545
+ /** Connector shape: perpendicular offset of the label. */
1546
+ labelOffset?: number;
1547
+ /** Connector shape: stroke style to Mermaid edge mapping. */
1548
+ mermaidEdgeStyle?: 'solid' | 'thick' | 'dotted';
1549
+ /** Parallelogram/trapezoid slant amount as a % of width. */
1550
+ slantPercent?: number;
1551
+ /** Trapezoid top width as a % of the bottom width (0–100). */
1552
+ topWidthPercent?: number;
1553
+ /** Document shape: wave amplitude as a % of height. */
1554
+ waveAmplitudePercent?: number;
1279
1555
  };
1280
1556
  }
1281
1557
  type SerializedViewbox = Viewbox;
@@ -1317,6 +1593,15 @@ interface HistorySnapshot {
1317
1593
  clipMaskGroups?: SerializedClipMaskGroup[];
1318
1594
  /** Document-level metadata (title, description, author, etc.) */
1319
1595
  documentMetadata?: DocumentMetadata;
1596
+ /** Document-level `<script>` elements (SVG 2 §15.9). */
1597
+ documentScripts?: DocumentScript[];
1598
+ /**
1599
+ * Document-level `<style>` blocks captured from the source SVG and
1600
+ * re-emitted verbatim on export. Used for CSS whose effect targets
1601
+ * def-scoped content (mask / clipPath / symbol interiors) that the
1602
+ * editor cannot translate into AnimationTracks.
1603
+ */
1604
+ documentStyles?: DocumentStyle[];
1320
1605
  /** Template variable definitions with defaults. */
1321
1606
  templateVariables?: TemplateVariable[];
1322
1607
  /** Animation timeline (tracks, keyframes, easing). */
@@ -1325,6 +1610,12 @@ interface HistorySnapshot {
1325
1610
  customPatterns?: CustomPatternDef[];
1326
1611
  /** Symbol definitions (reusable component templates). */
1327
1612
  symbols?: SerializedSymbolDef[];
1613
+ /**
1614
+ * Marker definitions (reusable vertex-attached graphics: arrowheads, dots,
1615
+ * etc.). Built-in markers are reconstituted at load time by MarkerManager
1616
+ * and are NOT persisted here — only user-authored defs are stored.
1617
+ */
1618
+ markers?: SerializedMarkerDef[];
1328
1619
  }
1329
1620
  /**
1330
1621
  * A variant axis on a component symbol. Each axis has a name (e.g.
@@ -1384,6 +1675,74 @@ interface SerializedSymbolDef {
1384
1675
  */
1385
1676
  variantThumbnails?: Record<string, string>;
1386
1677
  }
1678
+ /**
1679
+ * A reusable `<marker>` definition (SVG 2 §11.6). Markers are vertex-attached
1680
+ * graphics — arrowheads, vertex dots, decorations — referenced via
1681
+ * `marker-start` / `marker-mid` / `marker-end` attributes on stroked shapes.
1682
+ *
1683
+ * The browser handles per-vertex positioning, scaling (via `markerUnits`),
1684
+ * and orientation (via `orient`, including tangent-aware `auto` mode on
1685
+ * curved paths). MarkerManager only maintains the DOM `<defs>` entries in
1686
+ * sync with this serialized state.
1687
+ *
1688
+ * Simpler than `SerializedSymbolDef` — markers have no variants, no instance
1689
+ * overrides, and no placed instances (they attach via attribute references).
1690
+ */
1691
+ interface SerializedMarkerDef {
1692
+ /**
1693
+ * Unique identifier.
1694
+ * - Built-in markers use stable ids: `mkr-builtin-arrow`, `mkr-builtin-open-arrow`,
1695
+ * `mkr-builtin-circle`, `mkr-builtin-diamond`, `mkr-builtin-square`.
1696
+ * - User-created markers use `mkr-<guid>`.
1697
+ */
1698
+ id: string;
1699
+ /** Human-readable name shown in the markers panel. */
1700
+ name: string;
1701
+ /** SVG viewBox string ("minX minY width height"). */
1702
+ viewBox: string;
1703
+ /** X reference point — where the marker's "tip" aligns with the host vertex. */
1704
+ refX: number;
1705
+ refY: number;
1706
+ markerWidth: number;
1707
+ markerHeight: number;
1708
+ /**
1709
+ * `strokeWidth` scales the marker with the host's stroke-width (default,
1710
+ * typical for arrows). `userSpaceOnUse` renders at fixed size regardless
1711
+ * of stroke.
1712
+ */
1713
+ markerUnits: 'strokeWidth' | 'userSpaceOnUse';
1714
+ /**
1715
+ * `auto` rotates to match the path tangent at each vertex.
1716
+ * `auto-start-reverse` reverses the start marker (so arrowheads don't
1717
+ * point inward at path starts). A number is a fixed rotation in degrees.
1718
+ */
1719
+ orient: 'auto' | 'auto-start-reverse' | number;
1720
+ /**
1721
+ * Inner geometry. For user markers this is the authoritative source —
1722
+ * edited via isolation mode and re-rendered into the DOM `<marker>` child.
1723
+ * For built-ins this is `[]` in v1; built-ins render from the descriptor
1724
+ * registry (`getMarkerDescriptors()`) and are not editable.
1725
+ */
1726
+ shapes: SerializedShape[];
1727
+ /** Groups within the marker (mirrors `SerializedSymbolDef.groups`). */
1728
+ groups?: SerializedGroup[];
1729
+ /** Base64 data-URI thumbnail for the markers panel. */
1730
+ thumbnail?: string;
1731
+ /**
1732
+ * Animation tracks scoped to the marker's inner shapes. Each track's
1733
+ * `shapeId` references an id in `shapes`. During isolation editing these
1734
+ * tracks are merged into the document timeline (tagged `scope:
1735
+ * 'marker:<id>'`) so the user can edit them; on save they're extracted
1736
+ * back here. On SVG export the tracks render as SMIL `<animate>` elements
1737
+ * inside the `<marker>` DOM so they play at every attached vertex.
1738
+ */
1739
+ animations?: SerializedAnimationTimeline['tracks'];
1740
+ /**
1741
+ * True for editor-shipped built-ins (arrow, open-arrow, circle, diamond,
1742
+ * square). Built-ins are non-deletable, non-renamable, and non-editable.
1743
+ */
1744
+ builtIn?: boolean;
1745
+ }
1387
1746
  interface SerializedGroup {
1388
1747
  id: string;
1389
1748
  parentId: string | null;
@@ -1777,6 +2136,65 @@ declare function extractVariables(snapshot: HistorySnapshot): ExtractedVariables
1777
2136
  */
1778
2137
  declare function parseVariableArgs(args: string[]): VariableMap;
1779
2138
 
2139
+ /**
2140
+ * @svgsketch/core — Coordinate precision utilities.
2141
+ *
2142
+ * Pure rounding utilities used at every state-capture boundary in the
2143
+ * editor (per-shape command capture, full snapshot capture, SVG export)
2144
+ * to enforce a configurable decimal precision on persisted/exported
2145
+ * coordinate values.
2146
+ *
2147
+ * Rounding fires only on the way OUT of the document model (save, export,
2148
+ * undo capture). Imports are never rounded — see DocumentMetadata's
2149
+ * `coordinatePrecision` field for the policy.
2150
+ *
2151
+ * Industry context: Adobe Illustrator, Inkscape, Affinity Designer, and
2152
+ * SVGO all expose a precision control. Default 3 decimals matches SVGO
2153
+ * and Illustrator.
2154
+ */
2155
+
2156
+ /** Default precision when DocumentMetadata.coordinatePrecision is unset. */
2157
+ declare const DEFAULT_COORDINATE_PRECISION = 3;
2158
+ /**
2159
+ * Maximum precision we accept. Above 12 the rounding becomes a no-op for
2160
+ * practical SVG coordinate ranges (float64 has ~15-17 significant digits).
2161
+ */
2162
+ declare const MAX_COORDINATE_PRECISION = 12;
2163
+ /**
2164
+ * Resolve an optional precision value to a concrete one. Clamps to the
2165
+ * supported range and substitutes the default for `undefined` / `null` /
2166
+ * non-finite inputs.
2167
+ */
2168
+ declare function getEffectivePrecision(p: number | undefined | null): number;
2169
+ /**
2170
+ * Round a single number to N decimal places. Non-finite inputs (NaN,
2171
+ * Infinity) pass through unchanged so we never poison data with NaN.
2172
+ */
2173
+ declare function roundCoord(value: number, precision: number): number;
2174
+ /**
2175
+ * Round every numeric token in a string in place. Does not touch any
2176
+ * non-numeric content (operators, commands, whitespace).
2177
+ */
2178
+ declare function roundNumberString(s: string, precision: number): string;
2179
+ /**
2180
+ * Round all coordinate-bearing numeric fields in a SerializedShape's
2181
+ * state. Returns a new object — input is not mutated.
2182
+ *
2183
+ * `id` and `type` are passed through unchanged.
2184
+ */
2185
+ declare function roundSerializedShape(shape: SerializedShape, precision: number): SerializedShape;
2186
+ /**
2187
+ * Round all coordinate-bearing fields in a complete HistorySnapshot.
2188
+ * Used at the snapshot-level capture boundary (file save, cloud sync).
2189
+ *
2190
+ * Returns a new snapshot with shapes, viewboxes, guides, measurements,
2191
+ * and the animation timeline rounded. Document metadata (titles, IDs,
2192
+ * etc.) and structural fields (groups, clipMaskGroups, scripts, symbols)
2193
+ * pass through with their numeric leaves rounded but their structure
2194
+ * preserved.
2195
+ */
2196
+ declare function roundSnapshot(snapshot: HistorySnapshot, precision: number): HistorySnapshot;
2197
+
1780
2198
  /**
1781
2199
  * Document-level SVG renderer.
1782
2200
  *
@@ -2051,6 +2469,7 @@ declare function generatePatternSvgContent(patternType: string, scale: number, c
2051
2469
  *
2052
2470
  * @packageDocumentation
2053
2471
  */
2472
+
2054
2473
  interface MarkerDescriptor {
2055
2474
  /** Marker element id (e.g., 'line-marker-arrow'). */
2056
2475
  id: string;
@@ -2075,6 +2494,22 @@ declare const MARKER_HEIGHT = 6;
2075
2494
  * `markerUnits="strokeWidth"`, and `orient="auto-start-reverse"`.
2076
2495
  */
2077
2496
  declare function getMarkerDescriptors(): MarkerDescriptor[];
2497
+ /**
2498
+ * Maps the legacy marker ids (used by line endpoint shape state) to the new
2499
+ * first-class MarkerManager ids. The legacy ids remain valid references in
2500
+ * the DOM — built-ins are emitted under BOTH ids to preserve backwards
2501
+ * compat with saved docs that reference `url(#line-marker-arrow)`.
2502
+ */
2503
+ declare const BUILTIN_MARKER_ID_MAP: Record<string, string>;
2504
+ /**
2505
+ * Return `SerializedMarkerDef`s for the built-in line endpoint markers.
2506
+ *
2507
+ * Built-ins carry `shapes: []` — their geometry is rendered by the editor
2508
+ * directly from the descriptor registry rather than from `SerializedShape`s.
2509
+ * This keeps descriptor → shape conversion out of v1 scope. Consequence:
2510
+ * built-ins are non-editable (the markers panel disables Edit on them).
2511
+ */
2512
+ declare function getBuiltInMarkerDefs(): SerializedMarkerDef[];
2078
2513
 
2079
2514
  /**
2080
2515
  * SMIL animation renderer — converts SerializedAnimationTimeline
@@ -3349,4 +3784,4 @@ declare class Document {
3349
3784
  private _ensureMetadata;
3350
3785
  }
3351
3786
 
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 };
3787
+ 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 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, type LightSource, Line, type LineEndpointValue, type LineNodeProps, type LinearEasingPoint, type LinearGradient, LinearGradientBuilder, type LinkTarget, MARKER_HEIGHT, MARKER_VIEWBOX, MARKER_WIDTH, MAX_COORDINATE_PRECISION, 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, 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 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, getBuiltInMarkerDefs, getEasingCubicBezier, getEffectivePrecision, getMarkerDescriptors, getPatternElements, linearGradient, migrateSnapshot, parseDocument, parseVariableArgs, pattern, radialGradient, renderAnimationElements, renderCircle, renderEllipse, renderFilterDefs, renderFilterPrimitivesForType, renderImage, renderLine, renderPolygonShape, renderPolyline, renderRectangle, renderShape, renderSpline, renderText, renderToSvg, roundCoord, roundNumberString, roundSerializedShape, roundSnapshot, stringifyDocument, substituteString, substituteVariables, validateSnapshot, verticesToPath };