@grida/svg-editor 1.0.0-alpha.16 → 1.0.0-alpha.18

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.
@@ -644,6 +644,8 @@ declare class SvgDocument implements DocumentEvents {
644
644
  * stays the same and React skips the re-render of the whole tree.
645
645
  */
646
646
  private _structure_version;
647
+ /** Total listener-visible mutation count. See the `revision` getter. */
648
+ private _revision;
647
649
  /** Bumps on writes that can shift world-space bounds (`GEOMETRY_ATTRS`,
648
650
  * `set_text`, `insert`, `remove`). Cache key for `GeometryProvider`;
649
651
  * see ../../docs/geometry.md. */
@@ -657,6 +659,18 @@ declare class SvgDocument implements DocumentEvents {
657
659
  on_change(fn: () => void): () => void;
658
660
  /** See `_structure_version` for what this counter signals. */
659
661
  get structure_version(): number;
662
+ /**
663
+ * Total mutation counter — advances on EVERY listener-visible mutation
664
+ * (attribute, style, text, topology, load/reset), unlike the selective
665
+ * `structure_version` / `geometry_version` channels. The single
666
+ * edit-version source: anything derived from this document — the
667
+ * editor's `content_version` / `dirty`, memoized reads, a rendered
668
+ * projection — answers "am I current?" by comparing values, with no
669
+ * event-ordering dependence. Advances BEFORE listeners fire, so a
670
+ * read issued from inside a change listener already sees the new
671
+ * value.
672
+ */
673
+ get revision(): number;
660
674
  /** See `_geometry_version` for what this counter signals. */
661
675
  get geometry_version(): number;
662
676
  /**
@@ -671,10 +685,9 @@ declare class SvgDocument implements DocumentEvents {
671
685
  * settled glyph metrics. See ../../docs/geometry.md §Limitations.
672
686
  *
673
687
  * Deliberately does NOT call `emit()`: this is not a document edit, so
674
- * it must not bump `doc_version` / mark the doc dirty / touch undo
675
- * (the editor's `on_change` handler does all three). The editor's
676
- * `_internal.bump_geometry` advances `geometry_version` here and fans
677
- * out the geometry listeners itself.
688
+ * `revision` must not advance no dirty flag, no undo, no render
689
+ * flush. The editor's `_internal.bump_geometry` advances
690
+ * `geometry_version` here and fans out the geometry listeners itself.
678
691
  */
679
692
  bump_geometry(): void;
680
693
  private emit;
@@ -1382,6 +1395,129 @@ declare class Keymap {
1382
1395
  private chunkKeysFor;
1383
1396
  }
1384
1397
  //#endregion
1398
+ //#region src/core/subtree.d.ts
1399
+ declare namespace subtree {
1400
+ /**
1401
+ * Document-order comparator over node ids. Builds the index once per
1402
+ * call (one full tree walk) — create one comparator per operation and
1403
+ * reuse it, as `clipboard.extract_payload` does.
1404
+ */
1405
+ function by_document_order(doc: SvgDocument): (a: NodeId, b: NodeId) => number;
1406
+ /**
1407
+ * Selection normalization — the half of extraction that payload
1408
+ * extraction (copy) and subtree clone share, per the FRD:
1409
+ * dedupe → live elements only → ancestor subtrees subsume selected
1410
+ * descendants (`prune_nested_nodes`) → DOCUMENT order regardless of
1411
+ * selection order (sibling order is paint order, and paint order is
1412
+ * meaning). Stale / non-element / detached ids are skipped, never
1413
+ * thrown — normalization is a filter, not a validator.
1414
+ */
1415
+ function normalize_roots(doc: SvgDocument, selection: ReadonlyArray<NodeId>, order?: (a: NodeId, b: NodeId) => number): NodeId[];
1416
+ /** One origin → clone pairing with the clone's placement, captured at
1417
+ * plan time. `before` is the origin's next sibling NODE (element or
1418
+ * trivia) so the clone lands immediately after its origin. */
1419
+ type SubtreeClonePlanEntry = {
1420
+ origin: NodeId;
1421
+ /** Registered in the document's node map, DETACHED (`create_fragment`
1422
+ * style) — the consumer inserts it inside its own history closure. */
1423
+ clone: NodeId; /** `parent_of(origin)` at plan time. */
1424
+ parent: NodeId; /** `next_sibling_of(origin)` at plan time; `null` = append. */
1425
+ before: NodeId | null;
1426
+ };
1427
+ type SubtreeClonePlan = ReadonlyArray<SubtreeClonePlanEntry>;
1428
+ /**
1429
+ * Build a clone plan for the selection: for each normalized origin,
1430
+ * serialize its subtree verbatim and re-adopt it under fresh runtime
1431
+ * NodeIds via `create_fragment` — the markup round-trip rides the same
1432
+ * trivia-preserving emit and never-rewrite-ids adoption the package
1433
+ * already guarantees, so `serialize_node(clone) === serialize_node(origin)`
1434
+ * byte-for-byte once inserted.
1435
+ *
1436
+ * Clones are returned DETACHED (plan, don't insert): consumers own
1437
+ * insertion inside their history closures so redo can re-insert the
1438
+ * same NodeIds (`remove` keeps nodes in the id map).
1439
+ *
1440
+ * Skipped origins (refusals, normalized away — not errors):
1441
+ * - the document root and any other parentless node (no sibling slot);
1442
+ * - nested `<svg>` elements — `create_fragment` deliberately treats a
1443
+ * lone `<svg>` root as a full-document shell and discards it (the
1444
+ * FRD's paste rule), which would silently unwrap the clone; refusing
1445
+ * beats mishandling.
1446
+ *
1447
+ * An empty selection (or one that normalizes to nothing) yields an
1448
+ * empty plan — the caller's no-op.
1449
+ */
1450
+ function clone_plan(doc: SvgDocument, selection: ReadonlyArray<NodeId>): SubtreeClonePlan;
1451
+ /**
1452
+ * Attach every plan clone at its captured anchor. Anchors predate the
1453
+ * plan (captured before any insertion), so no entry anchors on another
1454
+ * entry's clone — each insert is independent and the interleaved
1455
+ * `A, A′, B, B′` order falls out of the per-origin anchors.
1456
+ *
1457
+ * Idempotent: `doc.insert` detaches-then-splices, so re-attaching an
1458
+ * already-live clone repositions it to the same slot. History redo
1459
+ * closures rely on this.
1460
+ */
1461
+ function insert_plan(doc: SvgDocument, plan: SubtreeClonePlan): void;
1462
+ /**
1463
+ * Detach every plan clone. Order-independent for the same reason
1464
+ * {@link insert_plan} is: anchors are never plan clones. Removed nodes
1465
+ * stay in the document's id map (standard removed-node policy), so a
1466
+ * later {@link insert_plan} over the same plan restores them.
1467
+ */
1468
+ function remove_plan(doc: SvgDocument, plan: SubtreeClonePlan): void;
1469
+ /**
1470
+ * The last committed duplication — the memory the repeating-offset
1471
+ * behavior reads (gridaco/grida#825; spec:
1472
+ * [docs/wg/feat-svg-editor/subtree-clone.md](../../../../docs/wg/feat-svg-editor/subtree-clone.md)
1473
+ * §Repeating offset). Armed by `commands.duplicate` and by a cloned
1474
+ * translate commit (Alt-drag); consumed and re-armed by the next
1475
+ * `duplicate()`. Editor-session state — never observable, never in
1476
+ * history. Staleness is caught at use by {@link repeat_delta}, not by
1477
+ * per-mutation bookkeeping.
1478
+ *
1479
+ * The arrays are INDEX-PAIRED: `clones[i]` is the clone of
1480
+ * `origins[i]` (both producers derive them from the same
1481
+ * {@link SubtreeClonePlan}). {@link repeat_delta}'s per-member
1482
+ * rigidity check depends on that pairing.
1483
+ */
1484
+ type DuplicationRecord = {
1485
+ origins: ReadonlyArray<NodeId>;
1486
+ clones: ReadonlyArray<NodeId>;
1487
+ };
1488
+ /**
1489
+ * The repeating-offset delta (gridaco/grida#825): given the previous
1490
+ * duplication's record and the CURRENT duplicate's normalized origins,
1491
+ * return the world-space offset the fresh clones should repeat, or
1492
+ * `null` for "no repeat — duplicate in place".
1493
+ *
1494
+ * The repeat fires only when the record still witnesses
1495
+ * "duplicate, then rigidly translate the copies":
1496
+ * - `targets` is exactly `record.clones`, in the same (document)
1497
+ * order — the user is duplicating the previous duplication's
1498
+ * copies and nothing else;
1499
+ * - `bounds_of` answers for EVERY member of both sets (a detached
1500
+ * member, a measureless tag, or a missing geometry provider all
1501
+ * refuse);
1502
+ * - EVERY clone is rigid against its own origin (the record's
1503
+ * arrays are index-paired): same size, displaced by the same
1504
+ * delta as the union, within {@link REPEAT_RIGID_EPSILON}. The
1505
+ * check is per member, not per envelope — a rearranged or
1506
+ * resized inner copy is no longer a translate even when the
1507
+ * envelope-defining copies keep the union bbox intact;
1508
+ * - the union top-left delta exceeds the same tolerance (a copy
1509
+ * that never moved — or drifted by float noise only — repeats
1510
+ * nothing; the in-place duplicate stays byte-equal instead of
1511
+ * inheriting noise-sized attribute writes).
1512
+ *
1513
+ * Pure and gesture-grade: reads only through `bounds_of`, never
1514
+ * throws — every failed precondition degrades to `null` (the main
1515
+ * editor's `active_duplication` assert-on-mismatch is deliberately
1516
+ * NOT copied; ⌘D must never crash on a stale record).
1517
+ */
1518
+ function repeat_delta(record: DuplicationRecord | null, targets: ReadonlyArray<NodeId>, bounds_of: (id: NodeId) => Rect | null): Vec2 | null;
1519
+ }
1520
+ //#endregion
1385
1521
  //#region src/core/geometry.d.ts
1386
1522
  /**
1387
1523
  * Read-only access to world-space node bounds and hit-tests.
@@ -1390,6 +1526,19 @@ declare class Keymap {
1390
1526
  * will query dozens of nodes per pointermove. The driver wraps SVG
1391
1527
  * `getBBox` + `getCTM`; the memoizer caches per-`NodeId` to survive
1392
1528
  * the surface re-rendering the SVG tree every editor tick.
1529
+ *
1530
+ * **Freshness contract.** Every read MUST reflect the CURRENT document
1531
+ * — including when issued synchronously from inside a doc-change
1532
+ * listener (`subscribe_geometry` fires mid-mutation, before any
1533
+ * render). An implementation backed by a lazily-synced projection
1534
+ * (e.g. a rendered DOM tree) must flush that projection before
1535
+ * reading; compare `SvgDocument.revision` against the projection's
1536
+ * last-rendered revision. Returning the previous document's geometry
1537
+ * is not a transient glitch: the `MemoizedGeometryProvider` wrapper
1538
+ * caches whatever the driver returns, so one stale read poisons every
1539
+ * later consumer until the next invalidation (align/resize then plan
1540
+ * against one-mutation-old bounds and oscillate — see
1541
+ * `__tests__/geometry-stale-read.browser.test.ts`).
1393
1542
  */
1394
1543
  interface GeometryProvider {
1395
1544
  /**
@@ -1766,6 +1915,93 @@ type Commands = {
1766
1915
  }): boolean;
1767
1916
  reorder(direction: ReorderDirection): void;
1768
1917
  remove(): void;
1918
+ /**
1919
+ * Copy the selection as a **standalone SVG document** (the payload is
1920
+ * the file format — no private envelope). The payload carries the
1921
+ * outbound `url(#…)` / `href` reference closure in one `<defs>` block
1922
+ * and declares every namespace prefix the fragment borrows from
1923
+ * ancestor scope; ancestor transforms, inherited presentation, and the
1924
+ * viewport are deliberately NOT carried (verbatim policy — see the FRD).
1925
+ *
1926
+ * Pure read: no document mutation, no history entry. The payload is
1927
+ * always written to the editor's internal clipboard buffer (the
1928
+ * transport floor — cannot fail) and, when a `ClipboardProvider` is
1929
+ * configured, delivered to it best-effort (a failed provider write is
1930
+ * dev-warned, never a copy failure).
1931
+ *
1932
+ * Returns the payload string, or `null` on empty / non-live selection
1933
+ * (a no-op, not an error — copy has no refusal path).
1934
+ */
1935
+ copy(): string | null;
1936
+ /**
1937
+ * Copy, then delete the selection — ONE history step labeled `"cut"`
1938
+ * with {@link remove}'s exact capture/revert semantics. The payload is
1939
+ * secured in the internal buffer BEFORE the deletion commits, so a
1940
+ * failed external write never strands the user with deleted content
1941
+ * and no copy. The clipboard write is not part of the history step:
1942
+ * undo restores the document and leaves the buffer holding the payload
1943
+ * (cut → undo → paste works as a move idiom).
1944
+ *
1945
+ * Returns the payload string, or `null` on empty selection (no
1946
+ * mutation, no history).
1947
+ */
1948
+ cut(): string | null;
1949
+ /**
1950
+ * Paste SVG markup — `text` when given, else the internal clipboard
1951
+ * buffer. Synchronous over delivered text: acquisition from a native
1952
+ * clipboard event or an async provider read is the invoking channel's
1953
+ * job and completes before this command runs.
1954
+ *
1955
+ * Accepts anything {@link insert_fragment} parses (bare fragment or
1956
+ * full document — the editor's own payloads are an ordinary case, not
1957
+ * a privileged one) and inserts it with the same atomic semantics:
1958
+ * one history step, subtrees adopted verbatim, ids never rewritten,
1959
+ * namespace declarations hoisted, appended at the document top level,
1960
+ * inserted roots selected.
1961
+ *
1962
+ * **Gesture-grade refusal table** (deliberately weaker than
1963
+ * `insert_fragment`'s): paste's input is environment-supplied — prose,
1964
+ * URLs, and JSON are what clipboards hold most of the day — so
1965
+ * non-parseable input is a **no-op refusal** (`[]`, no mutation, no
1966
+ * history), never a thrown error. A non-string argument still throws
1967
+ * `TypeError` (caller bug — no acquisition channel produces one).
1968
+ * Empty selection→buffer misses (`undefined` text, empty buffer) also
1969
+ * return `[]`.
1970
+ */
1971
+ paste(text?: string): NodeId[];
1972
+ /**
1973
+ * Duplicate the selection in place — the **subtree-clone** operation
1974
+ * (the clipboard FRD's second extraction operation; design note:
1975
+ * `docs/wg/feat-svg-editor/subtree-clone.md`). Each normalized
1976
+ * selection root is cloned verbatim (byte-equal subtree markup — and
1977
+ * therefore NO defs closure, NO namespace shell: the destination is
1978
+ * the source document) and inserted as its origin's next sibling, so
1979
+ * the clone paints directly above its origin. Selection moves to the
1980
+ * clones. ONE history step; a single `undo()` removes the clones and
1981
+ * restores the prior selection.
1982
+ *
1983
+ * Authored `id=""` attributes are cloned verbatim, NEVER rewritten —
1984
+ * the document gains colliding ids that resolve first-in-document-order
1985
+ * (so a clone's internal self-reference resolves to the ORIGINAL);
1986
+ * dedup is the explicit Tidy command's job.
1987
+ *
1988
+ * **Repeating offset** (gridaco/grida#825, spec §Repeating offset):
1989
+ * duplicate, move the copy, duplicate again — the next copy lands at
1990
+ * the same relative offset from the previous one (Figma's repeating
1991
+ * duplicate; an Alt-drag clone commit arms the same memory, so ⌘D
1992
+ * after a clone-drag repeats the drag offset). Still ONE history
1993
+ * step: a single `undo()` removes copy + offset together. Requires an
1994
+ * attached geometry provider; when the repeat's preconditions don't
1995
+ * hold (selection isn't the previous clones, a copy was resized,
1996
+ * nothing moved, no geometry) the command degrades to the plain
1997
+ * in-place duplicate above — never an error.
1998
+ *
1999
+ * Refusal (no mutation, no history): an empty selection, or one that
2000
+ * normalizes to nothing cloneable (document root, nested `<svg>`,
2001
+ * stale / non-element ids) → `[]`. Returns the clone ids in document
2002
+ * order otherwise.
2003
+ */
2004
+ duplicate(): NodeId[];
1769
2005
  /**
1770
2006
  * Wrap the current selection in a new plain `<g>`. Returns `true` if
1771
2007
  * the wrap was performed (a history step was pushed and the new group
@@ -2030,6 +2266,11 @@ declare function _create_svg_editor_internal(opts: CreateSvgEditorOptions): {
2030
2266
  doc: SvgDocument;
2031
2267
  history: {
2032
2268
  preview: (label: string) => import("@grida/history").Preview;
2269
+ undo_label: () => string | null;
2270
+ };
2271
+ clipboard: {
2272
+ copy: () => string | null;
2273
+ cut: () => string | null;
2033
2274
  };
2034
2275
  insert_text_preview: (initial: Readonly<Record<string, string>>, opts?: {
2035
2276
  parent?: NodeId;
@@ -2041,6 +2282,7 @@ declare function _create_svg_editor_internal(opts: CreateSvgEditorOptions): {
2041
2282
  emit: () => void;
2042
2283
  subscribe_translate_commit(cb: () => void): () => void;
2043
2284
  notify_translate_commit: () => void;
2285
+ seed_duplication(record: subtree.DuplicationRecord): void;
2044
2286
  set_content_edit_driver(fn: ((target: NodeId) => boolean) | null): void;
2045
2287
  set_surface_hover_override_driver(fn: ((id: NodeId | null) => void) | null): void;
2046
2288
  push_surface_hover(id: NodeId | null): void;
package/dist/index.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { $ as RadialGradientDefinition, A as EditorState, B as LinearGradientDefinition, D as ClipboardProvider, F as GradientEntry, G as PaintFallback, H as Mode, I as GradientStop, K as PaintPreviewSession, L as InsertPreviewSession, M as FileIOProvider, N as FontResolver, O as Color, P as GradientDefinition, Q as Providers, R as InsertableTag, S as AlignDirection, U as NodeId, V as Matrix2D, W as Paint, X as PropertyValue, Y as PreviewSession, Z as Provenance, _ as PathModel, a as SelectMode, at as Vec2, b as Verb, c as SvgEditor, et as Rect, it as Unsubscribe, j as EditorStyle, k as DEFAULT_STYLE, l as createSvgEditor, n as CreateSvgEditorOptions, nt as TOOL_CURSOR, o as Surface, q as PaintValue, rt as Tool, s as SurfaceHandle, t as Commands, tt as ReorderDirection, v as PathSnapshot, x as VertexId, y as SegmentId, z as InvalidComputedValue } from "./editor-D2eQe8lB.mjs";
1
+ import { $ as RadialGradientDefinition, A as EditorState, B as LinearGradientDefinition, D as ClipboardProvider, F as GradientEntry, G as PaintFallback, H as Mode, I as GradientStop, K as PaintPreviewSession, L as InsertPreviewSession, M as FileIOProvider, N as FontResolver, O as Color, P as GradientDefinition, Q as Providers, R as InsertableTag, S as AlignDirection, U as NodeId, V as Matrix2D, W as Paint, X as PropertyValue, Y as PreviewSession, Z as Provenance, _ as PathModel, a as SelectMode, at as Vec2, b as Verb, c as SvgEditor, et as Rect, it as Unsubscribe, j as EditorStyle, k as DEFAULT_STYLE, l as createSvgEditor, n as CreateSvgEditorOptions, nt as TOOL_CURSOR, o as Surface, q as PaintValue, rt as Tool, s as SurfaceHandle, t as Commands, tt as ReorderDirection, v as PathSnapshot, x as VertexId, y as SegmentId, z as InvalidComputedValue } from "./editor-KqpIW1qm.mjs";
2
2
  export { type AlignDirection, type ClipboardProvider, type Color, type Commands, type CreateSvgEditorOptions, DEFAULT_STYLE, type EditorState, type EditorStyle, type FileIOProvider, type FontResolver, type GradientDefinition, type GradientEntry, type GradientStop, type InsertPreviewSession, type InsertableTag, type InvalidComputedValue, type LinearGradientDefinition, type Matrix2D, type Mode, type NodeId, type Paint, type PaintFallback, type PaintPreviewSession, type PaintValue, PathModel, type PathSnapshot, type PreviewSession, type PropertyValue, type Provenance, type Providers, type RadialGradientDefinition, type Rect, type ReorderDirection, type SegmentId, type SelectMode, type Surface, type SurfaceHandle, type SvgEditor, TOOL_CURSOR, type Tool, type Unsubscribe, type Vec2, type Verb, type VertexId, createSvgEditor };
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { $ as RadialGradientDefinition, A as EditorState, B as LinearGradientDefinition, D as ClipboardProvider, F as GradientEntry, G as PaintFallback, H as Mode, I as GradientStop, K as PaintPreviewSession, L as InsertPreviewSession, M as FileIOProvider, N as FontResolver, O as Color, P as GradientDefinition, Q as Providers, R as InsertableTag, S as AlignDirection, U as NodeId, V as Matrix2D, W as Paint, X as PropertyValue, Y as PreviewSession, Z as Provenance, _ as PathModel, a as SelectMode, at as Vec2, b as Verb, c as SvgEditor, et as Rect, it as Unsubscribe, j as EditorStyle, k as DEFAULT_STYLE, l as createSvgEditor, n as CreateSvgEditorOptions, nt as TOOL_CURSOR, o as Surface, q as PaintValue, rt as Tool, s as SurfaceHandle, t as Commands, tt as ReorderDirection, v as PathSnapshot, x as VertexId, y as SegmentId, z as InvalidComputedValue } from "./editor-CYoGJ3Hf.js";
1
+ import { $ as RadialGradientDefinition, A as EditorState, B as LinearGradientDefinition, D as ClipboardProvider, F as GradientEntry, G as PaintFallback, H as Mode, I as GradientStop, K as PaintPreviewSession, L as InsertPreviewSession, M as FileIOProvider, N as FontResolver, O as Color, P as GradientDefinition, Q as Providers, R as InsertableTag, S as AlignDirection, U as NodeId, V as Matrix2D, W as Paint, X as PropertyValue, Y as PreviewSession, Z as Provenance, _ as PathModel, a as SelectMode, at as Vec2, b as Verb, c as SvgEditor, et as Rect, it as Unsubscribe, j as EditorStyle, k as DEFAULT_STYLE, l as createSvgEditor, n as CreateSvgEditorOptions, nt as TOOL_CURSOR, o as Surface, q as PaintValue, rt as Tool, s as SurfaceHandle, t as Commands, tt as ReorderDirection, v as PathSnapshot, x as VertexId, y as SegmentId, z as InvalidComputedValue } from "./editor-BSxTUsW_.js";
2
2
  export { type AlignDirection, type ClipboardProvider, type Color, type Commands, type CreateSvgEditorOptions, DEFAULT_STYLE, type EditorState, type EditorStyle, type FileIOProvider, type FontResolver, type GradientDefinition, type GradientEntry, type GradientStop, type InsertPreviewSession, type InsertableTag, type InvalidComputedValue, type LinearGradientDefinition, type Matrix2D, type Mode, type NodeId, type Paint, type PaintFallback, type PaintPreviewSession, type PaintValue, PathModel, type PathSnapshot, type PreviewSession, type PropertyValue, type Provenance, type Providers, type RadialGradientDefinition, type Rect, type ReorderDirection, type SegmentId, type SelectMode, type Surface, type SurfaceHandle, type SvgEditor, TOOL_CURSOR, type Tool, type Unsubscribe, type Vec2, type Verb, type VertexId, createSvgEditor };
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_model = require("./model-D0nU_EkL.js");
3
- const require_editor = require("./editor-C6Lj1In-.js");
2
+ const require_model = require("./model-BLhMJZKJ.js");
3
+ const require_editor = require("./editor-Be6UrMeV.js");
4
4
  exports.DEFAULT_STYLE = require_model.DEFAULT_STYLE;
5
5
  exports.PathModel = require_model.PathModel;
6
6
  exports.TOOL_CURSOR = require_model.TOOL_CURSOR;
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { t as createSvgEditor } from "./editor-DKQOIKuU.mjs";
2
- import { i as TOOL_CURSOR, r as DEFAULT_STYLE, t as PathModel } from "./model-L3t9ixT_.mjs";
1
+ import { t as createSvgEditor } from "./editor-BkCbYCz2.mjs";
2
+ import { i as TOOL_CURSOR, r as DEFAULT_STYLE, t as PathModel } from "./model-DU0GOMwM.mjs";
3
3
  export { DEFAULT_STYLE, PathModel, TOOL_CURSOR, createSvgEditor };