@pixerate/editor 0.22.0 → 0.24.0

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 (188) hide show
  1. package/README.md +175 -2
  2. package/THIRD_PARTY_NOTICES.md +139 -0
  3. package/dist/agent/index.cjs +87 -111
  4. package/dist/agent/index.cjs.map +1 -1
  5. package/dist/agent/index.d.cts +70 -211
  6. package/dist/agent/index.d.ts +70 -211
  7. package/dist/agent/index.js +78 -102
  8. package/dist/agent/index.js.map +1 -1
  9. package/dist/arrangeShortcuts-B8O3f8-P.d.cts +184 -0
  10. package/dist/arrangeShortcuts-sLlD2rSX.d.ts +184 -0
  11. package/dist/canvas/index.cjs +2075 -86
  12. package/dist/canvas/index.cjs.map +1 -1
  13. package/dist/canvas/index.d.cts +608 -186
  14. package/dist/canvas/index.d.ts +608 -186
  15. package/dist/canvas/index.js +2060 -71
  16. package/dist/canvas/index.js.map +1 -1
  17. package/dist/chunk-26BVFKHU.cjs +453 -0
  18. package/dist/chunk-26BVFKHU.cjs.map +1 -0
  19. package/dist/chunk-2H7ZHPEJ.js +762 -0
  20. package/dist/chunk-2H7ZHPEJ.js.map +1 -0
  21. package/dist/{chunk-DENSCKFC.js → chunk-3CN2WD3X.js} +1730 -189
  22. package/dist/chunk-3CN2WD3X.js.map +1 -0
  23. package/dist/{chunk-JJDLPEWL.js → chunk-3LV6RRPH.js} +2 -2
  24. package/dist/{chunk-MJZBNWG7.js → chunk-5S3Z4PPF.js} +78 -557
  25. package/dist/chunk-5S3Z4PPF.js.map +1 -0
  26. package/dist/chunk-664LQYFJ.js +115 -0
  27. package/dist/chunk-664LQYFJ.js.map +1 -0
  28. package/dist/chunk-7DWMJCAT.js +453 -0
  29. package/dist/chunk-7DWMJCAT.js.map +1 -0
  30. package/dist/chunk-ARRTP33I.js +101 -0
  31. package/dist/chunk-ARRTP33I.js.map +1 -0
  32. package/dist/chunk-CPOKFNBG.cjs +101 -0
  33. package/dist/chunk-CPOKFNBG.cjs.map +1 -0
  34. package/dist/{chunk-AA4ZEVCC.cjs → chunk-D27YFC46.cjs} +101 -580
  35. package/dist/chunk-D27YFC46.cjs.map +1 -0
  36. package/dist/chunk-D6FH2YAX.cjs +131 -0
  37. package/dist/chunk-D6FH2YAX.cjs.map +1 -0
  38. package/dist/{chunk-4SUNJZWB.cjs → chunk-FD4LPFAE.cjs} +48 -200
  39. package/dist/chunk-FD4LPFAE.cjs.map +1 -0
  40. package/dist/chunk-FODNLX5N.js +749 -0
  41. package/dist/chunk-FODNLX5N.js.map +1 -0
  42. package/dist/{chunk-OYXSKQFR.js → chunk-FPENXAEJ.js} +35 -187
  43. package/dist/chunk-FPENXAEJ.js.map +1 -0
  44. package/dist/chunk-G2I4QJOT.cjs +762 -0
  45. package/dist/chunk-G2I4QJOT.cjs.map +1 -0
  46. package/dist/chunk-HLIMTC6N.js +1 -0
  47. package/dist/chunk-HLIMTC6N.js.map +1 -0
  48. package/dist/{chunk-QGHGJ56O.js → chunk-ITBSKI26.js} +1483 -19
  49. package/dist/chunk-ITBSKI26.js.map +1 -0
  50. package/dist/{chunk-6M3BCTBD.cjs → chunk-MA2F5KHF.cjs} +470 -242
  51. package/dist/chunk-MA2F5KHF.cjs.map +1 -0
  52. package/dist/{chunk-SAZRENEZ.cjs → chunk-MCSJFWAO.cjs} +1733 -192
  53. package/dist/chunk-MCSJFWAO.cjs.map +1 -0
  54. package/dist/chunk-MKA3AHLV.cjs +256 -0
  55. package/dist/chunk-MKA3AHLV.cjs.map +1 -0
  56. package/dist/chunk-OLZJXL4R.cjs +749 -0
  57. package/dist/chunk-OLZJXL4R.cjs.map +1 -0
  58. package/dist/chunk-OXSV64JX.js +689 -0
  59. package/dist/chunk-OXSV64JX.js.map +1 -0
  60. package/dist/chunk-P3RQ5UJE.cjs +689 -0
  61. package/dist/chunk-P3RQ5UJE.cjs.map +1 -0
  62. package/dist/chunk-P6ODPZ4W.js +256 -0
  63. package/dist/chunk-P6ODPZ4W.js.map +1 -0
  64. package/dist/chunk-PGNZKFQS.js +685 -0
  65. package/dist/chunk-PGNZKFQS.js.map +1 -0
  66. package/dist/chunk-PL4JB3BF.cjs +1 -0
  67. package/dist/chunk-PL4JB3BF.cjs.map +1 -0
  68. package/dist/{chunk-GVSMRPHB.cjs → chunk-SBCZ6RN5.cjs} +1568 -104
  69. package/dist/chunk-SBCZ6RN5.cjs.map +1 -0
  70. package/dist/{chunk-CL37JGFW.cjs → chunk-SML64VJG.cjs} +4 -4
  71. package/dist/{chunk-CL37JGFW.cjs.map → chunk-SML64VJG.cjs.map} +1 -1
  72. package/dist/chunk-TNNJXF46.cjs +115 -0
  73. package/dist/chunk-TNNJXF46.cjs.map +1 -0
  74. package/dist/chunk-U5HZSFCS.js +131 -0
  75. package/dist/chunk-U5HZSFCS.js.map +1 -0
  76. package/dist/{chunk-RU52I7QO.js → chunk-U5KWZU4X.js} +388 -160
  77. package/dist/chunk-U5KWZU4X.js.map +1 -0
  78. package/dist/chunk-XNORY7M6.cjs +685 -0
  79. package/dist/chunk-XNORY7M6.cjs.map +1 -0
  80. package/dist/commands/index.cjs +860 -0
  81. package/dist/commands/index.cjs.map +1 -0
  82. package/dist/commands/index.d.cts +244 -0
  83. package/dist/commands/index.d.ts +244 -0
  84. package/dist/commands/index.js +860 -0
  85. package/dist/commands/index.js.map +1 -0
  86. package/dist/comment-store-BEMgVlAA.d.cts +135 -0
  87. package/dist/comment-store-BEMgVlAA.d.ts +135 -0
  88. package/dist/compare/index.cjs +15 -0
  89. package/dist/compare/index.cjs.map +1 -0
  90. package/dist/compare/index.d.cts +58 -0
  91. package/dist/compare/index.d.ts +58 -0
  92. package/dist/compare/index.js +15 -0
  93. package/dist/compare/index.js.map +1 -0
  94. package/dist/{controller-B7GIybc4.d.cts → controller-BhLLAoi8.d.cts} +119 -5
  95. package/dist/{controller-B7GIybc4.d.ts → controller-BhLLAoi8.d.ts} +119 -5
  96. package/dist/documents-BQjzJNe2.d.ts +76 -0
  97. package/dist/documents-KRTPhvst.d.cts +76 -0
  98. package/dist/extensions/index.cjs +53 -5
  99. package/dist/extensions/index.cjs.map +1 -1
  100. package/dist/extensions/index.d.cts +7 -3
  101. package/dist/extensions/index.d.ts +7 -3
  102. package/dist/extensions/index.js +52 -4
  103. package/dist/generation/index.cjs +1373 -0
  104. package/dist/generation/index.cjs.map +1 -0
  105. package/dist/generation/index.d.cts +554 -0
  106. package/dist/generation/index.d.ts +554 -0
  107. package/dist/generation/index.js +1373 -0
  108. package/dist/generation/index.js.map +1 -0
  109. package/dist/grammar/index.cjs +48 -3
  110. package/dist/grammar/index.cjs.map +1 -1
  111. package/dist/grammar/index.d.cts +322 -100
  112. package/dist/grammar/index.d.ts +322 -100
  113. package/dist/grammar/index.js +54 -9
  114. package/dist/history/index.cjs +12 -2
  115. package/dist/history/index.cjs.map +1 -1
  116. package/dist/history/index.d.cts +211 -7
  117. package/dist/history/index.d.ts +211 -7
  118. package/dist/history/index.js +13 -3
  119. package/dist/image-editor/index.cjs +2244 -38
  120. package/dist/image-editor/index.cjs.map +1 -1
  121. package/dist/image-editor/index.d.cts +742 -4
  122. package/dist/image-editor/index.d.ts +742 -4
  123. package/dist/image-editor/index.js +2222 -16
  124. package/dist/image-editor/index.js.map +1 -1
  125. package/dist/{index-CCr_z9kF.d.cts → index-BhJBSm2d.d.cts} +370 -4
  126. package/dist/{index-Ck6ajwXh.d.ts → index-fJrlkJCd.d.ts} +370 -4
  127. package/dist/index.cjs +193 -98
  128. package/dist/index.cjs.map +1 -1
  129. package/dist/index.d.cts +17 -48
  130. package/dist/index.d.ts +17 -48
  131. package/dist/index.js +198 -103
  132. package/dist/index.js.map +1 -1
  133. package/dist/migrate-iTlm3a8h.d.cts +112 -0
  134. package/dist/migrate-iTlm3a8h.d.ts +112 -0
  135. package/dist/persistence/index.cjs +676 -0
  136. package/dist/persistence/index.cjs.map +1 -0
  137. package/dist/persistence/index.d.cts +347 -0
  138. package/dist/persistence/index.d.ts +347 -0
  139. package/dist/persistence/index.js +676 -0
  140. package/dist/persistence/index.js.map +1 -0
  141. package/dist/registry-BDe-vlv3.d.ts +171 -0
  142. package/dist/registry-D32LpIc4.d.cts +354 -0
  143. package/dist/registry-DnzpgY27.d.cts +171 -0
  144. package/dist/registry-evKTP4ls.d.ts +354 -0
  145. package/dist/schema-DYDGdYL9.d.cts +41 -0
  146. package/dist/schema-DYDGdYL9.d.ts +41 -0
  147. package/dist/serializers/index.cjs +4 -3
  148. package/dist/serializers/index.cjs.map +1 -1
  149. package/dist/serializers/index.d.cts +2 -1
  150. package/dist/serializers/index.d.ts +2 -1
  151. package/dist/serializers/index.js +3 -2
  152. package/dist/sourcemap-C8AH3MBQ.d.cts +91 -0
  153. package/dist/sourcemap-DA1Evhrv.d.ts +91 -0
  154. package/dist/spreadsheet/index.cjs +53 -3
  155. package/dist/spreadsheet/index.cjs.map +1 -1
  156. package/dist/spreadsheet/index.d.cts +247 -18
  157. package/dist/spreadsheet/index.d.ts +247 -18
  158. package/dist/spreadsheet/index.js +58 -8
  159. package/dist/{tokens-CyLZmIei.d.cts → tokens-D7yXvUU6.d.cts} +15 -2
  160. package/dist/{tokens-CyLZmIei.d.ts → tokens-D7yXvUU6.d.ts} +15 -2
  161. package/dist/{track-changes-BSF58RK0.d.cts → track-changes-BK5sVf4_.d.cts} +18 -136
  162. package/dist/{track-changes-BSF58RK0.d.ts → track-changes-CDjCrwKe.d.ts} +18 -136
  163. package/dist/{types-CJ4U-HHI.d.ts → types-DX4Mh4SL.d.cts} +1 -1
  164. package/dist/{types-CJ4U-HHI.d.cts → types-DX4Mh4SL.d.ts} +1 -1
  165. package/dist/types-GT5a5YAX.d.cts +86 -0
  166. package/dist/types-GT5a5YAX.d.ts +86 -0
  167. package/package.json +23 -2
  168. package/dist/chunk-2TWGLC5K.cjs +0 -262
  169. package/dist/chunk-2TWGLC5K.cjs.map +0 -1
  170. package/dist/chunk-4SUNJZWB.cjs.map +0 -1
  171. package/dist/chunk-6M3BCTBD.cjs.map +0 -1
  172. package/dist/chunk-AA4ZEVCC.cjs.map +0 -1
  173. package/dist/chunk-AXV2ZW34.cjs +0 -118
  174. package/dist/chunk-AXV2ZW34.cjs.map +0 -1
  175. package/dist/chunk-B2ZRLN4S.js +0 -118
  176. package/dist/chunk-B2ZRLN4S.js.map +0 -1
  177. package/dist/chunk-DENSCKFC.js.map +0 -1
  178. package/dist/chunk-GVSMRPHB.cjs.map +0 -1
  179. package/dist/chunk-KAADNAPF.js +0 -262
  180. package/dist/chunk-KAADNAPF.js.map +0 -1
  181. package/dist/chunk-MJZBNWG7.js.map +0 -1
  182. package/dist/chunk-OYXSKQFR.js.map +0 -1
  183. package/dist/chunk-QGHGJ56O.js.map +0 -1
  184. package/dist/chunk-RU52I7QO.js.map +0 -1
  185. package/dist/chunk-SAZRENEZ.cjs.map +0 -1
  186. package/dist/types-BZgcDsC5.d.cts +0 -42
  187. package/dist/types-BZgcDsC5.d.ts +0 -42
  188. /package/dist/{chunk-JJDLPEWL.js.map → chunk-3LV6RRPH.js.map} +0 -0
@@ -1,19 +1,34 @@
1
- import { H as HistoryManagerOptions, a as HistoryState, C as Command, M as MergedExecutionOptions, S as SnapshotCommandOptions } from '../types-BZgcDsC5.cjs';
1
+ import { b as HistoryManagerOptions, H as HistoryState, C as Command, M as MergedExecutionOptions, c as HistoryMark, a as HistoryEntry, S as SnapshotCommandOptions } from '../types-GT5a5YAX.cjs';
2
2
 
3
3
  /**
4
4
  * UI-agnostic History and Undo/Redo manager supporting command closures,
5
- * snapshot diffs, transaction batching, and high-frequency event coalescing.
5
+ * snapshot diffs, transaction batching, high-frequency event coalescing,
6
+ * keyed gestures, undo marks, a memory budget and a History-panel listing.
6
7
  */
7
8
  declare class HistoryManager {
8
9
  private undoStack;
9
10
  private redoStack;
10
11
  private readonly maxDepth;
12
+ private readonly maxBytes;
13
+ private readonly sizeOf?;
11
14
  private isApplying;
12
15
  private batchDepth;
13
16
  private currentBatch;
14
17
  private listeners;
15
18
  private onStateChange?;
16
19
  private cachedState;
20
+ private cachedEntries;
21
+ private nextId;
22
+ private revision;
23
+ /** Bumped by `clear()`; marks from an earlier epoch are stale. */
24
+ private epoch;
25
+ /** Number of steps dropped from the bottom (depth / byte budget) so far. */
26
+ private dropped;
27
+ /** Key of the gesture that the top step belongs to (see `executeMerged`). */
28
+ private gestureKey;
29
+ private gestureEntryId;
30
+ /** Key every merged execute takes while a gesture is held (`beginGesture`). */
31
+ private heldKey;
17
32
  constructor(options?: HistoryManagerOptions);
18
33
  private computeState;
19
34
  /**
@@ -21,18 +36,51 @@ declare class HistoryManager {
21
36
  * Cached to maintain referential equality across renders for useSyncExternalStore.
22
37
  */
23
38
  getState(): HistoryState;
39
+ /**
40
+ * Monotonic counter bumped on every history change (execute, merge, undo,
41
+ * redo, revert, clear). Useful as a cache key, e.g. for `DirtyTracker`.
42
+ */
43
+ getRevision(): number;
24
44
  private notify;
45
+ private measure;
46
+ private makeEntry;
47
+ /** Pushes a step, clears redo and applies the depth and byte limits. */
48
+ private record;
49
+ /**
50
+ * Keeps the stacks within `maxBytes`: the oldest undo steps that do not fit
51
+ * are dropped, but the most recent undo step is always kept.
52
+ */
53
+ private trim;
54
+ /** Approximate bytes held by the undo and redo stacks (see `maxBytes`). */
55
+ getByteSize(): number;
56
+ private resetGesture;
25
57
  /**
26
58
  * Executes a command and pushes it onto the undo stack.
27
- * Clears the redo stack.
59
+ * Clears the redo stack and ends the current gesture.
28
60
  */
29
61
  execute(command: Command): void;
30
62
  /**
31
- * Executes a command, coalescing it with the previous command if they share
32
- * the same `tag` and occurred within `windowMs` (default: 300ms).
33
- * Useful for high-frequency interactions like slider scrubs or node drags.
63
+ * Executes a command as part of a continuous interaction (slider scrub, node drag).
64
+ *
65
+ * - With `options.key` (or while a gesture is held with `beginGesture`):
66
+ * consecutive merged executes with the same key fold into one undo step,
67
+ * however long the gesture lasts. Recording any other command, undo, redo,
68
+ * `revertTo`, `goTo`, `clear` or `endGesture()` ends the gesture.
69
+ * - Without a key: coalesces with the previous command if they share the same
70
+ * `tag` and occurred within `windowMs` (default: 300ms).
34
71
  */
35
72
  executeMerged(command: Command, options?: MergedExecutionOptions): void;
73
+ /**
74
+ * Holds a gesture: until `endGesture()`, every `executeMerged` call (whatever
75
+ * its own key or tag) joins one undo step, e.g. an automation pass and
76
+ * whatever is dragged during it. Commands recorded with `execute` still end
77
+ * the current step; the next merged execute then starts a new one.
78
+ */
79
+ beginGesture(key: string): void;
80
+ /** Ends the current (keyed or held) gesture; the next merged execute starts a new step. */
81
+ endGesture(): void;
82
+ /** The key of the gesture currently merging into the top step, if any. */
83
+ getGestureKey(): string | null;
36
84
  /**
37
85
  * Batches multiple commands executed within `fn` into a single atomic undo entry.
38
86
  */
@@ -42,6 +90,9 @@ declare class HistoryManager {
42
90
  * Commands executed by the undo closures themselves are not recorded.
43
91
  */
44
92
  private rollback;
93
+ /** Undoes the top step (caller holds `isApplying`). Throws leave it on the stack. */
94
+ private undoOne;
95
+ private redoOne;
45
96
  /**
46
97
  * Reverts the most recent command on the undo stack.
47
98
  * Returns true if a command was undone, false otherwise.
@@ -52,6 +103,30 @@ declare class HistoryManager {
52
103
  * Returns true if a command was redone, false otherwise.
53
104
  */
54
105
  redo(): boolean;
106
+ /**
107
+ * Captures the current point in the history (its top step), for `revertTo`.
108
+ */
109
+ mark(): HistoryMark;
110
+ /** Whether `mark` still points into the undo history. */
111
+ isMarkValid(mark: HistoryMark): boolean;
112
+ /**
113
+ * Takes back every step made since `mark` (merged or not), e.g. to cancel a
114
+ * drag with Escape: the state returns to how it was at `mark`, and neither
115
+ * undo nor redo keeps the reverted steps. Does nothing when `mark` has left
116
+ * the history (undone past, dropped by the limits, or cleared).
117
+ * Returns how many steps were taken back.
118
+ */
119
+ revertTo(mark: HistoryMark): number;
120
+ /**
121
+ * Lists the steps for a History panel: undo steps oldest first, then redo
122
+ * steps (the next redo first). Cached until the history changes.
123
+ */
124
+ getEntries(): HistoryEntry[];
125
+ /**
126
+ * Undoes or redoes until the step at `index` (from `getEntries`) is the
127
+ * current one; `-1` undoes everything. Returns how many steps were applied.
128
+ */
129
+ goTo(index: number): number;
55
130
  /**
56
131
  * Clears both undo and redo stacks.
57
132
  */
@@ -72,4 +147,133 @@ declare class HistoryManager {
72
147
  */
73
148
  declare function createHistoryManager(options?: HistoryManagerOptions): HistoryManager;
74
149
 
75
- export { Command, HistoryManager, HistoryManagerOptions, HistoryState, MergedExecutionOptions, SnapshotCommandOptions, createHistoryManager };
150
+ /**
151
+ * Compares two values for structural equality.
152
+ * Handles primitives, objects, arrays, and null/undefined.
153
+ */
154
+ declare function defaultIsEqual<T>(a: T, b: T): boolean;
155
+ interface DirtyTrackerOptions<T> {
156
+ /**
157
+ * Equality check. When `normalize` is set it receives the normalized values.
158
+ */
159
+ isEqual?: (a: T, b: T) => boolean;
160
+ /**
161
+ * Projects a value onto the part that counts as "the document" before
162
+ * comparing, e.g. `({ selection, viewport, ...doc }) => doc` so that
163
+ * selecting, scrolling or zooming never marks the document dirty.
164
+ */
165
+ normalize?: (value: T) => unknown;
166
+ }
167
+ /**
168
+ * Tracks a baseline (saved) value and determines whether the current value is
169
+ * dirty (modified).
170
+ *
171
+ * Stateless use: `isDirty(current)`. Stateful use: feed values with
172
+ * `update(current, revision?)`, read `dirty`, `subscribe` to changes, call
173
+ * `markClean()` after saving and wrap programmatic loads in `suppress(fn)`.
174
+ */
175
+ declare class DirtyTracker<T = unknown> {
176
+ private baseline;
177
+ private readonly isEqual;
178
+ private readonly normalize?;
179
+ private normalizedBaseline;
180
+ /** `isDirty` result as of a revision (and baseline version). */
181
+ private cache;
182
+ private baselineVersion;
183
+ private suppressDepth;
184
+ private hasValue;
185
+ private lastValue;
186
+ private dirtyState;
187
+ private listeners;
188
+ constructor(initialBaseline: T, options?: DirtyTrackerOptions<T> | ((a: T, b: T) => boolean));
189
+ /**
190
+ * Returns current baseline value.
191
+ */
192
+ getBaseline(): T;
193
+ private changeBaseline;
194
+ /**
195
+ * Sets a new baseline value without triggering any dirty state.
196
+ * If a value is being tracked (`update`), `dirty` is recomputed against it.
197
+ */
198
+ setBaseline(value: T): void;
199
+ private compare;
200
+ /**
201
+ * Checks whether the given value differs from the baseline.
202
+ * With a `revision` (e.g. `HistoryManager.getRevision()`), the result is
203
+ * cached and reused for the same revision until the baseline changes.
204
+ */
205
+ isDirty(current: T, revision?: number): boolean;
206
+ /**
207
+ * Resets the baseline to the provided current value (or clears dirty status).
208
+ */
209
+ reset(current: T): void;
210
+ /**
211
+ * Records the current value and returns whether it is dirty. While
212
+ * suppressed (`suppress`), the value becomes the new baseline instead, so
213
+ * programmatic loads and restores never mark the document dirty.
214
+ */
215
+ update(current: T, revision?: number): boolean;
216
+ /** Whether the last value passed to `update` differs from the baseline. */
217
+ get dirty(): boolean;
218
+ /** Whether `suppress` is currently running. */
219
+ get suppressed(): boolean;
220
+ /**
221
+ * Marks the document saved: `current` (default: the last value passed to
222
+ * `update`) becomes the baseline.
223
+ */
224
+ markClean(...args: [] | [current: T]): void;
225
+ /**
226
+ * Runs `fn` without marking anything dirty: every `update` during it
227
+ * rebaselines. Re-entrant (depth counter). If `fn` returns a promise, the
228
+ * suppression lasts until it settles.
229
+ */
230
+ suppress<R>(fn: () => R): R;
231
+ /**
232
+ * Subscribes to changes of `dirty`. The listener is called immediately with
233
+ * the current value. Returns an unsubscribe function.
234
+ */
235
+ subscribe(listener: (dirty: boolean) => void): () => void;
236
+ private setDirtyState;
237
+ }
238
+ /**
239
+ * Creates a DirtyTracker instance.
240
+ */
241
+ declare function createDirtyTracker<T>(initialBaseline: T, options?: DirtyTrackerOptions<T> | ((a: T, b: T) => boolean)): DirtyTracker<T>;
242
+ /**
243
+ * Runs `fn` with dirty tracking suppressed (see `DirtyTracker.suppress`).
244
+ */
245
+ declare function withoutDirty<R>(tracker: DirtyTracker<any>, fn: () => R): R;
246
+ /** Minimal history surface used by `bindDirtyToHistory` (`HistoryManager` satisfies it). */
247
+ interface DirtyHistorySource {
248
+ subscribe(listener: (...args: any[]) => void): () => void;
249
+ getRevision?(): number;
250
+ }
251
+ interface BindDirtyToHistoryOptions<T> extends DirtyTrackerOptions<T> {
252
+ history: DirtyHistorySource;
253
+ /** Reads the current document value. */
254
+ getValue: () => T;
255
+ /** Existing tracker to drive (default: a new one baselined on `getValue()`). */
256
+ tracker?: DirtyTracker<T>;
257
+ }
258
+ interface HistoryDirtyBinding<T> {
259
+ readonly tracker: DirtyTracker<T>;
260
+ /** Whether the document differs from the saved baseline. */
261
+ readonly dirty: boolean;
262
+ /** Marks the current value as saved. */
263
+ markClean(): void;
264
+ /** Runs `fn` (e.g. a load or restore) without marking the document dirty. */
265
+ suppress<R>(fn: () => R): R;
266
+ /** Re-reads the value after a change made outside the history. */
267
+ refresh(): boolean;
268
+ subscribe(listener: (dirty: boolean) => void): () => void;
269
+ /** Stops listening to the history. */
270
+ destroy(): void;
271
+ }
272
+ /**
273
+ * Keeps a `DirtyTracker` in step with a `HistoryManager`: every history change
274
+ * re-reads the value (cached per history revision), so undoing back to the
275
+ * saved state makes the document clean again.
276
+ */
277
+ declare function bindDirtyToHistory<T>(options: BindDirtyToHistoryOptions<T>): HistoryDirtyBinding<T>;
278
+
279
+ export { type BindDirtyToHistoryOptions, Command, type DirtyHistorySource, DirtyTracker, type DirtyTrackerOptions, type HistoryDirtyBinding, HistoryEntry, HistoryManager, HistoryManagerOptions, HistoryMark, HistoryState, MergedExecutionOptions, SnapshotCommandOptions, bindDirtyToHistory, createDirtyTracker, createHistoryManager, defaultIsEqual, withoutDirty };
@@ -1,19 +1,34 @@
1
- import { H as HistoryManagerOptions, a as HistoryState, C as Command, M as MergedExecutionOptions, S as SnapshotCommandOptions } from '../types-BZgcDsC5.js';
1
+ import { b as HistoryManagerOptions, H as HistoryState, C as Command, M as MergedExecutionOptions, c as HistoryMark, a as HistoryEntry, S as SnapshotCommandOptions } from '../types-GT5a5YAX.js';
2
2
 
3
3
  /**
4
4
  * UI-agnostic History and Undo/Redo manager supporting command closures,
5
- * snapshot diffs, transaction batching, and high-frequency event coalescing.
5
+ * snapshot diffs, transaction batching, high-frequency event coalescing,
6
+ * keyed gestures, undo marks, a memory budget and a History-panel listing.
6
7
  */
7
8
  declare class HistoryManager {
8
9
  private undoStack;
9
10
  private redoStack;
10
11
  private readonly maxDepth;
12
+ private readonly maxBytes;
13
+ private readonly sizeOf?;
11
14
  private isApplying;
12
15
  private batchDepth;
13
16
  private currentBatch;
14
17
  private listeners;
15
18
  private onStateChange?;
16
19
  private cachedState;
20
+ private cachedEntries;
21
+ private nextId;
22
+ private revision;
23
+ /** Bumped by `clear()`; marks from an earlier epoch are stale. */
24
+ private epoch;
25
+ /** Number of steps dropped from the bottom (depth / byte budget) so far. */
26
+ private dropped;
27
+ /** Key of the gesture that the top step belongs to (see `executeMerged`). */
28
+ private gestureKey;
29
+ private gestureEntryId;
30
+ /** Key every merged execute takes while a gesture is held (`beginGesture`). */
31
+ private heldKey;
17
32
  constructor(options?: HistoryManagerOptions);
18
33
  private computeState;
19
34
  /**
@@ -21,18 +36,51 @@ declare class HistoryManager {
21
36
  * Cached to maintain referential equality across renders for useSyncExternalStore.
22
37
  */
23
38
  getState(): HistoryState;
39
+ /**
40
+ * Monotonic counter bumped on every history change (execute, merge, undo,
41
+ * redo, revert, clear). Useful as a cache key, e.g. for `DirtyTracker`.
42
+ */
43
+ getRevision(): number;
24
44
  private notify;
45
+ private measure;
46
+ private makeEntry;
47
+ /** Pushes a step, clears redo and applies the depth and byte limits. */
48
+ private record;
49
+ /**
50
+ * Keeps the stacks within `maxBytes`: the oldest undo steps that do not fit
51
+ * are dropped, but the most recent undo step is always kept.
52
+ */
53
+ private trim;
54
+ /** Approximate bytes held by the undo and redo stacks (see `maxBytes`). */
55
+ getByteSize(): number;
56
+ private resetGesture;
25
57
  /**
26
58
  * Executes a command and pushes it onto the undo stack.
27
- * Clears the redo stack.
59
+ * Clears the redo stack and ends the current gesture.
28
60
  */
29
61
  execute(command: Command): void;
30
62
  /**
31
- * Executes a command, coalescing it with the previous command if they share
32
- * the same `tag` and occurred within `windowMs` (default: 300ms).
33
- * Useful for high-frequency interactions like slider scrubs or node drags.
63
+ * Executes a command as part of a continuous interaction (slider scrub, node drag).
64
+ *
65
+ * - With `options.key` (or while a gesture is held with `beginGesture`):
66
+ * consecutive merged executes with the same key fold into one undo step,
67
+ * however long the gesture lasts. Recording any other command, undo, redo,
68
+ * `revertTo`, `goTo`, `clear` or `endGesture()` ends the gesture.
69
+ * - Without a key: coalesces with the previous command if they share the same
70
+ * `tag` and occurred within `windowMs` (default: 300ms).
34
71
  */
35
72
  executeMerged(command: Command, options?: MergedExecutionOptions): void;
73
+ /**
74
+ * Holds a gesture: until `endGesture()`, every `executeMerged` call (whatever
75
+ * its own key or tag) joins one undo step, e.g. an automation pass and
76
+ * whatever is dragged during it. Commands recorded with `execute` still end
77
+ * the current step; the next merged execute then starts a new one.
78
+ */
79
+ beginGesture(key: string): void;
80
+ /** Ends the current (keyed or held) gesture; the next merged execute starts a new step. */
81
+ endGesture(): void;
82
+ /** The key of the gesture currently merging into the top step, if any. */
83
+ getGestureKey(): string | null;
36
84
  /**
37
85
  * Batches multiple commands executed within `fn` into a single atomic undo entry.
38
86
  */
@@ -42,6 +90,9 @@ declare class HistoryManager {
42
90
  * Commands executed by the undo closures themselves are not recorded.
43
91
  */
44
92
  private rollback;
93
+ /** Undoes the top step (caller holds `isApplying`). Throws leave it on the stack. */
94
+ private undoOne;
95
+ private redoOne;
45
96
  /**
46
97
  * Reverts the most recent command on the undo stack.
47
98
  * Returns true if a command was undone, false otherwise.
@@ -52,6 +103,30 @@ declare class HistoryManager {
52
103
  * Returns true if a command was redone, false otherwise.
53
104
  */
54
105
  redo(): boolean;
106
+ /**
107
+ * Captures the current point in the history (its top step), for `revertTo`.
108
+ */
109
+ mark(): HistoryMark;
110
+ /** Whether `mark` still points into the undo history. */
111
+ isMarkValid(mark: HistoryMark): boolean;
112
+ /**
113
+ * Takes back every step made since `mark` (merged or not), e.g. to cancel a
114
+ * drag with Escape: the state returns to how it was at `mark`, and neither
115
+ * undo nor redo keeps the reverted steps. Does nothing when `mark` has left
116
+ * the history (undone past, dropped by the limits, or cleared).
117
+ * Returns how many steps were taken back.
118
+ */
119
+ revertTo(mark: HistoryMark): number;
120
+ /**
121
+ * Lists the steps for a History panel: undo steps oldest first, then redo
122
+ * steps (the next redo first). Cached until the history changes.
123
+ */
124
+ getEntries(): HistoryEntry[];
125
+ /**
126
+ * Undoes or redoes until the step at `index` (from `getEntries`) is the
127
+ * current one; `-1` undoes everything. Returns how many steps were applied.
128
+ */
129
+ goTo(index: number): number;
55
130
  /**
56
131
  * Clears both undo and redo stacks.
57
132
  */
@@ -72,4 +147,133 @@ declare class HistoryManager {
72
147
  */
73
148
  declare function createHistoryManager(options?: HistoryManagerOptions): HistoryManager;
74
149
 
75
- export { Command, HistoryManager, HistoryManagerOptions, HistoryState, MergedExecutionOptions, SnapshotCommandOptions, createHistoryManager };
150
+ /**
151
+ * Compares two values for structural equality.
152
+ * Handles primitives, objects, arrays, and null/undefined.
153
+ */
154
+ declare function defaultIsEqual<T>(a: T, b: T): boolean;
155
+ interface DirtyTrackerOptions<T> {
156
+ /**
157
+ * Equality check. When `normalize` is set it receives the normalized values.
158
+ */
159
+ isEqual?: (a: T, b: T) => boolean;
160
+ /**
161
+ * Projects a value onto the part that counts as "the document" before
162
+ * comparing, e.g. `({ selection, viewport, ...doc }) => doc` so that
163
+ * selecting, scrolling or zooming never marks the document dirty.
164
+ */
165
+ normalize?: (value: T) => unknown;
166
+ }
167
+ /**
168
+ * Tracks a baseline (saved) value and determines whether the current value is
169
+ * dirty (modified).
170
+ *
171
+ * Stateless use: `isDirty(current)`. Stateful use: feed values with
172
+ * `update(current, revision?)`, read `dirty`, `subscribe` to changes, call
173
+ * `markClean()` after saving and wrap programmatic loads in `suppress(fn)`.
174
+ */
175
+ declare class DirtyTracker<T = unknown> {
176
+ private baseline;
177
+ private readonly isEqual;
178
+ private readonly normalize?;
179
+ private normalizedBaseline;
180
+ /** `isDirty` result as of a revision (and baseline version). */
181
+ private cache;
182
+ private baselineVersion;
183
+ private suppressDepth;
184
+ private hasValue;
185
+ private lastValue;
186
+ private dirtyState;
187
+ private listeners;
188
+ constructor(initialBaseline: T, options?: DirtyTrackerOptions<T> | ((a: T, b: T) => boolean));
189
+ /**
190
+ * Returns current baseline value.
191
+ */
192
+ getBaseline(): T;
193
+ private changeBaseline;
194
+ /**
195
+ * Sets a new baseline value without triggering any dirty state.
196
+ * If a value is being tracked (`update`), `dirty` is recomputed against it.
197
+ */
198
+ setBaseline(value: T): void;
199
+ private compare;
200
+ /**
201
+ * Checks whether the given value differs from the baseline.
202
+ * With a `revision` (e.g. `HistoryManager.getRevision()`), the result is
203
+ * cached and reused for the same revision until the baseline changes.
204
+ */
205
+ isDirty(current: T, revision?: number): boolean;
206
+ /**
207
+ * Resets the baseline to the provided current value (or clears dirty status).
208
+ */
209
+ reset(current: T): void;
210
+ /**
211
+ * Records the current value and returns whether it is dirty. While
212
+ * suppressed (`suppress`), the value becomes the new baseline instead, so
213
+ * programmatic loads and restores never mark the document dirty.
214
+ */
215
+ update(current: T, revision?: number): boolean;
216
+ /** Whether the last value passed to `update` differs from the baseline. */
217
+ get dirty(): boolean;
218
+ /** Whether `suppress` is currently running. */
219
+ get suppressed(): boolean;
220
+ /**
221
+ * Marks the document saved: `current` (default: the last value passed to
222
+ * `update`) becomes the baseline.
223
+ */
224
+ markClean(...args: [] | [current: T]): void;
225
+ /**
226
+ * Runs `fn` without marking anything dirty: every `update` during it
227
+ * rebaselines. Re-entrant (depth counter). If `fn` returns a promise, the
228
+ * suppression lasts until it settles.
229
+ */
230
+ suppress<R>(fn: () => R): R;
231
+ /**
232
+ * Subscribes to changes of `dirty`. The listener is called immediately with
233
+ * the current value. Returns an unsubscribe function.
234
+ */
235
+ subscribe(listener: (dirty: boolean) => void): () => void;
236
+ private setDirtyState;
237
+ }
238
+ /**
239
+ * Creates a DirtyTracker instance.
240
+ */
241
+ declare function createDirtyTracker<T>(initialBaseline: T, options?: DirtyTrackerOptions<T> | ((a: T, b: T) => boolean)): DirtyTracker<T>;
242
+ /**
243
+ * Runs `fn` with dirty tracking suppressed (see `DirtyTracker.suppress`).
244
+ */
245
+ declare function withoutDirty<R>(tracker: DirtyTracker<any>, fn: () => R): R;
246
+ /** Minimal history surface used by `bindDirtyToHistory` (`HistoryManager` satisfies it). */
247
+ interface DirtyHistorySource {
248
+ subscribe(listener: (...args: any[]) => void): () => void;
249
+ getRevision?(): number;
250
+ }
251
+ interface BindDirtyToHistoryOptions<T> extends DirtyTrackerOptions<T> {
252
+ history: DirtyHistorySource;
253
+ /** Reads the current document value. */
254
+ getValue: () => T;
255
+ /** Existing tracker to drive (default: a new one baselined on `getValue()`). */
256
+ tracker?: DirtyTracker<T>;
257
+ }
258
+ interface HistoryDirtyBinding<T> {
259
+ readonly tracker: DirtyTracker<T>;
260
+ /** Whether the document differs from the saved baseline. */
261
+ readonly dirty: boolean;
262
+ /** Marks the current value as saved. */
263
+ markClean(): void;
264
+ /** Runs `fn` (e.g. a load or restore) without marking the document dirty. */
265
+ suppress<R>(fn: () => R): R;
266
+ /** Re-reads the value after a change made outside the history. */
267
+ refresh(): boolean;
268
+ subscribe(listener: (dirty: boolean) => void): () => void;
269
+ /** Stops listening to the history. */
270
+ destroy(): void;
271
+ }
272
+ /**
273
+ * Keeps a `DirtyTracker` in step with a `HistoryManager`: every history change
274
+ * re-reads the value (cached per history revision), so undoing back to the
275
+ * saved state makes the document clean again.
276
+ */
277
+ declare function bindDirtyToHistory<T>(options: BindDirtyToHistoryOptions<T>): HistoryDirtyBinding<T>;
278
+
279
+ export { type BindDirtyToHistoryOptions, Command, type DirtyHistorySource, DirtyTracker, type DirtyTrackerOptions, type HistoryDirtyBinding, HistoryEntry, HistoryManager, HistoryManagerOptions, HistoryMark, HistoryState, MergedExecutionOptions, SnapshotCommandOptions, bindDirtyToHistory, createDirtyTracker, createHistoryManager, defaultIsEqual, withoutDirty };
@@ -1,9 +1,19 @@
1
1
  import {
2
+ DirtyTracker,
2
3
  HistoryManager,
3
- createHistoryManager
4
- } from "../chunk-KAADNAPF.js";
4
+ bindDirtyToHistory,
5
+ createDirtyTracker,
6
+ createHistoryManager,
7
+ defaultIsEqual,
8
+ withoutDirty
9
+ } from "../chunk-2H7ZHPEJ.js";
5
10
  export {
11
+ DirtyTracker,
6
12
  HistoryManager,
7
- createHistoryManager
13
+ bindDirtyToHistory,
14
+ createDirtyTracker,
15
+ createHistoryManager,
16
+ defaultIsEqual,
17
+ withoutDirty
8
18
  };
9
19
  //# sourceMappingURL=index.js.map