@thomasfosterau/effect-richtext 0.0.0 → 0.1.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 (176) hide show
  1. package/LICENSE +48 -0
  2. package/README.md +117 -1
  3. package/dist/_virtual/_rolldown/runtime.js +12 -0
  4. package/dist/commands/commands.d.ts +323 -0
  5. package/dist/commands/commands.js +722 -0
  6. package/dist/commands/internal.js +43 -0
  7. package/dist/commands/keymaps.d.ts +46 -0
  8. package/dist/commands/keymaps.js +64 -0
  9. package/dist/commands.d.ts +3 -0
  10. package/dist/commands.js +3 -0
  11. package/dist/compat/commands.d.ts +250 -0
  12. package/dist/compat/commands.js +275 -0
  13. package/dist/compat/internal/core.d.ts +20 -0
  14. package/dist/compat/internal/core.js +148 -0
  15. package/dist/compat/internal/props.js +82 -0
  16. package/dist/compat/keymap.d.ts +21 -0
  17. package/dist/compat/keymap.js +38 -0
  18. package/dist/compat/model.d.ts +893 -0
  19. package/dist/compat/model.js +1212 -0
  20. package/dist/compat/orderedmap.d.ts +74 -0
  21. package/dist/compat/orderedmap.js +124 -0
  22. package/dist/compat/schema-basic.d.ts +38 -0
  23. package/dist/compat/schema-basic.js +238 -0
  24. package/dist/compat/schema-list.d.ts +81 -0
  25. package/dist/compat/schema-list.js +156 -0
  26. package/dist/compat/state.d.ts +415 -0
  27. package/dist/compat/state.js +689 -0
  28. package/dist/compat/test-builder.d.ts +98 -0
  29. package/dist/compat/test-builder.js +197 -0
  30. package/dist/compat/transform.d.ts +458 -0
  31. package/dist/compat/transform.js +803 -0
  32. package/dist/compat/view.d.ts +411 -0
  33. package/dist/compat/view.js +409 -0
  34. package/dist/dropcursor.d.ts +46 -0
  35. package/dist/dropcursor.js +176 -0
  36. package/dist/extensions/defaults.d.ts +716 -0
  37. package/dist/extensions/defaults.js +209 -0
  38. package/dist/extensions/editor.d.ts +246 -0
  39. package/dist/extensions/editor.js +271 -0
  40. package/dist/extensions/extension.d.ts +375 -0
  41. package/dist/extensions/extension.js +233 -0
  42. package/dist/extensions.d.ts +4 -0
  43. package/dist/extensions.js +4 -0
  44. package/dist/gapcursor.d.ts +66 -0
  45. package/dist/gapcursor.js +273 -0
  46. package/dist/history.d.ts +178 -0
  47. package/dist/history.js +412 -0
  48. package/dist/html.d.ts +158 -0
  49. package/dist/html.js +164 -0
  50. package/dist/inputrules.d.ts +271 -0
  51. package/dist/inputrules.js +321 -0
  52. package/dist/internal/attempt.js +15 -0
  53. package/dist/internal/json.js +29 -0
  54. package/dist/keymap/keymap.d.ts +130 -0
  55. package/dist/keymap/keymap.js +159 -0
  56. package/dist/keymap.d.ts +2 -0
  57. package/dist/keymap.js +1 -0
  58. package/dist/markdown/errors.d.ts +23 -0
  59. package/dist/markdown/errors.js +26 -0
  60. package/dist/markdown/from_markdown.d.ts +185 -0
  61. package/dist/markdown/from_markdown.js +266 -0
  62. package/dist/markdown/schema.d.ts +522 -0
  63. package/dist/markdown/schema.js +292 -0
  64. package/dist/markdown/to_markdown.d.ts +251 -0
  65. package/dist/markdown/to_markdown.js +413 -0
  66. package/dist/markdown.d.ts +5 -0
  67. package/dist/markdown.js +5 -0
  68. package/dist/model/attrsCodec.js +48 -0
  69. package/dist/model/comparedeep.js +17 -0
  70. package/dist/model/content.d.ts +232 -0
  71. package/dist/model/content.js +630 -0
  72. package/dist/model/diff.js +66 -0
  73. package/dist/model/dom.d.ts +3 -0
  74. package/dist/model/errors.d.ts +90 -0
  75. package/dist/model/errors.js +76 -0
  76. package/dist/model/fragment.d.ts +131 -0
  77. package/dist/model/fragment.js +262 -0
  78. package/dist/model/from_dom.d.ts +299 -0
  79. package/dist/model/from_dom.js +618 -0
  80. package/dist/model/json.d.ts +37 -0
  81. package/dist/model/json.js +126 -0
  82. package/dist/model/mark.d.ts +73 -0
  83. package/dist/model/mark.js +121 -0
  84. package/dist/model/node.d.ts +267 -0
  85. package/dist/model/node.js +434 -0
  86. package/dist/model/replace.d.ts +78 -0
  87. package/dist/model/replace.js +207 -0
  88. package/dist/model/resolvedpos.d.ts +196 -0
  89. package/dist/model/resolvedpos.js +305 -0
  90. package/dist/model/schema.d.ts +740 -0
  91. package/dist/model/schema.js +451 -0
  92. package/dist/model/to_dom.d.ts +169 -0
  93. package/dist/model/to_dom.js +238 -0
  94. package/dist/model.d.ts +12 -0
  95. package/dist/model.js +12 -0
  96. package/dist/placeholder.d.ts +53 -0
  97. package/dist/placeholder.js +79 -0
  98. package/dist/reactive/observer.d.ts +54 -0
  99. package/dist/reactive/observer.js +61 -0
  100. package/dist/reactive/selectors.d.ts +22 -0
  101. package/dist/reactive/selectors.js +61 -0
  102. package/dist/reactive/stateref.d.ts +72 -0
  103. package/dist/reactive/stateref.js +71 -0
  104. package/dist/reactive/streams.d.ts +83 -0
  105. package/dist/reactive/streams.js +85 -0
  106. package/dist/reactive.d.ts +16 -0
  107. package/dist/reactive.js +26 -0
  108. package/dist/schema-basic.d.ts +448 -0
  109. package/dist/schema-basic.js +269 -0
  110. package/dist/schema-list/commands.d.ts +66 -0
  111. package/dist/schema-list/commands.js +203 -0
  112. package/dist/schema-list.d.ts +92 -0
  113. package/dist/schema-list.js +100 -0
  114. package/dist/state/errors.d.ts +39 -0
  115. package/dist/state/errors.js +32 -0
  116. package/dist/state/plugin.d.ts +232 -0
  117. package/dist/state/plugin.js +82 -0
  118. package/dist/state/selection.d.ts +297 -0
  119. package/dist/state/selection.js +486 -0
  120. package/dist/state/state.d.ts +212 -0
  121. package/dist/state/state.js +489 -0
  122. package/dist/state/transaction.d.ts +145 -0
  123. package/dist/state/transaction.js +195 -0
  124. package/dist/state.d.ts +6 -0
  125. package/dist/state.js +6 -0
  126. package/dist/test-builder.d.ts +3582 -0
  127. package/dist/test-builder.js +239 -0
  128. package/dist/transform/attr_step.d.ts +60 -0
  129. package/dist/transform/attr_step.js +105 -0
  130. package/dist/transform/errors.d.ts +50 -0
  131. package/dist/transform/errors.js +35 -0
  132. package/dist/transform/map.d.ts +182 -0
  133. package/dist/transform/map.js +280 -0
  134. package/dist/transform/mark.js +98 -0
  135. package/dist/transform/mark_set_step.js +69 -0
  136. package/dist/transform/mark_step.d.ts +113 -0
  137. package/dist/transform/mark_step.js +225 -0
  138. package/dist/transform/replace.d.ts +18 -0
  139. package/dist/transform/replace.js +381 -0
  140. package/dist/transform/replace_step.d.ts +109 -0
  141. package/dist/transform/replace_step.js +175 -0
  142. package/dist/transform/step.d.ts +157 -0
  143. package/dist/transform/step.js +168 -0
  144. package/dist/transform/structure.d.ts +89 -0
  145. package/dist/transform/structure.js +350 -0
  146. package/dist/transform/transform.d.ts +248 -0
  147. package/dist/transform/transform.js +373 -0
  148. package/dist/transform.d.ts +10 -0
  149. package/dist/transform.js +10 -0
  150. package/dist/view/browser.js +39 -0
  151. package/dist/view/capturekeys.js +282 -0
  152. package/dist/view/clipboard.d.ts +8 -0
  153. package/dist/view/clipboard.js +245 -0
  154. package/dist/view/decoration.d.ts +339 -0
  155. package/dist/view/decoration.js +566 -0
  156. package/dist/view/dom.d.ts +18 -0
  157. package/dist/view/dom.js +140 -0
  158. package/dist/view/domchange.js +295 -0
  159. package/dist/view/domcoords.d.ts +22 -0
  160. package/dist/view/domcoords.js +448 -0
  161. package/dist/view/domobserver.d.ts +47 -0
  162. package/dist/view/domobserver.js +328 -0
  163. package/dist/view/errors.d.ts +18 -0
  164. package/dist/view/errors.js +21 -0
  165. package/dist/view/input.d.ts +58 -0
  166. package/dist/view/input.js +704 -0
  167. package/dist/view/selection.js +198 -0
  168. package/dist/view/view.d.ts +699 -0
  169. package/dist/view/view.js +623 -0
  170. package/dist/view/viewdesc.d.ts +236 -0
  171. package/dist/view/viewdesc.js +1205 -0
  172. package/dist/view-css.d.ts +43 -0
  173. package/dist/view-css.js +124 -0
  174. package/dist/view.d.ts +6 -0
  175. package/dist/view.js +4 -0
  176. package/package.json +200 -4
@@ -0,0 +1,178 @@
1
+ import { AnySchema } from "./model/schema.js";
2
+ import "./model.js";
3
+ import { Mapping, StepMap } from "./transform/map.js";
4
+ import { Step } from "./transform/step.js";
5
+ import { Transform } from "./transform/transform.js";
6
+ import "./state.js";
7
+ import { Dispatch, Transaction } from "./state/transaction.js";
8
+ import { SelectionBookmark } from "./state/selection.js";
9
+ import { EditorState } from "./state/state.js";
10
+ import { EditorViewLike, Plugin } from "./state/plugin.js";
11
+ import "./transform.js";
12
+ import * as Effect from "effect/Effect";
13
+ import RopeSequence from "rope-sequence";
14
+ interface PopResult {
15
+ readonly remaining: Branch;
16
+ readonly transform: Transaction<any>;
17
+ readonly selection: SelectionBookmark<any>;
18
+ }
19
+ /** @internal */
20
+ export declare class Branch {
21
+ readonly items: RopeSequence<Item>;
22
+ readonly eventCount: number;
23
+ constructor(items: RopeSequence<Item>, eventCount: number);
24
+ popEvent(state: EditorState<any, any, any>, preserveItems: boolean): PopResult | null;
25
+ addTransform(transform: Transform<any>, selection: SelectionBookmark<any> | undefined, histOptions: HistoryConfig, preserveItems: boolean): Branch;
26
+ remapping(from: number, to: number): Mapping;
27
+ addMaps(array: ReadonlyArray<StepMap>): Branch;
28
+ rebased(rebasedTransform: Transform<any>, rebasedCount: number): Branch;
29
+ emptyItemCount(): number;
30
+ compress(upto?: number): Branch;
31
+ static empty: Branch;
32
+ }
33
+ /** @internal */
34
+ export declare class Item {
35
+ readonly map: StepMap;
36
+ readonly step?: Step<any> | undefined;
37
+ readonly selection?: SelectionBookmark<any> | undefined;
38
+ readonly mirrorOffset?: number | undefined;
39
+ constructor(map: StepMap, step?: Step<any> | undefined, selection?: SelectionBookmark<any> | undefined, mirrorOffset?: number | undefined);
40
+ merge(other: Item): Item | undefined;
41
+ }
42
+ /**
43
+ * The value of the state field that tracks undo/redo history for that
44
+ * state. Will be stored in the plugin state when the history plugin is
45
+ * active. Its contents are opaque.
46
+ *
47
+ * @since 0.1.0
48
+ * @category models
49
+ */
50
+ export declare class HistoryState {
51
+ /** @internal */
52
+ readonly done: Branch;
53
+ /** @internal */
54
+ readonly undone: Branch;
55
+ /** @internal */
56
+ readonly prevRanges: ReadonlyArray<number> | null;
57
+ /** @internal */
58
+ readonly prevTime: number;
59
+ /** @internal */
60
+ readonly prevComposition: number;
61
+ /** @internal */
62
+ constructor(
63
+ /** @internal */
64
+ done: Branch,
65
+ /** @internal */
66
+ undone: Branch,
67
+ /** @internal */
68
+ prevRanges: ReadonlyArray<number> | null,
69
+ /** @internal */
70
+ prevTime: number,
71
+ /** @internal */
72
+ prevComposition: number);
73
+ }
74
+ /**
75
+ * Set a flag on the given transaction that will prevent further steps
76
+ * from being appended to an existing history event (so that they
77
+ * require a separate undo command to undo).
78
+ *
79
+ * @since 0.1.0
80
+ * @category transactions
81
+ */
82
+ export declare const closeHistory: <Sc extends AnySchema>(tr: Transaction<Sc>) => Transaction<Sc>;
83
+ interface HistoryConfig {
84
+ readonly depth: number;
85
+ readonly newGroupDelay: number;
86
+ }
87
+ /**
88
+ * Options for the history plugin.
89
+ *
90
+ * @since 0.1.0
91
+ * @category models
92
+ */
93
+ export interface HistoryOptions {
94
+ /**
95
+ * The amount of history events that are collected before the oldest
96
+ * events are discarded. Defaults to 100.
97
+ */
98
+ readonly depth?: number | undefined;
99
+ /**
100
+ * The delay between changes after which a new group should be
101
+ * started. Defaults to 500 (milliseconds). Note that when changes
102
+ * aren't adjacent, a new group is always started.
103
+ */
104
+ readonly newGroupDelay?: number | undefined;
105
+ }
106
+ /**
107
+ * A command provided by this module. It works with any schema and
108
+ * needs no services.
109
+ *
110
+ * @since 0.1.0
111
+ * @category models
112
+ */
113
+ export type HistoryCommand = <Sc extends AnySchema>(state: EditorState<Sc, any, any>, dispatch?: Dispatch<Sc>, view?: EditorViewLike) => Effect.Effect<boolean>;
114
+ /**
115
+ * Returns a plugin that enables the undo history for an editor. The
116
+ * plugin will track undo and redo stacks, which can be used with the
117
+ * `undo` and `redo` commands.
118
+ *
119
+ * You can set an `"addToHistory"` metadata property of `false` on a
120
+ * transaction to prevent it from being rolled back by undo.
121
+ *
122
+ * @since 0.1.0
123
+ * @category constructors
124
+ */
125
+ export declare const history: (config?: HistoryOptions) => Plugin<HistoryState>;
126
+ /**
127
+ * A command that undoes the last change, if any.
128
+ *
129
+ * @since 0.1.0
130
+ * @category commands
131
+ */
132
+ export declare const undo: HistoryCommand;
133
+ /**
134
+ * A command that redoes the last undone change, if any.
135
+ *
136
+ * @since 0.1.0
137
+ * @category commands
138
+ */
139
+ export declare const redo: HistoryCommand;
140
+ /**
141
+ * A command that undoes the last change. Doesn't scroll the selection
142
+ * into view.
143
+ *
144
+ * @since 0.1.0
145
+ * @category commands
146
+ */
147
+ export declare const undoNoScroll: HistoryCommand;
148
+ /**
149
+ * A command that redoes the last undone change. Doesn't scroll the
150
+ * selection into view.
151
+ *
152
+ * @since 0.1.0
153
+ * @category commands
154
+ */
155
+ export declare const redoNoScroll: HistoryCommand;
156
+ /**
157
+ * The amount of undoable events available in a given state.
158
+ *
159
+ * @since 0.1.0
160
+ * @category getters
161
+ */
162
+ export declare const undoDepth: (state: EditorState<any, any, any>) => number;
163
+ /**
164
+ * The amount of redoable events available in a given editor state.
165
+ *
166
+ * @since 0.1.0
167
+ * @category getters
168
+ */
169
+ export declare const redoDepth: (state: EditorState<any, any, any>) => number;
170
+ /**
171
+ * Returns true if the given transaction was generated by the history
172
+ * plugin.
173
+ *
174
+ * @since 0.1.0
175
+ * @category guards
176
+ */
177
+ export declare const isHistoryTransaction: (tr: Transaction<any>) => boolean;
178
+ export {};
@@ -0,0 +1,412 @@
1
+ import { Plugin, PluginKey } from "./state/plugin.js";
2
+ import { Mapping } from "./transform/map.js";
3
+ import * as Arr from "effect/Array";
4
+ import * as Effect from "effect/Effect";
5
+ import * as Option from "effect/Option";
6
+ import RopeSequence from "rope-sequence";
7
+ // src/history.ts
8
+ /**
9
+ * An undo/redo history for the editor, ported from
10
+ * `prosemirror-history`.
11
+ *
12
+ * ```ts skip-type-checking
13
+ * const state = EditorState.createUnsafe({ schema, plugins: [history()] })
14
+ * // ...
15
+ * yield* undo(state, dispatch)
16
+ * ```
17
+ *
18
+ * @since 0.1.0
19
+ */
20
+ const max_empty_items = 500;
21
+ const DEPTH_OVERFLOW = 20;
22
+ /** @internal */
23
+ var Branch = class Branch {
24
+ constructor(items, eventCount) {
25
+ this.items = items;
26
+ this.eventCount = eventCount;
27
+ }
28
+ popEvent(state, preserveItems) {
29
+ if (this.eventCount === 0) return null;
30
+ let end = this.items.length;
31
+ for (;; end--) if (this.items.get(end - 1).selection) {
32
+ --end;
33
+ break;
34
+ }
35
+ let remap, mapFrom;
36
+ if (preserveItems) {
37
+ remap = this.remapping(end, this.items.length);
38
+ mapFrom = remap.maps.length;
39
+ }
40
+ const transform = state.tr;
41
+ let selection, remaining;
42
+ const addAfter = [], addBefore = [];
43
+ this.items.forEach((item, i) => {
44
+ if (!item.step) {
45
+ if (!remap) {
46
+ remap = this.remapping(end, i + 1);
47
+ mapFrom = remap.maps.length;
48
+ }
49
+ mapFrom--;
50
+ addBefore.push(item);
51
+ return;
52
+ }
53
+ if (remap) {
54
+ addBefore.push(new Item(item.map));
55
+ const step = Option.getOrNull(item.step.map(remap.slice(mapFrom)));
56
+ let map;
57
+ if (step && transform.maybeStep(step).docOrNull) {
58
+ map = transform.mapping.maps[transform.mapping.maps.length - 1];
59
+ addAfter.push(new Item(map, void 0, void 0, addAfter.length + addBefore.length));
60
+ }
61
+ mapFrom--;
62
+ if (map) remap.appendMap(map, mapFrom);
63
+ } else transform.maybeStep(item.step);
64
+ if (item.selection) {
65
+ selection = remap ? item.selection.map(remap.slice(mapFrom)) : item.selection;
66
+ remaining = new Branch(this.items.slice(0, end).append(addBefore.reverse().concat(addAfter)), this.eventCount - 1);
67
+ return false;
68
+ }
69
+ }, this.items.length, 0);
70
+ return {
71
+ remaining,
72
+ transform,
73
+ selection
74
+ };
75
+ }
76
+ addTransform(transform, selection, histOptions, preserveItems) {
77
+ const newItems = [];
78
+ let eventCount = this.eventCount;
79
+ let oldItems = this.items, lastItem = !preserveItems && oldItems.length ? oldItems.get(oldItems.length - 1) : null;
80
+ for (let i = 0; i < transform.steps.length; i++) {
81
+ const step = transform.steps[i].invert(transform.docs[i]);
82
+ let item = new Item(transform.mapping.maps[i], step, selection);
83
+ const merged = lastItem && lastItem.merge(item);
84
+ if (merged) {
85
+ item = merged;
86
+ if (i) newItems.pop();
87
+ else oldItems = oldItems.slice(0, oldItems.length - 1);
88
+ }
89
+ newItems.push(item);
90
+ if (selection) {
91
+ eventCount++;
92
+ selection = void 0;
93
+ }
94
+ if (!preserveItems) lastItem = item;
95
+ }
96
+ const overflow = eventCount - histOptions.depth;
97
+ if (overflow > DEPTH_OVERFLOW) {
98
+ oldItems = cutOffEvents(oldItems, overflow);
99
+ eventCount -= overflow;
100
+ }
101
+ return new Branch(oldItems.append(newItems), eventCount);
102
+ }
103
+ remapping(from, to) {
104
+ const maps = new Mapping();
105
+ this.items.forEach((item, i) => {
106
+ const mirrorPos = item.mirrorOffset != null && i - item.mirrorOffset >= from ? maps.maps.length - item.mirrorOffset : void 0;
107
+ maps.appendMap(item.map, mirrorPos);
108
+ }, from, to);
109
+ return maps;
110
+ }
111
+ addMaps(array) {
112
+ if (this.eventCount === 0) return this;
113
+ return new Branch(this.items.append(array.map((map) => new Item(map))), this.eventCount);
114
+ }
115
+ rebased(rebasedTransform, rebasedCount) {
116
+ if (!this.eventCount) return this;
117
+ const count = Math.min(this.items.length, rebasedCount);
118
+ const rebasedItems = [], start = this.items.length - count;
119
+ const mapping = rebasedTransform.mapping;
120
+ let newUntil = rebasedTransform.steps.length;
121
+ let eventCount = this.eventCount;
122
+ this.items.forEach((item) => {
123
+ if (item.selection) eventCount--;
124
+ }, start);
125
+ let iRebased = count;
126
+ this.items.forEach((item) => {
127
+ const pos = mapping.getMirrorOrUndefined(--iRebased);
128
+ if (pos == null) return;
129
+ newUntil = Math.min(newUntil, pos);
130
+ const map = mapping.maps[pos];
131
+ if (item.step) {
132
+ const step = rebasedTransform.steps[pos].invert(rebasedTransform.docs[pos]);
133
+ const selection = item.selection && item.selection.map(mapping.slice(iRebased + 1, pos));
134
+ if (selection) eventCount++;
135
+ rebasedItems.push(new Item(map, step, selection));
136
+ } else rebasedItems.push(new Item(map));
137
+ }, start);
138
+ const newMaps = [];
139
+ for (let i = count; i < newUntil; i++) newMaps.push(new Item(mapping.maps[i]));
140
+ const items = this.items.slice(0, start).append(newMaps).append(rebasedItems);
141
+ let branch = new Branch(items, eventCount);
142
+ if (branch.emptyItemCount() > max_empty_items) branch = branch.compress(this.items.length - rebasedItems.length);
143
+ return branch;
144
+ }
145
+ emptyItemCount() {
146
+ let count = 0;
147
+ this.items.forEach((item) => {
148
+ if (!item.step) count++;
149
+ });
150
+ return count;
151
+ }
152
+ compress(upto = this.items.length) {
153
+ const remap = this.remapping(0, upto);
154
+ let mapFrom = remap.maps.length;
155
+ const items = [];
156
+ let events = 0;
157
+ this.items.forEach((item, i) => {
158
+ if (i >= upto) {
159
+ items.push(item);
160
+ if (item.selection) events++;
161
+ } else if (item.step) {
162
+ const step = Option.getOrNull(item.step.map(remap.slice(mapFrom))), map = step && step.getMap();
163
+ mapFrom--;
164
+ if (map) remap.appendMap(map, mapFrom);
165
+ if (step) {
166
+ const selection = item.selection && item.selection.map(remap.slice(mapFrom));
167
+ if (selection) events++;
168
+ const newItem = new Item(map.invert(), step, selection), last = items.length - 1;
169
+ const merged = items.length ? items[last].merge(newItem) : void 0;
170
+ if (merged) items[last] = merged;
171
+ else items.push(newItem);
172
+ }
173
+ } else if (item.map) mapFrom--;
174
+ }, this.items.length, 0);
175
+ return new Branch(RopeSequence.from(items.reverse()), events);
176
+ }
177
+ static {
178
+ this.empty = new Branch(RopeSequence.empty, 0);
179
+ }
180
+ };
181
+ function cutOffEvents(items, n) {
182
+ let cutPoint;
183
+ items.forEach((item, i) => {
184
+ if (item.selection && n-- === 0) {
185
+ cutPoint = i;
186
+ return false;
187
+ }
188
+ });
189
+ return items.slice(cutPoint);
190
+ }
191
+ /** @internal */
192
+ var Item = class Item {
193
+ constructor(map, step, selection, mirrorOffset) {
194
+ this.map = map;
195
+ this.step = step;
196
+ this.selection = selection;
197
+ this.mirrorOffset = mirrorOffset;
198
+ }
199
+ merge(other) {
200
+ if (this.step && other.step && !other.selection) {
201
+ const step = Option.getOrNull(other.step.merge(this.step));
202
+ if (step) return new Item(step.getMap().invert(), step, this.selection);
203
+ }
204
+ }
205
+ };
206
+ /**
207
+ * The value of the state field that tracks undo/redo history for that
208
+ * state. Will be stored in the plugin state when the history plugin is
209
+ * active. Its contents are opaque.
210
+ *
211
+ * @since 0.1.0
212
+ * @category models
213
+ */
214
+ var HistoryState = class {
215
+ /** @internal */
216
+ constructor(done, undone, prevRanges, prevTime, prevComposition) {
217
+ this.done = done;
218
+ this.undone = undone;
219
+ this.prevRanges = prevRanges;
220
+ this.prevTime = prevTime;
221
+ this.prevComposition = prevComposition;
222
+ }
223
+ };
224
+ const meta = (tr, key) => Option.getOrUndefined(tr.getMeta(key));
225
+ function applyTransaction(history, state, tr, options) {
226
+ const historyTr = meta(tr, historyKey);
227
+ if (historyTr) return historyTr.historyState;
228
+ if (meta(tr, closeHistoryKey)) history = new HistoryState(history.done, history.undone, null, 0, -1);
229
+ const appended = meta(tr, "appendedTransaction");
230
+ let rebased;
231
+ if (Arr.isReadonlyArrayEmpty(tr.steps)) return history;
232
+ else if (appended && meta(appended, historyKey)) {
233
+ if (meta(appended, historyKey).redo) return new HistoryState(history.done.addTransform(tr, void 0, options, mustPreserveItems(state)), history.undone, rangesFor(tr.mapping.maps), history.prevTime, history.prevComposition);
234
+ else return new HistoryState(history.done, history.undone.addTransform(tr, void 0, options, mustPreserveItems(state)), null, history.prevTime, history.prevComposition);
235
+ } else if (meta(tr, "addToHistory") !== false && !(appended && meta(appended, "addToHistory") === false)) {
236
+ const composition = meta(tr, "composition");
237
+ const newGroup = history.prevTime === 0 || !appended && history.prevComposition !== composition && (history.prevTime < (tr.time || 0) - options.newGroupDelay || !isAdjacentTo(tr, history.prevRanges));
238
+ const prevRanges = appended ? mapRanges(history.prevRanges, tr.mapping) : rangesFor(tr.mapping.maps);
239
+ return new HistoryState(history.done.addTransform(tr, newGroup ? state.selection.getBookmark() : void 0, options, mustPreserveItems(state)), Branch.empty, prevRanges, tr.time, composition == null ? history.prevComposition : composition);
240
+ } else if (rebased = meta(tr, "rebased")) return new HistoryState(history.done.rebased(tr, rebased), history.undone.rebased(tr, rebased), mapRanges(history.prevRanges, tr.mapping), history.prevTime, history.prevComposition);
241
+ else return new HistoryState(history.done.addMaps(tr.mapping.maps), history.undone.addMaps(tr.mapping.maps), mapRanges(history.prevRanges, tr.mapping), history.prevTime, history.prevComposition);
242
+ }
243
+ function isAdjacentTo(transform, prevRanges) {
244
+ if (!prevRanges) return false;
245
+ if (!transform.docChanged) return true;
246
+ let adjacent = false;
247
+ transform.mapping.maps[0].forEach((start, end) => {
248
+ for (let i = 0; i < prevRanges.length; i += 2) if (start <= prevRanges[i + 1] && end >= prevRanges[i]) adjacent = true;
249
+ });
250
+ return adjacent;
251
+ }
252
+ function rangesFor(maps) {
253
+ const result = [];
254
+ for (let i = maps.length - 1; i >= 0; i--) {
255
+ maps[i].forEach((_from, _to, from, to) => result.push(from, to));
256
+ if (Arr.isArrayNonEmpty(result)) break;
257
+ }
258
+ return result;
259
+ }
260
+ function mapRanges(ranges, mapping) {
261
+ if (!ranges) return null;
262
+ const result = [];
263
+ for (let i = 0; i < ranges.length; i += 2) {
264
+ const from = mapping.map(ranges[i], 1), to = mapping.map(ranges[i + 1], -1);
265
+ if (from <= to) result.push(from, to);
266
+ }
267
+ return result;
268
+ }
269
+ function histTransaction(history, state, redo) {
270
+ const preserveItems = mustPreserveItems(state);
271
+ const plugin = Option.getOrUndefined(historyKey.get(state));
272
+ if (!plugin) return null;
273
+ const histOptions = plugin.spec.config;
274
+ const pop = (redo ? history.undone : history.done).popEvent(state, preserveItems);
275
+ if (!pop) return null;
276
+ const selection = pop.selection.resolve(pop.transform.doc);
277
+ const added = (redo ? history.done : history.undone).addTransform(pop.transform, state.selection.getBookmark(), histOptions, preserveItems);
278
+ const newHist = new HistoryState(redo ? added : pop.remaining, redo ? pop.remaining : added, null, 0, -1);
279
+ return pop.transform.setSelectionUnsafe(selection).setMeta(historyKey, {
280
+ redo,
281
+ historyState: newHist
282
+ });
283
+ }
284
+ let cachedPreserveItems = false;
285
+ let cachedPreserveItemsPlugins = null;
286
+ function mustPreserveItems(state) {
287
+ const plugins = state.plugins;
288
+ if (cachedPreserveItemsPlugins !== plugins) {
289
+ cachedPreserveItems = false;
290
+ cachedPreserveItemsPlugins = plugins;
291
+ for (let i = 0; i < plugins.length; i++) if (plugins[i].spec.historyPreserveItems) {
292
+ cachedPreserveItems = true;
293
+ break;
294
+ }
295
+ }
296
+ return cachedPreserveItems;
297
+ }
298
+ /**
299
+ * Set a flag on the given transaction that will prevent further steps
300
+ * from being appended to an existing history event (so that they
301
+ * require a separate undo command to undo).
302
+ *
303
+ * @since 0.1.0
304
+ * @category transactions
305
+ */
306
+ const closeHistory = (tr) => tr.setMeta(closeHistoryKey, true);
307
+ const historyKey = new PluginKey("history");
308
+ const closeHistoryKey = new PluginKey("closeHistory");
309
+ /**
310
+ * Returns a plugin that enables the undo history for an editor. The
311
+ * plugin will track undo and redo stacks, which can be used with the
312
+ * `undo` and `redo` commands.
313
+ *
314
+ * You can set an `"addToHistory"` metadata property of `false` on a
315
+ * transaction to prevent it from being rolled back by undo.
316
+ *
317
+ * @since 0.1.0
318
+ * @category constructors
319
+ */
320
+ const history = (config = {}) => {
321
+ const options = {
322
+ depth: config.depth || 100,
323
+ newGroupDelay: config.newGroupDelay || 500
324
+ };
325
+ return new Plugin({
326
+ key: historyKey,
327
+ state: {
328
+ init() {
329
+ return new HistoryState(Branch.empty, Branch.empty, null, 0, -1);
330
+ },
331
+ apply(tr, hist, state) {
332
+ return applyTransaction(hist, state, tr, options);
333
+ }
334
+ },
335
+ config: options,
336
+ props: { handleDOMEvents: { beforeinput(view, e) {
337
+ const inputType = e.inputType;
338
+ const command = inputType === "historyUndo" ? undo : inputType === "historyRedo" ? redo : null;
339
+ if (!command || !view.editable) return false;
340
+ e.preventDefault();
341
+ return command(view.state, view.dispatch);
342
+ } } }
343
+ });
344
+ };
345
+ const buildCommand = (redo, scroll) => (state, dispatch) => Effect.suspend(() => {
346
+ const hist = Option.getOrUndefined(historyKey.getState(state));
347
+ if (!hist || (redo ? hist.undone : hist.done).eventCount === 0) return Effect.succeed(false);
348
+ if (dispatch) {
349
+ const tr = histTransaction(hist, state, redo);
350
+ if (tr) return Effect.as(dispatch(scroll ? tr.scrollIntoView() : tr), true);
351
+ }
352
+ return Effect.succeed(true);
353
+ });
354
+ /**
355
+ * A command that undoes the last change, if any.
356
+ *
357
+ * @since 0.1.0
358
+ * @category commands
359
+ */
360
+ const undo = buildCommand(false, true);
361
+ /**
362
+ * A command that redoes the last undone change, if any.
363
+ *
364
+ * @since 0.1.0
365
+ * @category commands
366
+ */
367
+ const redo = buildCommand(true, true);
368
+ /**
369
+ * A command that undoes the last change. Doesn't scroll the selection
370
+ * into view.
371
+ *
372
+ * @since 0.1.0
373
+ * @category commands
374
+ */
375
+ const undoNoScroll = buildCommand(false, false);
376
+ /**
377
+ * A command that redoes the last undone change. Doesn't scroll the
378
+ * selection into view.
379
+ *
380
+ * @since 0.1.0
381
+ * @category commands
382
+ */
383
+ const redoNoScroll = buildCommand(true, false);
384
+ /**
385
+ * The amount of undoable events available in a given state.
386
+ *
387
+ * @since 0.1.0
388
+ * @category getters
389
+ */
390
+ const undoDepth = (state) => {
391
+ const hist = Option.getOrUndefined(historyKey.getState(state));
392
+ return hist ? hist.done.eventCount : 0;
393
+ };
394
+ /**
395
+ * The amount of redoable events available in a given editor state.
396
+ *
397
+ * @since 0.1.0
398
+ * @category getters
399
+ */
400
+ const redoDepth = (state) => {
401
+ const hist = Option.getOrUndefined(historyKey.getState(state));
402
+ return hist ? hist.undone.eventCount : 0;
403
+ };
404
+ /**
405
+ * Returns true if the given transaction was generated by the history
406
+ * plugin.
407
+ *
408
+ * @since 0.1.0
409
+ * @category guards
410
+ */
411
+ const isHistoryTransaction = (tr) => Option.isSome(tr.getMeta(historyKey));
412
+ export { Branch, HistoryState, Item, closeHistory, history, isHistoryTransaction, redo, redoDepth, redoNoScroll, undo, undoDepth, undoNoScroll };