@prosekit/extensions 0.11.5 → 0.11.6

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 (51) hide show
  1. package/dist/drop-indicator-E7nCfdnR.js +58 -0
  2. package/dist/drop-indicator-E7nCfdnR.js.map +1 -0
  3. package/dist/file-DVUhe5KJ.js +134 -0
  4. package/dist/file-DVUhe5KJ.js.map +1 -0
  5. package/dist/index-DY6lIIYV.d.ts +134 -0
  6. package/dist/index-DY6lIIYV.d.ts.map +1 -0
  7. package/dist/{mark-rule-BCqIZMDu.js → mark-rule-CGmswjQ_.js} +1 -1
  8. package/dist/{mark-rule-BCqIZMDu.js.map → mark-rule-CGmswjQ_.js.map} +1 -1
  9. package/dist/{paste-rule-DIEJKIje.js → paste-rule-BIztzELg.js} +1 -1
  10. package/dist/{paste-rule-DIEJKIje.js.map → paste-rule-BIztzELg.js.map} +1 -1
  11. package/dist/prosekit-extensions-code-block.d.ts +1 -1
  12. package/dist/prosekit-extensions-drop-indicator.d.ts +3 -106
  13. package/dist/prosekit-extensions-drop-indicator.d.ts.map +1 -1
  14. package/dist/prosekit-extensions-drop-indicator.js +1 -1
  15. package/dist/prosekit-extensions-file.d.ts +2 -126
  16. package/dist/prosekit-extensions-file.js +2 -128
  17. package/dist/prosekit-extensions-hard-break.d.ts +0 -4
  18. package/dist/prosekit-extensions-hard-break.d.ts.map +1 -1
  19. package/dist/prosekit-extensions-image.d.ts +79 -3
  20. package/dist/prosekit-extensions-image.d.ts.map +1 -1
  21. package/dist/prosekit-extensions-image.js +88 -8
  22. package/dist/prosekit-extensions-image.js.map +1 -1
  23. package/dist/prosekit-extensions-link.js +2 -2
  24. package/dist/prosekit-extensions-list.js +2 -2
  25. package/dist/prosekit-extensions-mark-rule.js +1 -1
  26. package/dist/prosekit-extensions-paragraph.d.ts +0 -4
  27. package/dist/prosekit-extensions-paragraph.d.ts.map +1 -1
  28. package/dist/prosekit-extensions-paste-rule.js +1 -1
  29. package/dist/prosekit-extensions-placeholder.js +2 -2
  30. package/dist/prosekit-extensions-table.js +2 -2
  31. package/dist/prosekit-extensions.d.ts +1 -1
  32. package/dist/{shiki-highlighter-chunk-DSPM0T27.d.ts → shiki-highlighter-chunk-Cwu1Jr9o.d.ts} +1 -1
  33. package/dist/{shiki-highlighter-chunk-DSPM0T27.d.ts.map → shiki-highlighter-chunk-Cwu1Jr9o.d.ts.map} +1 -1
  34. package/dist/shiki-highlighter-chunk.d.ts +1 -1
  35. package/dist/{table-Bi7WsMI3.js → table-BNwuK7xg.js} +2 -2
  36. package/dist/{table-Bi7WsMI3.js.map → table-BNwuK7xg.js.map} +1 -1
  37. package/package.json +7 -6
  38. package/src/drop-indicator/drop-indicator-facet.ts +6 -28
  39. package/src/drop-indicator/drop-indicator.ts +3 -5
  40. package/src/drop-indicator/index.ts +6 -6
  41. package/src/file/file-upload.ts +29 -8
  42. package/src/image/image-commands.ts +12 -3
  43. package/src/image/image-upload-handler.ts +156 -0
  44. package/src/image/index.ts +9 -0
  45. package/dist/drop-indicator-D1eHOhSi.js +0 -267
  46. package/dist/drop-indicator-D1eHOhSi.js.map +0 -1
  47. package/dist/prosekit-extensions-file.d.ts.map +0 -1
  48. package/dist/prosekit-extensions-file.js.map +0 -1
  49. package/src/drop-indicator/drop-indicator-plugin.ts +0 -147
  50. package/src/drop-indicator/drop-target.ts +0 -168
  51. package/src/drop-indicator/types.ts +0 -90
@@ -1,267 +0,0 @@
1
- import { defineFacet, defineFacetPayload, isNodeSelection, pluginFacet } from "@prosekit/core";
2
- import { NodeSelection, Plugin, PluginKey, TextSelection } from "@prosekit/pm/state";
3
- import { isHTMLElement } from "@ocavue/utils";
4
-
5
- //#region src/drop-indicator/drop-target.ts
6
- function getTargetsByView(view) {
7
- let stack = [[-1, view.state.doc]];
8
- let targets = [];
9
- while (stack.length > 0) {
10
- const [pos, node] = stack.pop();
11
- if (pos >= 0) {
12
- let dom = view.nodeDOM(pos);
13
- if (dom && isHTMLElement(dom)) {
14
- let { top, bottom, left: x1, right: x2 } = dom.getBoundingClientRect();
15
- targets.push([pos, [
16
- x1,
17
- top,
18
- x2,
19
- top
20
- ]], [pos + node.nodeSize, [
21
- x1,
22
- bottom,
23
- x2,
24
- bottom
25
- ]]);
26
- }
27
- }
28
- if (node.isBlock && !node.isTextblock) {
29
- let childPos = pos + 1;
30
- for (let child of node.children) {
31
- stack.push([childPos, child]);
32
- childPos += child.nodeSize;
33
- }
34
- }
35
- }
36
- return targets;
37
- }
38
- /**
39
- * @internal
40
- */
41
- function buildGetTarget(view, onDrag) {
42
- let prevTargets = [];
43
- let prevDoc;
44
- let prevRect;
45
- const getTargets = () => {
46
- const rect = view.dom.getBoundingClientRect();
47
- const doc = view.state.doc;
48
- if (prevTargets && prevDoc && prevRect && rect.width === prevRect.width && rect.height === prevRect.height && rect.x === prevRect.x && rect.y === prevRect.y && prevDoc.eq(doc)) return prevTargets;
49
- prevRect = rect;
50
- prevDoc = doc;
51
- prevTargets = getTargetsByView(view);
52
- return prevTargets;
53
- };
54
- const getTargetImpl = (point, event) => {
55
- if (!view.editable || view.isDestroyed) return;
56
- const compare = (p1, p2) => {
57
- const [pos1, line1] = p1;
58
- const [pos2, line2] = p2;
59
- const p1Distance = pointLineDistance(point, line1);
60
- const p2Distance = pointLineDistance(point, line2);
61
- return p1Distance - p2Distance || pos1 - pos2;
62
- };
63
- let targets = getTargets();
64
- targets.sort(compare);
65
- targets = targets.slice(0, 8);
66
- const target = targets.find((target$1) => onDrag({
67
- view,
68
- pos: target$1[0],
69
- event
70
- }) !== false);
71
- if (target && isDraggingToItself(view, target[0])) return;
72
- return target;
73
- };
74
- let prevPoint;
75
- let prevTarget;
76
- const getTargetCached = (point, event) => {
77
- if (prevPoint && pointEqual(prevPoint, point)) return prevTarget;
78
- prevPoint = point;
79
- prevTarget = getTargetImpl(point, event);
80
- return prevTarget;
81
- };
82
- return getTargetCached;
83
- }
84
- function pointEqual(a, b) {
85
- return a[0] === b[0] && a[1] === b[1];
86
- }
87
- function pointPointDistance(a, b) {
88
- return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);
89
- }
90
- function pointLineDistance(point, line) {
91
- return Math.min(pointPointDistance(point, [line[0], line[1]]), pointPointDistance(point, [line[2], line[3]]));
92
- }
93
- /**
94
- * Whether the dragging node is being dragged to the same position. For example,
95
- * dragging a list node into a new position that is just below the list node, or
96
- * dragging a nested quoteblock into itself.
97
- */
98
- function isDraggingToItself(view, pos) {
99
- const dragging = view.dragging;
100
- if (!dragging) return;
101
- const { move } = dragging;
102
- if (!move) return;
103
- const selection = view.state.selection;
104
- if (!isNodeSelection(selection)) return;
105
- const { from, to } = selection;
106
- return from <= pos && pos <= to;
107
- }
108
-
109
- //#endregion
110
- //#region src/drop-indicator/drop-indicator-plugin.ts
111
- /**
112
- * @internal
113
- */
114
- function createDropIndicatorPlugin(options) {
115
- let getTarget;
116
- return new Plugin({
117
- key: new PluginKey("prosekit-drop-indicator"),
118
- view: (view) => {
119
- getTarget = buildGetTarget(view, options.onDrag);
120
- return createDropIndicatorView(view, getTarget, options);
121
- },
122
- props: { handleDrop(view, event, slice, move) {
123
- if (!getTarget) return false;
124
- const target = getTarget([event.clientX, event.clientY], event);
125
- if (!target) return false;
126
- event.preventDefault();
127
- let insertPos = target[0];
128
- let tr = view.state.tr;
129
- if (move) {
130
- let { node } = view.dragging || {};
131
- if (node) node.replace(tr);
132
- else tr.deleteSelection();
133
- }
134
- let pos = tr.mapping.map(insertPos);
135
- let isNode = slice.openStart == 0 && slice.openEnd == 0 && slice.content.childCount == 1;
136
- let beforeInsert = tr.doc;
137
- if (isNode) tr.replaceRangeWith(pos, pos, slice.content.firstChild);
138
- else tr.replaceRange(pos, pos, slice);
139
- if (tr.doc.eq(beforeInsert)) return true;
140
- let $pos = tr.doc.resolve(pos);
141
- if (isNode && NodeSelection.isSelectable(slice.content.firstChild) && $pos.nodeAfter && $pos.nodeAfter.sameMarkup(slice.content.firstChild)) tr.setSelection(new NodeSelection($pos));
142
- else {
143
- let end = tr.mapping.map(insertPos);
144
- tr.mapping.maps[tr.mapping.maps.length - 1].forEach((_from, _to, _newFrom, newTo) => end = newTo);
145
- tr.setSelection(selectionBetween(view, $pos, tr.doc.resolve(end)));
146
- }
147
- view.focus();
148
- view.dispatch(tr.setMeta("uiEvent", "drop"));
149
- return true;
150
- } }
151
- });
152
- }
153
- function selectionBetween(view, $anchor, $head, bias) {
154
- return view.someProp("createSelectionBetween", (f) => f(view, $anchor, $head)) || TextSelection.between($anchor, $head, bias);
155
- }
156
- function createDropIndicatorView(view, getTarget, options) {
157
- let dom = view.dom;
158
- let hideId;
159
- let prevX;
160
- let prevY;
161
- let hasDragOverEvent = false;
162
- const scheduleHide = () => {
163
- if (hideId) clearTimeout(hideId);
164
- hasDragOverEvent = false;
165
- hideId = setTimeout(() => {
166
- if (hasDragOverEvent) return;
167
- options.onHide();
168
- }, 30);
169
- };
170
- const handleDragOver = (event) => {
171
- hasDragOverEvent = true;
172
- const { clientX, clientY } = event;
173
- if (prevX === clientX && prevY === clientY) return;
174
- prevX = clientX;
175
- prevY = clientY;
176
- let target = getTarget([clientX, clientY], event);
177
- if (!target) {
178
- scheduleHide();
179
- return;
180
- } else {
181
- const [pos, [x1, y1, x2, y2]] = target;
182
- const line = {
183
- p1: {
184
- x: x1,
185
- y: y1
186
- },
187
- p2: {
188
- x: x2,
189
- y: y2
190
- }
191
- };
192
- options.onShow({
193
- view,
194
- pos,
195
- line
196
- });
197
- }
198
- };
199
- dom.addEventListener("dragover", handleDragOver);
200
- dom.addEventListener("dragend", scheduleHide);
201
- dom.addEventListener("drop", scheduleHide);
202
- dom.addEventListener("dragleave", scheduleHide);
203
- const destroy = () => {
204
- dom.removeEventListener("dragover", handleDragOver);
205
- dom.removeEventListener("dragend", scheduleHide);
206
- dom.removeEventListener("drop", scheduleHide);
207
- dom.removeEventListener("dragleave", scheduleHide);
208
- };
209
- return { destroy };
210
- }
211
-
212
- //#endregion
213
- //#region src/drop-indicator/drop-indicator-facet.ts
214
- /**
215
- * @internal
216
- */
217
- function defineDropIndicatorPayload(payload) {
218
- return defineFacetPayload(dropIndicatorFacet, [payload]);
219
- }
220
- const dropIndicatorFacet = defineFacet({
221
- parent: pluginFacet,
222
- singleton: true,
223
- reducer: (payloads) => {
224
- let showHandlers = payloads.map((p) => p.onShow).filter((x) => !!x);
225
- let hideHandlers = payloads.map((p) => p.onHide).filter((x) => !!x);
226
- let dragHandlers = payloads.map((p) => p.onDrag).filter((x) => !!x);
227
- let showHandler = (options) => {
228
- for (let fn of showHandlers) fn(options);
229
- };
230
- let hideHandler = () => {
231
- for (let fn of hideHandlers) fn();
232
- };
233
- let dragHandler = (options) => {
234
- for (let fn of dragHandlers) if (fn(options) === false) return false;
235
- return true;
236
- };
237
- if (showHandlers.length === 0) return [];
238
- return createDropIndicatorPlugin({
239
- onDrag: dragHandler,
240
- onShow: showHandler,
241
- onHide: hideHandler
242
- });
243
- }
244
- });
245
-
246
- //#endregion
247
- //#region src/drop-indicator/drop-indicator.ts
248
- /**
249
- * Defines an extension that controls the behavior of the drop indicator.
250
- *
251
- * This extension itself doesn't draw the drop indicator, but it provides the
252
- * necessary callbacks to do so. You probably don't want to use this extension
253
- * directly, but rather use the `<DropIndicator>` component.
254
- *
255
- * You can add this extension multiple times. If any extension has `onDrag`
256
- * callback defined, and it returns `false`, then the drop point will be
257
- * discarded.
258
- *
259
- * @public
260
- */
261
- function defineDropIndicator(options) {
262
- return defineDropIndicatorPayload(options ?? {});
263
- }
264
-
265
- //#endregion
266
- export { defineDropIndicator };
267
- //# sourceMappingURL=drop-indicator-D1eHOhSi.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"drop-indicator-D1eHOhSi.js","names":["stack: StackItem[]","targets: DropTarget[]","prevTargets: DropTarget[]","prevDoc: ProseMirrorNode | undefined","prevRect: DOMRect | undefined","getTargetImpl: GetTarget","target","prevPoint: Point | undefined","prevTarget: DropTarget | undefined","getTargetCached: GetTarget","getTarget: GetTarget | undefined","hideId: ReturnType<typeof setTimeout> | undefined","prevX: number | undefined","prevY: number | undefined","hasDragOverEvent: boolean","showHandler: ShowHandler","hideHandler: VoidFunction","dragHandler: DragEventHandler"],"sources":["../src/drop-indicator/drop-target.ts","../src/drop-indicator/drop-indicator-plugin.ts","../src/drop-indicator/drop-indicator-facet.ts","../src/drop-indicator/drop-indicator.ts"],"sourcesContent":["import { isHTMLElement } from '@ocavue/utils'\nimport { isNodeSelection } from '@prosekit/core'\nimport type { ProseMirrorNode } from '@prosekit/pm/model'\nimport type { EditorView } from '@prosekit/pm/view'\n\nimport type { DragEventHandler } from './types'\n\ntype Point = readonly [x: number, y: number]\n\ntype Line = readonly [x1: number, y1: number, x2: number, y2: number]\n\n/**\n * @internal\n */\ntype DropTarget = readonly [pos: number, line: Line]\n\nfunction getTargetsByView(view: EditorView): DropTarget[] {\n type StackItem = [pos: number, node: ProseMirrorNode]\n let stack: StackItem[] = [[-1, view.state.doc]]\n let targets: DropTarget[] = []\n\n while (stack.length > 0) {\n const [pos, node] = stack.pop()!\n if (pos >= 0) {\n let dom = view.nodeDOM(pos)\n if (dom && isHTMLElement(dom)) {\n let rect = dom.getBoundingClientRect()\n let { top, bottom, left: x1, right: x2 } = rect\n targets.push(\n [pos, [x1, top, x2, top]],\n [pos + node.nodeSize, [x1, bottom, x2, bottom]],\n )\n }\n }\n if (node.isBlock && !node.isTextblock) {\n let childPos = pos + 1\n for (let child of node.children) {\n stack.push([childPos, child])\n childPos += child.nodeSize\n }\n }\n }\n\n return targets\n}\n\n/**\n * @internal\n */\nexport type GetTarget = (point: Point, event: DragEvent) => DropTarget | undefined\n\n/**\n * @internal\n */\nexport function buildGetTarget(\n view: EditorView,\n onDrag: DragEventHandler,\n): GetTarget {\n let prevTargets: DropTarget[] = []\n let prevDoc: ProseMirrorNode | undefined\n let prevRect: DOMRect | undefined\n\n const getTargets = (): DropTarget[] => {\n const rect = view.dom.getBoundingClientRect()\n const doc = view.state.doc\n\n if (\n prevTargets && prevDoc && prevRect\n && rect.width === prevRect.width\n && rect.height === prevRect.height\n && rect.x === prevRect.x\n && rect.y === prevRect.y\n && prevDoc.eq(doc)\n ) {\n return prevTargets\n }\n\n prevRect = rect\n prevDoc = doc\n prevTargets = getTargetsByView(view)\n return prevTargets\n }\n\n const getTargetImpl: GetTarget = (point, event) => {\n if (!view.editable || view.isDestroyed) {\n return\n }\n\n const compare = (p1: DropTarget, p2: DropTarget): number => {\n const [pos1, line1] = p1\n const [pos2, line2] = p2\n const p1Distance = pointLineDistance(point, line1)\n const p2Distance = pointLineDistance(point, line2)\n\n return (p1Distance - p2Distance) || (pos1 - pos2)\n }\n\n let targets = getTargets()\n targets.sort(compare)\n\n // Only consider the first few targets for performance reasons.\n targets = targets.slice(0, 8)\n\n // Find the closest valid target.\n const target = targets.find(target => onDrag({ view, pos: target[0], event }) !== false)\n\n // If the dragging node is already at the target position, we ignore this\n // target. Notice that we don't pick the second better target here.\n if (target && isDraggingToItself(view, target[0])) {\n return undefined\n }\n\n return target\n }\n\n let prevPoint: Point | undefined\n let prevTarget: DropTarget | undefined\n\n const getTargetCached: GetTarget = (point, event) => {\n if (prevPoint && pointEqual(prevPoint, point)) {\n return prevTarget\n }\n\n prevPoint = point\n prevTarget = getTargetImpl(point, event)\n return prevTarget\n }\n\n return getTargetCached\n}\n\nfunction pointEqual(a: Point, b: Point) {\n return a[0] === b[0] && a[1] === b[1]\n}\n\nfunction pointPointDistance(a: Point, b: Point) {\n // Manhattan distance\n return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1])\n}\n\nfunction pointLineDistance(point: Point, line: Line) {\n // Notice that we are actually not calculating the distance between the point\n // and the line. Instead, we are calculating the distance between the point\n // and the two endpoints of the line.\n return Math.min(\n pointPointDistance(point, [line[0], line[1]]),\n pointPointDistance(point, [line[2], line[3]]),\n )\n}\n\n/**\n * Whether the dragging node is being dragged to the same position. For example,\n * dragging a list node into a new position that is just below the list node, or\n * dragging a nested quoteblock into itself.\n */\nfunction isDraggingToItself(view: EditorView, pos: number) {\n const dragging = view.dragging\n if (!dragging) return\n\n const { move } = dragging\n if (!move) return\n\n const selection = view.state.selection\n if (!isNodeSelection(selection)) return\n\n const { from, to } = selection\n return from <= pos && pos <= to\n}\n","import type { ResolvedPos } from '@prosekit/pm/model'\nimport {\n NodeSelection,\n Plugin,\n PluginKey,\n TextSelection,\n type PluginView,\n} from '@prosekit/pm/state'\nimport type { EditorView } from '@prosekit/pm/view'\n\nimport {\n buildGetTarget,\n type GetTarget,\n} from './drop-target'\nimport type {\n DragEventHandler,\n ShowHandler,\n ViewDragging,\n} from './types'\n\n/**\n * @internal\n */\ninterface DropIndicatorPluginOptions {\n onDrag: DragEventHandler\n onShow: ShowHandler\n onHide: VoidFunction\n}\n\n/**\n * @internal\n */\nexport function createDropIndicatorPlugin(options: DropIndicatorPluginOptions): Plugin {\n let getTarget: GetTarget | undefined\n\n return new Plugin({\n key: new PluginKey('prosekit-drop-indicator'),\n view: (view) => {\n getTarget = buildGetTarget(view, options.onDrag)\n return createDropIndicatorView(view, getTarget, options)\n },\n props: {\n handleDrop(view, event, slice, move): boolean {\n if (!getTarget) return false\n\n const target = getTarget([event.clientX, event.clientY], event)\n\n if (!target) return false\n\n event.preventDefault()\n let insertPos = target[0]\n\n let tr = view.state.tr\n if (move) {\n let { node } = (view.dragging as ViewDragging | null) || {}\n if (node) node.replace(tr)\n else tr.deleteSelection()\n }\n\n let pos = tr.mapping.map(insertPos)\n let isNode = slice.openStart == 0 && slice.openEnd == 0 && slice.content.childCount == 1\n let beforeInsert = tr.doc\n if (isNode) tr.replaceRangeWith(pos, pos, slice.content.firstChild!)\n else tr.replaceRange(pos, pos, slice)\n if (tr.doc.eq(beforeInsert)) {\n return true\n }\n\n let $pos = tr.doc.resolve(pos)\n if (\n isNode && NodeSelection.isSelectable(slice.content.firstChild!)\n && $pos.nodeAfter && $pos.nodeAfter.sameMarkup(slice.content.firstChild!)\n ) {\n tr.setSelection(new NodeSelection($pos))\n } else {\n let end = tr.mapping.map(insertPos)\n tr.mapping.maps[tr.mapping.maps.length - 1].forEach((_from, _to, _newFrom, newTo) => end = newTo)\n tr.setSelection(selectionBetween(view, $pos, tr.doc.resolve(end)))\n }\n view.focus()\n view.dispatch(tr.setMeta('uiEvent', 'drop'))\n return true\n },\n },\n })\n}\n\nfunction selectionBetween(view: EditorView, $anchor: ResolvedPos, $head: ResolvedPos, bias?: number) {\n return view.someProp('createSelectionBetween', f => f(view, $anchor, $head))\n || TextSelection.between($anchor, $head, bias)\n}\n\nfunction createDropIndicatorView(view: EditorView, getTarget: GetTarget, options: DropIndicatorPluginOptions): PluginView {\n let dom = view.dom\n let hideId: ReturnType<typeof setTimeout> | undefined\n let prevX: number | undefined\n let prevY: number | undefined\n let hasDragOverEvent: boolean = false\n\n const scheduleHide = () => {\n if (hideId) {\n clearTimeout(hideId)\n }\n\n hasDragOverEvent = false\n hideId = setTimeout(() => {\n if (hasDragOverEvent) return\n options.onHide()\n }, 30)\n }\n\n const handleDragOver = (event: DragEvent): void => {\n hasDragOverEvent = true\n\n const { clientX, clientY } = event\n if (prevX === clientX && prevY === clientY) {\n return\n }\n prevX = clientX\n prevY = clientY\n\n let target = getTarget([clientX, clientY], event)\n\n if (!target) {\n scheduleHide()\n return\n } else {\n const [pos, [x1, y1, x2, y2]] = target\n const line = { p1: { x: x1, y: y1 }, p2: { x: x2, y: y2 } }\n options.onShow({ view, pos, line })\n }\n }\n\n dom.addEventListener('dragover', handleDragOver)\n dom.addEventListener('dragend', scheduleHide)\n dom.addEventListener('drop', scheduleHide)\n dom.addEventListener('dragleave', scheduleHide)\n\n const destroy = () => {\n dom.removeEventListener('dragover', handleDragOver)\n dom.removeEventListener('dragend', scheduleHide)\n dom.removeEventListener('drop', scheduleHide)\n dom.removeEventListener('dragleave', scheduleHide)\n }\n\n return { destroy }\n}\n","import {\n defineFacet,\n defineFacetPayload,\n pluginFacet,\n type PlainExtension,\n type PluginPayload,\n} from '@prosekit/core'\n\nimport { createDropIndicatorPlugin } from './drop-indicator-plugin'\nimport type {\n DragEventHandler,\n ShowHandler,\n} from './types'\n\n/**\n * @internal\n */\nexport function defineDropIndicatorPayload(\n payload: DropIndicatorPayload,\n): PlainExtension {\n return defineFacetPayload(dropIndicatorFacet, [payload]) as PlainExtension\n}\n\n/**\n * @internal\n */\nexport interface DropIndicatorPayload {\n /**\n * A callback that is called when the drop indicator should be shown.\n */\n onShow?: ShowHandler\n\n /**\n * A callback that is called when the drop indicator should be hidden.\n */\n onHide?: VoidFunction\n\n /**\n * A callback that is called when the `dragover` event is fired. You can\n * return `false` to disable the current drop point and thus hide the drop\n * indicator.\n */\n onDrag?: DragEventHandler\n}\n\nconst dropIndicatorFacet = defineFacet<DropIndicatorPayload, PluginPayload>({\n parent: pluginFacet,\n singleton: true,\n reducer: (payloads: DropIndicatorPayload[]): PluginPayload => {\n let showHandlers = payloads.map(p => p.onShow).filter(x => !!x)\n let hideHandlers = payloads.map(p => p.onHide).filter(x => !!x)\n let dragHandlers = payloads.map(p => p.onDrag).filter(x => !!x)\n\n let showHandler: ShowHandler = (options) => {\n for (let fn of showHandlers) {\n fn(options)\n }\n }\n\n let hideHandler: VoidFunction = () => {\n for (let fn of hideHandlers) {\n fn()\n }\n }\n\n let dragHandler: DragEventHandler = (options): boolean => {\n for (let fn of dragHandlers) {\n if (fn(options) === false) return false\n }\n return true\n }\n\n if (showHandlers.length === 0) {\n // No `onShow` event handler, so we don't need to create a plugin.\n return []\n }\n\n return createDropIndicatorPlugin({\n onDrag: dragHandler,\n onShow: showHandler,\n onHide: hideHandler,\n })\n },\n})\n","import type { PlainExtension } from '@prosekit/core'\n\nimport {\n defineDropIndicatorPayload,\n type DropIndicatorPayload,\n} from './drop-indicator-facet'\n\n/**\n * @internal\n */\nexport type DropIndicatorExtension = PlainExtension\n\n/**\n * Defines an extension that controls the behavior of the drop indicator.\n *\n * This extension itself doesn't draw the drop indicator, but it provides the\n * necessary callbacks to do so. You probably don't want to use this extension\n * directly, but rather use the `<DropIndicator>` component.\n *\n * You can add this extension multiple times. If any extension has `onDrag`\n * callback defined, and it returns `false`, then the drop point will be\n * discarded.\n *\n * @public\n */\nexport function defineDropIndicator(\n options?: DropIndicatorOptions,\n): DropIndicatorExtension {\n return defineDropIndicatorPayload(options ?? {})\n}\n\n/**\n * Options for {@link defineDropIndicator}.\n *\n * @public\n */\nexport interface DropIndicatorOptions extends DropIndicatorPayload {}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"prosekit-extensions-file.d.ts","names":[],"sources":["../src/file/file-drop-handler.ts","../src/file/file-paste-handler.ts","../src/file/file-upload.ts"],"sourcesContent":[],"mappings":";;;;UAYiB,sBAAA;;AAAjB;;MAIQ,EAAA,UAAA;;;;EAwBI,KAAA,EAnBH,SAmBG;EAII;;;MAEb,EApBK,IAoBL;EAAc;;;;AClCjB;;;;;;AAuBA;AAIgB,KDCJ,eAAA,GCD0B,CAAA,OAAA,EDE3B,sBCF2B,EAAA,GAAA,OAAA,GAAA,IAAA;AAAA,iBDKtB,qBAAA,CCLsB,OAAA,EDM3B,eCN2B,CAAA,EDOnC,cCPmC;;;UA3BrB,uBAAA;;ADAjB;;MAIQ,ECAA,UDAA;;;;EAwBI,KAAA,ECnBH,cDmBkB;EAIX;;;MAEb,ECpBK,IDoBL;;;;;AClCH;;;AASS,KAcG,gBAAA,GAdH,CAAA,OAAA,EAeE,uBAfF,EAAA,GAAA,OAAA,GAAA,IAAA;AAKD,iBAaQ,sBAAA,CAbR,OAAA,EAcG,gBAdH,CAAA,EAeL,cAfK;;;;;;UCvBS,cAAA;EFSA,MAAA,EAAA,MAAA;EAAsB,KAAA,EAAA,MAAA;;AAS9B,UETQ,eAAA,CFSR;;;AAmBT;EAIgB,IAAA,EE5BR,IF4BQ;EAAqB;;;EAEpB,UAAA,EAAA,CAAA,QAAA,EEzBQ,cFyBR,EAAA,GAAA,IAAA;;;;AClCjB;;AAIQ,KCYI,QDZJ,CAAA,MAAA,CAAA,GAAA,CAAA,OAAA,ECYiC,eDZjC,EAAA,GCYqD,ODZrD,CCY6D,MDZ7D,CAAA;;;;AAmBI,cCFC,UDEe,CAAA,MACjB,CAAA,CAAA;EAGK;;;;;;;;ACpChB;EASiB,UAAA,IAAA,EAAA,OAAe;EAAA;;;EASO,SAAA,QAAA,EA4BlB,OA5BkB,CA4BV,MA5BU,CAAA;EAO3B,QAAA,WAAQ;EAAA;;;;;AAKpB;EAAuB,WAAA,CAAA;IAAA,IAAA;IAAA;GAAA,EAAA;IAgBM,IAAA,EAUa,IAVb;IAAR,QAAA,EAUqC,QAVrC,CAU8C,MAV9C,CAAA;;;;;mBAUqC,CAAA,QAAA,EAAA,CAAA,QAAA,EAgCjC,cAhCiC,EAAA,GAAA,IAAA,CAAA,EAiCrD,YAjCqD;;;;SA+CrD,GAAA,CAAA,SAAA,OAAA,CAAA,CAAA,SAAA,EAAA,MAAA,CAAA,EAAA,UAAA,CAAW,MAAX,CAAA,GAAA,SAAA;EAAU"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"prosekit-extensions-file.js","names":["getFiles","facet","getFiles","dropHandler: DropHandler","pasteHandler: PasteHandler"],"sources":["../src/file/helpers.ts","../src/file/file-drop-handler.ts","../src/file/file-paste-handler.ts","../src/file/file-upload.ts"],"sourcesContent":["import type { EditorView } from '@prosekit/pm/view'\n\ntype FileHandler<E extends Event> = (options: {\n view: EditorView\n event: E\n file: File\n}) => boolean | void\n\nfunction handleFile<E extends Event>(\n view: EditorView,\n event: E,\n file: File,\n handlers: FileHandler<E>[],\n) {\n // The last item in `handlers` should has the highest priority.\n for (let i = handlers.length - 1; i >= 0; i--) {\n const handler = handlers[i]\n if (handler({ view, event, file })) {\n return true\n }\n }\n return false\n}\n\nexport function handleEvent<E extends Event>(\n view: EditorView,\n event: E,\n handlers: FileHandler<E>[],\n getFiles: (event: E) => File[],\n): boolean {\n const files = getFiles(event)\n let handled = false\n for (const file of files) {\n if (handleFile(view, event, file, handlers)) {\n handled = true\n }\n }\n return handled\n}\n","import {\n defineFacet,\n defineFacetPayload,\n editorEventFacet,\n type DropHandler,\n type EditorEventPayload,\n type PlainExtension,\n} from '@prosekit/core'\nimport type { EditorView } from '@prosekit/pm/view'\n\nimport { handleEvent } from './helpers'\n\nexport interface FileDropHandlerOptions {\n /**\n * The editor view.\n */\n view: EditorView\n\n /**\n * The event that triggered the drop.\n */\n event: DragEvent\n\n /**\n * The file that was dropped.\n */\n file: File\n\n /**\n * The position of the document where the file was dropped.\n */\n pos: number\n}\n\n/**\n * A function that handles one of the files in a drop event.\n *\n * Returns `true` if the file was handled and thus should not be handled by\n * other handlers.\n */\nexport type FileDropHandler = (\n options: FileDropHandlerOptions,\n) => boolean | void\n\nexport function defineFileDropHandler(\n handler: FileDropHandler,\n): PlainExtension {\n return defineFacetPayload(facet, [handler]) as PlainExtension\n}\n\nfunction getFiles(event: DragEvent) {\n return Array.from(event.dataTransfer?.files ?? [])\n}\n\nconst facet = defineFacet<FileDropHandler, EditorEventPayload>({\n parent: editorEventFacet,\n singleton: true,\n reducer: (handlers: FileDropHandler[]): EditorEventPayload => {\n const dropHandler: DropHandler = (view, event): boolean => {\n const position = view.posAtCoords({ left: event.x, top: event.y })\n if (!position) {\n return false\n }\n const pos = position.inside > 0 ? position.inside : position.pos\n\n return handleEvent<DragEvent>(\n view,\n event,\n handlers.map((handler) => (options) => handler({ ...options, pos })),\n getFiles,\n )\n }\n return ['drop', dropHandler]\n },\n})\n","import {\n defineFacet,\n defineFacetPayload,\n editorEventFacet,\n type EditorEventPayload,\n type PasteHandler,\n type PlainExtension,\n} from '@prosekit/core'\nimport type { EditorView } from '@prosekit/pm/view'\n\nimport { handleEvent } from './helpers'\n\nexport interface FilePasteHandlerOptions {\n /**\n * The editor view.\n */\n view: EditorView\n\n /**\n * The event that triggered the paste.\n */\n event: ClipboardEvent\n\n /**\n * The file that was pasted.\n */\n file: File\n}\n\n/**\n * A function that handles one of the files in a paste event.\n *\n * Returns `true` if the file was handled and thus should not be handled by\n * other handlers.\n */\nexport type FilePasteHandler = (\n options: FilePasteHandlerOptions,\n) => boolean | void\n\nexport function defineFilePasteHandler(\n handler: FilePasteHandler,\n): PlainExtension {\n return defineFacetPayload(facet, [handler]) as PlainExtension\n}\n\nfunction getFiles(event: ClipboardEvent) {\n return Array.from(event.clipboardData?.files ?? [])\n}\n\nconst facet = defineFacet<FilePasteHandler, EditorEventPayload>({\n parent: editorEventFacet,\n singleton: true,\n reducer: (handlers: FilePasteHandler[]): EditorEventPayload => {\n const pasteHandler: PasteHandler = (view, event): boolean => {\n return handleEvent<ClipboardEvent>(view, event, handlers, getFiles)\n }\n return ['paste', pasteHandler]\n },\n})\n","/**\n * An interface representing the upload progress.\n */\nexport interface UploadProgress {\n // A number representing the amount of work already performed by the\n // underlying process.\n loaded: number\n // A number representing the total amount of work that the underlying\n // process is in the progress of performing.\n total: number\n}\n\nexport interface UploaderOptions {\n /**\n * The file to be uploaded.\n */\n file: File\n\n /**\n * A callback function that should be called with the upload progress updates.\n */\n onProgress: (progress: UploadProgress) => void\n}\n\n/**\n * The implementation of the actual upload function. You need to implement this\n * function to upload files to your desired destination.\n */\nexport type Uploader<Result> = (options: UploaderOptions) => Promise<Result>\n\n/**\n * A class that represents a upload task.\n */\nexport class UploadTask<Result> {\n /**\n * An [object URL](https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL)\n * representing the file to be uploaded. This URL will be revoked once the\n * upload is complete successfully.\n */\n readonly objectURL: string\n\n /**\n * A boolean indicating whether the upload is complete (either successfully or with an error).\n */\n protected done = false\n\n /**\n * A promise that fulfills once the upload is complete, or rejects if an error occurs.\n */\n readonly finished: Promise<Result>\n\n private subscribers: ((progress: UploadProgress) => void)[] = []\n\n /**\n * Creates a new upload task. You can find the upload task by its object URL\n * later using `UploadTask.get()`.\n *\n * @param options - The options for the upload task.\n */\n constructor({ file, uploader }: { file: File; uploader: Uploader<Result> }) {\n this.objectURL = URL.createObjectURL(file)\n this.finished = new Promise((resolve, reject) => {\n const maybePromise = uploader({\n file,\n onProgress: (progress) => {\n for (const subscriber of this.subscribers) {\n subscriber(progress)\n }\n },\n })\n Promise.resolve(maybePromise).then(\n (result) => {\n this.done = true\n URL.revokeObjectURL(this.objectURL)\n resolve(result)\n },\n (error) => {\n this.done = true\n reject(\n new Error('[prosekit] Failed to upload file', { cause: error }),\n )\n },\n )\n })\n store.set(this.objectURL, this)\n }\n\n /**\n * Subscribes to progress updates. Returns a function to unsubscribe.\n */\n public subscribeProgress(\n callback: (progress: UploadProgress) => void,\n ): VoidFunction {\n this.subscribers.push(callback)\n return () => {\n this.subscribers = this.subscribers.filter(\n (subscriber) => subscriber !== callback,\n )\n }\n }\n\n /**\n * Finds an upload task by its object URL.\n */\n static get<Result = unknown>(\n objectURL: string,\n ): UploadTask<Result> | undefined {\n return store.get(objectURL) as UploadTask<Result> | undefined\n }\n\n /**\n * Deletes an upload task by its object URL.\n */\n static delete(objectURL: string): void {\n store.delete(objectURL)\n }\n}\n\nconst store = new Map<string, UploadTask<unknown>>()\n"],"mappings":";;;AAQA,SAAS,WACP,MACA,OACA,MACA,UACA;AAEA,MAAK,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;EAC7C,MAAM,UAAU,SAAS;AACzB,MAAI,QAAQ;GAAE;GAAM;GAAO;GAAM,CAAC,CAChC,QAAO;;AAGX,QAAO;;AAGT,SAAgB,YACd,MACA,OACA,UACA,YACS;CACT,MAAM,QAAQA,WAAS,MAAM;CAC7B,IAAI,UAAU;AACd,MAAK,MAAM,QAAQ,MACjB,KAAI,WAAW,MAAM,OAAO,MAAM,SAAS,CACzC,WAAU;AAGd,QAAO;;;;;ACOT,SAAgB,sBACd,SACgB;AAChB,QAAO,mBAAmBC,SAAO,CAAC,QAAQ,CAAC;;AAG7C,SAASC,WAAS,OAAkB;AAClC,QAAO,MAAM,KAAK,MAAM,cAAc,SAAS,EAAE,CAAC;;AAGpD,MAAMD,UAAQ,YAAiD;CAC7D,QAAQ;CACR,WAAW;CACX,UAAU,aAAoD;EAC5D,MAAME,eAA4B,MAAM,UAAmB;GACzD,MAAM,WAAW,KAAK,YAAY;IAAE,MAAM,MAAM;IAAG,KAAK,MAAM;IAAG,CAAC;AAClE,OAAI,CAAC,SACH,QAAO;GAET,MAAM,MAAM,SAAS,SAAS,IAAI,SAAS,SAAS,SAAS;AAE7D,UAAO,YACL,MACA,OACA,SAAS,KAAK,aAAa,YAAY,QAAQ;IAAE,GAAG;IAAS;IAAK,CAAC,CAAC,EACpED,WACD;;AAEH,SAAO,CAAC,QAAQ,YAAY;;CAE/B,CAAC;;;;ACnCF,SAAgB,uBACd,SACgB;AAChB,QAAO,mBAAmB,OAAO,CAAC,QAAQ,CAAC;;AAG7C,SAAS,SAAS,OAAuB;AACvC,QAAO,MAAM,KAAK,MAAM,eAAe,SAAS,EAAE,CAAC;;AAGrD,MAAM,QAAQ,YAAkD;CAC9D,QAAQ;CACR,WAAW;CACX,UAAU,aAAqD;EAC7D,MAAME,gBAA8B,MAAM,UAAmB;AAC3D,UAAO,YAA4B,MAAM,OAAO,UAAU,SAAS;;AAErE,SAAO,CAAC,SAAS,aAAa;;CAEjC,CAAC;;;;;;;ACzBF,IAAa,aAAb,MAAgC;;;;;;;CA0B9B,YAAY,EAAE,MAAM,YAAwD;cAf3D;qBAO6C,EAAE;AAS9D,OAAK,YAAY,IAAI,gBAAgB,KAAK;AAC1C,OAAK,WAAW,IAAI,SAAS,SAAS,WAAW;GAC/C,MAAM,eAAe,SAAS;IAC5B;IACA,aAAa,aAAa;AACxB,UAAK,MAAM,cAAc,KAAK,YAC5B,YAAW,SAAS;;IAGzB,CAAC;AACF,WAAQ,QAAQ,aAAa,CAAC,MAC3B,WAAW;AACV,SAAK,OAAO;AACZ,QAAI,gBAAgB,KAAK,UAAU;AACnC,YAAQ,OAAO;OAEhB,UAAU;AACT,SAAK,OAAO;AACZ,WACE,IAAI,MAAM,oCAAoC,EAAE,OAAO,OAAO,CAAC,CAChE;KAEJ;IACD;AACF,QAAM,IAAI,KAAK,WAAW,KAAK;;;;;CAMjC,AAAO,kBACL,UACc;AACd,OAAK,YAAY,KAAK,SAAS;AAC/B,eAAa;AACX,QAAK,cAAc,KAAK,YAAY,QACjC,eAAe,eAAe,SAChC;;;;;;CAOL,OAAO,IACL,WACgC;AAChC,SAAO,MAAM,IAAI,UAAU;;;;;CAM7B,OAAO,OAAO,WAAyB;AACrC,QAAM,OAAO,UAAU;;;AAI3B,MAAM,wBAAQ,IAAI,KAAkC"}
@@ -1,147 +0,0 @@
1
- import type { ResolvedPos } from '@prosekit/pm/model'
2
- import {
3
- NodeSelection,
4
- Plugin,
5
- PluginKey,
6
- TextSelection,
7
- type PluginView,
8
- } from '@prosekit/pm/state'
9
- import type { EditorView } from '@prosekit/pm/view'
10
-
11
- import {
12
- buildGetTarget,
13
- type GetTarget,
14
- } from './drop-target'
15
- import type {
16
- DragEventHandler,
17
- ShowHandler,
18
- ViewDragging,
19
- } from './types'
20
-
21
- /**
22
- * @internal
23
- */
24
- interface DropIndicatorPluginOptions {
25
- onDrag: DragEventHandler
26
- onShow: ShowHandler
27
- onHide: VoidFunction
28
- }
29
-
30
- /**
31
- * @internal
32
- */
33
- export function createDropIndicatorPlugin(options: DropIndicatorPluginOptions): Plugin {
34
- let getTarget: GetTarget | undefined
35
-
36
- return new Plugin({
37
- key: new PluginKey('prosekit-drop-indicator'),
38
- view: (view) => {
39
- getTarget = buildGetTarget(view, options.onDrag)
40
- return createDropIndicatorView(view, getTarget, options)
41
- },
42
- props: {
43
- handleDrop(view, event, slice, move): boolean {
44
- if (!getTarget) return false
45
-
46
- const target = getTarget([event.clientX, event.clientY], event)
47
-
48
- if (!target) return false
49
-
50
- event.preventDefault()
51
- let insertPos = target[0]
52
-
53
- let tr = view.state.tr
54
- if (move) {
55
- let { node } = (view.dragging as ViewDragging | null) || {}
56
- if (node) node.replace(tr)
57
- else tr.deleteSelection()
58
- }
59
-
60
- let pos = tr.mapping.map(insertPos)
61
- let isNode = slice.openStart == 0 && slice.openEnd == 0 && slice.content.childCount == 1
62
- let beforeInsert = tr.doc
63
- if (isNode) tr.replaceRangeWith(pos, pos, slice.content.firstChild!)
64
- else tr.replaceRange(pos, pos, slice)
65
- if (tr.doc.eq(beforeInsert)) {
66
- return true
67
- }
68
-
69
- let $pos = tr.doc.resolve(pos)
70
- if (
71
- isNode && NodeSelection.isSelectable(slice.content.firstChild!)
72
- && $pos.nodeAfter && $pos.nodeAfter.sameMarkup(slice.content.firstChild!)
73
- ) {
74
- tr.setSelection(new NodeSelection($pos))
75
- } else {
76
- let end = tr.mapping.map(insertPos)
77
- tr.mapping.maps[tr.mapping.maps.length - 1].forEach((_from, _to, _newFrom, newTo) => end = newTo)
78
- tr.setSelection(selectionBetween(view, $pos, tr.doc.resolve(end)))
79
- }
80
- view.focus()
81
- view.dispatch(tr.setMeta('uiEvent', 'drop'))
82
- return true
83
- },
84
- },
85
- })
86
- }
87
-
88
- function selectionBetween(view: EditorView, $anchor: ResolvedPos, $head: ResolvedPos, bias?: number) {
89
- return view.someProp('createSelectionBetween', f => f(view, $anchor, $head))
90
- || TextSelection.between($anchor, $head, bias)
91
- }
92
-
93
- function createDropIndicatorView(view: EditorView, getTarget: GetTarget, options: DropIndicatorPluginOptions): PluginView {
94
- let dom = view.dom
95
- let hideId: ReturnType<typeof setTimeout> | undefined
96
- let prevX: number | undefined
97
- let prevY: number | undefined
98
- let hasDragOverEvent: boolean = false
99
-
100
- const scheduleHide = () => {
101
- if (hideId) {
102
- clearTimeout(hideId)
103
- }
104
-
105
- hasDragOverEvent = false
106
- hideId = setTimeout(() => {
107
- if (hasDragOverEvent) return
108
- options.onHide()
109
- }, 30)
110
- }
111
-
112
- const handleDragOver = (event: DragEvent): void => {
113
- hasDragOverEvent = true
114
-
115
- const { clientX, clientY } = event
116
- if (prevX === clientX && prevY === clientY) {
117
- return
118
- }
119
- prevX = clientX
120
- prevY = clientY
121
-
122
- let target = getTarget([clientX, clientY], event)
123
-
124
- if (!target) {
125
- scheduleHide()
126
- return
127
- } else {
128
- const [pos, [x1, y1, x2, y2]] = target
129
- const line = { p1: { x: x1, y: y1 }, p2: { x: x2, y: y2 } }
130
- options.onShow({ view, pos, line })
131
- }
132
- }
133
-
134
- dom.addEventListener('dragover', handleDragOver)
135
- dom.addEventListener('dragend', scheduleHide)
136
- dom.addEventListener('drop', scheduleHide)
137
- dom.addEventListener('dragleave', scheduleHide)
138
-
139
- const destroy = () => {
140
- dom.removeEventListener('dragover', handleDragOver)
141
- dom.removeEventListener('dragend', scheduleHide)
142
- dom.removeEventListener('drop', scheduleHide)
143
- dom.removeEventListener('dragleave', scheduleHide)
144
- }
145
-
146
- return { destroy }
147
- }
@@ -1,168 +0,0 @@
1
- import { isHTMLElement } from '@ocavue/utils'
2
- import { isNodeSelection } from '@prosekit/core'
3
- import type { ProseMirrorNode } from '@prosekit/pm/model'
4
- import type { EditorView } from '@prosekit/pm/view'
5
-
6
- import type { DragEventHandler } from './types'
7
-
8
- type Point = readonly [x: number, y: number]
9
-
10
- type Line = readonly [x1: number, y1: number, x2: number, y2: number]
11
-
12
- /**
13
- * @internal
14
- */
15
- type DropTarget = readonly [pos: number, line: Line]
16
-
17
- function getTargetsByView(view: EditorView): DropTarget[] {
18
- type StackItem = [pos: number, node: ProseMirrorNode]
19
- let stack: StackItem[] = [[-1, view.state.doc]]
20
- let targets: DropTarget[] = []
21
-
22
- while (stack.length > 0) {
23
- const [pos, node] = stack.pop()!
24
- if (pos >= 0) {
25
- let dom = view.nodeDOM(pos)
26
- if (dom && isHTMLElement(dom)) {
27
- let rect = dom.getBoundingClientRect()
28
- let { top, bottom, left: x1, right: x2 } = rect
29
- targets.push(
30
- [pos, [x1, top, x2, top]],
31
- [pos + node.nodeSize, [x1, bottom, x2, bottom]],
32
- )
33
- }
34
- }
35
- if (node.isBlock && !node.isTextblock) {
36
- let childPos = pos + 1
37
- for (let child of node.children) {
38
- stack.push([childPos, child])
39
- childPos += child.nodeSize
40
- }
41
- }
42
- }
43
-
44
- return targets
45
- }
46
-
47
- /**
48
- * @internal
49
- */
50
- export type GetTarget = (point: Point, event: DragEvent) => DropTarget | undefined
51
-
52
- /**
53
- * @internal
54
- */
55
- export function buildGetTarget(
56
- view: EditorView,
57
- onDrag: DragEventHandler,
58
- ): GetTarget {
59
- let prevTargets: DropTarget[] = []
60
- let prevDoc: ProseMirrorNode | undefined
61
- let prevRect: DOMRect | undefined
62
-
63
- const getTargets = (): DropTarget[] => {
64
- const rect = view.dom.getBoundingClientRect()
65
- const doc = view.state.doc
66
-
67
- if (
68
- prevTargets && prevDoc && prevRect
69
- && rect.width === prevRect.width
70
- && rect.height === prevRect.height
71
- && rect.x === prevRect.x
72
- && rect.y === prevRect.y
73
- && prevDoc.eq(doc)
74
- ) {
75
- return prevTargets
76
- }
77
-
78
- prevRect = rect
79
- prevDoc = doc
80
- prevTargets = getTargetsByView(view)
81
- return prevTargets
82
- }
83
-
84
- const getTargetImpl: GetTarget = (point, event) => {
85
- if (!view.editable || view.isDestroyed) {
86
- return
87
- }
88
-
89
- const compare = (p1: DropTarget, p2: DropTarget): number => {
90
- const [pos1, line1] = p1
91
- const [pos2, line2] = p2
92
- const p1Distance = pointLineDistance(point, line1)
93
- const p2Distance = pointLineDistance(point, line2)
94
-
95
- return (p1Distance - p2Distance) || (pos1 - pos2)
96
- }
97
-
98
- let targets = getTargets()
99
- targets.sort(compare)
100
-
101
- // Only consider the first few targets for performance reasons.
102
- targets = targets.slice(0, 8)
103
-
104
- // Find the closest valid target.
105
- const target = targets.find(target => onDrag({ view, pos: target[0], event }) !== false)
106
-
107
- // If the dragging node is already at the target position, we ignore this
108
- // target. Notice that we don't pick the second better target here.
109
- if (target && isDraggingToItself(view, target[0])) {
110
- return undefined
111
- }
112
-
113
- return target
114
- }
115
-
116
- let prevPoint: Point | undefined
117
- let prevTarget: DropTarget | undefined
118
-
119
- const getTargetCached: GetTarget = (point, event) => {
120
- if (prevPoint && pointEqual(prevPoint, point)) {
121
- return prevTarget
122
- }
123
-
124
- prevPoint = point
125
- prevTarget = getTargetImpl(point, event)
126
- return prevTarget
127
- }
128
-
129
- return getTargetCached
130
- }
131
-
132
- function pointEqual(a: Point, b: Point) {
133
- return a[0] === b[0] && a[1] === b[1]
134
- }
135
-
136
- function pointPointDistance(a: Point, b: Point) {
137
- // Manhattan distance
138
- return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1])
139
- }
140
-
141
- function pointLineDistance(point: Point, line: Line) {
142
- // Notice that we are actually not calculating the distance between the point
143
- // and the line. Instead, we are calculating the distance between the point
144
- // and the two endpoints of the line.
145
- return Math.min(
146
- pointPointDistance(point, [line[0], line[1]]),
147
- pointPointDistance(point, [line[2], line[3]]),
148
- )
149
- }
150
-
151
- /**
152
- * Whether the dragging node is being dragged to the same position. For example,
153
- * dragging a list node into a new position that is just below the list node, or
154
- * dragging a nested quoteblock into itself.
155
- */
156
- function isDraggingToItself(view: EditorView, pos: number) {
157
- const dragging = view.dragging
158
- if (!dragging) return
159
-
160
- const { move } = dragging
161
- if (!move) return
162
-
163
- const selection = view.state.selection
164
- if (!isNodeSelection(selection)) return
165
-
166
- const { from, to } = selection
167
- return from <= pos && pos <= to
168
- }