@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.
- package/README.md +21 -4
- package/dist/{dom-BMzX1CXZ.d.ts → dom-CQkWJNrK.d.ts} +77 -6
- package/dist/{dom-DKQ4Vt3z.js → dom-CfYDV311.js} +342 -55
- package/dist/{dom-OP-kmK8k.mjs → dom-Dub-TMoN.mjs} +342 -55
- package/dist/{dom-TctdgRnn.d.mts → dom-Dw2SPHgc.d.mts} +77 -6
- package/dist/dom.d.mts +3 -3
- package/dist/dom.d.ts +3 -3
- package/dist/dom.js +1 -1
- package/dist/dom.mjs +1 -1
- package/dist/{editor-Be6UrMeV.js → editor-4U9LAZ6r.js} +70 -182
- package/dist/{editor-BkCbYCz2.mjs → editor-B1GmFnS9.mjs} +63 -175
- package/dist/{editor-KqpIW1qm.d.mts → editor-CcW4BVth.d.mts} +54 -0
- package/dist/{editor-BSxTUsW_.d.ts → editor-CxqRhhzP.d.ts} +54 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{model-BLhMJZKJ.js → model-CzL6_zId.js} +179 -1
- package/dist/{model-DU0GOMwM.mjs → model-DS5MxDrd.mjs} +161 -2
- package/dist/presets.d.mts +2 -2
- package/dist/presets.d.ts +2 -2
- package/dist/presets.js +3 -4
- package/dist/presets.mjs +2 -3
- package/dist/react.d.mts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +13 -2
- package/dist/react.mjs +13 -2
- package/package.json +6 -5
|
@@ -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-
|
|
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
|
|
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
|
|
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: () =>
|
|
1585
|
-
|
|
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
|
-
|
|
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 (!
|
|
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 (!
|
|
2491
|
-
active = false;
|
|
2377
|
+
if (!live()) return;
|
|
2492
2378
|
preview.commit();
|
|
2493
2379
|
},
|
|
2494
2380
|
discard() {
|
|
2495
|
-
if (!
|
|
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
|
-
|
|
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 (!
|
|
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 (!
|
|
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-
|
|
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-
|
|
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-
|
|
3
|
-
const require_editor = require("./editor-
|
|
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-
|
|
2
|
-
import { i as TOOL_CURSOR, r as DEFAULT_STYLE, t as PathModel } from "./model-
|
|
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 };
|