@flighthq/command 0.4.1-edge.28.7f8e221

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.
Files changed (41) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +17 -0
  3. package/dist/command.d.ts +14 -0
  4. package/dist/command.d.ts.map +1 -0
  5. package/dist/command.js +63 -0
  6. package/dist/command.js.map +1 -0
  7. package/dist/commandBinding.d.ts +9 -0
  8. package/dist/commandBinding.d.ts.map +1 -0
  9. package/dist/commandBinding.js +147 -0
  10. package/dist/commandBinding.js.map +1 -0
  11. package/dist/commandHistory.d.ts +22 -0
  12. package/dist/commandHistory.d.ts.map +1 -0
  13. package/dist/commandHistory.js +127 -0
  14. package/dist/commandHistory.js.map +1 -0
  15. package/dist/commandHistorySignals.d.ts +5 -0
  16. package/dist/commandHistorySignals.d.ts.map +1 -0
  17. package/dist/commandHistorySignals.js +15 -0
  18. package/dist/commandHistorySignals.js.map +1 -0
  19. package/dist/commandTransaction.d.ts +7 -0
  20. package/dist/commandTransaction.d.ts.map +1 -0
  21. package/dist/commandTransaction.js +64 -0
  22. package/dist/commandTransaction.js.map +1 -0
  23. package/dist/contract.d.ts +7 -0
  24. package/dist/contract.d.ts.map +1 -0
  25. package/dist/contract.js +7 -0
  26. package/dist/contract.js.map +1 -0
  27. package/dist/explainCommandDispatch.d.ts +3 -0
  28. package/dist/explainCommandDispatch.d.ts.map +1 -0
  29. package/dist/explainCommandDispatch.js +23 -0
  30. package/dist/explainCommandDispatch.js.map +1 -0
  31. package/dist/index.d.ts +7 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +7 -0
  34. package/dist/index.js.map +1 -0
  35. package/package.json +51 -0
  36. package/src/command.test.ts +115 -0
  37. package/src/commandBinding.test.ts +219 -0
  38. package/src/commandHistory.test.ts +203 -0
  39. package/src/commandHistorySignals.test.ts +46 -0
  40. package/src/commandTransaction.test.ts +174 -0
  41. package/src/explainCommandDispatch.test.ts +42 -0
package/LICENSE.md ADDED
@@ -0,0 +1,9 @@
1
+ # MIT License
2
+
3
+ Copyright (c) 2013-2026 Joshua Granick and other contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,17 @@
1
+ # @flighthq/command
2
+
3
+ Undo/redo command history — commands are plain kind-tagged data (property set, add/remove/reorder child, composite) whose execute/undo/merge are free functions registered per kind in a keyed table and resolved at dispatch, with a stack tracking applied/redoable entries, per-kind merge coalescing for drag sequences, nestable transaction brackets that fold many commands into one entry, an optional maxSize cap, and an opt-in onChange signal; no closures on the stack, so entries stay inspectable data
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ npm install @flighthq/command
9
+ ```
10
+
11
+ Import the supported application-facing API from `@flighthq/command`. The `@flighthq/command/contract` export is the wider package-to-package contract used to compose Flight itself.
12
+
13
+ This package is part of the locked-version Flight SDK graph. Applications may instead install and import `@flighthq/sdk` when package-level tree shaking is sufficient.
14
+
15
+ - [Flight project](https://github.com/flighthq/flight)
16
+ - [Source for @flighthq/command@0.4.1-edge.28.7f8e221](https://github.com/flighthq/flight/tree/7f8e221c72f4afa55c07bf31862b2e3d60e1c81f/packages/command)
17
+ - [License](https://github.com/flighthq/flight/blob/7f8e221c72f4afa55c07bf31862b2e3d60e1c81f/LICENSE.md)
@@ -0,0 +1,14 @@
1
+ import type { AddNodeChildCommand, Command, CompositeCommand, NodeAny, RemoveNodeChildCommand, ReorderNodeChildCommand, SetNodePropertyCommand } from '@flighthq/types/contract';
2
+ /** Adds `child` to `parent`. `index` of `-1` appends. */
3
+ export declare function createAddNodeChildCommand(label: string, parent: NodeAny, child: NodeAny, index?: number): AddNodeChildCommand;
4
+ /** Applies `children` as one history entry, in order; undo runs them in reverse. Nesting is allowed. */
5
+ export declare function createCompositeCommand(label: string, children: readonly Command[]): CompositeCommand;
6
+ export declare function createRemoveNodeChildCommand(label: string, parent: NodeAny, child: NodeAny): RemoveNodeChildCommand;
7
+ export declare function createReorderNodeChildCommand(label: string, parent: NodeAny, child: NodeAny, toIndex: number): ReorderNodeChildCommand;
8
+ export declare function createSetNodePropertyCommand(label: string, target: NodeAny, property: string, value: unknown, mergeWindow?: number, time?: number): SetNodePropertyCommand;
9
+ export declare function createSetNodePropertyCommandBatch(label: string, entries: readonly Readonly<{
10
+ property: string;
11
+ target: NodeAny;
12
+ value: unknown;
13
+ }>[], mergeWindow?: number, time?: number): SetNodePropertyCommand;
14
+ //# sourceMappingURL=command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,mBAAmB,EACnB,OAAO,EAEP,gBAAgB,EAChB,OAAO,EACP,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,0BAA0B,CAAC;AAiBlC,yDAAyD;AACzD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,OAAO,EACd,KAAK,SAAK,GACT,mBAAmB,CAErB;AAED,wGAAwG;AACxG,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,gBAAgB,CAEpG;AAID,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,sBAAsB,CAEnH;AAGD,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,MAAM,GACd,uBAAuB,CASzB;AAQD,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,WAAW,SAAI,EACf,IAAI,SAAI,GACP,sBAAsB,CAQxB;AAID,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,SAAS,QAAQ,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,EAAE,EACnF,WAAW,SAAI,EACf,IAAI,SAAI,GACP,sBAAsB,CAQxB"}
@@ -0,0 +1,63 @@
1
+ import { getNodeChildIndex } from '@flighthq/node/contract';
2
+ import { AddNodeChildCommandKind, CompositeCommandKind, RemoveNodeChildCommandKind, ReorderNodeChildCommandKind, SetNodePropertyCommandKind, } from '@flighthq/types/contract';
3
+ // Constructors for the built-in command kinds. Each returns PLAIN DATA — no method, no captured closure —
4
+ // so the result can be inspected by a history panel, compared, and (once nodes carry stable identity)
5
+ // written to disk. The behaviour that acts on this data is registered separately per kind.
6
+ //
7
+ // Each constructor captures what undo will need AT CREATION TIME: the previous property value, the child's
8
+ // current index. That is why these are `create*` rather than plain literals, and why a caller must build a
9
+ // command BEFORE applying the change by hand.
10
+ /** Adds `child` to `parent`. `index` of `-1` appends. */
11
+ export function createAddNodeChildCommand(label, parent, child, index = -1) {
12
+ return { child, index, kind: AddNodeChildCommandKind, label, parent };
13
+ }
14
+ /** Applies `children` as one history entry, in order; undo runs them in reverse. Nesting is allowed. */
15
+ export function createCompositeCommand(label, children) {
16
+ return { children: [...children], kind: CompositeCommandKind, label };
17
+ }
18
+ // Removes `child` from `parent`, capturing its CURRENT index so undo restores position and not merely
19
+ // membership. Build this before removing the child — once it is detached the index is gone.
20
+ export function createRemoveNodeChildCommand(label, parent, child) {
21
+ return { child, index: getNodeChildIndex(parent, child), kind: RemoveNodeChildCommandKind, label, parent };
22
+ }
23
+ // Moves `child` to `toIndex`, capturing where it started. Build this before moving the child.
24
+ export function createReorderNodeChildCommand(label, parent, child, toIndex) {
25
+ return {
26
+ child,
27
+ fromIndex: getNodeChildIndex(parent, child),
28
+ kind: ReorderNodeChildCommandKind,
29
+ label,
30
+ parent,
31
+ toIndex,
32
+ };
33
+ }
34
+ // One property assignment. `before` is read from the node NOW, so build this before writing the value.
35
+ //
36
+ // `mergeWindow` and `time` drive coalescing: two commands over the same target and property merge when
37
+ // both carry a positive window and the elapsed time fits inside it, which is what turns a drag into one
38
+ // undo entry. Both default to 0, meaning every change is its own entry. `time` is supplied by the caller
39
+ // because this package takes no clock dependency — and a caller-supplied number stays serializable.
40
+ export function createSetNodePropertyCommand(label, target, property, value, mergeWindow = 0, time = 0) {
41
+ return {
42
+ entries: [{ after: value, before: readNodeProperty(target, property), property, target }],
43
+ kind: SetNodePropertyCommandKind,
44
+ label,
45
+ mergeWindow,
46
+ time,
47
+ };
48
+ }
49
+ // Several property assignments applied together as one entry — the shape a gizmo drag produces when it
50
+ // writes x and y at once. Each `before` is read now, in the order given.
51
+ export function createSetNodePropertyCommandBatch(label, entries, mergeWindow = 0, time = 0) {
52
+ const captured = entries.map((entry) => ({
53
+ after: entry.value,
54
+ before: readNodeProperty(entry.target, entry.property),
55
+ property: entry.property,
56
+ target: entry.target,
57
+ }));
58
+ return { entries: captured, kind: SetNodePropertyCommandKind, label, mergeWindow, time };
59
+ }
60
+ function readNodeProperty(target, property) {
61
+ return target[property];
62
+ }
63
+ //# sourceMappingURL=command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAW5D,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,0BAA0B,EAC1B,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,0BAA0B,CAAC;AAElC,0GAA0G;AAC1G,sGAAsG;AACtG,2FAA2F;AAC3F,EAAE;AACF,2GAA2G;AAC3G,2GAA2G;AAC3G,8CAA8C;AAE9C,yDAAyD;AACzD,MAAM,UAAU,yBAAyB,CACvC,KAAa,EACb,MAAe,EACf,KAAc,EACd,KAAK,GAAG,CAAC,CAAC;IAEV,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AACxE,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,sBAAsB,CAAC,KAAa,EAAE,QAA4B;IAChF,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAG,QAAQ,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC;AACxE,CAAC;AAED,sGAAsG;AACtG,4FAA4F;AAC5F,MAAM,UAAU,4BAA4B,CAAC,KAAa,EAAE,MAAe,EAAE,KAAc;IACzF,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,0BAA0B,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC7G,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,6BAA6B,CAC3C,KAAa,EACb,MAAe,EACf,KAAc,EACd,OAAe;IAEf,OAAO;QACL,KAAK;QACL,SAAS,EAAE,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC;QAC3C,IAAI,EAAE,2BAA2B;QACjC,KAAK;QACL,MAAM;QACN,OAAO;KACR,CAAC;AACJ,CAAC;AAED,uGAAuG;AACvG,EAAE;AACF,uGAAuG;AACvG,wGAAwG;AACxG,yGAAyG;AACzG,oGAAoG;AACpG,MAAM,UAAU,4BAA4B,CAC1C,KAAa,EACb,MAAe,EACf,QAAgB,EAChB,KAAc,EACd,WAAW,GAAG,CAAC,EACf,IAAI,GAAG,CAAC;IAER,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QACzF,IAAI,EAAE,0BAA0B;QAChC,KAAK;QACL,WAAW;QACX,IAAI;KACL,CAAC;AACJ,CAAC;AAED,uGAAuG;AACvG,yEAAyE;AACzE,MAAM,UAAU,iCAAiC,CAC/C,KAAa,EACb,OAAmF,EACnF,WAAW,GAAG,CAAC,EACf,IAAI,GAAG,CAAC;IAER,MAAM,QAAQ,GAA2B,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC/D,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC;QACtD,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC,CAAC,CAAC;IACJ,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,0BAA0B,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;AAC3F,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAyB,EAAE,QAAgB;IACnE,OAAQ,MAAuD,CAAC,QAAQ,CAAC,CAAC;AAC5E,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { CommandBinding, CommandHistory, Kind, KeyedTable } from '@flighthq/types/contract';
2
+ /** An empty command binding table. Every kind a history will dispatch must be registered into it. */
3
+ export declare function createCommandBindingTable(): KeyedTable<CommandBinding>;
4
+ /** The binding registered for `kind`, or `null` when nothing is. */
5
+ export declare function getCommandBinding(history: Readonly<CommandHistory>, kind: Kind): CommandBinding | null;
6
+ export declare function hasCommandBinding(history: Readonly<CommandHistory>, kind: Kind): boolean;
7
+ export declare function registerCommandBinding(history: CommandHistory, kind: Kind, binding: CommandBinding): void;
8
+ export declare function registerDefaultCommandBindings(history: CommandHistory): void;
9
+ //# sourceMappingURL=commandBinding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandBinding.d.ts","sourceRoot":"","sources":["../src/commandBinding.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,cAAc,EACd,cAAc,EAEd,IAAI,EACJ,UAAU,EAKX,MAAM,0BAA0B,CAAC;AAWlC,qGAAqG;AACrG,wBAAgB,yBAAyB,IAAI,UAAU,CAAC,cAAc,CAAC,CAEtE;AAED,oEAAoE;AACpE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,cAAc,GAAG,IAAI,CAEtG;AAKD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAExF;AAKD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAEzG;AAID,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAM5E"}
@@ -0,0 +1,147 @@
1
+ import { addNodeChildAt, getNodeChildCount, removeNodeChild, setNodeChildIndex } from '@flighthq/node/contract';
2
+ import { createKeyedTable, getRegistryTableEntry, withRegistryTableEntry } from '@flighthq/registry/contract';
3
+ import { AddNodeChildCommandKind, CommandBindingMissPolicy, CommandBindingRegistryId, CompositeCommandKind, RemoveNodeChildCommandKind, ReorderNodeChildCommandKind, SetNodePropertyCommandKind, } from '@flighthq/types/contract';
4
+ /** An empty command binding table. Every kind a history will dispatch must be registered into it. */
5
+ export function createCommandBindingTable() {
6
+ return createKeyedTable(CommandBindingRegistryId, CommandBindingMissPolicy);
7
+ }
8
+ /** The binding registered for `kind`, or `null` when nothing is. */
9
+ export function getCommandBinding(history, kind) {
10
+ return getRegistryTableEntry(history.bindings, kind);
11
+ }
12
+ // Why a `null` return and no throw: an unregistered kind is an expected lookup failure, not API misuse,
13
+ // so it takes the sentinel every other registry miss in this SDK takes. `explainCommandDispatch` is the
14
+ // shakeable query that says WHICH kind was missing, per the diagnostics inversion rule.
15
+ export function hasCommandBinding(history, kind) {
16
+ return getCommandBinding(history, kind) !== null;
17
+ }
18
+ // Binds behaviour to a command kind. NOT called at module load anywhere in this package — a caller opts
19
+ // in, which is what keeps unused command kinds shakeable and lets a consumer override a built-in binding
20
+ // or add a vendor-prefixed kind of their own. Last write wins.
21
+ export function registerCommandBinding(history, kind, binding) {
22
+ history.bindings = withRegistryTableEntry(history.bindings, kind, binding);
23
+ }
24
+ // Registers the five built-in kinds. An explicit call rather than a side effect at import: a history that
25
+ // only dispatches a caller's own kinds never references these, so they shake out of the bundle.
26
+ export function registerDefaultCommandBindings(history) {
27
+ registerCommandBinding(history, AddNodeChildCommandKind, addNodeChildCommandBinding);
28
+ registerCommandBinding(history, CompositeCommandKind, compositeCommandBinding(history));
29
+ registerCommandBinding(history, RemoveNodeChildCommandKind, removeNodeChildCommandBinding);
30
+ registerCommandBinding(history, ReorderNodeChildCommandKind, reorderNodeChildCommandBinding);
31
+ registerCommandBinding(history, SetNodePropertyCommandKind, setNodePropertyCommandBinding);
32
+ }
33
+ const addNodeChildCommandBinding = {
34
+ execute: (command) => {
35
+ const add = command;
36
+ addNodeChildAt(add.parent, add.child, resolveInsertIndex(add.parent, add.index));
37
+ },
38
+ undo: (command) => {
39
+ const add = command;
40
+ removeNodeChild(add.parent, add.child);
41
+ },
42
+ };
43
+ // The composite binding is the ONE binding that needs the history, because dispatching a child means
44
+ // resolving the child's own kind against the same table. It takes the history as a parameter rather than
45
+ // closing over mutable state: the table it reads is re-read on every call, so a binding registered after
46
+ // this one is still found.
47
+ function compositeCommandBinding(history) {
48
+ return {
49
+ execute: (command) => {
50
+ const children = command.children;
51
+ for (let i = 0; i < children.length; i++) {
52
+ getCommandBinding(history, children[i].kind)?.execute(children[i]);
53
+ }
54
+ },
55
+ // Reverse order, which is not a detail: undoing an add-then-reorder forward would reorder a child
56
+ // that the add has not yet been taken back.
57
+ undo: (command) => {
58
+ const children = command.children;
59
+ for (let i = children.length - 1; i >= 0; i--) {
60
+ getCommandBinding(history, children[i].kind)?.undo(children[i]);
61
+ }
62
+ },
63
+ };
64
+ }
65
+ const removeNodeChildCommandBinding = {
66
+ execute: (command) => {
67
+ const remove = command;
68
+ removeNodeChild(remove.parent, remove.child);
69
+ },
70
+ // Restores POSITION as well as membership, using the index captured when the command was created.
71
+ undo: (command) => {
72
+ const remove = command;
73
+ addNodeChildAt(remove.parent, remove.child, resolveInsertIndex(remove.parent, remove.index));
74
+ },
75
+ };
76
+ const reorderNodeChildCommandBinding = {
77
+ execute: (command) => {
78
+ const reorder = command;
79
+ setNodeChildIndex(reorder.parent, reorder.child, reorder.toIndex);
80
+ },
81
+ undo: (command) => {
82
+ const reorder = command;
83
+ setNodeChildIndex(reorder.parent, reorder.child, reorder.fromIndex);
84
+ },
85
+ };
86
+ // Reads `before`/`after` off the command's own entries rather than sampling the node, so undo restores the
87
+ // value recorded at capture time even if something else has written the property since.
88
+ const setNodePropertyCommandBinding = {
89
+ execute: (command) => {
90
+ const entries = command.entries;
91
+ for (let i = 0; i < entries.length; i++) {
92
+ writeNodeProperty(entries[i].target, entries[i].property, entries[i].after);
93
+ }
94
+ },
95
+ // Coalesces a drag: the merged command keeps the ORIGINAL `before` and takes the newest `after`, so one
96
+ // undo returns to the position the gesture started from. Merges only when both commands touch the same
97
+ // targets and properties in the same order, and both carry a window that the elapsed time fits inside.
98
+ merge: (previous, next) => {
99
+ if (previous.kind !== next.kind)
100
+ return null;
101
+ const a = previous;
102
+ const b = next;
103
+ if (a.mergeWindow <= 0 || b.mergeWindow <= 0)
104
+ return null;
105
+ if (b.time - a.time > b.mergeWindow)
106
+ return null;
107
+ if (a.entries.length !== b.entries.length)
108
+ return null;
109
+ for (let i = 0; i < a.entries.length; i++) {
110
+ if (a.entries[i].target !== b.entries[i].target)
111
+ return null;
112
+ if (a.entries[i].property !== b.entries[i].property)
113
+ return null;
114
+ }
115
+ return {
116
+ entries: a.entries.map((entry, i) => ({
117
+ after: b.entries[i].after,
118
+ before: entry.before,
119
+ property: entry.property,
120
+ target: entry.target,
121
+ })),
122
+ kind: a.kind,
123
+ label: b.label,
124
+ mergeWindow: b.mergeWindow,
125
+ time: b.time,
126
+ };
127
+ },
128
+ undo: (command) => {
129
+ const entries = command.entries;
130
+ for (let i = entries.length - 1; i >= 0; i--) {
131
+ writeNodeProperty(entries[i].target, entries[i].property, entries[i].before);
132
+ }
133
+ },
134
+ };
135
+ // `-1` appends. Resolved against the CURRENT child count rather than the count at capture time, because an
136
+ // undo that restores a child to index 7 of a parent that now holds three children must place it at the end
137
+ // rather than fail.
138
+ function resolveInsertIndex(parent, index) {
139
+ const count = getNodeChildCount(parent);
140
+ return index < 0 || index > count ? count : index;
141
+ }
142
+ // A property write on a node is a plain field assignment — the invalidation doctrine makes transforms
143
+ // recompute by default, so a command does not stamp a revision of its own.
144
+ function writeNodeProperty(target, property, value) {
145
+ target[property] = value;
146
+ }
147
+ //# sourceMappingURL=commandBinding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandBinding.js","sourceRoot":"","sources":["../src/commandBinding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { Command, CommandHistory } from '@flighthq/types/contract';
2
+ /** Whether there is an applied entry to reverse. */
3
+ export declare function canRedoCommand(history: Readonly<CommandHistory>): boolean;
4
+ /** Whether there is a reversed entry ahead of the cursor to re-apply. */
5
+ export declare function canUndoCommand(history: Readonly<CommandHistory>): boolean;
6
+ export declare function clearCommandHistory(history: CommandHistory): void;
7
+ /** An empty history with no bindings registered. `maxSize` of `0` (the default) is unbounded. */
8
+ export declare function createCommandHistory(maxSize?: number): CommandHistory;
9
+ export declare function executeCommand(history: CommandHistory, command: Command): boolean;
10
+ /** Every entry, oldest first, including the reversed ones ahead of the cursor. */
11
+ export declare function getCommandHistoryEntries(history: Readonly<CommandHistory>): readonly Command[];
12
+ /** The count of applied entries — entries before it are applied, entries from it on are redoable. */
13
+ export declare function getCommandHistoryIndex(history: Readonly<CommandHistory>): number;
14
+ /** The label of the entry redo would re-apply, or null. */
15
+ export declare function getCommandHistoryRedoLabel(history: Readonly<CommandHistory>): string | null;
16
+ /** The label of the entry undo would reverse, or null. */
17
+ export declare function getCommandHistoryUndoLabel(history: Readonly<CommandHistory>): string | null;
18
+ export declare function notifyCommandHistoryChanged(history: Readonly<CommandHistory>): void;
19
+ export declare function redoCommand(history: CommandHistory): boolean;
20
+ /** Reverses the most recently applied entry. */
21
+ export declare function undoCommand(history: CommandHistory): boolean;
22
+ //# sourceMappingURL=commandHistory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandHistory.d.ts","sourceRoot":"","sources":["../src/commandHistory.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAIxE,oDAAoD;AACpD,wBAAgB,cAAc,CAAC,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,OAAO,CAEzE;AAED,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,OAAO,CAEzE;AAID,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAQjE;AAED,iGAAiG;AACjG,wBAAgB,oBAAoB,CAAC,OAAO,SAAI,GAAG,cAAc,CAWhE;AAUD,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAuBjF;AAED,kFAAkF;AAClF,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,SAAS,OAAO,EAAE,CAE9F;AAED,qGAAqG;AACrG,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,MAAM,CAEhF;AAED,2DAA2D;AAC3D,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,MAAM,GAAG,IAAI,CAE3F;AAED,0DAA0D;AAC1D,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,MAAM,GAAG,IAAI,CAE3F;AAID,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,IAAI,CAEnF;AAKD,wBAAgB,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAS5D;AAED,gDAAgD;AAChD,wBAAgB,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAS5D"}
@@ -0,0 +1,127 @@
1
+ import { emitSignal } from '@flighthq/signals/contract';
2
+ import { createCommandBindingTable, getCommandBinding } from './commandBinding';
3
+ /** Whether there is an applied entry to reverse. */
4
+ export function canRedoCommand(history) {
5
+ return history.index < history.entries.length;
6
+ }
7
+ /** Whether there is a reversed entry ahead of the cursor to re-apply. */
8
+ export function canUndoCommand(history) {
9
+ return history.index > 0;
10
+ }
11
+ // Drops every entry and resets the cursor. Does NOT undo anything — clearing a history forgets how to
12
+ // reverse the work, it does not reverse it. Emits only if there was something to forget.
13
+ export function clearCommandHistory(history) {
14
+ if (history.entries.length === 0 && history.index === 0)
15
+ return;
16
+ history.entries.length = 0;
17
+ history.index = 0;
18
+ history.transactionDepth = 0;
19
+ history.transactionIndex = 0;
20
+ history.transactionLabel = null;
21
+ notifyCommandHistoryChanged(history);
22
+ }
23
+ /** An empty history with no bindings registered. `maxSize` of `0` (the default) is unbounded. */
24
+ export function createCommandHistory(maxSize = 0) {
25
+ return {
26
+ bindings: createCommandBindingTable(),
27
+ entries: [],
28
+ index: 0,
29
+ maxSize,
30
+ onChange: null,
31
+ transactionDepth: 0,
32
+ transactionIndex: 0,
33
+ transactionLabel: null,
34
+ };
35
+ }
36
+ // Applies `command` and pushes it. Returns false and changes nothing when the command's kind has no
37
+ // registered binding — an unregistered kind is an expected lookup failure, so it takes a sentinel rather
38
+ // than a throw, and refusing to push is what stops an entry undo would silently skip from reaching the
39
+ // stack.
40
+ //
41
+ // Redoable entries ahead of the cursor are discarded: a new action after an undo forks the timeline.
42
+ // Inside a transaction no merge is attempted, because the whole bracket is about to fold into one entry
43
+ // anyway and merging first would only change which label survives.
44
+ export function executeCommand(history, command) {
45
+ const binding = getCommandBinding(history, command.kind);
46
+ if (binding === null)
47
+ return false;
48
+ binding.execute(command);
49
+ if (history.index < history.entries.length)
50
+ history.entries.length = history.index;
51
+ const previous = history.index > 0 ? history.entries[history.index - 1] : null;
52
+ const mergeable = history.transactionDepth === 0 && previous !== null && history.index > history.transactionIndex;
53
+ if (mergeable && binding.merge !== undefined) {
54
+ const merged = binding.merge(previous, command);
55
+ if (merged !== null) {
56
+ history.entries[history.index - 1] = merged;
57
+ notifyCommandHistoryChanged(history);
58
+ return true;
59
+ }
60
+ }
61
+ history.entries.push(command);
62
+ history.index++;
63
+ trimCommandHistory(history);
64
+ notifyCommandHistoryChanged(history);
65
+ return true;
66
+ }
67
+ /** Every entry, oldest first, including the reversed ones ahead of the cursor. */
68
+ export function getCommandHistoryEntries(history) {
69
+ return history.entries;
70
+ }
71
+ /** The count of applied entries — entries before it are applied, entries from it on are redoable. */
72
+ export function getCommandHistoryIndex(history) {
73
+ return history.index;
74
+ }
75
+ /** The label of the entry redo would re-apply, or null. */
76
+ export function getCommandHistoryRedoLabel(history) {
77
+ return canRedoCommand(history) ? history.entries[history.index].label : null;
78
+ }
79
+ /** The label of the entry undo would reverse, or null. */
80
+ export function getCommandHistoryUndoLabel(history) {
81
+ return canUndoCommand(history) ? history.entries[history.index - 1].label : null;
82
+ }
83
+ // Emits the opt-in change signal if a caller allocated one. Internal rather than exported: emitting a
84
+ // change nobody made is how a history panel learns to distrust the signal.
85
+ export function notifyCommandHistoryChanged(history) {
86
+ if (history.onChange !== null)
87
+ emitSignal(history.onChange);
88
+ }
89
+ // Re-applies the next reversed entry. Uses the registered `execute`; there is no separate `redo` hook,
90
+ // because a command whose re-application differs from its first application is two commands wearing one
91
+ // name.
92
+ export function redoCommand(history) {
93
+ if (!canRedoCommand(history))
94
+ return false;
95
+ const command = history.entries[history.index];
96
+ const binding = getCommandBinding(history, command.kind);
97
+ if (binding === null)
98
+ return false;
99
+ binding.execute(command);
100
+ history.index++;
101
+ notifyCommandHistoryChanged(history);
102
+ return true;
103
+ }
104
+ /** Reverses the most recently applied entry. */
105
+ export function undoCommand(history) {
106
+ if (!canUndoCommand(history))
107
+ return false;
108
+ const command = history.entries[history.index - 1];
109
+ const binding = getCommandBinding(history, command.kind);
110
+ if (binding === null)
111
+ return false;
112
+ binding.undo(command);
113
+ history.index--;
114
+ notifyCommandHistoryChanged(history);
115
+ return true;
116
+ }
117
+ // Drops from the OLDEST end so the most recent history survives, and moves the cursor with it. A composite
118
+ // counts as one entry, which is the point of folding a transaction.
119
+ function trimCommandHistory(history) {
120
+ if (history.maxSize <= 0 || history.entries.length <= history.maxSize)
121
+ return;
122
+ const excess = history.entries.length - history.maxSize;
123
+ history.entries.splice(0, excess);
124
+ history.index = Math.max(0, history.index - excess);
125
+ history.transactionIndex = Math.max(0, history.transactionIndex - excess);
126
+ }
127
+ //# sourceMappingURL=commandHistory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandHistory.js","sourceRoot":"","sources":["../src/commandHistory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAGxD,OAAO,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAEhF,oDAAoD;AACpD,MAAM,UAAU,cAAc,CAAC,OAAiC;IAC9D,OAAO,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;AAChD,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,cAAc,CAAC,OAAiC;IAC9D,OAAO,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC;AAC3B,CAAC;AAED,sGAAsG;AACtG,yFAAyF;AACzF,MAAM,UAAU,mBAAmB,CAAC,OAAuB;IACzD,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,KAAK,KAAK,CAAC;QAAE,OAAO;IAChE,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3B,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC;IAClB,OAAO,CAAC,gBAAgB,GAAG,CAAC,CAAC;IAC7B,OAAO,CAAC,gBAAgB,GAAG,CAAC,CAAC;IAC7B,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAChC,2BAA2B,CAAC,OAAO,CAAC,CAAC;AACvC,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,oBAAoB,CAAC,OAAO,GAAG,CAAC;IAC9C,OAAO;QACL,QAAQ,EAAE,yBAAyB,EAAE;QACrC,OAAO,EAAE,EAAE;QACX,KAAK,EAAE,CAAC;QACR,OAAO;QACP,QAAQ,EAAE,IAAI;QACd,gBAAgB,EAAE,CAAC;QACnB,gBAAgB,EAAE,CAAC;QACnB,gBAAgB,EAAE,IAAI;KACvB,CAAC;AACJ,CAAC;AAED,oGAAoG;AACpG,yGAAyG;AACzG,uGAAuG;AACvG,SAAS;AACT,EAAE;AACF,qGAAqG;AACrG,wGAAwG;AACxG,mEAAmE;AACnE,MAAM,UAAU,cAAc,CAAC,OAAuB,EAAE,OAAgB;IACtE,MAAM,OAAO,GAAG,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAEnC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACzB,IAAI,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAEnF,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/E,MAAM,SAAS,GAAG,OAAO,CAAC,gBAAgB,KAAK,CAAC,IAAI,QAAQ,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAClH,IAAI,SAAS,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAChD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC;YAC5C,2BAA2B,CAAC,OAAO,CAAC,CAAC;YACrC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC5B,2BAA2B,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,wBAAwB,CAAC,OAAiC;IACxE,OAAO,OAAO,CAAC,OAAO,CAAC;AACzB,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,sBAAsB,CAAC,OAAiC;IACtE,OAAO,OAAO,CAAC,KAAK,CAAC;AACvB,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,0BAA0B,CAAC,OAAiC;IAC1E,OAAO,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/E,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,0BAA0B,CAAC,OAAiC;IAC1E,OAAO,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACnF,CAAC;AAED,sGAAsG;AACtG,2EAA2E;AAC3E,MAAM,UAAU,2BAA2B,CAAC,OAAiC;IAC3E,IAAI,OAAO,CAAC,QAAQ,KAAK,IAAI;QAAE,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC9D,CAAC;AAED,uGAAuG;AACvG,wGAAwG;AACxG,QAAQ;AACR,MAAM,UAAU,WAAW,CAAC,OAAuB;IACjD,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACnC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACzB,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,2BAA2B,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,WAAW,CAAC,OAAuB;IACjD,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IACnD,MAAM,OAAO,GAAG,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACnC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtB,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,2BAA2B,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,2GAA2G;AAC3G,oEAAoE;AACpE,SAAS,kBAAkB,CAAC,OAAuB;IACjD,IAAI,OAAO,CAAC,OAAO,IAAI,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO;QAAE,OAAO;IAC9E,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IACxD,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAClC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC;IACpD,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,gBAAgB,GAAG,MAAM,CAAC,CAAC;AAC5E,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { CommandHistory, Signal } from '@flighthq/types/contract';
2
+ export declare function enableCommandHistorySignals(history: CommandHistory): Signal<() => void>;
3
+ /** The change signal if one was enabled, else null. Never allocates. */
4
+ export declare function getCommandHistorySignals(history: Readonly<CommandHistory>): Signal<() => void> | null;
5
+ //# sourceMappingURL=commandHistorySignals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandHistorySignals.d.ts","sourceRoot":"","sources":["../src/commandHistorySignals.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAMvE,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,CAGvF;AAED,wEAAwE;AACxE,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAErG"}
@@ -0,0 +1,15 @@
1
+ import { createSignal } from '@flighthq/signals/contract';
2
+ // Opts the history into its onChange signal, allocating it on first call and returning it (idempotent — a
3
+ // second call returns the same signal). onChange emits after any execute, undo, redo, clear, or transaction
4
+ // fold that changed state, which is what a history panel and undo/redo toolbar buttons listen to. A history
5
+ // that never calls this keeps onChange null and pays no signal allocation or dispatch cost.
6
+ export function enableCommandHistorySignals(history) {
7
+ if (history.onChange === null)
8
+ history.onChange = createSignal();
9
+ return history.onChange;
10
+ }
11
+ /** The change signal if one was enabled, else null. Never allocates. */
12
+ export function getCommandHistorySignals(history) {
13
+ return history.onChange;
14
+ }
15
+ //# sourceMappingURL=commandHistorySignals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandHistorySignals.js","sourceRoot":"","sources":["../src/commandHistorySignals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG1D,0GAA0G;AAC1G,4GAA4G;AAC5G,4GAA4G;AAC5G,4FAA4F;AAC5F,MAAM,UAAU,2BAA2B,CAAC,OAAuB;IACjE,IAAI,OAAO,CAAC,QAAQ,KAAK,IAAI;QAAE,OAAO,CAAC,QAAQ,GAAG,YAAY,EAAc,CAAC;IAC7E,OAAO,OAAO,CAAC,QAAQ,CAAC;AAC1B,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,wBAAwB,CAAC,OAAiC;IACxE,OAAO,OAAO,CAAC,QAAQ,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { CommandHistory } from '@flighthq/types/contract';
2
+ export declare function abortCommandTransaction(history: CommandHistory): boolean;
3
+ export declare function beginCommandTransaction(history: CommandHistory, label: string): void;
4
+ export declare function endCommandTransaction(history: CommandHistory): boolean;
5
+ /** Whether a bracket is currently open. */
6
+ export declare function isCommandTransactionOpen(history: Readonly<CommandHistory>): boolean;
7
+ //# sourceMappingURL=commandTransaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandTransaction.d.ts","sourceRoot":"","sources":["../src/commandTransaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAc/D,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAaxE;AAKD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAMpF;AAKD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAmBtE;AAED,2CAA2C;AAC3C,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,OAAO,CAEnF"}
@@ -0,0 +1,64 @@
1
+ import { createCompositeCommand } from './command';
2
+ import { getCommandBinding } from './commandBinding';
3
+ import { notifyCommandHistoryChanged } from './commandHistory';
4
+ // Transaction brackets, for operations whose full set of sub-commands is not known upfront — a gizmo drag
5
+ // that emits one command per frame, a paste that discovers what it is pasting as it goes.
6
+ //
7
+ // Commands execute normally inside the bracket; `end` folds everything pushed since `begin` into a single
8
+ // composite entry. This is why merging is suppressed inside a bracket: the fold is the coalescing.
9
+ // Unwinds and discards every command executed since the outermost `begin`. Undoes them in reverse, so a
10
+ // half-finished paste leaves the graph as it was found. Returns false when no transaction is open.
11
+ export function abortCommandTransaction(history) {
12
+ if (history.transactionDepth === 0)
13
+ return false;
14
+ const start = history.transactionIndex;
15
+ for (let i = history.entries.length - 1; i >= start; i--) {
16
+ const command = history.entries[i];
17
+ getCommandBinding(history, command.kind)?.undo(command);
18
+ }
19
+ history.entries.length = start;
20
+ history.index = start;
21
+ history.transactionDepth = 0;
22
+ history.transactionLabel = null;
23
+ notifyCommandHistoryChanged(history);
24
+ return true;
25
+ }
26
+ // Opens a bracket. Nesting is counted rather than stacked: only the OUTERMOST bracket folds, so a helper
27
+ // that brackets its own work does not fragment a caller's larger transaction into pieces. The label of the
28
+ // outermost begin is the one the folded entry carries.
29
+ export function beginCommandTransaction(history, label) {
30
+ if (history.transactionDepth === 0) {
31
+ history.transactionIndex = history.index;
32
+ history.transactionLabel = label;
33
+ }
34
+ history.transactionDepth++;
35
+ }
36
+ // Closes a bracket. On the outermost close, replaces everything pushed since `begin` with one composite
37
+ // entry carrying the transaction's label. A bracket that collected nothing leaves no entry at all — an
38
+ // empty undo step is worse than none, because it makes one undo press do nothing visible.
39
+ export function endCommandTransaction(history) {
40
+ if (history.transactionDepth === 0)
41
+ return false;
42
+ history.transactionDepth--;
43
+ if (history.transactionDepth > 0)
44
+ return true;
45
+ const start = history.transactionIndex;
46
+ const collected = history.entries.slice(start);
47
+ const label = history.transactionLabel ?? '';
48
+ history.transactionLabel = null;
49
+ if (collected.length === 0)
50
+ return true;
51
+ // A single collected command keeps its own identity rather than being wrapped: a composite of one is a
52
+ // layer of indirection that a history panel would have to see through, and its label would replace a
53
+ // more specific one with the bracket's generic name.
54
+ history.entries.length = start;
55
+ history.entries.push(collected.length === 1 ? collected[0] : createCompositeCommand(label, collected));
56
+ history.index = start + 1;
57
+ notifyCommandHistoryChanged(history);
58
+ return true;
59
+ }
60
+ /** Whether a bracket is currently open. */
61
+ export function isCommandTransactionOpen(history) {
62
+ return history.transactionDepth > 0;
63
+ }
64
+ //# sourceMappingURL=commandTransaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandTransaction.js","sourceRoot":"","sources":["../src/commandTransaction.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export * from './command';
2
+ export * from './commandBinding';
3
+ export * from './commandHistory';
4
+ export * from './commandHistorySignals';
5
+ export * from './commandTransaction';
6
+ export * from './explainCommandDispatch';
7
+ //# sourceMappingURL=contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC"}
@@ -0,0 +1,7 @@
1
+ export * from './command';
2
+ export * from './commandBinding';
3
+ export * from './commandHistory';
4
+ export * from './commandHistorySignals';
5
+ export * from './commandTransaction';
6
+ export * from './explainCommandDispatch';
7
+ //# sourceMappingURL=contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command, CommandDispatchExplanation, CommandHistory } from '@flighthq/types/contract';
2
+ export declare function explainCommandDispatch(history: Readonly<CommandHistory>, command: Readonly<Command>): CommandDispatchExplanation;
3
+ //# sourceMappingURL=explainCommandDispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explainCommandDispatch.d.ts","sourceRoot":"","sources":["../src/explainCommandDispatch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,0BAA0B,EAAE,cAAc,EAAoB,MAAM,0BAA0B,CAAC;AAQtH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,EACjC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,GACzB,0BAA0B,CAG5B"}