@grida/svg-editor 1.0.0-alpha.4 → 1.0.0-alpha.5
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/{dom-DJnZhtOd.d.mts → dom-CMXNUMjP.d.mts} +1 -1
- package/dist/{dom-CoVZzFqy.js → dom-DyJy1H6Q.js} +11 -7
- package/dist/{dom-Cn-RtjRL.d.ts → dom-eIgcZ4JC.d.ts} +1 -1
- package/dist/{dom-CmOu0HvI.mjs → dom-l5Y1Wf8C.mjs} +10 -6
- package/dist/dom.d.mts +1 -1
- package/dist/dom.d.ts +1 -1
- package/dist/dom.js +1 -1
- package/dist/dom.mjs +1 -1
- package/dist/{editor-CjK56cgb.mjs → editor-CRflVqEz.mjs} +33 -10
- package/dist/{editor-Uu6dZX4y.d.mts → editor-DdgqLDC9.d.ts} +132 -110
- package/dist/{editor-D2zZAyny.js → editor-Ds47eN37.js} +35 -12
- package/dist/{editor-D2l_CDr0.d.ts → editor-KRAmUodY.d.mts} +132 -110
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{paint-dDV-Trt9.js → paint-cTjePy5e.js} +1 -1
- package/dist/presets.d.mts +2 -2
- package/dist/presets.d.ts +2 -2
- package/dist/presets.js +10 -13
- package/dist/presets.mjs +10 -13
- package/dist/react.d.mts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +2 -2
- package/dist/react.mjs +2 -2
- package/package.json +3 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as Camera, f as Gestures, o as SurfaceHandle, s as SvgEditor } from "./editor-KRAmUodY.mjs";
|
|
2
2
|
import cmath from "@grida/cmath";
|
|
3
3
|
|
|
4
4
|
//#region src/dom.d.ts
|
|
@@ -29,7 +29,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
29
29
|
enumerable: true
|
|
30
30
|
}) : target, mod));
|
|
31
31
|
//#endregion
|
|
32
|
-
const require_paint = require("./paint-
|
|
32
|
+
const require_paint = require("./paint-cTjePy5e.js");
|
|
33
33
|
let _grida_text_editor_dom = require("@grida/text-editor/dom");
|
|
34
34
|
let _grida_hud = require("@grida/hud");
|
|
35
35
|
let _grida_cmath__measurement = require("@grida/cmath/_measurement");
|
|
@@ -564,7 +564,9 @@ var SvgTextSurface = class {
|
|
|
564
564
|
this.last_sel_end = -1;
|
|
565
565
|
this.textEl = textEl;
|
|
566
566
|
const ownerDoc = textEl.ownerDocument;
|
|
567
|
-
|
|
567
|
+
let mountAnchor = textEl;
|
|
568
|
+
while (mountAnchor.parentElement instanceof SVGElement && (mountAnchor.localName === "tspan" || mountAnchor.localName === "textPath")) mountAnchor = mountAnchor.parentElement;
|
|
569
|
+
const parent = mountAnchor.parentNode;
|
|
568
570
|
if (!parent) throw new Error("text element has no parent");
|
|
569
571
|
const computedWhitespace = ownerDoc.defaultView?.getComputedStyle(textEl).whiteSpace;
|
|
570
572
|
if (!(computedWhitespace === "pre" || computedWhitespace === "pre-wrap" || computedWhitespace === "break-spaces")) {
|
|
@@ -579,14 +581,14 @@ var SvgTextSurface = class {
|
|
|
579
581
|
selection.setAttribute("pointer-events", "none");
|
|
580
582
|
selection.setAttribute("data-svg-text-edit-selection", "");
|
|
581
583
|
selection.style.display = "none";
|
|
582
|
-
parent.insertBefore(selection,
|
|
584
|
+
parent.insertBefore(selection, mountAnchor);
|
|
583
585
|
this.selectionRect = selection;
|
|
584
586
|
const caret = ownerDoc.createElementNS(SVG_NS, "rect");
|
|
585
587
|
caret.setAttribute("fill", "#2563eb");
|
|
586
588
|
caret.setAttribute("pointer-events", "none");
|
|
587
589
|
caret.setAttribute("data-svg-text-edit-caret", "");
|
|
588
590
|
caret.style.display = "none";
|
|
589
|
-
parent.insertBefore(caret,
|
|
591
|
+
parent.insertBefore(caret, mountAnchor.nextSibling);
|
|
590
592
|
this.caretRect = caret;
|
|
591
593
|
}
|
|
592
594
|
setText(text) {
|
|
@@ -1329,7 +1331,7 @@ var DomSurface = class {
|
|
|
1329
1331
|
commit_intent(intent) {
|
|
1330
1332
|
switch (intent.kind) {
|
|
1331
1333
|
case "select":
|
|
1332
|
-
this.editor.commands.select(intent.ids, {
|
|
1334
|
+
this.editor.commands.select(intent.ids, { mode: intent.mode });
|
|
1333
1335
|
return;
|
|
1334
1336
|
case "deselect_all":
|
|
1335
1337
|
this.editor.commands.deselect();
|
|
@@ -1556,13 +1558,15 @@ var DomSurface = class {
|
|
|
1556
1558
|
if (!intent.additive) this.editor.commands.deselect();
|
|
1557
1559
|
return;
|
|
1558
1560
|
}
|
|
1559
|
-
this.editor.commands.select(ids, {
|
|
1561
|
+
this.editor.commands.select(ids, { mode: intent.additive ? "add" : "replace" });
|
|
1560
1562
|
}
|
|
1561
1563
|
enter_content_edit(id) {
|
|
1562
1564
|
if (this.text_edit) return false;
|
|
1563
1565
|
const el = this.element_index.get(id);
|
|
1564
|
-
if (!(el instanceof
|
|
1566
|
+
if (!(el instanceof SVGElement)) return false;
|
|
1565
1567
|
const doc = this.editor._internal;
|
|
1568
|
+
if (!doc.doc.is_text_edit_target(id)) return false;
|
|
1569
|
+
if (!(el instanceof SVGTextContentElement)) return false;
|
|
1566
1570
|
this.text_edit_target = id;
|
|
1567
1571
|
this.text_edit_original = doc.doc.text_of(id);
|
|
1568
1572
|
this.text_edit = TEXT_EDIT_PENDING;
|
|
@@ -532,7 +532,9 @@ var SvgTextSurface = class {
|
|
|
532
532
|
this.last_sel_end = -1;
|
|
533
533
|
this.textEl = textEl;
|
|
534
534
|
const ownerDoc = textEl.ownerDocument;
|
|
535
|
-
|
|
535
|
+
let mountAnchor = textEl;
|
|
536
|
+
while (mountAnchor.parentElement instanceof SVGElement && (mountAnchor.localName === "tspan" || mountAnchor.localName === "textPath")) mountAnchor = mountAnchor.parentElement;
|
|
537
|
+
const parent = mountAnchor.parentNode;
|
|
536
538
|
if (!parent) throw new Error("text element has no parent");
|
|
537
539
|
const computedWhitespace = ownerDoc.defaultView?.getComputedStyle(textEl).whiteSpace;
|
|
538
540
|
if (!(computedWhitespace === "pre" || computedWhitespace === "pre-wrap" || computedWhitespace === "break-spaces")) {
|
|
@@ -547,14 +549,14 @@ var SvgTextSurface = class {
|
|
|
547
549
|
selection.setAttribute("pointer-events", "none");
|
|
548
550
|
selection.setAttribute("data-svg-text-edit-selection", "");
|
|
549
551
|
selection.style.display = "none";
|
|
550
|
-
parent.insertBefore(selection,
|
|
552
|
+
parent.insertBefore(selection, mountAnchor);
|
|
551
553
|
this.selectionRect = selection;
|
|
552
554
|
const caret = ownerDoc.createElementNS(SVG_NS, "rect");
|
|
553
555
|
caret.setAttribute("fill", "#2563eb");
|
|
554
556
|
caret.setAttribute("pointer-events", "none");
|
|
555
557
|
caret.setAttribute("data-svg-text-edit-caret", "");
|
|
556
558
|
caret.style.display = "none";
|
|
557
|
-
parent.insertBefore(caret,
|
|
559
|
+
parent.insertBefore(caret, mountAnchor.nextSibling);
|
|
558
560
|
this.caretRect = caret;
|
|
559
561
|
}
|
|
560
562
|
setText(text) {
|
|
@@ -1297,7 +1299,7 @@ var DomSurface = class {
|
|
|
1297
1299
|
commit_intent(intent) {
|
|
1298
1300
|
switch (intent.kind) {
|
|
1299
1301
|
case "select":
|
|
1300
|
-
this.editor.commands.select(intent.ids, {
|
|
1302
|
+
this.editor.commands.select(intent.ids, { mode: intent.mode });
|
|
1301
1303
|
return;
|
|
1302
1304
|
case "deselect_all":
|
|
1303
1305
|
this.editor.commands.deselect();
|
|
@@ -1524,13 +1526,15 @@ var DomSurface = class {
|
|
|
1524
1526
|
if (!intent.additive) this.editor.commands.deselect();
|
|
1525
1527
|
return;
|
|
1526
1528
|
}
|
|
1527
|
-
this.editor.commands.select(ids, {
|
|
1529
|
+
this.editor.commands.select(ids, { mode: intent.additive ? "add" : "replace" });
|
|
1528
1530
|
}
|
|
1529
1531
|
enter_content_edit(id) {
|
|
1530
1532
|
if (this.text_edit) return false;
|
|
1531
1533
|
const el = this.element_index.get(id);
|
|
1532
|
-
if (!(el instanceof
|
|
1534
|
+
if (!(el instanceof SVGElement)) return false;
|
|
1533
1535
|
const doc = this.editor._internal;
|
|
1536
|
+
if (!doc.doc.is_text_edit_target(id)) return false;
|
|
1537
|
+
if (!(el instanceof SVGTextContentElement)) return false;
|
|
1534
1538
|
this.text_edit_target = id;
|
|
1535
1539
|
this.text_edit_original = doc.doc.text_of(id);
|
|
1536
1540
|
this.text_edit = TEXT_EDIT_PENDING;
|
package/dist/dom.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as DomSurfaceOptions, r as attach_dom_surface, t as DomSurfaceHandle } from "./dom-
|
|
1
|
+
import { n as DomSurfaceOptions, r as attach_dom_surface, t as DomSurfaceHandle } from "./dom-CMXNUMjP.mjs";
|
|
2
2
|
export { DomSurfaceHandle, DomSurfaceOptions, attach_dom_surface };
|
package/dist/dom.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as DomSurfaceOptions, r as attach_dom_surface, t as DomSurfaceHandle } from "./dom-
|
|
1
|
+
import { n as DomSurfaceOptions, r as attach_dom_surface, t as DomSurfaceHandle } from "./dom-eIgcZ4JC.js";
|
|
2
2
|
export { DomSurfaceHandle, DomSurfaceOptions, attach_dom_surface };
|
package/dist/dom.js
CHANGED
package/dist/dom.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as attach_dom_surface } from "./dom-
|
|
1
|
+
import { t as attach_dom_surface } from "./dom-l5Y1Wf8C.mjs";
|
|
2
2
|
export { attach_dom_surface };
|
|
@@ -489,7 +489,7 @@ var GradientsRegistry = class {
|
|
|
489
489
|
};
|
|
490
490
|
}
|
|
491
491
|
write_gradient(node, def) {
|
|
492
|
-
for (const c of
|
|
492
|
+
for (const c of this.doc.children_of(node).slice()) this.doc.remove(c);
|
|
493
493
|
const set_num = (name, v) => {
|
|
494
494
|
this.doc.set_attr(node, name, v === void 0 ? null : String(v));
|
|
495
495
|
};
|
|
@@ -730,7 +730,6 @@ function parse_attrs(src, from) {
|
|
|
730
730
|
const c = src[i];
|
|
731
731
|
if (c === "/") {
|
|
732
732
|
if (src[i + 1] !== ">") throw new Error("expected '/>' at " + i);
|
|
733
|
-
pre + "";
|
|
734
733
|
return {
|
|
735
734
|
attrs,
|
|
736
735
|
end_index: i + 2,
|
|
@@ -1012,6 +1011,25 @@ var SvgDocument = class SvgDocument {
|
|
|
1012
1011
|
if (!style) return [];
|
|
1013
1012
|
return parse_inline_style(style);
|
|
1014
1013
|
}
|
|
1014
|
+
/**
|
|
1015
|
+
* Whether `id` can be opened in the flat-string text editor.
|
|
1016
|
+
*
|
|
1017
|
+
* v1 contract: the editor only operates on a *single flat text run*. That
|
|
1018
|
+
* means the target must be a `<text>` or `<tspan>` whose direct children
|
|
1019
|
+
* are all text nodes (or it has no children). A `<text>` containing a
|
|
1020
|
+
* `<tspan>` is *not* honestly editable — `text_of` would drop the tspan
|
|
1021
|
+
* content from the editor's view, and a flat-text write would leave the
|
|
1022
|
+
* tspan dangling. Tspan-as-target is fine and well-defined when it's a
|
|
1023
|
+
* leaf; only the host decides whether to route double-click to a tspan
|
|
1024
|
+
* or its parent text.
|
|
1025
|
+
*/
|
|
1026
|
+
is_text_edit_target(id) {
|
|
1027
|
+
const n = this.nodes.get(id);
|
|
1028
|
+
if (!n || n.kind !== "element") return false;
|
|
1029
|
+
if (n.local !== "text" && n.local !== "tspan") return false;
|
|
1030
|
+
for (const c of n.children) if (this.nodes.get(c)?.kind !== "text") return false;
|
|
1031
|
+
return true;
|
|
1032
|
+
}
|
|
1015
1033
|
text_of(id) {
|
|
1016
1034
|
const n = this.nodes.get(id);
|
|
1017
1035
|
if (!n || n.kind !== "element") return "";
|
|
@@ -1327,7 +1345,7 @@ function createSvgEditor(opts) {
|
|
|
1327
1345
|
let load_version = 0;
|
|
1328
1346
|
let style = {
|
|
1329
1347
|
...DEFAULT_STYLE,
|
|
1330
|
-
...opts.style
|
|
1348
|
+
...opts.style
|
|
1331
1349
|
};
|
|
1332
1350
|
const providers = opts.providers ?? {};
|
|
1333
1351
|
const listeners = /* @__PURE__ */ new Set();
|
|
@@ -1380,11 +1398,16 @@ function createSvgEditor(opts) {
|
|
|
1380
1398
|
}
|
|
1381
1399
|
function select(target, opts) {
|
|
1382
1400
|
const ids = typeof target === "string" ? [target] : [...target];
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
}
|
|
1401
|
+
const mode = opts?.mode ?? "replace";
|
|
1402
|
+
if (mode === "replace") {
|
|
1403
|
+
set_selection(ids);
|
|
1404
|
+
return;
|
|
1405
|
+
}
|
|
1406
|
+
const next = new Set(selection);
|
|
1407
|
+
if (mode === "add") for (const id of ids) next.add(id);
|
|
1408
|
+
else for (const id of ids) if (next.has(id)) next.delete(id);
|
|
1409
|
+
else next.add(id);
|
|
1410
|
+
set_selection([...next]);
|
|
1388
1411
|
}
|
|
1389
1412
|
function deselect() {
|
|
1390
1413
|
set_selection([]);
|
|
@@ -1597,7 +1620,7 @@ function createSvgEditor(opts) {
|
|
|
1597
1620
|
function set_text(value) {
|
|
1598
1621
|
if (selection.length !== 1) return;
|
|
1599
1622
|
const target = selection[0];
|
|
1600
|
-
if (doc.
|
|
1623
|
+
if (!doc.is_text_edit_target(target)) return;
|
|
1601
1624
|
const original = doc.text_of(target);
|
|
1602
1625
|
if (original === value) return;
|
|
1603
1626
|
const apply = () => {
|
|
@@ -1640,7 +1663,7 @@ function createSvgEditor(opts) {
|
|
|
1640
1663
|
function enter_content_edit(target) {
|
|
1641
1664
|
const id = target ?? (selection.length === 1 ? selection[0] : null);
|
|
1642
1665
|
if (!id) return false;
|
|
1643
|
-
if (doc.
|
|
1666
|
+
if (!doc.is_text_edit_target(id)) return false;
|
|
1644
1667
|
if (!content_edit_driver) return false;
|
|
1645
1668
|
return content_edit_driver(id);
|
|
1646
1669
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import cmath from "@grida/cmath";
|
|
1
2
|
import * as _$_grida_history0 from "@grida/history";
|
|
2
3
|
import { Keybinding, Platform } from "@grida/keybinding";
|
|
3
|
-
import cmath from "@grida/cmath";
|
|
4
4
|
|
|
5
5
|
//#region src/types.d.ts
|
|
6
6
|
/**
|
|
@@ -321,113 +321,6 @@ declare class Camera {
|
|
|
321
321
|
private notify;
|
|
322
322
|
}
|
|
323
323
|
//#endregion
|
|
324
|
-
//#region src/commands/registry.d.ts
|
|
325
|
-
/**
|
|
326
|
-
* Command registry.
|
|
327
|
-
*
|
|
328
|
-
* A passive id-keyed registry of handlers. Built so that:
|
|
329
|
-
*
|
|
330
|
-
* - keybindings (in `src/keymap`) can address commands by stable id;
|
|
331
|
-
* - new commands can be added in ONE place (`src/commands/defaults.ts`)
|
|
332
|
-
* without growing the public surface of the editor;
|
|
333
|
-
* - "one key, many meanings" can be expressed via chain semantics: a
|
|
334
|
-
* handler returns `true` if it consumed, `false`/`void` otherwise,
|
|
335
|
-
* and the dispatcher tries the next candidate in the chain.
|
|
336
|
-
*
|
|
337
|
-
* Handlers are plain closures — they capture whatever editor reference
|
|
338
|
-
* they need. The registry itself stays unaware of the editor's type,
|
|
339
|
-
* which avoids a circular type dependency between editor and registry.
|
|
340
|
-
*/
|
|
341
|
-
/** Stable, dotted id for a command, e.g. `"history.undo"`. */
|
|
342
|
-
type CommandId = string;
|
|
343
|
-
/**
|
|
344
|
-
* A command handler.
|
|
345
|
-
*
|
|
346
|
-
* Return `true` if the handler consumed the invocation. Return `false`
|
|
347
|
-
* or `undefined` to signal "did not apply" — the dispatcher will try
|
|
348
|
-
* the next candidate registered for the same key.
|
|
349
|
-
*
|
|
350
|
-
* Handlers are closures: they capture their editor reference. No
|
|
351
|
-
* editor parameter is passed — keep handlers self-contained.
|
|
352
|
-
*/
|
|
353
|
-
type CommandHandler = (args?: unknown) => boolean | void;
|
|
354
|
-
declare class CommandRegistry {
|
|
355
|
-
private readonly map;
|
|
356
|
-
/**
|
|
357
|
-
* Register a command. Returns an unregister function. Re-registering
|
|
358
|
-
* the same id replaces the previous handler (last writer wins).
|
|
359
|
-
*/
|
|
360
|
-
register(id: CommandId, handler: CommandHandler): () => void;
|
|
361
|
-
/**
|
|
362
|
-
* Invoke a command by id. Returns `true` if the handler consumed,
|
|
363
|
-
* `false` otherwise (including unknown ids and handlers that returned
|
|
364
|
-
* `false`/`undefined`).
|
|
365
|
-
*/
|
|
366
|
-
invoke(id: CommandId, args?: unknown): boolean;
|
|
367
|
-
has(id: CommandId): boolean;
|
|
368
|
-
/** All registered ids, for debugging / introspection. */
|
|
369
|
-
ids(): readonly CommandId[];
|
|
370
|
-
}
|
|
371
|
-
//#endregion
|
|
372
|
-
//#region src/keymap/keymap.d.ts
|
|
373
|
-
type KeymapBinding = {
|
|
374
|
-
/** Declarative key combination. Build with `kb()` / `c()` / `seq()`. */keybinding: Keybinding; /** Command id to invoke on match. */
|
|
375
|
-
command: CommandId; /** Forwarded as the `args` parameter to the command handler. */
|
|
376
|
-
args?: unknown; /** Higher priorities run first in the chain. Default 0. */
|
|
377
|
-
priority?: number;
|
|
378
|
-
/**
|
|
379
|
-
* Reserved for V2; not honored by the V1 dispatcher. When added, this
|
|
380
|
-
* will be evaluated before the handler runs; if false, the binding is
|
|
381
|
-
* skipped without invoking the handler.
|
|
382
|
-
*/
|
|
383
|
-
when?: (ctx: unknown) => boolean;
|
|
384
|
-
};
|
|
385
|
-
declare class Keymap {
|
|
386
|
-
private readonly commands;
|
|
387
|
-
private readonly platformGetter;
|
|
388
|
-
/**
|
|
389
|
-
* Bindings bucketed by canonical chunk-key hash, computed per
|
|
390
|
-
* `@grida/keybinding`'s `chunkKey`. Each list is the chain for that
|
|
391
|
-
* key, sorted in dispatch order (priority desc, then registration
|
|
392
|
-
* order).
|
|
393
|
-
*/
|
|
394
|
-
private readonly buckets;
|
|
395
|
-
/** Insert order, so ties on priority are deterministic. */
|
|
396
|
-
private seq;
|
|
397
|
-
constructor(commands: CommandRegistry, platformGetter?: () => Platform);
|
|
398
|
-
/**
|
|
399
|
-
* Bind a key combination to a command. Returns an unbind function.
|
|
400
|
-
* The same `Keybinding` can be bound to multiple commands — they will
|
|
401
|
-
* all be tried in chain order on dispatch.
|
|
402
|
-
*/
|
|
403
|
-
bind(binding: KeymapBinding): () => void;
|
|
404
|
-
/**
|
|
405
|
-
* Remove bindings matching the spec. If both filters are passed, only
|
|
406
|
-
* bindings that match BOTH are removed.
|
|
407
|
-
*/
|
|
408
|
-
unbind(spec: {
|
|
409
|
-
keybinding?: Keybinding;
|
|
410
|
-
command?: CommandId;
|
|
411
|
-
}): void;
|
|
412
|
-
/** All registered bindings, for introspection. Order is not guaranteed. */
|
|
413
|
-
bindings(): readonly KeymapBinding[];
|
|
414
|
-
/**
|
|
415
|
-
* Match the event against bound chunks, then run candidates in chain
|
|
416
|
-
* order. Returns `true` and calls `preventDefault()` on the first
|
|
417
|
-
* handler that consumes; returns `false` if nothing matched or all
|
|
418
|
-
* matches fell through.
|
|
419
|
-
*/
|
|
420
|
-
dispatch(event: KeyboardEvent): boolean;
|
|
421
|
-
/**
|
|
422
|
-
* Compute the set of canonical hashes a `Keybinding` lights up. A
|
|
423
|
-
* binding with aliases (multiple sequences) contributes one hash per
|
|
424
|
-
* single-chunk alias; multi-chunk sequences (chords) are skipped in
|
|
425
|
-
* V1.
|
|
426
|
-
*/
|
|
427
|
-
private chunkKeysFor;
|
|
428
|
-
private has_safe_mod;
|
|
429
|
-
}
|
|
430
|
-
//#endregion
|
|
431
324
|
//#region src/core/parser.d.ts
|
|
432
325
|
type AttrToken = {
|
|
433
326
|
/** Verbatim source name including any prefix, e.g. "xlink:href". */raw_name: string; /** Prefix or null. */
|
|
@@ -557,6 +450,19 @@ declare class SvgDocument implements DocumentEvents {
|
|
|
557
450
|
property: string;
|
|
558
451
|
value: string;
|
|
559
452
|
}>;
|
|
453
|
+
/**
|
|
454
|
+
* Whether `id` can be opened in the flat-string text editor.
|
|
455
|
+
*
|
|
456
|
+
* v1 contract: the editor only operates on a *single flat text run*. That
|
|
457
|
+
* means the target must be a `<text>` or `<tspan>` whose direct children
|
|
458
|
+
* are all text nodes (or it has no children). A `<text>` containing a
|
|
459
|
+
* `<tspan>` is *not* honestly editable — `text_of` would drop the tspan
|
|
460
|
+
* content from the editor's view, and a flat-text write would leave the
|
|
461
|
+
* tspan dangling. Tspan-as-target is fine and well-defined when it's a
|
|
462
|
+
* leaf; only the host decides whether to route double-click to a tspan
|
|
463
|
+
* or its parent text.
|
|
464
|
+
*/
|
|
465
|
+
is_text_edit_target(id: NodeId): boolean;
|
|
560
466
|
text_of(id: NodeId): string;
|
|
561
467
|
/** Replace all direct text children with a single text node carrying `value`. */
|
|
562
468
|
set_text(id: NodeId, value: string): void;
|
|
@@ -586,6 +492,113 @@ type Defs = {
|
|
|
586
492
|
gradients: GradientsApi;
|
|
587
493
|
};
|
|
588
494
|
//#endregion
|
|
495
|
+
//#region src/commands/registry.d.ts
|
|
496
|
+
/**
|
|
497
|
+
* Command registry.
|
|
498
|
+
*
|
|
499
|
+
* A passive id-keyed registry of handlers. Built so that:
|
|
500
|
+
*
|
|
501
|
+
* - keybindings (in `src/keymap`) can address commands by stable id;
|
|
502
|
+
* - new commands can be added in ONE place (`src/commands/defaults.ts`)
|
|
503
|
+
* without growing the public surface of the editor;
|
|
504
|
+
* - "one key, many meanings" can be expressed via chain semantics: a
|
|
505
|
+
* handler returns `true` if it consumed, `false`/`void` otherwise,
|
|
506
|
+
* and the dispatcher tries the next candidate in the chain.
|
|
507
|
+
*
|
|
508
|
+
* Handlers are plain closures — they capture whatever editor reference
|
|
509
|
+
* they need. The registry itself stays unaware of the editor's type,
|
|
510
|
+
* which avoids a circular type dependency between editor and registry.
|
|
511
|
+
*/
|
|
512
|
+
/** Stable, dotted id for a command, e.g. `"history.undo"`. */
|
|
513
|
+
type CommandId = string;
|
|
514
|
+
/**
|
|
515
|
+
* A command handler.
|
|
516
|
+
*
|
|
517
|
+
* Return `true` if the handler consumed the invocation. Return `false`
|
|
518
|
+
* or `undefined` to signal "did not apply" — the dispatcher will try
|
|
519
|
+
* the next candidate registered for the same key.
|
|
520
|
+
*
|
|
521
|
+
* Handlers are closures: they capture their editor reference. No
|
|
522
|
+
* editor parameter is passed — keep handlers self-contained.
|
|
523
|
+
*/
|
|
524
|
+
type CommandHandler = (args?: unknown) => boolean | void;
|
|
525
|
+
declare class CommandRegistry {
|
|
526
|
+
private readonly map;
|
|
527
|
+
/**
|
|
528
|
+
* Register a command. Returns an unregister function. Re-registering
|
|
529
|
+
* the same id replaces the previous handler (last writer wins).
|
|
530
|
+
*/
|
|
531
|
+
register(id: CommandId, handler: CommandHandler): () => void;
|
|
532
|
+
/**
|
|
533
|
+
* Invoke a command by id. Returns `true` if the handler consumed,
|
|
534
|
+
* `false` otherwise (including unknown ids and handlers that returned
|
|
535
|
+
* `false`/`undefined`).
|
|
536
|
+
*/
|
|
537
|
+
invoke(id: CommandId, args?: unknown): boolean;
|
|
538
|
+
has(id: CommandId): boolean;
|
|
539
|
+
/** All registered ids, for debugging / introspection. */
|
|
540
|
+
ids(): readonly CommandId[];
|
|
541
|
+
}
|
|
542
|
+
//#endregion
|
|
543
|
+
//#region src/keymap/keymap.d.ts
|
|
544
|
+
type KeymapBinding = {
|
|
545
|
+
/** Declarative key combination. Build with `kb()` / `c()` / `seq()`. */keybinding: Keybinding; /** Command id to invoke on match. */
|
|
546
|
+
command: CommandId; /** Forwarded as the `args` parameter to the command handler. */
|
|
547
|
+
args?: unknown; /** Higher priorities run first in the chain. Default 0. */
|
|
548
|
+
priority?: number;
|
|
549
|
+
/**
|
|
550
|
+
* Reserved for V2; not honored by the V1 dispatcher. When added, this
|
|
551
|
+
* will be evaluated before the handler runs; if false, the binding is
|
|
552
|
+
* skipped without invoking the handler.
|
|
553
|
+
*/
|
|
554
|
+
when?: (ctx: unknown) => boolean;
|
|
555
|
+
};
|
|
556
|
+
declare class Keymap {
|
|
557
|
+
private readonly commands;
|
|
558
|
+
private readonly platformGetter;
|
|
559
|
+
/**
|
|
560
|
+
* Bindings bucketed by canonical chunk-key hash, computed per
|
|
561
|
+
* `@grida/keybinding`'s `chunkKey`. Each list is the chain for that
|
|
562
|
+
* key, sorted in dispatch order (priority desc, then registration
|
|
563
|
+
* order).
|
|
564
|
+
*/
|
|
565
|
+
private readonly buckets;
|
|
566
|
+
/** Insert order, so ties on priority are deterministic. */
|
|
567
|
+
private seq;
|
|
568
|
+
constructor(commands: CommandRegistry, platformGetter?: () => Platform);
|
|
569
|
+
/**
|
|
570
|
+
* Bind a key combination to a command. Returns an unbind function.
|
|
571
|
+
* The same `Keybinding` can be bound to multiple commands — they will
|
|
572
|
+
* all be tried in chain order on dispatch.
|
|
573
|
+
*/
|
|
574
|
+
bind(binding: KeymapBinding): () => void;
|
|
575
|
+
/**
|
|
576
|
+
* Remove bindings matching the spec. If both filters are passed, only
|
|
577
|
+
* bindings that match BOTH are removed.
|
|
578
|
+
*/
|
|
579
|
+
unbind(spec: {
|
|
580
|
+
keybinding?: Keybinding;
|
|
581
|
+
command?: CommandId;
|
|
582
|
+
}): void;
|
|
583
|
+
/** All registered bindings, for introspection. Order is not guaranteed. */
|
|
584
|
+
bindings(): readonly KeymapBinding[];
|
|
585
|
+
/**
|
|
586
|
+
* Match the event against bound chunks, then run candidates in chain
|
|
587
|
+
* order. Returns `true` and calls `preventDefault()` on the first
|
|
588
|
+
* handler that consumes; returns `false` if nothing matched or all
|
|
589
|
+
* matches fell through.
|
|
590
|
+
*/
|
|
591
|
+
dispatch(event: KeyboardEvent): boolean;
|
|
592
|
+
/**
|
|
593
|
+
* Compute the set of canonical hashes a `Keybinding` lights up. A
|
|
594
|
+
* binding with aliases (multiple sequences) contributes one hash per
|
|
595
|
+
* single-chunk alias; multi-chunk sequences (chords) are skipped in
|
|
596
|
+
* V1.
|
|
597
|
+
*/
|
|
598
|
+
private chunkKeysFor;
|
|
599
|
+
private has_safe_mod;
|
|
600
|
+
}
|
|
601
|
+
//#endregion
|
|
589
602
|
//#region src/core/properties.d.ts
|
|
590
603
|
declare function read_property(doc: SvgDocument, id: NodeId, property: string): PropertyValue;
|
|
591
604
|
//#endregion
|
|
@@ -675,9 +688,18 @@ type Surface = {
|
|
|
675
688
|
type SurfaceHandle = {
|
|
676
689
|
detach(): void;
|
|
677
690
|
};
|
|
691
|
+
/**
|
|
692
|
+
* Mode for `commands.select`. Matches the HUD's `SelectMode` vocabulary so
|
|
693
|
+
* intents can be threaded through without lossy collapsing.
|
|
694
|
+
*
|
|
695
|
+
* - `"replace"` (default) — set selection to `ids`, discarding the previous set.
|
|
696
|
+
* - `"add"` — union: each id in `ids` is added; existing members stay.
|
|
697
|
+
* - `"toggle"` — flip each id's membership (present → removed; absent → added).
|
|
698
|
+
*/
|
|
699
|
+
type SelectMode = "replace" | "add" | "toggle";
|
|
678
700
|
type Commands = {
|
|
679
701
|
select(target: NodeId | ReadonlyArray<NodeId>, opts?: {
|
|
680
|
-
|
|
702
|
+
mode?: SelectMode;
|
|
681
703
|
}): void;
|
|
682
704
|
deselect(): void;
|
|
683
705
|
enter_scope(group: NodeId): void;
|
|
@@ -815,4 +837,4 @@ declare function createSvgEditor(opts: CreateSvgEditorOptions): {
|
|
|
815
837
|
keymap: Keymap;
|
|
816
838
|
};
|
|
817
839
|
//#endregion
|
|
818
|
-
export {
|
|
840
|
+
export { InvalidComputedValue as A, Provenance as B, EditorState as C, GradientDefinition as D, FontResolver as E, PaintFallback as F, Unsubscribe as G, RadialGradientDefinition as H, PaintPreviewSession as I, Vec2 as K, PaintValue as L, Mode as M, NodeId as N, GradientEntry as O, Paint as P, PreviewSession as R, DEFAULT_STYLE as S, FileIOProvider as T, Rect as U, Providers as V, ReorderDirection as W, Camera as _, SelectMode as a, ClipboardProvider as b, createSvgEditor as c, GestureId as d, Gestures as f, BoundsResolver as g, CommandId as h, DomComputedResolver as i, LinearGradientDefinition as j, GradientStop as k, GestureBinding as l, CommandHandler as m, CreateSvgEditorOptions as n, SurfaceHandle as o, KeymapBinding as p, DomComputedPaint as r, SvgEditor as s, Commands as t, GestureContext as u, CameraConstraints as v, EditorStyle as w, Color as x, CameraOptions as y, PropertyValue as z };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
require("./dom-
|
|
2
|
-
const require_paint = require("./paint-
|
|
1
|
+
require("./dom-DyJy1H6Q.js");
|
|
2
|
+
const require_paint = require("./paint-cTjePy5e.js");
|
|
3
3
|
let _grida_history = require("@grida/history");
|
|
4
4
|
let _grida_keybinding = require("@grida/keybinding");
|
|
5
5
|
//#region src/commands/registry.ts
|
|
@@ -490,7 +490,7 @@ var GradientsRegistry = class {
|
|
|
490
490
|
};
|
|
491
491
|
}
|
|
492
492
|
write_gradient(node, def) {
|
|
493
|
-
for (const c of
|
|
493
|
+
for (const c of this.doc.children_of(node).slice()) this.doc.remove(c);
|
|
494
494
|
const set_num = (name, v) => {
|
|
495
495
|
this.doc.set_attr(node, name, v === void 0 ? null : String(v));
|
|
496
496
|
};
|
|
@@ -731,7 +731,6 @@ function parse_attrs(src, from) {
|
|
|
731
731
|
const c = src[i];
|
|
732
732
|
if (c === "/") {
|
|
733
733
|
if (src[i + 1] !== ">") throw new Error("expected '/>' at " + i);
|
|
734
|
-
pre + "";
|
|
735
734
|
return {
|
|
736
735
|
attrs,
|
|
737
736
|
end_index: i + 2,
|
|
@@ -1013,6 +1012,25 @@ var SvgDocument = class SvgDocument {
|
|
|
1013
1012
|
if (!style) return [];
|
|
1014
1013
|
return parse_inline_style(style);
|
|
1015
1014
|
}
|
|
1015
|
+
/**
|
|
1016
|
+
* Whether `id` can be opened in the flat-string text editor.
|
|
1017
|
+
*
|
|
1018
|
+
* v1 contract: the editor only operates on a *single flat text run*. That
|
|
1019
|
+
* means the target must be a `<text>` or `<tspan>` whose direct children
|
|
1020
|
+
* are all text nodes (or it has no children). A `<text>` containing a
|
|
1021
|
+
* `<tspan>` is *not* honestly editable — `text_of` would drop the tspan
|
|
1022
|
+
* content from the editor's view, and a flat-text write would leave the
|
|
1023
|
+
* tspan dangling. Tspan-as-target is fine and well-defined when it's a
|
|
1024
|
+
* leaf; only the host decides whether to route double-click to a tspan
|
|
1025
|
+
* or its parent text.
|
|
1026
|
+
*/
|
|
1027
|
+
is_text_edit_target(id) {
|
|
1028
|
+
const n = this.nodes.get(id);
|
|
1029
|
+
if (!n || n.kind !== "element") return false;
|
|
1030
|
+
if (n.local !== "text" && n.local !== "tspan") return false;
|
|
1031
|
+
for (const c of n.children) if (this.nodes.get(c)?.kind !== "text") return false;
|
|
1032
|
+
return true;
|
|
1033
|
+
}
|
|
1016
1034
|
text_of(id) {
|
|
1017
1035
|
const n = this.nodes.get(id);
|
|
1018
1036
|
if (!n || n.kind !== "element") return "";
|
|
@@ -1328,7 +1346,7 @@ function createSvgEditor(opts) {
|
|
|
1328
1346
|
let load_version = 0;
|
|
1329
1347
|
let style = {
|
|
1330
1348
|
...DEFAULT_STYLE,
|
|
1331
|
-
...opts.style
|
|
1349
|
+
...opts.style
|
|
1332
1350
|
};
|
|
1333
1351
|
const providers = opts.providers ?? {};
|
|
1334
1352
|
const listeners = /* @__PURE__ */ new Set();
|
|
@@ -1381,11 +1399,16 @@ function createSvgEditor(opts) {
|
|
|
1381
1399
|
}
|
|
1382
1400
|
function select(target, opts) {
|
|
1383
1401
|
const ids = typeof target === "string" ? [target] : [...target];
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
}
|
|
1402
|
+
const mode = opts?.mode ?? "replace";
|
|
1403
|
+
if (mode === "replace") {
|
|
1404
|
+
set_selection(ids);
|
|
1405
|
+
return;
|
|
1406
|
+
}
|
|
1407
|
+
const next = new Set(selection);
|
|
1408
|
+
if (mode === "add") for (const id of ids) next.add(id);
|
|
1409
|
+
else for (const id of ids) if (next.has(id)) next.delete(id);
|
|
1410
|
+
else next.add(id);
|
|
1411
|
+
set_selection([...next]);
|
|
1389
1412
|
}
|
|
1390
1413
|
function deselect() {
|
|
1391
1414
|
set_selection([]);
|
|
@@ -1598,7 +1621,7 @@ function createSvgEditor(opts) {
|
|
|
1598
1621
|
function set_text(value) {
|
|
1599
1622
|
if (selection.length !== 1) return;
|
|
1600
1623
|
const target = selection[0];
|
|
1601
|
-
if (doc.
|
|
1624
|
+
if (!doc.is_text_edit_target(target)) return;
|
|
1602
1625
|
const original = doc.text_of(target);
|
|
1603
1626
|
if (original === value) return;
|
|
1604
1627
|
const apply = () => {
|
|
@@ -1641,7 +1664,7 @@ function createSvgEditor(opts) {
|
|
|
1641
1664
|
function enter_content_edit(target) {
|
|
1642
1665
|
const id = target ?? (selection.length === 1 ? selection[0] : null);
|
|
1643
1666
|
if (!id) return false;
|
|
1644
|
-
if (doc.
|
|
1667
|
+
if (!doc.is_text_edit_target(id)) return false;
|
|
1645
1668
|
if (!content_edit_driver) return false;
|
|
1646
1669
|
return content_edit_driver(id);
|
|
1647
1670
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import cmath from "@grida/cmath";
|
|
2
1
|
import * as _$_grida_history0 from "@grida/history";
|
|
3
2
|
import { Keybinding, Platform } from "@grida/keybinding";
|
|
3
|
+
import cmath from "@grida/cmath";
|
|
4
4
|
|
|
5
5
|
//#region src/types.d.ts
|
|
6
6
|
/**
|
|
@@ -321,113 +321,6 @@ declare class Camera {
|
|
|
321
321
|
private notify;
|
|
322
322
|
}
|
|
323
323
|
//#endregion
|
|
324
|
-
//#region src/commands/registry.d.ts
|
|
325
|
-
/**
|
|
326
|
-
* Command registry.
|
|
327
|
-
*
|
|
328
|
-
* A passive id-keyed registry of handlers. Built so that:
|
|
329
|
-
*
|
|
330
|
-
* - keybindings (in `src/keymap`) can address commands by stable id;
|
|
331
|
-
* - new commands can be added in ONE place (`src/commands/defaults.ts`)
|
|
332
|
-
* without growing the public surface of the editor;
|
|
333
|
-
* - "one key, many meanings" can be expressed via chain semantics: a
|
|
334
|
-
* handler returns `true` if it consumed, `false`/`void` otherwise,
|
|
335
|
-
* and the dispatcher tries the next candidate in the chain.
|
|
336
|
-
*
|
|
337
|
-
* Handlers are plain closures — they capture whatever editor reference
|
|
338
|
-
* they need. The registry itself stays unaware of the editor's type,
|
|
339
|
-
* which avoids a circular type dependency between editor and registry.
|
|
340
|
-
*/
|
|
341
|
-
/** Stable, dotted id for a command, e.g. `"history.undo"`. */
|
|
342
|
-
type CommandId = string;
|
|
343
|
-
/**
|
|
344
|
-
* A command handler.
|
|
345
|
-
*
|
|
346
|
-
* Return `true` if the handler consumed the invocation. Return `false`
|
|
347
|
-
* or `undefined` to signal "did not apply" — the dispatcher will try
|
|
348
|
-
* the next candidate registered for the same key.
|
|
349
|
-
*
|
|
350
|
-
* Handlers are closures: they capture their editor reference. No
|
|
351
|
-
* editor parameter is passed — keep handlers self-contained.
|
|
352
|
-
*/
|
|
353
|
-
type CommandHandler = (args?: unknown) => boolean | void;
|
|
354
|
-
declare class CommandRegistry {
|
|
355
|
-
private readonly map;
|
|
356
|
-
/**
|
|
357
|
-
* Register a command. Returns an unregister function. Re-registering
|
|
358
|
-
* the same id replaces the previous handler (last writer wins).
|
|
359
|
-
*/
|
|
360
|
-
register(id: CommandId, handler: CommandHandler): () => void;
|
|
361
|
-
/**
|
|
362
|
-
* Invoke a command by id. Returns `true` if the handler consumed,
|
|
363
|
-
* `false` otherwise (including unknown ids and handlers that returned
|
|
364
|
-
* `false`/`undefined`).
|
|
365
|
-
*/
|
|
366
|
-
invoke(id: CommandId, args?: unknown): boolean;
|
|
367
|
-
has(id: CommandId): boolean;
|
|
368
|
-
/** All registered ids, for debugging / introspection. */
|
|
369
|
-
ids(): readonly CommandId[];
|
|
370
|
-
}
|
|
371
|
-
//#endregion
|
|
372
|
-
//#region src/keymap/keymap.d.ts
|
|
373
|
-
type KeymapBinding = {
|
|
374
|
-
/** Declarative key combination. Build with `kb()` / `c()` / `seq()`. */keybinding: Keybinding; /** Command id to invoke on match. */
|
|
375
|
-
command: CommandId; /** Forwarded as the `args` parameter to the command handler. */
|
|
376
|
-
args?: unknown; /** Higher priorities run first in the chain. Default 0. */
|
|
377
|
-
priority?: number;
|
|
378
|
-
/**
|
|
379
|
-
* Reserved for V2; not honored by the V1 dispatcher. When added, this
|
|
380
|
-
* will be evaluated before the handler runs; if false, the binding is
|
|
381
|
-
* skipped without invoking the handler.
|
|
382
|
-
*/
|
|
383
|
-
when?: (ctx: unknown) => boolean;
|
|
384
|
-
};
|
|
385
|
-
declare class Keymap {
|
|
386
|
-
private readonly commands;
|
|
387
|
-
private readonly platformGetter;
|
|
388
|
-
/**
|
|
389
|
-
* Bindings bucketed by canonical chunk-key hash, computed per
|
|
390
|
-
* `@grida/keybinding`'s `chunkKey`. Each list is the chain for that
|
|
391
|
-
* key, sorted in dispatch order (priority desc, then registration
|
|
392
|
-
* order).
|
|
393
|
-
*/
|
|
394
|
-
private readonly buckets;
|
|
395
|
-
/** Insert order, so ties on priority are deterministic. */
|
|
396
|
-
private seq;
|
|
397
|
-
constructor(commands: CommandRegistry, platformGetter?: () => Platform);
|
|
398
|
-
/**
|
|
399
|
-
* Bind a key combination to a command. Returns an unbind function.
|
|
400
|
-
* The same `Keybinding` can be bound to multiple commands — they will
|
|
401
|
-
* all be tried in chain order on dispatch.
|
|
402
|
-
*/
|
|
403
|
-
bind(binding: KeymapBinding): () => void;
|
|
404
|
-
/**
|
|
405
|
-
* Remove bindings matching the spec. If both filters are passed, only
|
|
406
|
-
* bindings that match BOTH are removed.
|
|
407
|
-
*/
|
|
408
|
-
unbind(spec: {
|
|
409
|
-
keybinding?: Keybinding;
|
|
410
|
-
command?: CommandId;
|
|
411
|
-
}): void;
|
|
412
|
-
/** All registered bindings, for introspection. Order is not guaranteed. */
|
|
413
|
-
bindings(): readonly KeymapBinding[];
|
|
414
|
-
/**
|
|
415
|
-
* Match the event against bound chunks, then run candidates in chain
|
|
416
|
-
* order. Returns `true` and calls `preventDefault()` on the first
|
|
417
|
-
* handler that consumes; returns `false` if nothing matched or all
|
|
418
|
-
* matches fell through.
|
|
419
|
-
*/
|
|
420
|
-
dispatch(event: KeyboardEvent): boolean;
|
|
421
|
-
/**
|
|
422
|
-
* Compute the set of canonical hashes a `Keybinding` lights up. A
|
|
423
|
-
* binding with aliases (multiple sequences) contributes one hash per
|
|
424
|
-
* single-chunk alias; multi-chunk sequences (chords) are skipped in
|
|
425
|
-
* V1.
|
|
426
|
-
*/
|
|
427
|
-
private chunkKeysFor;
|
|
428
|
-
private has_safe_mod;
|
|
429
|
-
}
|
|
430
|
-
//#endregion
|
|
431
324
|
//#region src/core/parser.d.ts
|
|
432
325
|
type AttrToken = {
|
|
433
326
|
/** Verbatim source name including any prefix, e.g. "xlink:href". */raw_name: string; /** Prefix or null. */
|
|
@@ -557,6 +450,19 @@ declare class SvgDocument implements DocumentEvents {
|
|
|
557
450
|
property: string;
|
|
558
451
|
value: string;
|
|
559
452
|
}>;
|
|
453
|
+
/**
|
|
454
|
+
* Whether `id` can be opened in the flat-string text editor.
|
|
455
|
+
*
|
|
456
|
+
* v1 contract: the editor only operates on a *single flat text run*. That
|
|
457
|
+
* means the target must be a `<text>` or `<tspan>` whose direct children
|
|
458
|
+
* are all text nodes (or it has no children). A `<text>` containing a
|
|
459
|
+
* `<tspan>` is *not* honestly editable — `text_of` would drop the tspan
|
|
460
|
+
* content from the editor's view, and a flat-text write would leave the
|
|
461
|
+
* tspan dangling. Tspan-as-target is fine and well-defined when it's a
|
|
462
|
+
* leaf; only the host decides whether to route double-click to a tspan
|
|
463
|
+
* or its parent text.
|
|
464
|
+
*/
|
|
465
|
+
is_text_edit_target(id: NodeId): boolean;
|
|
560
466
|
text_of(id: NodeId): string;
|
|
561
467
|
/** Replace all direct text children with a single text node carrying `value`. */
|
|
562
468
|
set_text(id: NodeId, value: string): void;
|
|
@@ -586,6 +492,113 @@ type Defs = {
|
|
|
586
492
|
gradients: GradientsApi;
|
|
587
493
|
};
|
|
588
494
|
//#endregion
|
|
495
|
+
//#region src/commands/registry.d.ts
|
|
496
|
+
/**
|
|
497
|
+
* Command registry.
|
|
498
|
+
*
|
|
499
|
+
* A passive id-keyed registry of handlers. Built so that:
|
|
500
|
+
*
|
|
501
|
+
* - keybindings (in `src/keymap`) can address commands by stable id;
|
|
502
|
+
* - new commands can be added in ONE place (`src/commands/defaults.ts`)
|
|
503
|
+
* without growing the public surface of the editor;
|
|
504
|
+
* - "one key, many meanings" can be expressed via chain semantics: a
|
|
505
|
+
* handler returns `true` if it consumed, `false`/`void` otherwise,
|
|
506
|
+
* and the dispatcher tries the next candidate in the chain.
|
|
507
|
+
*
|
|
508
|
+
* Handlers are plain closures — they capture whatever editor reference
|
|
509
|
+
* they need. The registry itself stays unaware of the editor's type,
|
|
510
|
+
* which avoids a circular type dependency between editor and registry.
|
|
511
|
+
*/
|
|
512
|
+
/** Stable, dotted id for a command, e.g. `"history.undo"`. */
|
|
513
|
+
type CommandId = string;
|
|
514
|
+
/**
|
|
515
|
+
* A command handler.
|
|
516
|
+
*
|
|
517
|
+
* Return `true` if the handler consumed the invocation. Return `false`
|
|
518
|
+
* or `undefined` to signal "did not apply" — the dispatcher will try
|
|
519
|
+
* the next candidate registered for the same key.
|
|
520
|
+
*
|
|
521
|
+
* Handlers are closures: they capture their editor reference. No
|
|
522
|
+
* editor parameter is passed — keep handlers self-contained.
|
|
523
|
+
*/
|
|
524
|
+
type CommandHandler = (args?: unknown) => boolean | void;
|
|
525
|
+
declare class CommandRegistry {
|
|
526
|
+
private readonly map;
|
|
527
|
+
/**
|
|
528
|
+
* Register a command. Returns an unregister function. Re-registering
|
|
529
|
+
* the same id replaces the previous handler (last writer wins).
|
|
530
|
+
*/
|
|
531
|
+
register(id: CommandId, handler: CommandHandler): () => void;
|
|
532
|
+
/**
|
|
533
|
+
* Invoke a command by id. Returns `true` if the handler consumed,
|
|
534
|
+
* `false` otherwise (including unknown ids and handlers that returned
|
|
535
|
+
* `false`/`undefined`).
|
|
536
|
+
*/
|
|
537
|
+
invoke(id: CommandId, args?: unknown): boolean;
|
|
538
|
+
has(id: CommandId): boolean;
|
|
539
|
+
/** All registered ids, for debugging / introspection. */
|
|
540
|
+
ids(): readonly CommandId[];
|
|
541
|
+
}
|
|
542
|
+
//#endregion
|
|
543
|
+
//#region src/keymap/keymap.d.ts
|
|
544
|
+
type KeymapBinding = {
|
|
545
|
+
/** Declarative key combination. Build with `kb()` / `c()` / `seq()`. */keybinding: Keybinding; /** Command id to invoke on match. */
|
|
546
|
+
command: CommandId; /** Forwarded as the `args` parameter to the command handler. */
|
|
547
|
+
args?: unknown; /** Higher priorities run first in the chain. Default 0. */
|
|
548
|
+
priority?: number;
|
|
549
|
+
/**
|
|
550
|
+
* Reserved for V2; not honored by the V1 dispatcher. When added, this
|
|
551
|
+
* will be evaluated before the handler runs; if false, the binding is
|
|
552
|
+
* skipped without invoking the handler.
|
|
553
|
+
*/
|
|
554
|
+
when?: (ctx: unknown) => boolean;
|
|
555
|
+
};
|
|
556
|
+
declare class Keymap {
|
|
557
|
+
private readonly commands;
|
|
558
|
+
private readonly platformGetter;
|
|
559
|
+
/**
|
|
560
|
+
* Bindings bucketed by canonical chunk-key hash, computed per
|
|
561
|
+
* `@grida/keybinding`'s `chunkKey`. Each list is the chain for that
|
|
562
|
+
* key, sorted in dispatch order (priority desc, then registration
|
|
563
|
+
* order).
|
|
564
|
+
*/
|
|
565
|
+
private readonly buckets;
|
|
566
|
+
/** Insert order, so ties on priority are deterministic. */
|
|
567
|
+
private seq;
|
|
568
|
+
constructor(commands: CommandRegistry, platformGetter?: () => Platform);
|
|
569
|
+
/**
|
|
570
|
+
* Bind a key combination to a command. Returns an unbind function.
|
|
571
|
+
* The same `Keybinding` can be bound to multiple commands — they will
|
|
572
|
+
* all be tried in chain order on dispatch.
|
|
573
|
+
*/
|
|
574
|
+
bind(binding: KeymapBinding): () => void;
|
|
575
|
+
/**
|
|
576
|
+
* Remove bindings matching the spec. If both filters are passed, only
|
|
577
|
+
* bindings that match BOTH are removed.
|
|
578
|
+
*/
|
|
579
|
+
unbind(spec: {
|
|
580
|
+
keybinding?: Keybinding;
|
|
581
|
+
command?: CommandId;
|
|
582
|
+
}): void;
|
|
583
|
+
/** All registered bindings, for introspection. Order is not guaranteed. */
|
|
584
|
+
bindings(): readonly KeymapBinding[];
|
|
585
|
+
/**
|
|
586
|
+
* Match the event against bound chunks, then run candidates in chain
|
|
587
|
+
* order. Returns `true` and calls `preventDefault()` on the first
|
|
588
|
+
* handler that consumes; returns `false` if nothing matched or all
|
|
589
|
+
* matches fell through.
|
|
590
|
+
*/
|
|
591
|
+
dispatch(event: KeyboardEvent): boolean;
|
|
592
|
+
/**
|
|
593
|
+
* Compute the set of canonical hashes a `Keybinding` lights up. A
|
|
594
|
+
* binding with aliases (multiple sequences) contributes one hash per
|
|
595
|
+
* single-chunk alias; multi-chunk sequences (chords) are skipped in
|
|
596
|
+
* V1.
|
|
597
|
+
*/
|
|
598
|
+
private chunkKeysFor;
|
|
599
|
+
private has_safe_mod;
|
|
600
|
+
}
|
|
601
|
+
//#endregion
|
|
589
602
|
//#region src/core/properties.d.ts
|
|
590
603
|
declare function read_property(doc: SvgDocument, id: NodeId, property: string): PropertyValue;
|
|
591
604
|
//#endregion
|
|
@@ -675,9 +688,18 @@ type Surface = {
|
|
|
675
688
|
type SurfaceHandle = {
|
|
676
689
|
detach(): void;
|
|
677
690
|
};
|
|
691
|
+
/**
|
|
692
|
+
* Mode for `commands.select`. Matches the HUD's `SelectMode` vocabulary so
|
|
693
|
+
* intents can be threaded through without lossy collapsing.
|
|
694
|
+
*
|
|
695
|
+
* - `"replace"` (default) — set selection to `ids`, discarding the previous set.
|
|
696
|
+
* - `"add"` — union: each id in `ids` is added; existing members stay.
|
|
697
|
+
* - `"toggle"` — flip each id's membership (present → removed; absent → added).
|
|
698
|
+
*/
|
|
699
|
+
type SelectMode = "replace" | "add" | "toggle";
|
|
678
700
|
type Commands = {
|
|
679
701
|
select(target: NodeId | ReadonlyArray<NodeId>, opts?: {
|
|
680
|
-
|
|
702
|
+
mode?: SelectMode;
|
|
681
703
|
}): void;
|
|
682
704
|
deselect(): void;
|
|
683
705
|
enter_scope(group: NodeId): void;
|
|
@@ -815,4 +837,4 @@ declare function createSvgEditor(opts: CreateSvgEditorOptions): {
|
|
|
815
837
|
keymap: Keymap;
|
|
816
838
|
};
|
|
817
839
|
//#endregion
|
|
818
|
-
export {
|
|
840
|
+
export { InvalidComputedValue as A, Provenance as B, EditorState as C, GradientDefinition as D, FontResolver as E, PaintFallback as F, Unsubscribe as G, RadialGradientDefinition as H, PaintPreviewSession as I, Vec2 as K, PaintValue as L, Mode as M, NodeId as N, GradientEntry as O, Paint as P, PreviewSession as R, DEFAULT_STYLE as S, FileIOProvider as T, Rect as U, Providers as V, ReorderDirection as W, Camera as _, SelectMode as a, ClipboardProvider as b, createSvgEditor as c, GestureId as d, Gestures as f, BoundsResolver as g, CommandId as h, DomComputedResolver as i, LinearGradientDefinition as j, GradientStop as k, GestureBinding as l, CommandHandler as m, CreateSvgEditorOptions as n, SurfaceHandle as o, KeymapBinding as p, DomComputedPaint as r, SvgEditor as s, Commands as t, GestureContext as u, CameraConstraints as v, EditorStyle as w, Color as x, CameraOptions as y, PropertyValue as z };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
export { BoundsResolver, Camera, CameraConstraints, CameraOptions, ClipboardProvider, Color, CommandHandler, CommandId, Commands, CreateSvgEditorOptions, DEFAULT_STYLE, DomComputedPaint, DomComputedResolver, EditorState, EditorStyle, FileIOProvider, FontResolver, GestureBinding, GestureContext, GestureId, Gestures, GradientDefinition, GradientEntry, GradientStop, InvalidComputedValue, KeymapBinding, LinearGradientDefinition, Mode, NodeId, Paint, PaintFallback, PaintPreviewSession, PaintValue, PreviewSession, PropertyValue, Provenance, Providers, RadialGradientDefinition, Rect, ReorderDirection, SurfaceHandle, SvgEditor, Unsubscribe, Vec2, createSvgEditor };
|
|
1
|
+
import { A as InvalidComputedValue, B as Provenance, C as EditorState, D as GradientDefinition, E as FontResolver, F as PaintFallback, G as Unsubscribe, H as RadialGradientDefinition, I as PaintPreviewSession, K as Vec2, L as PaintValue, M as Mode, N as NodeId, O as GradientEntry, P as Paint, R as PreviewSession, S as DEFAULT_STYLE, T as FileIOProvider, U as Rect, V as Providers, W as ReorderDirection, _ as Camera, a as SelectMode, b as ClipboardProvider, c as createSvgEditor, d as GestureId, f as Gestures, g as BoundsResolver, h as CommandId, i as DomComputedResolver, j as LinearGradientDefinition, k as GradientStop, l as GestureBinding, m as CommandHandler, n as CreateSvgEditorOptions, o as SurfaceHandle, p as KeymapBinding, r as DomComputedPaint, s as SvgEditor, t as Commands, u as GestureContext, v as CameraConstraints, w as EditorStyle, x as Color, y as CameraOptions, z as PropertyValue } from "./editor-KRAmUodY.mjs";
|
|
2
|
+
export { BoundsResolver, Camera, CameraConstraints, CameraOptions, ClipboardProvider, Color, CommandHandler, CommandId, Commands, CreateSvgEditorOptions, DEFAULT_STYLE, DomComputedPaint, DomComputedResolver, EditorState, EditorStyle, FileIOProvider, FontResolver, GestureBinding, GestureContext, GestureId, Gestures, GradientDefinition, GradientEntry, GradientStop, InvalidComputedValue, KeymapBinding, LinearGradientDefinition, Mode, NodeId, Paint, PaintFallback, PaintPreviewSession, PaintValue, PreviewSession, PropertyValue, Provenance, Providers, RadialGradientDefinition, Rect, ReorderDirection, SelectMode, SurfaceHandle, SvgEditor, Unsubscribe, Vec2, createSvgEditor };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
export { BoundsResolver, Camera, CameraConstraints, CameraOptions, ClipboardProvider, Color, CommandHandler, CommandId, Commands, CreateSvgEditorOptions, DEFAULT_STYLE, DomComputedPaint, DomComputedResolver, EditorState, EditorStyle, FileIOProvider, FontResolver, GestureBinding, GestureContext, GestureId, Gestures, GradientDefinition, GradientEntry, GradientStop, InvalidComputedValue, KeymapBinding, LinearGradientDefinition, Mode, NodeId, Paint, PaintFallback, PaintPreviewSession, PaintValue, PreviewSession, PropertyValue, Provenance, Providers, RadialGradientDefinition, Rect, ReorderDirection, SurfaceHandle, SvgEditor, Unsubscribe, Vec2, createSvgEditor };
|
|
1
|
+
import { A as InvalidComputedValue, B as Provenance, C as EditorState, D as GradientDefinition, E as FontResolver, F as PaintFallback, G as Unsubscribe, H as RadialGradientDefinition, I as PaintPreviewSession, K as Vec2, L as PaintValue, M as Mode, N as NodeId, O as GradientEntry, P as Paint, R as PreviewSession, S as DEFAULT_STYLE, T as FileIOProvider, U as Rect, V as Providers, W as ReorderDirection, _ as Camera, a as SelectMode, b as ClipboardProvider, c as createSvgEditor, d as GestureId, f as Gestures, g as BoundsResolver, h as CommandId, i as DomComputedResolver, j as LinearGradientDefinition, k as GradientStop, l as GestureBinding, m as CommandHandler, n as CreateSvgEditorOptions, o as SurfaceHandle, p as KeymapBinding, r as DomComputedPaint, s as SvgEditor, t as Commands, u as GestureContext, v as CameraConstraints, w as EditorStyle, x as Color, y as CameraOptions, z as PropertyValue } from "./editor-DdgqLDC9.js";
|
|
2
|
+
export { BoundsResolver, Camera, CameraConstraints, CameraOptions, ClipboardProvider, Color, CommandHandler, CommandId, Commands, CreateSvgEditorOptions, DEFAULT_STYLE, DomComputedPaint, DomComputedResolver, EditorState, EditorStyle, FileIOProvider, FontResolver, GestureBinding, GestureContext, GestureId, Gestures, GradientDefinition, GradientEntry, GradientStop, InvalidComputedValue, KeymapBinding, LinearGradientDefinition, Mode, NodeId, Paint, PaintFallback, PaintPreviewSession, PaintValue, PreviewSession, PropertyValue, Provenance, Providers, RadialGradientDefinition, Rect, ReorderDirection, SelectMode, SurfaceHandle, SvgEditor, Unsubscribe, Vec2, createSvgEditor };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_editor = require("./editor-
|
|
2
|
+
const require_editor = require("./editor-Ds47eN37.js");
|
|
3
3
|
exports.DEFAULT_STYLE = require_editor.DEFAULT_STYLE;
|
|
4
4
|
exports.createSvgEditor = require_editor.createSvgEditor;
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as DEFAULT_STYLE, t as createSvgEditor } from "./editor-
|
|
1
|
+
import { n as DEFAULT_STYLE, t as createSvgEditor } from "./editor-CRflVqEz.mjs";
|
|
2
2
|
export { DEFAULT_STYLE, createSvgEditor };
|
package/dist/presets.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as DomSurfaceOptions, t as DomSurfaceHandle } from "./dom-
|
|
1
|
+
import { s as SvgEditor } from "./editor-KRAmUodY.mjs";
|
|
2
|
+
import { n as DomSurfaceOptions, t as DomSurfaceHandle } from "./dom-CMXNUMjP.mjs";
|
|
3
3
|
declare namespace keynote_d_exports {
|
|
4
4
|
export { KeynoteAttachOptions, KeynoteSurfaceHandle, attach };
|
|
5
5
|
}
|
package/dist/presets.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as DomSurfaceOptions, t as DomSurfaceHandle } from "./dom-
|
|
1
|
+
import { s as SvgEditor } from "./editor-DdgqLDC9.js";
|
|
2
|
+
import { n as DomSurfaceOptions, t as DomSurfaceHandle } from "./dom-eIgcZ4JC.js";
|
|
3
3
|
declare namespace keynote_d_exports {
|
|
4
4
|
export { KeynoteAttachOptions, KeynoteSurfaceHandle, attach };
|
|
5
5
|
}
|
package/dist/presets.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_dom = require("./dom-
|
|
2
|
+
const require_dom = require("./dom-DyJy1H6Q.js");
|
|
3
3
|
//#region src/presets/keynote.ts
|
|
4
4
|
var keynote_exports = /* @__PURE__ */ require_dom.__exportAll({ attach: () => attach });
|
|
5
5
|
/**
|
|
@@ -16,28 +16,25 @@ var keynote_exports = /* @__PURE__ */ require_dom.__exportAll({ attach: () => at
|
|
|
16
16
|
* additionally tears down the load subscription.
|
|
17
17
|
*/
|
|
18
18
|
function attach(editor, opts) {
|
|
19
|
-
let padding = opts.padding ?? 80;
|
|
20
19
|
const inner = require_dom.attach_dom_surface(editor, {
|
|
21
20
|
...opts.surface,
|
|
22
21
|
container: opts.container,
|
|
23
22
|
fit: true
|
|
24
23
|
});
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
const apply = (p) => {
|
|
25
|
+
inner.camera.constraints = {
|
|
26
|
+
type: "cover",
|
|
27
|
+
bounds: "<root>",
|
|
28
|
+
padding: p
|
|
29
|
+
};
|
|
29
30
|
};
|
|
30
|
-
|
|
31
|
+
apply(opts.padding ?? 80);
|
|
32
|
+
const unsub_load = editor.subscribe_with_selector((s) => s.load_version, () => inner.camera.fit("<root>", { margin: inner.camera.constraints?.padding ?? 0 }));
|
|
31
33
|
return {
|
|
32
34
|
camera: inner.camera,
|
|
33
35
|
gestures: inner.gestures,
|
|
34
36
|
set_padding(p) {
|
|
35
|
-
|
|
36
|
-
inner.camera.constraints = {
|
|
37
|
-
type: "cover",
|
|
38
|
-
bounds: "<root>",
|
|
39
|
-
padding: p
|
|
40
|
-
};
|
|
37
|
+
apply(p);
|
|
41
38
|
inner.camera.fit("<root>", { margin: p });
|
|
42
39
|
},
|
|
43
40
|
detach: () => {
|
package/dist/presets.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-CfYAbeIz.mjs";
|
|
2
|
-
import { t as attach_dom_surface } from "./dom-
|
|
2
|
+
import { t as attach_dom_surface } from "./dom-l5Y1Wf8C.mjs";
|
|
3
3
|
//#region src/presets/keynote.ts
|
|
4
4
|
var keynote_exports = /* @__PURE__ */ __exportAll({ attach: () => attach });
|
|
5
5
|
/**
|
|
@@ -16,28 +16,25 @@ var keynote_exports = /* @__PURE__ */ __exportAll({ attach: () => attach });
|
|
|
16
16
|
* additionally tears down the load subscription.
|
|
17
17
|
*/
|
|
18
18
|
function attach(editor, opts) {
|
|
19
|
-
let padding = opts.padding ?? 80;
|
|
20
19
|
const inner = attach_dom_surface(editor, {
|
|
21
20
|
...opts.surface,
|
|
22
21
|
container: opts.container,
|
|
23
22
|
fit: true
|
|
24
23
|
});
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
const apply = (p) => {
|
|
25
|
+
inner.camera.constraints = {
|
|
26
|
+
type: "cover",
|
|
27
|
+
bounds: "<root>",
|
|
28
|
+
padding: p
|
|
29
|
+
};
|
|
29
30
|
};
|
|
30
|
-
|
|
31
|
+
apply(opts.padding ?? 80);
|
|
32
|
+
const unsub_load = editor.subscribe_with_selector((s) => s.load_version, () => inner.camera.fit("<root>", { margin: inner.camera.constraints?.padding ?? 0 }));
|
|
31
33
|
return {
|
|
32
34
|
camera: inner.camera,
|
|
33
35
|
gestures: inner.gestures,
|
|
34
36
|
set_padding(p) {
|
|
35
|
-
|
|
36
|
-
inner.camera.constraints = {
|
|
37
|
-
type: "cover",
|
|
38
|
-
bounds: "<root>",
|
|
39
|
-
padding: p
|
|
40
|
-
};
|
|
37
|
+
apply(p);
|
|
41
38
|
inner.camera.fit("<root>", { margin: p });
|
|
42
39
|
},
|
|
43
40
|
detach: () => {
|
package/dist/react.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as DomSurfaceHandle } from "./dom-
|
|
1
|
+
import { C as EditorState, V as Providers, s as SvgEditor, t as Commands, w as EditorStyle } from "./editor-KRAmUodY.mjs";
|
|
2
|
+
import { t as DomSurfaceHandle } from "./dom-CMXNUMjP.mjs";
|
|
3
3
|
import cmath from "@grida/cmath";
|
|
4
4
|
import { ReactNode } from "react";
|
|
5
5
|
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
package/dist/react.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as DomSurfaceHandle } from "./dom-
|
|
1
|
+
import { C as EditorState, V as Providers, s as SvgEditor, t as Commands, w as EditorStyle } from "./editor-DdgqLDC9.js";
|
|
2
|
+
import { t as DomSurfaceHandle } from "./dom-eIgcZ4JC.js";
|
|
3
3
|
import cmath from "@grida/cmath";
|
|
4
4
|
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
5
5
|
import { ReactNode } from "react";
|
package/dist/react.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const require_dom = require("./dom-
|
|
4
|
-
const require_editor = require("./editor-
|
|
3
|
+
const require_dom = require("./dom-DyJy1H6Q.js");
|
|
4
|
+
const require_editor = require("./editor-Ds47eN37.js");
|
|
5
5
|
let react = require("react");
|
|
6
6
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
7
|
//#region src/react.tsx
|
package/dist/react.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { t as createSvgEditor } from "./editor-
|
|
3
|
-
import { t as attach_dom_surface } from "./dom-
|
|
2
|
+
import { t as createSvgEditor } from "./editor-CRflVqEz.mjs";
|
|
3
|
+
import { t as attach_dom_surface } from "./dom-l5Y1Wf8C.mjs";
|
|
4
4
|
import { createContext, useContext, useEffect, useMemo, useRef, useSyncExternalStore } from "react";
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
6
|
//#region src/react.tsx
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grida/svg-editor",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.5",
|
|
4
4
|
"description": "Headless SVG editor (experimental).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Grida",
|
|
@@ -39,11 +39,11 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"svg-pathdata": "^7.2.0",
|
|
42
|
+
"@grida/cmath": "0.1.0",
|
|
42
43
|
"@grida/history": "0.1.0",
|
|
43
44
|
"@grida/hud": "0.1.0",
|
|
44
|
-
"@grida/text-editor": "0.1.0",
|
|
45
45
|
"@grida/keybinding": "0.1.0",
|
|
46
|
-
"@grida/
|
|
46
|
+
"@grida/text-editor": "0.1.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/react": "^19",
|