@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,409 @@
1
+ import { Decoration as Decoration$1, DecorationGroup as DecorationGroup$1, DecorationSet as DecorationSet$1 } from "../view/decoration.js";
2
+ import { EditorView as EditorView$1, __endComposition as __endComposition$1, __parseFromClipboard as __parseFromClipboard$1 } from "../view/view.js";
3
+ import { CORE, adopt, guard, link, registerWrapper, unwrap, unwrapArray, wrap, wrapArray } from "./internal/core.js";
4
+ import { propsToCore } from "./internal/props.js";
5
+ import * as Option from "effect/Option";
6
+ // src/compat/view.ts
7
+ /**
8
+ * A `prosemirror-view`-compatible facade over `@thomasfosterau/effect-richtext/view`.
9
+ *
10
+ * `new EditorView(place, props)` creates a core view with
11
+ * `EditorView.makeUnsafe`, translating the ProseMirror-style props
12
+ * (which receive and return facades) into core props. Decorations wrap
13
+ * core decorations.
14
+ *
15
+ * Ported API surface from prosemirror-view (MIT, Marijn Haverbeke and others).
16
+ *
17
+ * @since 0.1.0
18
+ */
19
+ const ORIGINAL = Symbol.for("effect-richtext/compat/original");
20
+ const widgetConstructors = /* @__PURE__ */ new WeakMap();
21
+ const widgetToCore = (toDOM) => {
22
+ if (typeof toDOM !== "function") return toDOM;
23
+ let found = widgetConstructors.get(toDOM);
24
+ if (!found) {
25
+ found = (view, getPos) => toDOM(wrap(view), getPos);
26
+ widgetConstructors.set(toDOM, found);
27
+ }
28
+ return found;
29
+ };
30
+ const specToCore = (spec) => {
31
+ if (!spec || !spec.marks) return spec;
32
+ return {
33
+ ...spec,
34
+ marks: unwrapArray(spec.marks),
35
+ [ORIGINAL]: spec
36
+ };
37
+ };
38
+ const originalSpec = (spec) => spec && (spec[ORIGINAL] ?? spec);
39
+ /**
40
+ * Decoration objects can be provided to the view through the
41
+ * `decorations` prop.
42
+ *
43
+ * @since 0.1.0
44
+ * @category models
45
+ */
46
+ var Decoration = class {
47
+ /** The start position of the decoration. */
48
+ get from() {
49
+ return this[CORE].from;
50
+ }
51
+ /** The end position. Will be the same as `from` for widget decorations. */
52
+ get to() {
53
+ return this[CORE].to;
54
+ }
55
+ /** @internal */
56
+ get type() {
57
+ return this[CORE].type;
58
+ }
59
+ /** The spec provided when creating this decoration. */
60
+ get spec() {
61
+ return originalSpec(this[CORE].spec);
62
+ }
63
+ /** @internal */
64
+ get inline() {
65
+ return this[CORE].inline;
66
+ }
67
+ /** @internal */
68
+ get widget() {
69
+ return this[CORE].widget;
70
+ }
71
+ /** @internal */
72
+ eq(other, offset = 0) {
73
+ return this[CORE].eq(other[CORE], offset);
74
+ }
75
+ /** Creates a widget decoration, which is a DOM node that's shown in the document at the given position. */
76
+ static widget(pos, toDOM, spec) {
77
+ return wrap(Decoration$1.widget(pos, widgetToCore(toDOM), specToCore(spec)));
78
+ }
79
+ /** Creates an inline decoration, which adds the given attributes to each inline node between `from` and `to`. */
80
+ static inline(from, to, attrs, spec) {
81
+ return wrap(Decoration$1.inline(from, to, attrs, spec));
82
+ }
83
+ /** Creates a node decoration. */
84
+ static node(from, to, attrs, spec) {
85
+ return wrap(Decoration$1.node(from, to, attrs, spec));
86
+ }
87
+ };
88
+ registerWrapper(Decoration$1, (core) => adopt(Decoration.prototype, core));
89
+ /**
90
+ * A collection of decorations, organized in such a way that the
91
+ * drawing algorithm can efficiently use and compare them.
92
+ *
93
+ * @since 0.1.0
94
+ * @category models
95
+ */
96
+ var DecorationSet = class {
97
+ /** Create a set of decorations, using the structure of the given document. */
98
+ static create(doc, decorations) {
99
+ return wrap(DecorationSet$1.create(doc[CORE], decorations.map(unwrap)));
100
+ }
101
+ /** Find all decorations in this set which touch the given range (including decorations that start or end directly at the boundaries) and match the given predicate on their spec. */
102
+ find(start, end, predicate) {
103
+ return this[CORE].find(start, end, predicate && ((spec) => predicate(originalSpec(spec)))).map(wrap);
104
+ }
105
+ /** Map the set of decorations in response to a change in the document. */
106
+ map(mapping, doc, options) {
107
+ const onRemove = options && options.onRemove;
108
+ return wrap(this[CORE].map(unwrap(mapping), doc[CORE], onRemove && { onRemove: (spec) => onRemove(originalSpec(spec)) }));
109
+ }
110
+ /** Add the given array of decorations to the ones in the set, producing a new set. */
111
+ add(doc, decorations) {
112
+ return wrap(this[CORE].add(doc[CORE], decorations.map(unwrap)));
113
+ }
114
+ /** Create a new set that contains the decorations in this set, minus the ones in the given array. */
115
+ remove(decorations) {
116
+ return wrap(this[CORE].remove(decorations.map(unwrap)));
117
+ }
118
+ /** @internal */
119
+ forChild(offset, node) {
120
+ return wrap(this[CORE].forChild(offset, node[CORE]));
121
+ }
122
+ /** @internal */
123
+ eq(other) {
124
+ return this[CORE].eq(unwrap(other));
125
+ }
126
+ /** @internal */
127
+ locals(node) {
128
+ return wrapArray(this[CORE].locals(node[CORE]));
129
+ }
130
+ /** @internal */
131
+ forEachSet(f) {
132
+ this[CORE].forEachSet((set) => f(wrap(set)));
133
+ }
134
+ /** @internal */
135
+ get local() {
136
+ return wrapArray(this[CORE].local);
137
+ }
138
+ /** @internal */
139
+ get children() {
140
+ return this[CORE].children.map(wrap);
141
+ }
142
+ /** @internal */
143
+ static removeOverlap(spans) {
144
+ const core = unwrapArray(spans);
145
+ const result = DecorationSet$1.removeOverlap(core);
146
+ return result === core ? spans : result.map(wrap);
147
+ }
148
+ };
149
+ registerWrapper(DecorationSet$1, (core) => adopt(DecorationSet.prototype, core));
150
+ DecorationSet.empty = wrap(DecorationSet$1.empty);
151
+ /** A facade for the core's (non-exported) group of decoration sources. @internal */
152
+ var DecorationGroup = class {
153
+ map(mapping, doc) {
154
+ return wrap(this[CORE].map(unwrap(mapping), doc[CORE]));
155
+ }
156
+ forChild(offset, child) {
157
+ return wrap(this[CORE].forChild(offset, child[CORE]));
158
+ }
159
+ eq(other) {
160
+ return this[CORE].eq(unwrap(other));
161
+ }
162
+ forEachSet(f) {
163
+ this[CORE].forEachSet((set) => f(wrap(set)));
164
+ }
165
+ locals(node) {
166
+ return wrapArray(this[CORE].locals(node[CORE]));
167
+ }
168
+ };
169
+ registerWrapper(DecorationGroup$1, (core) => adopt(DecorationGroup.prototype, core));
170
+ const constructing = [];
171
+ /**
172
+ * An editor view manages the DOM structure that represents an editable
173
+ * document.
174
+ *
175
+ * @since 0.1.0
176
+ * @category models
177
+ */
178
+ var EditorView = class {
179
+ /** Create a view. */
180
+ constructor(place, props) {
181
+ this._props = props;
182
+ this.propsCache = /* @__PURE__ */ new WeakMap();
183
+ this.dispatch = this.dispatch.bind(this);
184
+ constructing.push(this);
185
+ try {
186
+ const core = guard(() => EditorView$1.makeUnsafe(place, this.propsToCore(props)));
187
+ link(this, core);
188
+ } finally {
189
+ constructing.pop();
190
+ }
191
+ }
192
+ propsToCore(props) {
193
+ return propsToCore(props, this, this.propsCache);
194
+ }
195
+ /** The view's current state. */
196
+ get state() {
197
+ return wrap(this[CORE].state);
198
+ }
199
+ /** An editable DOM node containing the document. */
200
+ get dom() {
201
+ return this[CORE].dom;
202
+ }
203
+ /** Indicates whether the editor is currently editable. */
204
+ get editable() {
205
+ return this[CORE].editable;
206
+ }
207
+ /** When editor content is being dragged, this object contains information about the dragged slice and whether it is being copied or moved. */
208
+ get dragging() {
209
+ const dragging = this[CORE].dragging;
210
+ return dragging && {
211
+ slice: wrap(dragging.slice),
212
+ move: dragging.move
213
+ };
214
+ }
215
+ set dragging(value) {
216
+ this[CORE].dragging = value && {
217
+ slice: value.slice[CORE],
218
+ move: value.move
219
+ };
220
+ }
221
+ /** Holds `true` when a composition is active. */
222
+ get composing() {
223
+ return this[CORE].composing;
224
+ }
225
+ /** The view's current props. */
226
+ get props() {
227
+ if (this._props.state != this.state) {
228
+ const prev = this._props;
229
+ this._props = {};
230
+ for (const name in prev) this._props[name] = prev[name];
231
+ this._props.state = this.state;
232
+ }
233
+ return this._props;
234
+ }
235
+ /** Update the view's props. Will immediately cause an update to the DOM. */
236
+ update(props) {
237
+ this._props = props;
238
+ guard(() => this[CORE].update(this.propsToCore(props)));
239
+ }
240
+ /** Update the view by updating existing props object with the object given as argument. */
241
+ setProps(props) {
242
+ const updated = {};
243
+ for (const name in this._props) updated[name] = this._props[name];
244
+ updated.state = this.state;
245
+ for (const name in props) updated[name] = props[name];
246
+ this.update(updated);
247
+ }
248
+ /** Update the editor's `state` prop, without touching any of the other props. */
249
+ updateState(state) {
250
+ guard(() => this[CORE].updateState(state[CORE]));
251
+ }
252
+ someProp(propName, f) {
253
+ const prop = this._props && this._props[propName];
254
+ let value;
255
+ if (prop != null && (value = f ? f(prop) : prop)) return value;
256
+ const direct = this._props.plugins || [];
257
+ for (let i = 0; i < direct.length; i++) {
258
+ const prop = direct[i].props[propName];
259
+ if (prop != null && (value = f ? f(prop) : prop)) return value;
260
+ }
261
+ const plugins = this.state.plugins;
262
+ if (plugins) for (let i = 0; i < plugins.length; i++) {
263
+ const prop = plugins[i].props[propName];
264
+ if (prop != null && (value = f ? f(prop) : prop)) return value;
265
+ }
266
+ }
267
+ /** Query whether the view has focus. */
268
+ hasFocus() {
269
+ return this[CORE].hasFocus();
270
+ }
271
+ /** Focus the editor. */
272
+ focus() {
273
+ this[CORE].focus();
274
+ }
275
+ /** Get the document root in which the editor exists. */
276
+ get root() {
277
+ return this[CORE].root;
278
+ }
279
+ /** When an existing editor view is moved to a new document or shadow tree, call this to make it recompute its root. */
280
+ updateRoot() {
281
+ this[CORE].updateRoot();
282
+ }
283
+ /** Given a pair of viewport coordinates, return the document position that corresponds to them. */
284
+ posAtCoords(coords) {
285
+ return Option.getOrNull(this[CORE].posAtCoords(coords));
286
+ }
287
+ /** Returns the viewport rectangle at a given document position. */
288
+ coordsAtPos(pos, side = 1) {
289
+ return guard(() => this[CORE].coordsAtPos(pos, side));
290
+ }
291
+ /** Find the DOM position that corresponds to the given document position. */
292
+ domAtPos(pos, side = 0) {
293
+ return guard(() => this[CORE].domAtPos(pos, side));
294
+ }
295
+ /** Find the DOM node that represents the document node after the given position. */
296
+ nodeDOM(pos) {
297
+ return Option.getOrNull(this[CORE].nodeDOM(pos));
298
+ }
299
+ /** Find the document position that corresponds to a given DOM position. */
300
+ posAtDOM(node, offset, bias = -1) {
301
+ return guard(() => this[CORE].posAtDOMUnsafe(node, offset, bias));
302
+ }
303
+ /** Find out whether the selection is at the end of a textblock when moving in a given direction. */
304
+ endOfTextblock(dir, state) {
305
+ return this[CORE].endOfTextblock(dir, state && state[CORE]);
306
+ }
307
+ /** Run the editor's paste logic with the given HTML string. */
308
+ pasteHTML(html, event) {
309
+ return guard(() => this[CORE].pasteHTML(html, event));
310
+ }
311
+ /** Run the editor's paste logic with the given plain-text input. */
312
+ pasteText(text, event) {
313
+ return guard(() => this[CORE].pasteText(text, event));
314
+ }
315
+ /** Serialize the given slice as it would be if it was copied from this editor. */
316
+ serializeForClipboard(slice) {
317
+ const result = guard(() => this[CORE].serializeForClipboard(slice[CORE]));
318
+ return {
319
+ dom: result.dom,
320
+ text: result.text,
321
+ slice: wrap(result.slice)
322
+ };
323
+ }
324
+ /** Removes the editor from the DOM and destroys all node views. */
325
+ destroy() {
326
+ this[CORE].destroy();
327
+ }
328
+ /** This is true when the view has been destroyed (and thus should not be used anymore). */
329
+ get isDestroyed() {
330
+ return this[CORE].isDestroyed;
331
+ }
332
+ /** Used for testing. */
333
+ dispatchEvent(event) {
334
+ this[CORE].dispatchEvent(event);
335
+ }
336
+ /** Dispatch a transaction. */
337
+ dispatch(tr) {
338
+ guard(() => this[CORE].dispatchUnsafe(tr[CORE]));
339
+ }
340
+ /** @internal */
341
+ domSelectionRange() {
342
+ return this[CORE].domSelectionRange();
343
+ }
344
+ /** @internal */
345
+ domSelection() {
346
+ return this[CORE].domSelection();
347
+ }
348
+ /** @internal */
349
+ scrollToSelection() {
350
+ this[CORE].scrollToSelection();
351
+ }
352
+ /** @internal */
353
+ get domObserver() {
354
+ return this[CORE].domObserver;
355
+ }
356
+ /** @internal */
357
+ get docView() {
358
+ return this[CORE].docView;
359
+ }
360
+ /** @internal */
361
+ get input() {
362
+ return this[CORE].input;
363
+ }
364
+ /** @internal */
365
+ get focused() {
366
+ return this[CORE].focused;
367
+ }
368
+ /** @internal */
369
+ get markCursor() {
370
+ const marks = this[CORE].markCursor;
371
+ return marks && wrapArray(marks);
372
+ }
373
+ /** @internal */
374
+ get cursorWrapper() {
375
+ return this[CORE].cursorWrapper;
376
+ }
377
+ /** @internal */
378
+ get lastSelectedViewDesc() {
379
+ return this[CORE].lastSelectedViewDesc;
380
+ }
381
+ /** @internal */
382
+ get trackWrites() {
383
+ return this[CORE].trackWrites;
384
+ }
385
+ /** @internal */
386
+ get nodeViews() {
387
+ return this[CORE].nodeViews;
388
+ }
389
+ };
390
+ registerWrapper(EditorView$1, (core) => {
391
+ const facade = constructing.at(-1);
392
+ if (facade && !(CORE in facade)) return facade;
393
+ const view = adopt(EditorView.prototype, core);
394
+ view._props = core.props;
395
+ view.propsCache = /* @__PURE__ */ new WeakMap();
396
+ view.dispatch = view.dispatch.bind(view);
397
+ return view;
398
+ });
399
+ /** @internal */
400
+ const __parseFromClipboard = (view, text, html, plainText, $context) => wrap(__parseFromClipboard$1(view[CORE], text, html, plainText, $context[CORE]));
401
+ /** @internal */
402
+ const __endComposition = (view, restarting = false) => __endComposition$1(view[CORE], restarting);
403
+ function toCore(value) {
404
+ return unwrap(value);
405
+ }
406
+ function fromCore(value) {
407
+ return wrap(value);
408
+ }
409
+ export { Decoration, DecorationSet, EditorView, __endComposition, __parseFromClipboard, fromCore, toCore };
@@ -0,0 +1,46 @@
1
+ import { EditorView, PosAtCoords } from "./view/view.js";
2
+ import { Plugin } from "./state/plugin.js";
3
+ import "./state.js";
4
+ import "./view.js";
5
+ /**
6
+ * Options for `dropCursor`.
7
+ *
8
+ * @since 0.1.0
9
+ * @category models
10
+ */
11
+ export interface DropCursorOptions {
12
+ /**
13
+ * The color of the cursor. Defaults to `black`. Use `false` to apply
14
+ * no color and rely only on class.
15
+ */
16
+ readonly color?: string | false | undefined;
17
+ /** The precise width of the cursor in pixels. Defaults to 1. */
18
+ readonly width?: number | undefined;
19
+ /** A CSS class name to add to the cursor element. */
20
+ readonly class?: string | undefined;
21
+ }
22
+ /**
23
+ * The type of the `disableDropCursor` property node specs may define to
24
+ * control the showing of a drop cursor inside them.
25
+ *
26
+ * @since 0.1.0
27
+ * @category models
28
+ */
29
+ export type DisableDropCursor = boolean | ((view: EditorView<any, any, any>, pos: PosAtCoords, event: DragEvent) => boolean);
30
+ /**
31
+ * Create a plugin that, when added to an editor, causes a decoration to
32
+ * show up at the drop position when something is dragged over the
33
+ * editor.
34
+ *
35
+ * Nodes may add a `disableDropCursor` property (see `DisableDropCursor`)
36
+ * to their spec to control the showing of a drop cursor inside them.
37
+ * This may be a boolean or a function, which will be called with a view
38
+ * and a position, and should return a boolean.
39
+ *
40
+ * The cursor element gets the class `prosemirror-dropcursor-block` or
41
+ * `prosemirror-dropcursor-inline`, depending on the position.
42
+ *
43
+ * @since 0.1.0
44
+ * @category constructors
45
+ */
46
+ export declare const dropCursor: (options?: DropCursorOptions) => Plugin<undefined>;
@@ -0,0 +1,176 @@
1
+ import { Plugin } from "./state/plugin.js";
2
+ import { dropPoint } from "./transform/structure.js";
3
+ import * as Option from "effect/Option";
4
+ import * as Predicate from "effect/Predicate";
5
+ // src/dropcursor.ts
6
+ /**
7
+ * A plugin that shows a drop cursor (a line at the drop position) when
8
+ * something is dragged over the editor. Ported from
9
+ * `prosemirror-dropcursor`.
10
+ *
11
+ * @since 0.1.0
12
+ */
13
+ /**
14
+ * Create a plugin that, when added to an editor, causes a decoration to
15
+ * show up at the drop position when something is dragged over the
16
+ * editor.
17
+ *
18
+ * Nodes may add a `disableDropCursor` property (see `DisableDropCursor`)
19
+ * to their spec to control the showing of a drop cursor inside them.
20
+ * This may be a boolean or a function, which will be called with a view
21
+ * and a position, and should return a boolean.
22
+ *
23
+ * The cursor element gets the class `prosemirror-dropcursor-block` or
24
+ * `prosemirror-dropcursor-inline`, depending on the position.
25
+ *
26
+ * @since 0.1.0
27
+ * @category constructors
28
+ */
29
+ const dropCursor = (options = {}) => new Plugin({ view: (editorView) => new DropCursorView(editorView, options) });
30
+ const events = [
31
+ "dragover",
32
+ "dragend",
33
+ "drop",
34
+ "dragleave"
35
+ ];
36
+ var DropCursorView = class {
37
+ constructor(editorView, options) {
38
+ this.editorView = editorView;
39
+ this.cursorPos = null;
40
+ this.element = null;
41
+ this.timeout = void 0;
42
+ this.width = options.width ?? 1;
43
+ this.color = options.color === false ? void 0 : options.color || "black";
44
+ this.class = options.class;
45
+ this.handlers = events.map((name) => {
46
+ const handler = (e) => {
47
+ this[name](e);
48
+ };
49
+ editorView.dom.addEventListener(name, handler);
50
+ return {
51
+ name,
52
+ handler
53
+ };
54
+ });
55
+ }
56
+ destroy() {
57
+ this.handlers.forEach(({ handler, name }) => this.editorView.dom.removeEventListener(name, handler));
58
+ clearTimeout(this.timeout);
59
+ if (this.element) {
60
+ this.element.remove();
61
+ this.element = null;
62
+ }
63
+ }
64
+ update(editorView, prevState) {
65
+ if (this.cursorPos != null && prevState.doc !== editorView.state.doc) {
66
+ if (this.cursorPos > editorView.state.doc.content.size) this.setCursor(null);
67
+ else this.updateOverlay();
68
+ }
69
+ }
70
+ setCursor(pos) {
71
+ if (pos === this.cursorPos) return;
72
+ this.cursorPos = pos;
73
+ if (pos == null) {
74
+ this.element?.remove();
75
+ this.element = null;
76
+ } else this.updateOverlay();
77
+ }
78
+ updateOverlay() {
79
+ const view = this.editorView;
80
+ const $pos = view.state.doc.resolveUnsafe(this.cursorPos);
81
+ const isBlock = !$pos.parent.inlineContent;
82
+ let rect;
83
+ const editorDOM = view.dom, editorRect = editorDOM.getBoundingClientRect();
84
+ const scaleX = editorRect.width / editorDOM.offsetWidth, scaleY = editorRect.height / editorDOM.offsetHeight;
85
+ if (isBlock) {
86
+ const before = $pos.nodeBeforeOrNull, after = $pos.nodeAfterOrNull;
87
+ if (before || after) {
88
+ const node = Option.getOrNull(view.nodeDOM(this.cursorPos - (before ? before.nodeSize : 0)));
89
+ if (node) {
90
+ const nodeRect = node.getBoundingClientRect();
91
+ let top = before ? nodeRect.bottom : nodeRect.top;
92
+ if (before && after) {
93
+ const afterDOM = Option.getOrNull(view.nodeDOM(this.cursorPos));
94
+ if (afterDOM) top = (top + afterDOM.getBoundingClientRect().top) / 2;
95
+ }
96
+ const halfWidth = this.width / 2 * scaleY;
97
+ rect = {
98
+ left: nodeRect.left,
99
+ right: nodeRect.right,
100
+ top: top - halfWidth,
101
+ bottom: top + halfWidth
102
+ };
103
+ }
104
+ }
105
+ }
106
+ if (!rect) {
107
+ const coords = view.coordsAtPos(this.cursorPos);
108
+ const halfWidth = this.width / 2 * scaleX;
109
+ rect = {
110
+ left: coords.left - halfWidth,
111
+ right: coords.left + halfWidth,
112
+ top: coords.top,
113
+ bottom: coords.bottom
114
+ };
115
+ }
116
+ const doc = editorDOM.ownerDocument;
117
+ const parent = editorDOM.offsetParent;
118
+ if (!this.element) {
119
+ this.element = (parent ?? doc.body).appendChild(doc.createElement("div"));
120
+ if (this.class) this.element.className = this.class;
121
+ this.element.style.cssText = "position: absolute; z-index: 50; pointer-events: none;";
122
+ if (this.color) this.element.style.backgroundColor = this.color;
123
+ }
124
+ this.element.classList.toggle("prosemirror-dropcursor-block", isBlock);
125
+ this.element.classList.toggle("prosemirror-dropcursor-inline", !isBlock);
126
+ let parentLeft, parentTop;
127
+ const win = doc.defaultView ?? window;
128
+ if (!parent || parent === doc.body && win.getComputedStyle(parent).position === "static") {
129
+ parentLeft = -win.pageXOffset;
130
+ parentTop = -win.pageYOffset;
131
+ } else {
132
+ const rect = parent.getBoundingClientRect();
133
+ const parentScaleX = rect.width / parent.offsetWidth, parentScaleY = rect.height / parent.offsetHeight;
134
+ parentLeft = rect.left - parent.scrollLeft * parentScaleX;
135
+ parentTop = rect.top - parent.scrollTop * parentScaleY;
136
+ }
137
+ this.element.style.left = (rect.left - parentLeft) / scaleX + "px";
138
+ this.element.style.top = (rect.top - parentTop) / scaleY + "px";
139
+ this.element.style.width = (rect.right - rect.left) / scaleX + "px";
140
+ this.element.style.height = (rect.bottom - rect.top) / scaleY + "px";
141
+ }
142
+ scheduleRemoval(timeout) {
143
+ clearTimeout(this.timeout);
144
+ this.timeout = setTimeout(() => this.setCursor(null), timeout);
145
+ }
146
+ dragover(event) {
147
+ const view = this.editorView;
148
+ if (!view.editable) return;
149
+ const pos = Option.getOrNull(view.posAtCoords({
150
+ left: event.clientX,
151
+ top: event.clientY
152
+ }));
153
+ const node = pos && pos.inside >= 0 ? view.state.doc.nodeAtOrNull(pos.inside) : null;
154
+ const disableDropCursor = node ? node.type.spec.disableDropCursor : void 0;
155
+ const disabled = Predicate.isFunction(disableDropCursor) ? disableDropCursor(view, pos, event) : disableDropCursor;
156
+ if (pos && !disabled) {
157
+ let target = pos.pos;
158
+ if (view.dragging && view.dragging.slice) {
159
+ const point = Option.getOrNull(dropPoint(view.state.doc, target, view.dragging.slice));
160
+ if (point != null) target = point;
161
+ }
162
+ this.setCursor(target);
163
+ this.scheduleRemoval(5e3);
164
+ }
165
+ }
166
+ dragend() {
167
+ this.scheduleRemoval(20);
168
+ }
169
+ drop() {
170
+ this.scheduleRemoval(20);
171
+ }
172
+ dragleave(event) {
173
+ if (!this.editorView.dom.contains(event.relatedTarget)) this.setCursor(null);
174
+ }
175
+ };
176
+ export { dropCursor };