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

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.
@@ -1,4 +1,4 @@
1
- import { S as is_text_input_focused, _ as SVG_NS, a as paint, b as XMLNS_NS, g as subtree, h as transform, i as TOOL_CURSOR, m as group, n as insertions, p as translate_pipeline, r as DEFAULT_STYLE, s as resize_pipeline, u as rotate_pipeline, v as SvgDocument, x as array_shallow_equal, y as WELL_KNOWN_NS_PREFIXES } from "./model-DU0GOMwM.mjs";
1
+ import { C as TOOL_SET, S as is_text_input_focused, T as registerDefaultCommands, _ as SVG_NS, a as paint, b as XMLNS_NS, g as subtree, h as transform, i as TOOL_CURSOR, m as group, n as insertions, p as translate_pipeline, r as DEFAULT_STYLE, s as resize_pipeline, u as rotate_pipeline, v as SvgDocument, x as array_shallow_equal, y as WELL_KNOWN_NS_PREFIXES } from "./model-DS5MxDrd.mjs";
2
2
  import { HistoryImpl } from "@grida/history";
3
3
  import { KeyCode, M, chunkKey, eventToChunk, getKeyboardOS, kb, keybindingsToKeyCodes } from "@grida/keybinding";
4
4
  import cmath from "@grida/cmath";
@@ -37,164 +37,6 @@ var CommandRegistry = class {
37
37
  }
38
38
  };
39
39
  //#endregion
40
- //#region src/commands/defaults.ts
41
- /** Command id for `tool.set`. Bound to V/R/O/L in `keymap/defaults.ts`. */
42
- const TOOL_SET = "tool.set";
43
- /**
44
- * The headless default `transform.nudge` handler. Exported so a host
45
- * surface that overrides nudge (e.g. for faux-snap UX) can restore the
46
- * default on teardown — the registry doesn't stack handlers, so a plain
47
- * unregister leaves the slot empty.
48
- */
49
- function default_nudge_handler(editor) {
50
- return (args) => {
51
- if (editor.state.selection.length === 0) return false;
52
- const { dx, dy } = args;
53
- editor.commands.nudge({
54
- dx,
55
- dy
56
- });
57
- return true;
58
- };
59
- }
60
- function registerDefaultCommands(reg, editor) {
61
- reg.register("history.undo", () => {
62
- if (!editor.state.can_undo) return false;
63
- editor.commands.undo();
64
- return true;
65
- });
66
- reg.register("history.redo", () => {
67
- if (!editor.state.can_redo) return false;
68
- editor.commands.redo();
69
- return true;
70
- });
71
- reg.register("selection.deselect", () => {
72
- if (editor.state.selection.length === 0) return false;
73
- editor.commands.deselect();
74
- return true;
75
- });
76
- reg.register("selection.remove", () => {
77
- if (editor.state.selection.length === 0) return false;
78
- editor.commands.remove();
79
- return true;
80
- });
81
- reg.register("selection.group", () => {
82
- if (editor.state.mode !== "select") return false;
83
- if (editor.state.selection.length === 0) return false;
84
- return editor.commands.group();
85
- });
86
- reg.register("selection.duplicate", () => {
87
- if (editor.state.mode !== "select") return false;
88
- if (editor.state.selection.length === 0) return false;
89
- return editor.commands.duplicate().length > 0;
90
- });
91
- reg.register("selection.ungroup", () => {
92
- if (editor.state.mode !== "select") return false;
93
- if (editor.state.selection.length !== 1) return false;
94
- return editor.commands.ungroup();
95
- });
96
- reg.register("selection.resize_to", (args) => {
97
- if (editor.state.mode !== "select") return false;
98
- if (editor.state.selection.length === 0) return false;
99
- const target = args;
100
- return editor.commands.resize_to(target);
101
- });
102
- reg.register("selection.nudge_resize", (args) => {
103
- if (editor.state.mode !== "select") return false;
104
- if (editor.state.selection.length === 0) return false;
105
- const { dw, dh } = args;
106
- return editor.commands.resize_by({
107
- dw,
108
- dh
109
- });
110
- });
111
- reg.register("selection.rotate", (args) => {
112
- if (editor.state.mode !== "select") return false;
113
- if (editor.state.selection.length === 0) return false;
114
- const a = args;
115
- return editor.commands.rotate(a.angle, { pivot: a.pivot });
116
- });
117
- reg.register("selection.rotate_to", (args) => {
118
- if (editor.state.mode !== "select") return false;
119
- if (editor.state.selection.length === 0) return false;
120
- const a = args;
121
- return editor.commands.rotate_to(a.angle, { pivot: a.pivot });
122
- });
123
- reg.register("selection.flatten_transform", () => {
124
- if (editor.state.mode !== "select") return false;
125
- if (editor.state.selection.length === 0) return false;
126
- return editor.commands.flatten_transform();
127
- });
128
- reg.register("selection.all", () => {
129
- if (editor.state.mode !== "select") return false;
130
- return editor.commands.select_all();
131
- });
132
- reg.register("selection.sibling", (args) => {
133
- if (editor.state.mode !== "select") return false;
134
- return editor.commands.select_sibling(args);
135
- });
136
- reg.register("selection.align", (args) => {
137
- if (editor.state.mode !== "select") return false;
138
- return editor.commands.align(args);
139
- });
140
- reg.register("clipboard.copy", () => {
141
- if (editor.state.mode !== "select") return false;
142
- if (editor.state.selection.length === 0) return false;
143
- return editor.commands.copy() !== null;
144
- });
145
- reg.register("clipboard.cut", () => {
146
- if (editor.state.mode !== "select") return false;
147
- if (editor.state.selection.length === 0) return false;
148
- return editor.commands.cut() !== null;
149
- });
150
- reg.register("clipboard.paste", (args) => {
151
- if (editor.state.mode !== "select") return false;
152
- const text = args?.text;
153
- if (typeof text === "string") return editor.commands.paste(text).length > 0;
154
- const provider = editor.providers.clipboard;
155
- if (provider) {
156
- provider.read().then((text) => {
157
- if (text) editor.commands.paste(text);
158
- }).catch((err) => {
159
- console.warn("[svg-editor] clipboard provider read failed:", err);
160
- });
161
- return true;
162
- }
163
- return editor.commands.paste().length > 0;
164
- });
165
- reg.register("content.enter", () => editor.enter_content_edit());
166
- reg.register("hierarchy.enter", () => {
167
- if (editor.state.selection.length !== 1) return false;
168
- const id = editor.state.selection[0];
169
- const node = editor.tree().nodes.get(id);
170
- if (!node || node.children.length === 0) return false;
171
- editor.commands.select(node.children[0]);
172
- return true;
173
- });
174
- reg.register("hierarchy.exit", () => {
175
- if (editor.state.selection.length !== 1) return false;
176
- const id = editor.state.selection[0];
177
- const tree = editor.tree();
178
- const node = tree.nodes.get(id);
179
- if (!node || node.parent === null || node.parent === tree.root) return false;
180
- editor.commands.select(node.parent);
181
- return true;
182
- });
183
- reg.register("transform.nudge", default_nudge_handler(editor));
184
- reg.register("reorder", (args) => {
185
- if (editor.state.selection.length !== 1) return false;
186
- editor.commands.reorder(args);
187
- return true;
188
- });
189
- reg.register(TOOL_SET, (args) => {
190
- const next = args;
191
- const required_mode = next.type === "lasso" || next.type === "bend" ? "edit-content" : next.type === "insert" || next.type === "insert-text" ? "select" : null;
192
- if (required_mode !== null && editor.state.mode !== required_mode) return false;
193
- editor.set_tool(next);
194
- return true;
195
- });
196
- }
197
- //#endregion
198
40
  //#region src/keymap/keymap.ts
199
41
  /**
200
42
  * Keymap — bindings of declarative `Keybinding`s (from `@grida/keybinding`)
@@ -1525,8 +1367,28 @@ function _create_svg_editor_internal(opts) {
1525
1367
  if (properties.choose_write_carrier(doc, id, name) === "inline_style") doc.set_style(id, name, value);
1526
1368
  else doc.set_attr(id, name, value);
1527
1369
  }
1370
+ /** Open `preview_property` sessions, keyed by property name. A discrete
1371
+ * write to the same name supersedes the in-flight gesture: the session
1372
+ * is silently discarded so a later host-side `commit()` cannot replay
1373
+ * the stale previewed value over the discrete write. The stored
1374
+ * function reverts the previewed value and unregisters itself. */
1375
+ const open_property_previews = /* @__PURE__ */ new Map();
1376
+ function supersede_property_preview(name) {
1377
+ open_property_previews.get(name)?.();
1378
+ }
1379
+ /** End EVERY open preview session. Called by operations that detach
1380
+ * nodes (remove / cut, ungroup) or replace the document (load,
1381
+ * reset): the sessions' deltas target nodes that are about to die,
1382
+ * so a later close-time `commit()` would push a dead history step.
1383
+ * Must run BEFORE the destructive mutation — each discard reverts
1384
+ * its in-flight delta against the still-intact document. (Live
1385
+ * iteration is safe: each discard deletes only its own map entry.) */
1386
+ function discard_open_property_previews() {
1387
+ for (const discard of open_property_previews.values()) discard();
1388
+ }
1528
1389
  function set_property(name, value) {
1529
1390
  if (selection.length === 0) return;
1391
+ supersede_property_preview(name);
1530
1392
  const before = [];
1531
1393
  for (const id of selection) before.push({
1532
1394
  id,
@@ -1556,19 +1418,34 @@ function _create_svg_editor_internal(opts) {
1556
1418
  });
1557
1419
  }
1558
1420
  function preview_property(name) {
1421
+ supersede_property_preview(name);
1422
+ const targets = [...selection];
1559
1423
  const before = [];
1560
- for (const id of selection) before.push({
1424
+ for (const id of targets) before.push({
1561
1425
  id,
1562
1426
  attr: doc.get_attr(id, name),
1563
1427
  style: doc.get_style(id, name)
1564
1428
  });
1565
1429
  const preview = history.preview(`change ${name}`);
1430
+ const live = () => preview.state === "active";
1431
+ const close = () => {
1432
+ if (open_property_previews.get(name) === discard) open_property_previews.delete(name);
1433
+ };
1434
+ const discard = () => {
1435
+ close();
1436
+ if (live()) preview.discard();
1437
+ };
1438
+ open_property_previews.set(name, discard);
1566
1439
  return {
1440
+ get live() {
1441
+ return live();
1442
+ },
1567
1443
  update(value) {
1444
+ if (!live()) return;
1568
1445
  preview.set({
1569
1446
  providerId: PROVIDER_ID,
1570
1447
  apply: () => {
1571
- for (const id of selection) write_property(id, name, value);
1448
+ for (const id of targets) write_property(id, name, value);
1572
1449
  emit();
1573
1450
  },
1574
1451
  revert: () => {
@@ -1581,8 +1458,11 @@ function _create_svg_editor_internal(opts) {
1581
1458
  }
1582
1459
  });
1583
1460
  },
1584
- commit: () => preview.commit(),
1585
- discard: () => preview.discard()
1461
+ commit: () => {
1462
+ close();
1463
+ if (live()) preview.commit();
1464
+ },
1465
+ discard
1586
1466
  };
1587
1467
  }
1588
1468
  function set_paint(channel, p) {
@@ -1592,6 +1472,9 @@ function _create_svg_editor_internal(opts) {
1592
1472
  function preview_paint(channel) {
1593
1473
  const session = preview_property(channel);
1594
1474
  return {
1475
+ get live() {
1476
+ return session.live;
1477
+ },
1595
1478
  update: (p) => session.update(paint.serialize(p)),
1596
1479
  commit: () => session.commit(),
1597
1480
  discard: () => session.discard()
@@ -2147,6 +2030,7 @@ function _create_svg_editor_internal(opts) {
2147
2030
  if (selection.length === 0) return;
2148
2031
  const filtered = doc.prune_nested_nodes(selection).filter((id) => doc.parent_of(id) !== null);
2149
2032
  if (filtered.length === 0) return;
2033
+ discard_open_property_previews();
2150
2034
  const captures = [...filtered].sort(subtree.by_document_order(doc)).map((id) => ({
2151
2035
  id,
2152
2036
  parent: doc.parent_of(id),
@@ -2208,6 +2092,7 @@ function _create_svg_editor_internal(opts) {
2208
2092
  if (selection.length !== 1) return false;
2209
2093
  target = selection[0];
2210
2094
  }
2095
+ discard_open_property_previews();
2211
2096
  const plan = group.plan_ungroup(doc, target);
2212
2097
  if (!plan) return false;
2213
2098
  const group_id = plan.group_id;
@@ -2362,6 +2247,8 @@ function _create_svg_editor_internal(opts) {
2362
2247
  return copy_impl(true);
2363
2248
  }
2364
2249
  function cut_impl(deliver_external) {
2250
+ if (selection.length === 0) return null;
2251
+ discard_open_property_previews();
2365
2252
  const payload = copy_impl(deliver_external);
2366
2253
  if (payload === null) return null;
2367
2254
  remove_selection("cut");
@@ -2460,7 +2347,7 @@ function _create_svg_editor_internal(opts) {
2460
2347
  doc.insert(id, parent, insert_before);
2461
2348
  set_selection([id]);
2462
2349
  const preview = history.preview(`insert ${tag}`);
2463
- let active = true;
2350
+ const live = () => preview.state === "active";
2464
2351
  const apply = () => {
2465
2352
  for (const name in live_attrs) doc.set_attr(id, name, live_attrs[name]);
2466
2353
  if (doc.parent_of(id) === null) doc.insert(id, parent, insert_before);
@@ -2479,7 +2366,7 @@ function _create_svg_editor_internal(opts) {
2479
2366
  return {
2480
2367
  id,
2481
2368
  update(attrs) {
2482
- if (!active) return;
2369
+ if (!live()) return;
2483
2370
  for (const name in attrs) {
2484
2371
  live_attrs[name] = attrs[name];
2485
2372
  doc.set_attr(id, name, attrs[name]);
@@ -2487,13 +2374,11 @@ function _create_svg_editor_internal(opts) {
2487
2374
  preview.set(entry);
2488
2375
  },
2489
2376
  commit() {
2490
- if (!active) return;
2491
- active = false;
2377
+ if (!live()) return;
2492
2378
  preview.commit();
2493
2379
  },
2494
2380
  discard() {
2495
- if (!active) return;
2496
- active = false;
2381
+ if (!live()) return;
2497
2382
  preview.discard();
2498
2383
  }
2499
2384
  };
@@ -2535,7 +2420,7 @@ function _create_svg_editor_internal(opts) {
2535
2420
  set_selection(previous_selection);
2536
2421
  };
2537
2422
  const preview = history.preview("insert text");
2538
- let active = true;
2423
+ const live = () => preview.state === "active";
2539
2424
  preview.set({
2540
2425
  providerId: PROVIDER_ID,
2541
2426
  apply,
@@ -2544,14 +2429,12 @@ function _create_svg_editor_internal(opts) {
2544
2429
  return {
2545
2430
  id,
2546
2431
  commit() {
2547
- if (!active) return;
2548
- active = false;
2432
+ if (!live()) return;
2549
2433
  committed_text = doc.text_of(id);
2550
2434
  preview.commit();
2551
2435
  },
2552
2436
  discard() {
2553
- if (!active) return;
2554
- active = false;
2437
+ if (!live()) return;
2555
2438
  preview.discard();
2556
2439
  }
2557
2440
  };
@@ -2619,12 +2502,13 @@ function _create_svg_editor_internal(opts) {
2619
2502
  return content_edit_driver(id);
2620
2503
  }
2621
2504
  function load_svg(svg) {
2505
+ discard_open_property_previews();
2506
+ history.clear();
2622
2507
  doc.load(svg);
2623
2508
  selection = [];
2624
2509
  scope = null;
2625
2510
  mode = "select";
2626
2511
  tool = TOOL_CURSOR;
2627
- history.clear();
2628
2512
  active_duplication = null;
2629
2513
  baseline_revision = doc.revision;
2630
2514
  load_version++;
@@ -2690,6 +2574,7 @@ function _create_svg_editor_internal(opts) {
2690
2574
  return doc.serialize();
2691
2575
  }
2692
2576
  function reset() {
2577
+ discard_open_property_previews();
2693
2578
  history.clear();
2694
2579
  doc.reset_to_original();
2695
2580
  selection = [];
@@ -2919,6 +2804,9 @@ function _create_svg_editor_internal(opts) {
2919
2804
  set_geometry(p) {
2920
2805
  geometry_provider = p;
2921
2806
  },
2807
+ register_command(id, handler) {
2808
+ return registry.register(id, handler);
2809
+ },
2922
2810
  bump_geometry() {
2923
2811
  doc.bump_geometry();
2924
2812
  fire_geometry_listeners_if_advanced();
@@ -146,6 +146,18 @@ type PropertyValue<T = string | number> = {
146
146
  computed: T | InvalidComputedValue | null;
147
147
  provenance: Provenance;
148
148
  };
149
+ /**
150
+ * Computed-time color. `current_color` stays a keyword (CSS Color 4 §4.4)
151
+ * — its rgb resolution happens at *used* value, which needs the surface's
152
+ * painting context.
153
+ *
154
+ * For `rgb`, `value` is canonical lowercase hex — `#rrggbb`, or
155
+ * `#rrggbbaa` when alpha < 1 — whenever the literal is resolvable without
156
+ * a rendering context (named colors, hex, `rgb()`, `hsl()`, `hwb()`).
157
+ * Literals the editor does not resolve (`lab()` / `oklch()` / `color()` —
158
+ * gamut mapping out of scope) pass through as authored. The authored
159
+ * string is always available on the `declared` channel.
160
+ */
149
161
  type Color = {
150
162
  kind: "rgb";
151
163
  value: string;
@@ -355,12 +367,53 @@ type EditorState = {
355
367
  };
356
368
  type Unsubscribe = () => void;
357
369
  type ReorderDirection = "bring_forward" | "send_backward" | "bring_to_front" | "send_to_back";
370
+ /**
371
+ * Continuous-gesture write session returned by
372
+ * `commands.preview_property(name)`: many `update()` calls during a drag,
373
+ * one `commit()` (→ single history step) or `discard()` (→ no step).
374
+ *
375
+ * Lifecycle invariant: **the session ends as soon as its result can no
376
+ * longer become the document's next state** — and after it ends, for any
377
+ * reason, every method is a no-op (never a throw) and `live` is `false`.
378
+ * The ending events:
379
+ *
380
+ * - `commit()` / `discard()` — the host closes the gesture;
381
+ * - a discrete write to the same property (`set_property(name, …)`, and
382
+ * for paint channels `set_paint` / `set_paint_from_gradient`, which
383
+ * write through it) — the discrete write is the user's final intent
384
+ * and a later `commit()` must not replay the stale previewed value;
385
+ * - opening a second session on the same name (same supersession rule);
386
+ * - an operation that detaches the session's target nodes (`remove` /
387
+ * `cut`, `ungroup`) — sessions on EVERY name end, since the deltas
388
+ * would target detached nodes;
389
+ * - a document swap (`load` / `reset`) — every NodeId dies wholesale;
390
+ * - `undo` / `redo` — history discards all in-flight previews.
391
+ *
392
+ * A defensive `discard()` before a discrete write is valid but not
393
+ * required. Sessions on OTHER property names are untouched by discrete
394
+ * writes. Hosts that cache a session across renders should consult
395
+ * `live` and lazily reopen — the bundled React hooks do this.
396
+ *
397
+ * Known exclusion: the discrete GEOMETRY commands (`translate` / `nudge`,
398
+ * `resize*`, `rotate*`, `align`, `transform`, `flatten_transform`) write
399
+ * `x` / `y` / `width` / `height` / `transform` through their own
400
+ * pipelines and do NOT yet supersede a same-name property session —
401
+ * avoid mixing `preview_property` on geometry attributes with those
402
+ * commands until that lands.
403
+ */
358
404
  type PreviewSession = {
405
+ /** `true` while the session can still affect the document; `false`
406
+ * once it has ended for any of the reasons above. */
407
+ readonly live: boolean;
359
408
  update(value: string): void;
360
409
  commit(): void;
361
410
  discard(): void;
362
411
  };
412
+ /** `PreviewSession` over typed `Paint` values, from
413
+ * `commands.preview_paint(channel)`. Same lifecycle and supersession
414
+ * contract — the channel ("fill" / "stroke") is the property name. */
363
415
  type PaintPreviewSession = {
416
+ readonly live: boolean;
364
417
  update(paint: Paint): void;
365
418
  commit(): void;
366
419
  discard(): void;
@@ -2289,6 +2342,7 @@ declare function _create_svg_editor_internal(opts: CreateSvgEditorOptions): {
2289
2342
  push_pick(e: PickEvent): void;
2290
2343
  set_computed_resolver(fn: DomComputedResolver | null): void;
2291
2344
  set_geometry(p: GeometryProvider | null): void;
2345
+ register_command(id: string, handler: CommandHandler): () => void;
2292
2346
  bump_geometry(): void;
2293
2347
  };
2294
2348
  keymap: Keymap;
@@ -146,6 +146,18 @@ type PropertyValue<T = string | number> = {
146
146
  computed: T | InvalidComputedValue | null;
147
147
  provenance: Provenance;
148
148
  };
149
+ /**
150
+ * Computed-time color. `current_color` stays a keyword (CSS Color 4 §4.4)
151
+ * — its rgb resolution happens at *used* value, which needs the surface's
152
+ * painting context.
153
+ *
154
+ * For `rgb`, `value` is canonical lowercase hex — `#rrggbb`, or
155
+ * `#rrggbbaa` when alpha < 1 — whenever the literal is resolvable without
156
+ * a rendering context (named colors, hex, `rgb()`, `hsl()`, `hwb()`).
157
+ * Literals the editor does not resolve (`lab()` / `oklch()` / `color()` —
158
+ * gamut mapping out of scope) pass through as authored. The authored
159
+ * string is always available on the `declared` channel.
160
+ */
149
161
  type Color = {
150
162
  kind: "rgb";
151
163
  value: string;
@@ -355,12 +367,53 @@ type EditorState = {
355
367
  };
356
368
  type Unsubscribe = () => void;
357
369
  type ReorderDirection = "bring_forward" | "send_backward" | "bring_to_front" | "send_to_back";
370
+ /**
371
+ * Continuous-gesture write session returned by
372
+ * `commands.preview_property(name)`: many `update()` calls during a drag,
373
+ * one `commit()` (→ single history step) or `discard()` (→ no step).
374
+ *
375
+ * Lifecycle invariant: **the session ends as soon as its result can no
376
+ * longer become the document's next state** — and after it ends, for any
377
+ * reason, every method is a no-op (never a throw) and `live` is `false`.
378
+ * The ending events:
379
+ *
380
+ * - `commit()` / `discard()` — the host closes the gesture;
381
+ * - a discrete write to the same property (`set_property(name, …)`, and
382
+ * for paint channels `set_paint` / `set_paint_from_gradient`, which
383
+ * write through it) — the discrete write is the user's final intent
384
+ * and a later `commit()` must not replay the stale previewed value;
385
+ * - opening a second session on the same name (same supersession rule);
386
+ * - an operation that detaches the session's target nodes (`remove` /
387
+ * `cut`, `ungroup`) — sessions on EVERY name end, since the deltas
388
+ * would target detached nodes;
389
+ * - a document swap (`load` / `reset`) — every NodeId dies wholesale;
390
+ * - `undo` / `redo` — history discards all in-flight previews.
391
+ *
392
+ * A defensive `discard()` before a discrete write is valid but not
393
+ * required. Sessions on OTHER property names are untouched by discrete
394
+ * writes. Hosts that cache a session across renders should consult
395
+ * `live` and lazily reopen — the bundled React hooks do this.
396
+ *
397
+ * Known exclusion: the discrete GEOMETRY commands (`translate` / `nudge`,
398
+ * `resize*`, `rotate*`, `align`, `transform`, `flatten_transform`) write
399
+ * `x` / `y` / `width` / `height` / `transform` through their own
400
+ * pipelines and do NOT yet supersede a same-name property session —
401
+ * avoid mixing `preview_property` on geometry attributes with those
402
+ * commands until that lands.
403
+ */
358
404
  type PreviewSession = {
405
+ /** `true` while the session can still affect the document; `false`
406
+ * once it has ended for any of the reasons above. */
407
+ readonly live: boolean;
359
408
  update(value: string): void;
360
409
  commit(): void;
361
410
  discard(): void;
362
411
  };
412
+ /** `PreviewSession` over typed `Paint` values, from
413
+ * `commands.preview_paint(channel)`. Same lifecycle and supersession
414
+ * contract — the channel ("fill" / "stroke") is the property name. */
363
415
  type PaintPreviewSession = {
416
+ readonly live: boolean;
364
417
  update(paint: Paint): void;
365
418
  commit(): void;
366
419
  discard(): void;
@@ -2289,6 +2342,7 @@ declare function _create_svg_editor_internal(opts: CreateSvgEditorOptions): {
2289
2342
  push_pick(e: PickEvent): void;
2290
2343
  set_computed_resolver(fn: DomComputedResolver | null): void;
2291
2344
  set_geometry(p: GeometryProvider | null): void;
2345
+ register_command(id: string, handler: CommandHandler): () => void;
2292
2346
  bump_geometry(): void;
2293
2347
  };
2294
2348
  keymap: Keymap;
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-KqpIW1qm.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-CcW4BVth.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-BSxTUsW_.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-CxqRhhzP.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-BLhMJZKJ.js");
3
- const require_editor = require("./editor-Be6UrMeV.js");
2
+ const require_model = require("./model-CzL6_zId.js");
3
+ const require_editor = require("./editor-4U9LAZ6r.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-BkCbYCz2.mjs";
2
- import { i as TOOL_CURSOR, r as DEFAULT_STYLE, t as PathModel } from "./model-DU0GOMwM.mjs";
1
+ import { t as createSvgEditor } from "./editor-B1GmFnS9.mjs";
2
+ import { i as TOOL_CURSOR, r as DEFAULT_STYLE, t as PathModel } from "./model-DS5MxDrd.mjs";
3
3
  export { DEFAULT_STYLE, PathModel, TOOL_CURSOR, createSvgEditor };