@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,704 @@
1
+ import { Slice } from "../model/replace.js";
2
+ import { NodeSelection, Selection, TextSelection } from "../state/selection.js";
3
+ import { dropPoint } from "../transform/structure.js";
4
+ import { android, chrome, chrome_version, gecko, ie, ie_version, ios, mac, safari, webkit_version, windows } from "./browser.js";
5
+ import { captureKeyDown } from "./capturekeys.js";
6
+ import { parseFromClipboard, serializeForClipboard } from "./clipboard.js";
7
+ import { keyEvent, textNodeAfter, textNodeBefore } from "./dom.js";
8
+ import { selectionBetween, selectionFromDOM, selectionToDOM } from "./selection.js";
9
+ import * as Arr from "effect/Array";
10
+ import * as Option from "effect/Option";
11
+ import * as Predicate from "effect/Predicate";
12
+ import * as Result from "effect/Result";
13
+ // src/view/input.ts
14
+ /**
15
+ * DOM event handling.
16
+ *
17
+ * @internal
18
+ */
19
+ const handlers = {};
20
+ const editHandlers = {};
21
+ const isPassiveEvent = (event) => event === "touchstart" || event === "touchmove";
22
+ /** @internal */
23
+ var InputState = class {
24
+ constructor() {
25
+ this.shiftKey = false;
26
+ this.mouseDown = null;
27
+ this.lastKeyCode = null;
28
+ this.lastKeyCodeTime = 0;
29
+ this.lastKeyDispatched = false;
30
+ this.lastClick = {
31
+ time: 0,
32
+ x: 0,
33
+ y: 0,
34
+ type: "",
35
+ button: 0
36
+ };
37
+ this.lastSelectionOrigin = null;
38
+ this.lastSelectionTime = 0;
39
+ this.lastIOSEnter = 0;
40
+ this.lastIOSEnterFallbackTimeout = -1;
41
+ this.lastFocus = 0;
42
+ this.lastTouch = 0;
43
+ this.lastChromeDelete = 0;
44
+ this.composing = false;
45
+ this.compositionNode = null;
46
+ this.composingTimeout = -1;
47
+ this.compositionNodes = [];
48
+ this.compositionEndedAt = -2e8;
49
+ this.compositionID = 1;
50
+ this.badSafariComposition = false;
51
+ this.compositionPendingChanges = 0;
52
+ this.domChangeCount = 0;
53
+ this.eventHandlers = Object.create(null);
54
+ this.hideSelectionGuard = null;
55
+ }
56
+ };
57
+ /** @internal */
58
+ function initInput(view) {
59
+ for (const event in handlers) {
60
+ const handler = handlers[event];
61
+ view.dom.addEventListener(event, view.input.eventHandlers[event] = (event) => {
62
+ if (eventBelongsToView(view, event) && !runCustomHandler(view, event) && (view.editable || !(event.type in editHandlers))) handler(view, event);
63
+ }, isPassiveEvent(event) ? { passive: true } : void 0);
64
+ }
65
+ if (safari) view.dom.addEventListener("input", () => null);
66
+ ensureListeners(view);
67
+ }
68
+ function setSelectionOrigin(view, origin) {
69
+ view.input.lastSelectionOrigin = origin;
70
+ view.input.lastSelectionTime = Date.now();
71
+ }
72
+ /** @internal */
73
+ function destroyInput(view) {
74
+ if (view.input.mouseDown) view.input.mouseDown.done();
75
+ view.domObserver.stop();
76
+ for (const type in view.input.eventHandlers) view.dom.removeEventListener(type, view.input.eventHandlers[type]);
77
+ clearTimeout(view.input.composingTimeout);
78
+ clearTimeout(view.input.lastIOSEnterFallbackTimeout);
79
+ }
80
+ /** @internal */
81
+ function ensureListeners(view) {
82
+ view.someProp("handleDOMEvents", (currentHandlers) => {
83
+ for (const type in currentHandlers) if (!view.input.eventHandlers[type]) view.dom.addEventListener(type, view.input.eventHandlers[type] = (event) => runCustomHandler(view, event));
84
+ });
85
+ }
86
+ function runCustomHandler(view, event) {
87
+ return view.someProp("handleDOMEvents", (handlers) => {
88
+ const handler = handlers[event.type];
89
+ return handler ? view.runHandler(handler(view, event)) || event.defaultPrevented : false;
90
+ });
91
+ }
92
+ function eventBelongsToView(view, event) {
93
+ if (!event.bubbles) return true;
94
+ if (event.defaultPrevented) return false;
95
+ for (let node = event.target; node != view.dom; node = node.parentNode) if (!node || node.nodeType == 11 || node.pmViewDesc && node.pmViewDesc.stopEvent(event)) return false;
96
+ return true;
97
+ }
98
+ /** @internal */
99
+ function dispatchEvent(view, event) {
100
+ if (!runCustomHandler(view, event) && handlers[event.type] && (view.editable || !(event.type in editHandlers))) handlers[event.type](view, event);
101
+ }
102
+ /**
103
+ * Run `handleKeyDown` for `event` (or a synthesized Backspace / Enter key
104
+ * event), at most once per physical key press and never during
105
+ * composition (prosemirror-view 1.42.9).
106
+ *
107
+ * @internal
108
+ */
109
+ function dispatchKey(view, event) {
110
+ if (view.input.lastKeyDispatched || view.composing) return false;
111
+ view.input.lastKeyDispatched = true;
112
+ const key = Predicate.isString(event) ? keyEvent(event == "Backspace" ? 8 : 13, event) : event;
113
+ return view.someHandler("handleKeyDown", (f) => f(view, key));
114
+ }
115
+ editHandlers.keydown = (view, _event) => {
116
+ const event = _event;
117
+ view.input.shiftKey = event.keyCode == 16 || event.shiftKey;
118
+ if (inOrNearComposition(view, event)) return;
119
+ view.input.lastKeyCode = event.keyCode;
120
+ view.input.lastKeyCodeTime = Date.now();
121
+ view.input.lastKeyDispatched = false;
122
+ if (android && chrome && event.keyCode == 13) return;
123
+ if (event.keyCode != 229) view.domObserver.forceFlush();
124
+ if (ios && event.keyCode == 13 && !event.ctrlKey && !event.altKey && !event.metaKey) {
125
+ const now = Date.now();
126
+ view.input.lastIOSEnter = now;
127
+ view.input.lastIOSEnterFallbackTimeout = setTimeout(() => {
128
+ if (view.input.lastIOSEnter == now) {
129
+ dispatchKey(view, "Enter");
130
+ view.input.lastIOSEnter = 0;
131
+ }
132
+ }, 200);
133
+ } else if (dispatchKey(view, event) || captureKeyDown(view, event)) event.preventDefault();
134
+ else setSelectionOrigin(view, "key");
135
+ };
136
+ editHandlers.keyup = (view, event) => {
137
+ if (event.keyCode == 16) view.input.shiftKey = false;
138
+ };
139
+ editHandlers.keypress = (view, _event) => {
140
+ const event = _event;
141
+ if (inOrNearComposition(view, event) || !event.charCode || event.ctrlKey && !event.altKey || mac && event.metaKey) return;
142
+ if (view.someHandler("handleKeyPress", (f) => f(view, event))) {
143
+ event.preventDefault();
144
+ return;
145
+ }
146
+ const sel = view.state.selection;
147
+ if (!(sel instanceof TextSelection) || !sel.$from.sameParent(sel.$to)) {
148
+ const text = String.fromCharCode(event.charCode);
149
+ const deflt = () => view.state.tr.insertTextUnsafe(text).scrollIntoView();
150
+ if (!/[\r\n]/.test(text) && !view.someHandler("handleTextInput", (f) => f(view, sel.$from.pos, sel.$to.pos, text, deflt))) view.dispatchInternal(deflt());
151
+ event.preventDefault();
152
+ }
153
+ };
154
+ function eventCoords(event) {
155
+ return {
156
+ left: event.clientX,
157
+ top: event.clientY
158
+ };
159
+ }
160
+ function isNear(event, click) {
161
+ const dx = click.x - event.clientX, dy = click.y - event.clientY;
162
+ return dx * dx + dy * dy < 100;
163
+ }
164
+ function runHandlerOnContext(view, propName, pos, inside, event) {
165
+ if (inside == -1) return false;
166
+ const $pos = view.state.doc.resolveUnsafe(inside);
167
+ for (let i = $pos.depth + 1; i > 0; i--) if (view.someHandler(propName, (f) => i > $pos.depth ? f(view, pos, $pos.nodeAfterOrNull, $pos.beforeUnsafe(i), event, true) : f(view, pos, $pos.node(i), $pos.beforeUnsafe(i), event, false))) return true;
168
+ return false;
169
+ }
170
+ function updateSelection(view, selection, origin) {
171
+ if (!view.focused) view.focus();
172
+ if (view.state.selection.eq(selection)) return;
173
+ const tr = view.state.tr.setSelectionUnsafe(selection);
174
+ if (origin == "pointer") tr.setMeta("pointer", true);
175
+ view.dispatchInternal(tr);
176
+ }
177
+ function selectClickedLeaf(view, inside) {
178
+ if (inside == -1) return false;
179
+ const $pos = view.state.doc.resolveUnsafe(inside), node = $pos.nodeAfterOrNull;
180
+ if (node && node.isAtom && NodeSelection.isSelectable(node)) {
181
+ updateSelection(view, new NodeSelection($pos), "pointer");
182
+ return true;
183
+ }
184
+ return false;
185
+ }
186
+ function selectClickedNode(view, inside) {
187
+ if (inside == -1) return false;
188
+ const sel = view.state.selection;
189
+ let selectedNode, selectAt;
190
+ if (sel instanceof NodeSelection) selectedNode = sel.node;
191
+ const $pos = view.state.doc.resolveUnsafe(inside);
192
+ for (let i = $pos.depth + 1; i > 0; i--) {
193
+ const node = i > $pos.depth ? $pos.nodeAfterOrNull : $pos.node(i);
194
+ if (NodeSelection.isSelectable(node)) {
195
+ if (selectedNode && sel.$from.depth > 0 && i >= sel.$from.depth && $pos.beforeUnsafe(sel.$from.depth + 1) == sel.$from.pos) selectAt = $pos.beforeUnsafe(sel.$from.depth);
196
+ else selectAt = $pos.beforeUnsafe(i);
197
+ break;
198
+ }
199
+ }
200
+ if (selectAt != null) {
201
+ updateSelection(view, NodeSelection.createUnsafe(view.state.doc, selectAt), "pointer");
202
+ return true;
203
+ } else return false;
204
+ }
205
+ function handleSingleClick(view, pos, inside, event, selectNode) {
206
+ return runHandlerOnContext(view, "handleClickOn", pos, inside, event) || view.someHandler("handleClick", (f) => f(view, pos, event)) || (selectNode ? selectClickedNode(view, inside) : selectClickedLeaf(view, inside));
207
+ }
208
+ function handleDoubleClick(view, pos, inside, event) {
209
+ return runHandlerOnContext(view, "handleDoubleClickOn", pos, inside, event) || view.someHandler("handleDoubleClick", (f) => f(view, pos, event));
210
+ }
211
+ function handleTripleClick(view, pos, inside, event) {
212
+ return runHandlerOnContext(view, "handleTripleClickOn", pos, inside, event) || view.someHandler("handleTripleClick", (f) => f(view, pos, event)) || defaultTripleClick(view, inside, event);
213
+ }
214
+ function defaultTripleClick(view, inside, event) {
215
+ if (event.button != 0) return false;
216
+ const found = selectionForTripleClick(view, inside, true), doc = view.state.doc;
217
+ if (Option.isNone(found)) return false;
218
+ const selection = found.value;
219
+ updateSelection(view, selection, "pointer");
220
+ if (selection instanceof TextSelection && doc.eq(view.state.doc)) view.input.mouseDown = new TripleClickDrag(view, selection);
221
+ return true;
222
+ }
223
+ function selectionForTripleClick(view, inside, selectNodes) {
224
+ const doc = view.state.doc;
225
+ if (inside == -1) return doc.inlineContent ? Option.some(TextSelection.createUnsafe(doc, 0, doc.content.size)) : Option.none();
226
+ const $pos = doc.resolveUnsafe(inside);
227
+ for (let i = $pos.depth + 1; i > 0; i--) {
228
+ const node = i > $pos.depth ? $pos.nodeAfterOrNull : $pos.node(i);
229
+ const nodePos = $pos.beforeUnsafe(i);
230
+ if (node.inlineContent) return Option.some(TextSelection.createUnsafe(doc, nodePos + 1, nodePos + 1 + node.content.size));
231
+ else if (selectNodes && NodeSelection.isSelectable(node)) return Option.some(NodeSelection.createUnsafe(doc, nodePos));
232
+ }
233
+ return Option.none();
234
+ }
235
+ function forceDOMFlush(view) {
236
+ return endComposition(view);
237
+ }
238
+ const selectNodeModifier = mac ? "metaKey" : "ctrlKey";
239
+ handlers.mousedown = (view, _event) => {
240
+ const event = _event;
241
+ view.input.shiftKey = event.shiftKey;
242
+ const flushed = forceDOMFlush(view);
243
+ const now = Date.now();
244
+ let type = "singleClick";
245
+ if (now - view.input.lastClick.time < 500 && isNear(event, view.input.lastClick) && !event[selectNodeModifier] && view.input.lastClick.button == event.button) {
246
+ if (view.input.lastClick.type == "singleClick") type = "doubleClick";
247
+ else if (view.input.lastClick.type == "doubleClick") type = "tripleClick";
248
+ }
249
+ view.input.lastClick = {
250
+ time: now,
251
+ x: event.clientX,
252
+ y: event.clientY,
253
+ type,
254
+ button: event.button
255
+ };
256
+ if (view.input.mouseDown) view.input.mouseDown.done();
257
+ const pos = Option.getOrNull(view.posAtCoords(eventCoords(event)));
258
+ if (!pos) return;
259
+ if (type == "singleClick") view.input.mouseDown = new LeftMouseDown(view, pos, event, flushed);
260
+ else if ((type == "doubleClick" ? handleDoubleClick : handleTripleClick)(view, pos.pos, pos.inside, event)) event.preventDefault();
261
+ else setSelectionOrigin(view, "pointer");
262
+ };
263
+ var MouseDown = class {
264
+ constructor(view) {
265
+ this.view = view;
266
+ this.mightDrag = null;
267
+ view.root.addEventListener("mouseup", this.up = this.up.bind(this));
268
+ view.root.addEventListener("mousemove", this.move = this.move.bind(this));
269
+ }
270
+ up(_event) {
271
+ this.done();
272
+ }
273
+ move(event) {
274
+ if (event.buttons == 0) this.done();
275
+ }
276
+ done() {
277
+ this.view.root.removeEventListener("mouseup", this.up);
278
+ this.view.root.removeEventListener("mousemove", this.move);
279
+ if (this.view.input.mouseDown == this) this.view.input.mouseDown = null;
280
+ }
281
+ delaySelUpdate() {
282
+ return false;
283
+ }
284
+ };
285
+ var LeftMouseDown = class extends MouseDown {
286
+ constructor(view, pos, event, flushed) {
287
+ super(view);
288
+ this.pos = pos;
289
+ this.event = event;
290
+ this.flushed = flushed;
291
+ this.delayedSelectionSync = false;
292
+ this.startDoc = view.state.doc;
293
+ this.selectNode = event[selectNodeModifier];
294
+ this.allowDefault = event.shiftKey;
295
+ let targetNode, targetPos;
296
+ if (pos.inside > -1) {
297
+ targetNode = view.state.doc.nodeAtOrNull(pos.inside);
298
+ targetPos = pos.inside;
299
+ } else {
300
+ const $pos = view.state.doc.resolveUnsafe(pos.pos);
301
+ targetNode = $pos.parent;
302
+ targetPos = $pos.depth ? $pos.beforeUnsafe() : 0;
303
+ }
304
+ const target = flushed ? null : event.target;
305
+ const targetDesc = target ? view.docView.nearestDesc(target, true) : null;
306
+ this.target = targetDesc && targetDesc.nodeDOM.nodeType == 1 ? targetDesc.nodeDOM : null;
307
+ const { selection } = view.state;
308
+ if (event.button == 0 && (targetNode.type.spec.draggable && targetNode.type.spec.selectable !== false || selection instanceof NodeSelection && selection.from <= targetPos && selection.to > targetPos)) this.mightDrag = {
309
+ node: targetNode,
310
+ pos: targetPos,
311
+ addAttr: !!(this.target && !this.target.draggable),
312
+ setUneditable: !!(this.target && gecko && !this.target.hasAttribute("contentEditable"))
313
+ };
314
+ if (this.target && this.mightDrag && (this.mightDrag.addAttr || this.mightDrag.setUneditable)) {
315
+ this.view.domObserver.stop();
316
+ if (this.mightDrag.addAttr) this.target.draggable = true;
317
+ if (this.mightDrag.setUneditable) setTimeout(() => {
318
+ if (this.view.input.mouseDown == this) this.target.setAttribute("contentEditable", "false");
319
+ }, 20);
320
+ this.view.domObserver.start();
321
+ }
322
+ setSelectionOrigin(view, "pointer");
323
+ }
324
+ done() {
325
+ super.done();
326
+ if (this.mightDrag && this.target) {
327
+ this.view.domObserver.stop();
328
+ if (this.mightDrag.addAttr) this.target.removeAttribute("draggable");
329
+ if (this.mightDrag.setUneditable) this.target.removeAttribute("contentEditable");
330
+ this.view.domObserver.start();
331
+ }
332
+ if (this.delayedSelectionSync) setTimeout(() => {
333
+ if (!this.view.isDestroyed) selectionToDOM(this.view);
334
+ });
335
+ }
336
+ up(event) {
337
+ this.done();
338
+ if (!this.view.dom.contains(event.target)) return;
339
+ let pos = this.pos;
340
+ if (this.view.state.doc != this.startDoc) pos = Option.getOrNull(this.view.posAtCoords(eventCoords(event)));
341
+ this.updateAllowDefault(event);
342
+ if (this.allowDefault || !pos) setSelectionOrigin(this.view, "pointer");
343
+ else if (handleSingleClick(this.view, pos.pos, pos.inside, event, this.selectNode)) event.preventDefault();
344
+ else if (event.button == 0 && (this.flushed || safari && this.mightDrag && !this.mightDrag.node.isAtom || chrome && !this.view.state.selection.visible && Math.min(Math.abs(pos.pos - this.view.state.selection.from), Math.abs(pos.pos - this.view.state.selection.to)) <= 2)) {
345
+ updateSelection(this.view, Selection.near(this.view.state.doc.resolveUnsafe(pos.pos)), "pointer");
346
+ event.preventDefault();
347
+ } else setSelectionOrigin(this.view, "pointer");
348
+ }
349
+ move(event) {
350
+ this.updateAllowDefault(event);
351
+ setSelectionOrigin(this.view, "pointer");
352
+ super.move(event);
353
+ }
354
+ updateAllowDefault(event) {
355
+ if (!this.allowDefault && (Math.abs(this.event.x - event.clientX) > 4 || Math.abs(this.event.y - event.clientY) > 4)) this.allowDefault = true;
356
+ }
357
+ delaySelUpdate() {
358
+ if (!this.allowDefault) return false;
359
+ this.delayedSelectionSync = true;
360
+ return true;
361
+ }
362
+ };
363
+ var TripleClickDrag = class extends MouseDown {
364
+ constructor(view, startSelection) {
365
+ super(view);
366
+ this.startSelection = startSelection;
367
+ this.startDoc = view.state.doc;
368
+ }
369
+ move(event) {
370
+ if (event.buttons == 0 || this.view.isDestroyed || !this.view.state.doc.eq(this.startDoc)) {
371
+ this.done();
372
+ return;
373
+ }
374
+ event.preventDefault();
375
+ setSelectionOrigin(this.view, "pointer");
376
+ const found = Option.flatMap(this.view.posAtCoords(eventCoords(event)), (pos) => selectionForTripleClick(this.view, pos.inside, false));
377
+ if (Option.isNone(found)) return;
378
+ const target = found.value;
379
+ const { doc } = this.view.state, start = this.startSelection;
380
+ const [anchor, head] = target.from < start.from ? [start.to, target.from] : [start.from, target.to];
381
+ updateSelection(this.view, TextSelection.createUnsafe(doc, anchor, head), "pointer");
382
+ }
383
+ };
384
+ handlers.touchstart = (view) => {
385
+ view.input.lastTouch = Date.now();
386
+ forceDOMFlush(view);
387
+ setSelectionOrigin(view, "pointer");
388
+ };
389
+ handlers.touchmove = (view) => {
390
+ view.input.lastTouch = Date.now();
391
+ setSelectionOrigin(view, "pointer");
392
+ };
393
+ handlers.contextmenu = (view) => forceDOMFlush(view);
394
+ function inOrNearComposition(view, _event) {
395
+ if (view.composing) return true;
396
+ if (safari && Math.abs(Date.now() - view.input.compositionEndedAt) < 500) {
397
+ view.input.compositionEndedAt = -2e8;
398
+ return true;
399
+ }
400
+ return false;
401
+ }
402
+ const timeoutComposition = android ? 5e3 : -1;
403
+ function needsMarkCursor(view) {
404
+ const { state } = view, $pos = state.selection.$to;
405
+ if (!(state.selection instanceof TextSelection) || !state.selection.empty) return false;
406
+ return !!(state.storedMarksOrNull || !$pos.textOffset && $pos.parentOffset && $pos.nodeBeforeOrNull.marks.some((m) => m.type.spec.inclusive === false) || chrome && windows && selectionBeforeUneditable(view));
407
+ }
408
+ editHandlers.compositionstart = editHandlers.compositionupdate = (view) => {
409
+ if (!view.composing) {
410
+ view.domObserver.flush();
411
+ const { state } = view, $pos = state.selection.$to;
412
+ if (needsMarkCursor(view)) {
413
+ view.markCursor = view.state.storedMarksOrNull || $pos.marks();
414
+ endComposition(view, true);
415
+ view.markCursor = null;
416
+ } else {
417
+ endComposition(view, !state.selection.empty);
418
+ if (gecko && state.selection.empty && $pos.parentOffset && !$pos.textOffset && $pos.nodeBeforeOrNull.marks.length) {
419
+ const sel = view.domSelectionRange();
420
+ for (let node = sel.focusNode, offset = sel.focusOffset; node && node.nodeType == 1 && offset != 0;) {
421
+ const before = offset < 0 ? node.lastChild : node.childNodes[offset - 1];
422
+ if (!before) break;
423
+ if (before.nodeType == 3) {
424
+ const sel = view.domSelection();
425
+ if (sel) sel.collapse(before, before.nodeValue.length);
426
+ break;
427
+ } else {
428
+ node = before;
429
+ offset = -1;
430
+ }
431
+ }
432
+ }
433
+ }
434
+ view.input.composing = true;
435
+ }
436
+ scheduleComposeEnd(view, timeoutComposition);
437
+ };
438
+ function selectionBeforeUneditable(view) {
439
+ const { focusNode, focusOffset } = view.domSelectionRange();
440
+ if (!focusNode || focusNode.nodeType != 1 || focusOffset >= focusNode.childNodes.length) return false;
441
+ const next = focusNode.childNodes[focusOffset];
442
+ return next.nodeType == 1 && next.contentEditable == "false";
443
+ }
444
+ editHandlers.compositionend = (view, _event) => {
445
+ if (view.composing) {
446
+ view.input.composing = false;
447
+ view.input.compositionEndedAt = Date.now();
448
+ view.input.compositionPendingChanges = view.domObserver.pendingRecords().length ? view.input.compositionID : 0;
449
+ view.input.compositionNode = null;
450
+ if (view.input.badSafariComposition) view.domObserver.forceFlush();
451
+ else if (view.input.compositionPendingChanges) Promise.resolve().then(() => view.domObserver.flush());
452
+ view.input.compositionID++;
453
+ scheduleComposeEnd(view, 20);
454
+ }
455
+ };
456
+ function scheduleComposeEnd(view, delay) {
457
+ clearTimeout(view.input.composingTimeout);
458
+ if (delay > -1) view.input.composingTimeout = setTimeout(() => endComposition(view), delay);
459
+ }
460
+ /** @internal */
461
+ function clearComposition(view) {
462
+ if (view.composing) {
463
+ view.input.composing = false;
464
+ view.input.compositionEndedAt = Date.now();
465
+ }
466
+ while (Arr.isArrayNonEmpty(view.input.compositionNodes)) view.input.compositionNodes.pop().markParentsDirty();
467
+ }
468
+ /** @internal */
469
+ function findCompositionNode(view) {
470
+ const sel = view.domSelectionRange();
471
+ if (!sel.focusNode) return null;
472
+ const textBefore = textNodeBefore(sel.focusNode, sel.focusOffset);
473
+ const textAfter = textNodeAfter(sel.focusNode, sel.focusOffset);
474
+ if (textBefore && textAfter && textBefore != textAfter) {
475
+ const descAfter = textAfter.pmViewDesc, lastChanged = view.domObserver.lastChangedTextNode;
476
+ if (textBefore == lastChanged || textAfter == lastChanged) return lastChanged;
477
+ if (!descAfter || !descAfter.isText(textAfter.nodeValue)) return textAfter;
478
+ else if (view.input.compositionNode == textAfter) {
479
+ const descBefore = textBefore.pmViewDesc;
480
+ if (!(!descBefore || !descBefore.isText(textBefore.nodeValue))) return textAfter;
481
+ }
482
+ }
483
+ return textBefore || textAfter;
484
+ }
485
+ /** @internal */
486
+ function endComposition(view, restarting = false) {
487
+ if (android && view.domObserver.flushingSoon >= 0) return false;
488
+ view.domObserver.forceFlush();
489
+ clearComposition(view);
490
+ if (restarting || view.docView && view.docView.dirty) {
491
+ const sel = selectionFromDOM(view), cur = view.state.selection;
492
+ if (sel && !sel.eq(cur)) view.dispatchInternal(view.state.tr.setSelectionUnsafe(sel));
493
+ else if ((view.markCursor || restarting) && !cur.$from.node(cur.$from.sharedDepth(cur.to)).inlineContent) view.dispatchInternal(view.state.tr.deleteSelection());
494
+ else view.updateState(view.state);
495
+ return true;
496
+ }
497
+ return false;
498
+ }
499
+ function captureCopy(view, dom) {
500
+ if (!view.dom.parentNode) return;
501
+ const wrap = view.dom.parentNode.appendChild(document.createElement("div"));
502
+ wrap.appendChild(dom);
503
+ wrap.style.cssText = "position: fixed; left: -10000px; top: 10px";
504
+ const sel = getSelection(), range = document.createRange();
505
+ range.selectNodeContents(dom);
506
+ view.dom.blur();
507
+ sel.removeAllRanges();
508
+ sel.addRange(range);
509
+ setTimeout(() => {
510
+ if (wrap.parentNode) wrap.parentNode.removeChild(wrap);
511
+ view.focus();
512
+ }, 50);
513
+ }
514
+ const brokenClipboardAPI = ie && ie_version < 15 || ios && webkit_version < 604;
515
+ handlers.copy = editHandlers.cut = (view, _event) => {
516
+ const event = _event;
517
+ const sel = view.state.selection, cut = event.type == "cut";
518
+ if (sel.empty) return;
519
+ const data = brokenClipboardAPI ? null : event.clipboardData;
520
+ const slice = sel.content(), { dom, text } = serializeForClipboard(view, slice);
521
+ if (data) {
522
+ event.preventDefault();
523
+ data.clearData();
524
+ data.setData("text/html", dom.innerHTML);
525
+ data.setData("text/plain", text);
526
+ } else captureCopy(view, dom);
527
+ if (cut) view.dispatchInternal(view.state.tr.deleteSelection().scrollIntoView().setMeta("uiEvent", "cut"));
528
+ };
529
+ function sliceSingleNode(slice) {
530
+ return slice.openStart == 0 && slice.openEnd == 0 && slice.content.childCount == 1 ? slice.content.content[0] : null;
531
+ }
532
+ function capturePaste(view, event) {
533
+ if (!view.dom.parentNode) return;
534
+ const plainText = view.input.shiftKey || view.state.selection.$from.parent.type.spec.code;
535
+ const target = view.dom.parentNode.appendChild(document.createElement(plainText ? "textarea" : "div"));
536
+ if (!plainText) target.contentEditable = "true";
537
+ target.style.cssText = "position: fixed; left: -10000px; top: 10px";
538
+ target.focus();
539
+ const plain = view.input.shiftKey && view.input.lastKeyCode != 45;
540
+ setTimeout(() => {
541
+ view.focus();
542
+ if (target.parentNode) target.parentNode.removeChild(target);
543
+ if (plainText) doPaste(view, target.value, null, plain, event);
544
+ else doPaste(view, target.textContent, target.innerHTML, plain, event);
545
+ }, 50);
546
+ }
547
+ /** @internal */
548
+ function doPaste(view, text, html, preferPlain, event) {
549
+ const slice = parseFromClipboard(view, text, html, preferPlain, view.state.selection.$from);
550
+ if (view.someHandler("handlePaste", (f) => f(view, event, slice || Slice.empty))) return true;
551
+ if (!slice) return false;
552
+ const singleNode = sliceSingleNode(slice);
553
+ const tr = singleNode ? view.state.tr.replaceSelectionWith(singleNode, preferPlain) : view.state.tr.replaceSelection(slice);
554
+ view.dispatchInternal(tr.scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste"));
555
+ return true;
556
+ }
557
+ function getText(clipboardData) {
558
+ const text = clipboardData.getData("text/plain") || clipboardData.getData("Text");
559
+ if (text) return text;
560
+ const uris = clipboardData.getData("text/uri-list");
561
+ return uris ? uris.replace(/\r?\n/g, " ") : "";
562
+ }
563
+ editHandlers.paste = (view, _event) => {
564
+ const event = _event;
565
+ if (view.composing && !android) return;
566
+ const data = brokenClipboardAPI ? null : event.clipboardData;
567
+ const plain = view.input.shiftKey && view.input.lastKeyCode != 45;
568
+ if (data && doPaste(view, getText(data), data.getData("text/html"), plain, event)) event.preventDefault();
569
+ else capturePaste(view, event);
570
+ };
571
+ /** @internal */
572
+ var Dragging = class {
573
+ constructor(slice, move, node) {
574
+ this.slice = slice;
575
+ this.move = move;
576
+ this.node = node;
577
+ }
578
+ };
579
+ const dragCopyModifier = mac ? "altKey" : "ctrlKey";
580
+ function dragMoves(view, event) {
581
+ let asked = false, copy = false;
582
+ view.someProp("dragCopies", (test) => {
583
+ asked = true;
584
+ copy = copy || test(event);
585
+ });
586
+ return asked ? !copy : !event[dragCopyModifier];
587
+ }
588
+ handlers.dragstart = (view, _event) => {
589
+ const event = _event;
590
+ const mouseDown = view.input.mouseDown;
591
+ if (mouseDown) mouseDown.done();
592
+ if (!event.dataTransfer) return;
593
+ const sel = view.state.selection;
594
+ const pos = sel.empty ? null : Option.getOrNull(view.posAtCoords(eventCoords(event)));
595
+ let node;
596
+ if (pos && pos.pos >= sel.from && pos.pos <= (sel instanceof NodeSelection ? sel.to - 1 : sel.to)) {} else if (mouseDown && mouseDown.mightDrag) node = NodeSelection.createUnsafe(view.state.doc, mouseDown.mightDrag.pos);
597
+ else if (event.target && event.target.nodeType == 1) {
598
+ const desc = view.docView.nearestDesc(event.target, true);
599
+ if (desc && desc.node.type.spec.draggable && desc != view.docView) node = NodeSelection.createUnsafe(view.state.doc, desc.posBefore);
600
+ }
601
+ const draggedSlice = (node || view.state.selection).content();
602
+ const { dom, slice, text } = serializeForClipboard(view, draggedSlice);
603
+ if (!event.dataTransfer.files.length || !chrome || chrome_version > 120) event.dataTransfer.clearData();
604
+ event.dataTransfer.setData(brokenClipboardAPI ? "Text" : "text/html", dom.innerHTML);
605
+ event.dataTransfer.effectAllowed = "copyMove";
606
+ if (!brokenClipboardAPI) event.dataTransfer.setData("text/plain", text);
607
+ view.dragging = new Dragging(slice, dragMoves(view, event), node);
608
+ };
609
+ handlers.dragend = (view) => {
610
+ const dragging = view.dragging;
611
+ window.setTimeout(() => {
612
+ if (view.dragging == dragging) view.dragging = null;
613
+ }, 50);
614
+ };
615
+ editHandlers.dragover = editHandlers.dragenter = (_, e) => e.preventDefault();
616
+ editHandlers.drop = (view, event) => {
617
+ const result = Result.try(() => handleDrop(view, event, view.dragging));
618
+ view.dragging = null;
619
+ if (Result.isFailure(result)) throw result.failure;
620
+ };
621
+ function handleDrop(view, event, dragging) {
622
+ if (!event.dataTransfer) return;
623
+ const eventPos = Option.getOrNull(view.posAtCoords(eventCoords(event)));
624
+ if (!eventPos) return;
625
+ const $mouse = view.state.doc.resolveUnsafe(eventPos.pos);
626
+ let slice = dragging && dragging.slice;
627
+ if (slice) view.someProp("transformPasted", (f) => {
628
+ slice = f(slice, view, false);
629
+ });
630
+ else slice = parseFromClipboard(view, getText(event.dataTransfer), brokenClipboardAPI ? null : event.dataTransfer.getData("text/html"), false, $mouse);
631
+ const move = !!(dragging && dragMoves(view, event));
632
+ if (view.someHandler("handleDrop", (f) => f(view, event, slice || Slice.empty, move))) {
633
+ event.preventDefault();
634
+ return;
635
+ }
636
+ if (!slice) return;
637
+ event.preventDefault();
638
+ let insertPos = slice ? Option.getOrNull(dropPoint(view.state.doc, $mouse.pos, slice)) : $mouse.pos;
639
+ if (insertPos == null) insertPos = $mouse.pos;
640
+ const tr = view.state.tr;
641
+ if (move) {
642
+ const { node } = dragging;
643
+ if (node) node.replace(tr);
644
+ else tr.deleteSelection();
645
+ }
646
+ const pos = tr.mapping.map(insertPos);
647
+ const isNode = slice.openStart == 0 && slice.openEnd == 0 && slice.content.childCount == 1;
648
+ const beforeInsert = tr.doc;
649
+ if (isNode) tr.replaceRangeWithUnsafe(pos, pos, slice.content.content[0]);
650
+ else tr.replaceRangeUnsafe(pos, pos, slice);
651
+ if (tr.doc.eq(beforeInsert)) return;
652
+ const $pos = tr.doc.resolveUnsafe(pos);
653
+ if (isNode && NodeSelection.isSelectable(slice.content.content[0]) && $pos.nodeAfterOrNull && $pos.nodeAfterOrNull.sameMarkup(slice.content.content[0])) tr.setSelectionUnsafe(new NodeSelection($pos));
654
+ else {
655
+ let end = tr.mapping.map(insertPos);
656
+ tr.mapping.maps[tr.mapping.maps.length - 1].forEach((_from, _to, _newFrom, newTo) => end = newTo);
657
+ tr.setSelectionUnsafe(selectionBetween(view, $pos, tr.doc.resolveUnsafe(end)));
658
+ }
659
+ view.focus();
660
+ view.dispatchInternal(tr.setMeta("uiEvent", "drop"));
661
+ }
662
+ handlers.focus = (view) => {
663
+ view.input.lastFocus = Date.now();
664
+ if (!view.focused) {
665
+ view.domObserver.stop();
666
+ view.dom.classList.add("ProseMirror-focused");
667
+ view.domObserver.start();
668
+ view.focused = true;
669
+ const startSel = view.domSelectionRange();
670
+ if (!view.domObserver.currentSelection.eq(startSel)) {
671
+ const { focusNode, focusOffset } = startSel;
672
+ setTimeout(() => {
673
+ const newSel = view.domSelectionRange();
674
+ if (newSel.focusNode == focusNode && newSel.focusOffset == focusOffset && view.docView && view.hasFocus()) selectionToDOM(view);
675
+ }, 20);
676
+ }
677
+ }
678
+ };
679
+ handlers.blur = (view, _event) => {
680
+ const event = _event;
681
+ if (view.focused) {
682
+ view.domObserver.stop();
683
+ view.dom.classList.remove("ProseMirror-focused");
684
+ view.domObserver.start();
685
+ if (event.relatedTarget && view.dom.contains(event.relatedTarget)) view.domObserver.currentSelection.clear();
686
+ view.focused = false;
687
+ }
688
+ };
689
+ handlers.beforeinput = (view, _event) => {
690
+ if (android && _event.inputType == "deleteContentBackward") {
691
+ view.domObserver.flushSoon();
692
+ const { domChangeCount } = view.input;
693
+ setTimeout(() => {
694
+ if (view.input.domChangeCount != domChangeCount || view.domObserver.pendingRecords().length) return;
695
+ view.dom.blur();
696
+ view.focus();
697
+ if (dispatchKey(view, "Backspace")) return;
698
+ const $cursor = view.state.selection.$cursorOrNull;
699
+ if ($cursor && $cursor.pos > 0) view.dispatchInternal(view.state.tr.deleteUnsafe($cursor.pos - 1, $cursor.pos).scrollIntoView());
700
+ }, 50);
701
+ }
702
+ };
703
+ for (const prop in editHandlers) handlers[prop] = editHandlers[prop];
704
+ export { Dragging, InputState, clearComposition, destroyInput, dispatchEvent, dispatchKey, doPaste, endComposition, ensureListeners, findCompositionNode, initInput };