@tiptap/vue-3 3.20.2 → 3.20.3

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.
@@ -1,868 +0,0 @@
1
- // ../extension-bubble-menu/src/bubble-menu-plugin.ts
2
- import {
3
- arrow,
4
- autoPlacement,
5
- computePosition,
6
- flip,
7
- hide,
8
- inline,
9
- offset,
10
- shift,
11
- size
12
- } from "@floating-ui/dom";
13
- import { isTextSelection, posToDOMRect } from "@tiptap/core";
14
- import { NodeSelection, Plugin, PluginKey } from "@tiptap/pm/state";
15
- import { CellSelection } from "@tiptap/pm/tables";
16
- function combineDOMRects(rect1, rect2) {
17
- const top = Math.min(rect1.top, rect2.top);
18
- const bottom = Math.max(rect1.bottom, rect2.bottom);
19
- const left = Math.min(rect1.left, rect2.left);
20
- const right = Math.max(rect1.right, rect2.right);
21
- const width = right - left;
22
- const height = bottom - top;
23
- const x = left;
24
- const y = top;
25
- return new DOMRect(x, y, width, height);
26
- }
27
- var BubbleMenuView = class {
28
- constructor({
29
- editor,
30
- element,
31
- view,
32
- pluginKey = "bubbleMenu",
33
- updateDelay = 250,
34
- resizeDelay = 60,
35
- shouldShow,
36
- appendTo,
37
- getReferencedVirtualElement,
38
- options
39
- }) {
40
- this.preventHide = false;
41
- this.isVisible = false;
42
- this.scrollTarget = window;
43
- this.floatingUIOptions = {
44
- strategy: "absolute",
45
- placement: "top",
46
- offset: 8,
47
- flip: {},
48
- shift: {},
49
- arrow: false,
50
- size: false,
51
- autoPlacement: false,
52
- hide: false,
53
- inline: false,
54
- onShow: void 0,
55
- onHide: void 0,
56
- onUpdate: void 0,
57
- onDestroy: void 0
58
- };
59
- this.shouldShow = ({ view, state, from, to }) => {
60
- const { doc, selection } = state;
61
- const { empty } = selection;
62
- const isEmptyTextBlock = !doc.textBetween(from, to).length && isTextSelection(state.selection);
63
- const isChildOfMenu = this.element.contains(document.activeElement);
64
- const hasEditorFocus = view.hasFocus() || isChildOfMenu;
65
- if (!hasEditorFocus || empty || isEmptyTextBlock || !this.editor.isEditable) {
66
- return false;
67
- }
68
- return true;
69
- };
70
- this.mousedownHandler = () => {
71
- this.preventHide = true;
72
- };
73
- this.dragstartHandler = () => {
74
- this.hide();
75
- };
76
- /**
77
- * Handles the window resize event to update the position of the bubble menu.
78
- * It uses a debounce mechanism to prevent excessive updates.
79
- * The delay is defined by the `resizeDelay` property.
80
- */
81
- this.resizeHandler = () => {
82
- if (this.resizeDebounceTimer) {
83
- clearTimeout(this.resizeDebounceTimer);
84
- }
85
- this.resizeDebounceTimer = window.setTimeout(() => {
86
- this.updatePosition();
87
- }, this.resizeDelay);
88
- };
89
- this.focusHandler = () => {
90
- setTimeout(() => this.update(this.editor.view));
91
- };
92
- this.blurHandler = ({ event }) => {
93
- var _a;
94
- if (this.editor.isDestroyed) {
95
- this.destroy();
96
- return;
97
- }
98
- if (this.preventHide) {
99
- this.preventHide = false;
100
- return;
101
- }
102
- if ((event == null ? void 0 : event.relatedTarget) && ((_a = this.element.parentNode) == null ? void 0 : _a.contains(event.relatedTarget))) {
103
- return;
104
- }
105
- if ((event == null ? void 0 : event.relatedTarget) === this.editor.view.dom) {
106
- return;
107
- }
108
- this.hide();
109
- };
110
- this.handleDebouncedUpdate = (view, oldState) => {
111
- const selectionChanged = !(oldState == null ? void 0 : oldState.selection.eq(view.state.selection));
112
- const docChanged = !(oldState == null ? void 0 : oldState.doc.eq(view.state.doc));
113
- if (!selectionChanged && !docChanged) {
114
- return;
115
- }
116
- if (this.updateDebounceTimer) {
117
- clearTimeout(this.updateDebounceTimer);
118
- }
119
- this.updateDebounceTimer = window.setTimeout(() => {
120
- this.updateHandler(view, selectionChanged, docChanged, oldState);
121
- }, this.updateDelay);
122
- };
123
- this.updateHandler = (view, selectionChanged, docChanged, oldState) => {
124
- const { composing } = view;
125
- const isSame = !selectionChanged && !docChanged;
126
- if (composing || isSame) {
127
- return;
128
- }
129
- const shouldShow = this.getShouldShow(oldState);
130
- if (!shouldShow) {
131
- this.hide();
132
- return;
133
- }
134
- this.updatePosition();
135
- this.show();
136
- };
137
- /**
138
- * Handles the transaction event to update the position of the bubble menu.
139
- * This allows external code to trigger a position update via:
140
- * `editor.view.dispatch(editor.state.tr.setMeta(pluginKey, 'updatePosition'))`
141
- * The `pluginKey` defaults to `bubbleMenu`
142
- */
143
- this.transactionHandler = ({ transaction: tr }) => {
144
- const meta = tr.getMeta(this.pluginKey);
145
- if (meta === "updatePosition") {
146
- this.updatePosition();
147
- } else if (meta && typeof meta === "object" && meta.type === "updateOptions") {
148
- this.updateOptions(meta.options);
149
- }
150
- };
151
- var _a;
152
- this.editor = editor;
153
- this.element = element;
154
- this.view = view;
155
- this.pluginKey = pluginKey;
156
- this.updateDelay = updateDelay;
157
- this.resizeDelay = resizeDelay;
158
- this.appendTo = appendTo;
159
- this.scrollTarget = (_a = options == null ? void 0 : options.scrollTarget) != null ? _a : window;
160
- this.getReferencedVirtualElement = getReferencedVirtualElement;
161
- this.floatingUIOptions = {
162
- ...this.floatingUIOptions,
163
- ...options
164
- };
165
- this.element.tabIndex = 0;
166
- if (shouldShow) {
167
- this.shouldShow = shouldShow;
168
- }
169
- this.element.addEventListener("mousedown", this.mousedownHandler, { capture: true });
170
- this.view.dom.addEventListener("dragstart", this.dragstartHandler);
171
- this.editor.on("focus", this.focusHandler);
172
- this.editor.on("blur", this.blurHandler);
173
- this.editor.on("transaction", this.transactionHandler);
174
- window.addEventListener("resize", this.resizeHandler);
175
- this.scrollTarget.addEventListener("scroll", this.resizeHandler);
176
- this.update(view, view.state);
177
- if (this.getShouldShow()) {
178
- this.show();
179
- this.updatePosition();
180
- }
181
- }
182
- get middlewares() {
183
- const middlewares = [];
184
- if (this.floatingUIOptions.flip) {
185
- middlewares.push(flip(typeof this.floatingUIOptions.flip !== "boolean" ? this.floatingUIOptions.flip : void 0));
186
- }
187
- if (this.floatingUIOptions.shift) {
188
- middlewares.push(
189
- shift(typeof this.floatingUIOptions.shift !== "boolean" ? this.floatingUIOptions.shift : void 0)
190
- );
191
- }
192
- if (this.floatingUIOptions.offset) {
193
- middlewares.push(
194
- offset(typeof this.floatingUIOptions.offset !== "boolean" ? this.floatingUIOptions.offset : void 0)
195
- );
196
- }
197
- if (this.floatingUIOptions.arrow) {
198
- middlewares.push(arrow(this.floatingUIOptions.arrow));
199
- }
200
- if (this.floatingUIOptions.size) {
201
- middlewares.push(size(typeof this.floatingUIOptions.size !== "boolean" ? this.floatingUIOptions.size : void 0));
202
- }
203
- if (this.floatingUIOptions.autoPlacement) {
204
- middlewares.push(
205
- autoPlacement(
206
- typeof this.floatingUIOptions.autoPlacement !== "boolean" ? this.floatingUIOptions.autoPlacement : void 0
207
- )
208
- );
209
- }
210
- if (this.floatingUIOptions.hide) {
211
- middlewares.push(hide(typeof this.floatingUIOptions.hide !== "boolean" ? this.floatingUIOptions.hide : void 0));
212
- }
213
- if (this.floatingUIOptions.inline) {
214
- middlewares.push(
215
- inline(typeof this.floatingUIOptions.inline !== "boolean" ? this.floatingUIOptions.inline : void 0)
216
- );
217
- }
218
- return middlewares;
219
- }
220
- get virtualElement() {
221
- var _a, _b, _c;
222
- const { selection } = this.editor.state;
223
- const referencedVirtualElement = (_a = this.getReferencedVirtualElement) == null ? void 0 : _a.call(this);
224
- if (referencedVirtualElement) {
225
- return referencedVirtualElement;
226
- }
227
- if (!((_c = (_b = this.view) == null ? void 0 : _b.dom) == null ? void 0 : _c.parentNode)) {
228
- return;
229
- }
230
- const domRect = posToDOMRect(this.view, selection.from, selection.to);
231
- let virtualElement = {
232
- getBoundingClientRect: () => domRect,
233
- getClientRects: () => [domRect]
234
- };
235
- if (selection instanceof NodeSelection) {
236
- let node = this.view.nodeDOM(selection.from);
237
- const nodeViewWrapper = node.dataset.nodeViewWrapper ? node : node.querySelector("[data-node-view-wrapper]");
238
- if (nodeViewWrapper) {
239
- node = nodeViewWrapper;
240
- }
241
- if (node) {
242
- virtualElement = {
243
- getBoundingClientRect: () => node.getBoundingClientRect(),
244
- getClientRects: () => [node.getBoundingClientRect()]
245
- };
246
- }
247
- }
248
- if (selection instanceof CellSelection) {
249
- const { $anchorCell, $headCell } = selection;
250
- const from = $anchorCell ? $anchorCell.pos : $headCell.pos;
251
- const to = $headCell ? $headCell.pos : $anchorCell.pos;
252
- const fromDOM = this.view.nodeDOM(from);
253
- const toDOM = this.view.nodeDOM(to);
254
- if (!fromDOM || !toDOM) {
255
- return;
256
- }
257
- const clientRect = fromDOM === toDOM ? fromDOM.getBoundingClientRect() : combineDOMRects(
258
- fromDOM.getBoundingClientRect(),
259
- toDOM.getBoundingClientRect()
260
- );
261
- virtualElement = {
262
- getBoundingClientRect: () => clientRect,
263
- getClientRects: () => [clientRect]
264
- };
265
- }
266
- return virtualElement;
267
- }
268
- updatePosition() {
269
- const virtualElement = this.virtualElement;
270
- if (!virtualElement) {
271
- return;
272
- }
273
- computePosition(virtualElement, this.element, {
274
- placement: this.floatingUIOptions.placement,
275
- strategy: this.floatingUIOptions.strategy,
276
- middleware: this.middlewares
277
- }).then(({ x, y, strategy, middlewareData }) => {
278
- var _a, _b;
279
- if (((_a = middlewareData.hide) == null ? void 0 : _a.referenceHidden) || ((_b = middlewareData.hide) == null ? void 0 : _b.escaped)) {
280
- this.element.style.visibility = "hidden";
281
- return;
282
- }
283
- this.element.style.visibility = "visible";
284
- this.element.style.width = "max-content";
285
- this.element.style.position = strategy;
286
- this.element.style.left = `${x}px`;
287
- this.element.style.top = `${y}px`;
288
- if (this.isVisible && this.floatingUIOptions.onUpdate) {
289
- this.floatingUIOptions.onUpdate();
290
- }
291
- });
292
- }
293
- update(view, oldState) {
294
- const { state } = view;
295
- const hasValidSelection = state.selection.from !== state.selection.to;
296
- if (this.updateDelay > 0 && hasValidSelection) {
297
- this.handleDebouncedUpdate(view, oldState);
298
- return;
299
- }
300
- const selectionChanged = !(oldState == null ? void 0 : oldState.selection.eq(view.state.selection));
301
- const docChanged = !(oldState == null ? void 0 : oldState.doc.eq(view.state.doc));
302
- this.updateHandler(view, selectionChanged, docChanged, oldState);
303
- }
304
- getShouldShow(oldState) {
305
- var _a;
306
- const { state } = this.view;
307
- const { selection } = state;
308
- const { ranges } = selection;
309
- const from = Math.min(...ranges.map((range) => range.$from.pos));
310
- const to = Math.max(...ranges.map((range) => range.$to.pos));
311
- const shouldShow = (_a = this.shouldShow) == null ? void 0 : _a.call(this, {
312
- editor: this.editor,
313
- element: this.element,
314
- view: this.view,
315
- state,
316
- oldState,
317
- from,
318
- to
319
- });
320
- return shouldShow || false;
321
- }
322
- show() {
323
- var _a;
324
- if (this.isVisible) {
325
- return;
326
- }
327
- this.element.style.visibility = "visible";
328
- this.element.style.opacity = "1";
329
- const appendToElement = typeof this.appendTo === "function" ? this.appendTo() : this.appendTo;
330
- (_a = appendToElement != null ? appendToElement : this.view.dom.parentElement) == null ? void 0 : _a.appendChild(this.element);
331
- if (this.floatingUIOptions.onShow) {
332
- this.floatingUIOptions.onShow();
333
- }
334
- this.isVisible = true;
335
- }
336
- hide() {
337
- if (!this.isVisible) {
338
- return;
339
- }
340
- this.element.style.visibility = "hidden";
341
- this.element.style.opacity = "0";
342
- this.element.remove();
343
- if (this.floatingUIOptions.onHide) {
344
- this.floatingUIOptions.onHide();
345
- }
346
- this.isVisible = false;
347
- }
348
- updateOptions(newProps) {
349
- var _a;
350
- if (newProps.updateDelay !== void 0) {
351
- this.updateDelay = newProps.updateDelay;
352
- }
353
- if (newProps.resizeDelay !== void 0) {
354
- this.resizeDelay = newProps.resizeDelay;
355
- }
356
- if (newProps.appendTo !== void 0) {
357
- this.appendTo = newProps.appendTo;
358
- }
359
- if (newProps.getReferencedVirtualElement !== void 0) {
360
- this.getReferencedVirtualElement = newProps.getReferencedVirtualElement;
361
- }
362
- if (newProps.shouldShow !== void 0) {
363
- if (newProps.shouldShow) {
364
- this.shouldShow = newProps.shouldShow;
365
- }
366
- }
367
- if (newProps.options !== void 0) {
368
- const newScrollTarget = (_a = newProps.options.scrollTarget) != null ? _a : window;
369
- if (newScrollTarget !== this.scrollTarget) {
370
- this.scrollTarget.removeEventListener("scroll", this.resizeHandler);
371
- this.scrollTarget = newScrollTarget;
372
- this.scrollTarget.addEventListener("scroll", this.resizeHandler);
373
- }
374
- this.floatingUIOptions = {
375
- ...this.floatingUIOptions,
376
- ...newProps.options
377
- };
378
- }
379
- }
380
- destroy() {
381
- this.hide();
382
- this.element.removeEventListener("mousedown", this.mousedownHandler, { capture: true });
383
- this.view.dom.removeEventListener("dragstart", this.dragstartHandler);
384
- window.removeEventListener("resize", this.resizeHandler);
385
- this.scrollTarget.removeEventListener("scroll", this.resizeHandler);
386
- this.editor.off("focus", this.focusHandler);
387
- this.editor.off("blur", this.blurHandler);
388
- this.editor.off("transaction", this.transactionHandler);
389
- if (this.floatingUIOptions.onDestroy) {
390
- this.floatingUIOptions.onDestroy();
391
- }
392
- }
393
- };
394
- var BubbleMenuPlugin = (options) => {
395
- return new Plugin({
396
- key: typeof options.pluginKey === "string" ? new PluginKey(options.pluginKey) : options.pluginKey,
397
- view: (view) => new BubbleMenuView({ view, ...options })
398
- });
399
- };
400
-
401
- // src/menus/BubbleMenu.ts
402
- import { defineComponent, h, nextTick, onBeforeUnmount, onMounted, ref } from "vue";
403
- var BubbleMenu = defineComponent({
404
- name: "BubbleMenu",
405
- inheritAttrs: false,
406
- props: {
407
- pluginKey: {
408
- type: [String, Object],
409
- default: "bubbleMenu"
410
- },
411
- editor: {
412
- type: Object,
413
- required: true
414
- },
415
- updateDelay: {
416
- type: Number,
417
- default: void 0
418
- },
419
- resizeDelay: {
420
- type: Number,
421
- default: void 0
422
- },
423
- options: {
424
- type: Object,
425
- default: () => ({})
426
- },
427
- appendTo: {
428
- type: [Object, Function],
429
- default: void 0
430
- },
431
- shouldShow: {
432
- type: Function,
433
- default: null
434
- },
435
- getReferencedVirtualElement: {
436
- type: Function,
437
- default: void 0
438
- }
439
- },
440
- setup(props, { slots, attrs }) {
441
- const root = ref(null);
442
- onMounted(() => {
443
- const {
444
- editor,
445
- options,
446
- pluginKey,
447
- resizeDelay,
448
- appendTo,
449
- shouldShow,
450
- getReferencedVirtualElement,
451
- updateDelay
452
- } = props;
453
- const el = root.value;
454
- if (!el) {
455
- return;
456
- }
457
- el.style.visibility = "hidden";
458
- el.style.position = "absolute";
459
- el.remove();
460
- nextTick(() => {
461
- editor.registerPlugin(
462
- BubbleMenuPlugin({
463
- editor,
464
- element: el,
465
- options,
466
- pluginKey,
467
- resizeDelay,
468
- appendTo,
469
- shouldShow,
470
- getReferencedVirtualElement,
471
- updateDelay
472
- })
473
- );
474
- });
475
- });
476
- onBeforeUnmount(() => {
477
- const { pluginKey, editor } = props;
478
- editor.unregisterPlugin(pluginKey);
479
- });
480
- return () => {
481
- var _a;
482
- return h("div", { ref: root, ...attrs }, (_a = slots.default) == null ? void 0 : _a.call(slots));
483
- };
484
- }
485
- });
486
-
487
- // ../extension-floating-menu/src/floating-menu-plugin.ts
488
- import {
489
- arrow as arrow2,
490
- autoPlacement as autoPlacement2,
491
- computePosition as computePosition2,
492
- flip as flip2,
493
- hide as hide2,
494
- inline as inline2,
495
- offset as offset2,
496
- shift as shift2,
497
- size as size2
498
- } from "@floating-ui/dom";
499
- import { getText, getTextSerializersFromSchema, posToDOMRect as posToDOMRect2 } from "@tiptap/core";
500
- import { Plugin as Plugin2, PluginKey as PluginKey2 } from "@tiptap/pm/state";
501
- var FloatingMenuView = class {
502
- constructor({
503
- editor,
504
- element,
505
- view,
506
- pluginKey = "floatingMenu",
507
- updateDelay = 250,
508
- resizeDelay = 60,
509
- options,
510
- appendTo,
511
- shouldShow
512
- }) {
513
- this.preventHide = false;
514
- this.isVisible = false;
515
- this.scrollTarget = window;
516
- this.shouldShow = ({ view, state }) => {
517
- const { selection } = state;
518
- const { $anchor, empty } = selection;
519
- const isRootDepth = $anchor.depth === 1;
520
- const isEmptyTextBlock = $anchor.parent.isTextblock && !$anchor.parent.type.spec.code && !$anchor.parent.textContent && $anchor.parent.childCount === 0 && !this.getTextContent($anchor.parent);
521
- if (!view.hasFocus() || !empty || !isRootDepth || !isEmptyTextBlock || !this.editor.isEditable) {
522
- return false;
523
- }
524
- return true;
525
- };
526
- this.floatingUIOptions = {
527
- strategy: "absolute",
528
- placement: "right",
529
- offset: 8,
530
- flip: {},
531
- shift: {},
532
- arrow: false,
533
- size: false,
534
- autoPlacement: false,
535
- hide: false,
536
- inline: false
537
- };
538
- this.updateHandler = (view, selectionChanged, docChanged, oldState) => {
539
- const { composing } = view;
540
- const isSame = !selectionChanged && !docChanged;
541
- if (composing || isSame) {
542
- return;
543
- }
544
- const shouldShow = this.getShouldShow(oldState);
545
- if (!shouldShow) {
546
- this.hide();
547
- return;
548
- }
549
- this.updatePosition();
550
- this.show();
551
- };
552
- this.mousedownHandler = () => {
553
- this.preventHide = true;
554
- };
555
- this.focusHandler = () => {
556
- setTimeout(() => this.update(this.editor.view));
557
- };
558
- this.blurHandler = ({ event }) => {
559
- var _a;
560
- if (this.preventHide) {
561
- this.preventHide = false;
562
- return;
563
- }
564
- if ((event == null ? void 0 : event.relatedTarget) && ((_a = this.element.parentNode) == null ? void 0 : _a.contains(event.relatedTarget))) {
565
- return;
566
- }
567
- if ((event == null ? void 0 : event.relatedTarget) === this.editor.view.dom) {
568
- return;
569
- }
570
- this.hide();
571
- };
572
- /**
573
- * Handles the transaction event to update the position of the floating menu.
574
- * This allows external code to trigger a position update via:
575
- * `editor.view.dispatch(editor.state.tr.setMeta(pluginKey, 'updatePosition'))`
576
- * The `pluginKey` defaults to `floatingMenu`
577
- */
578
- this.transactionHandler = ({ transaction: tr }) => {
579
- const meta = tr.getMeta(this.pluginKey);
580
- if (meta === "updatePosition") {
581
- this.updatePosition();
582
- } else if (meta && typeof meta === "object" && meta.type === "updateOptions") {
583
- this.updateOptions(meta.options);
584
- }
585
- };
586
- /**
587
- * Handles the window resize event to update the position of the floating menu.
588
- * It uses a debounce mechanism to prevent excessive updates.
589
- * The delay is defined by the `resizeDelay` property.
590
- */
591
- this.resizeHandler = () => {
592
- if (this.resizeDebounceTimer) {
593
- clearTimeout(this.resizeDebounceTimer);
594
- }
595
- this.resizeDebounceTimer = window.setTimeout(() => {
596
- this.updatePosition();
597
- }, this.resizeDelay);
598
- };
599
- var _a;
600
- this.editor = editor;
601
- this.element = element;
602
- this.view = view;
603
- this.pluginKey = pluginKey;
604
- this.updateDelay = updateDelay;
605
- this.resizeDelay = resizeDelay;
606
- this.appendTo = appendTo;
607
- this.scrollTarget = (_a = options == null ? void 0 : options.scrollTarget) != null ? _a : window;
608
- this.floatingUIOptions = {
609
- ...this.floatingUIOptions,
610
- ...options
611
- };
612
- this.element.tabIndex = 0;
613
- if (shouldShow) {
614
- this.shouldShow = shouldShow;
615
- }
616
- this.element.addEventListener("mousedown", this.mousedownHandler, { capture: true });
617
- this.editor.on("focus", this.focusHandler);
618
- this.editor.on("blur", this.blurHandler);
619
- this.editor.on("transaction", this.transactionHandler);
620
- window.addEventListener("resize", this.resizeHandler);
621
- this.scrollTarget.addEventListener("scroll", this.resizeHandler);
622
- this.update(view, view.state);
623
- if (this.getShouldShow()) {
624
- this.show();
625
- this.updatePosition();
626
- }
627
- }
628
- getTextContent(node) {
629
- return getText(node, { textSerializers: getTextSerializersFromSchema(this.editor.schema) });
630
- }
631
- get middlewares() {
632
- const middlewares = [];
633
- if (this.floatingUIOptions.flip) {
634
- middlewares.push(flip2(typeof this.floatingUIOptions.flip !== "boolean" ? this.floatingUIOptions.flip : void 0));
635
- }
636
- if (this.floatingUIOptions.shift) {
637
- middlewares.push(
638
- shift2(typeof this.floatingUIOptions.shift !== "boolean" ? this.floatingUIOptions.shift : void 0)
639
- );
640
- }
641
- if (this.floatingUIOptions.offset) {
642
- middlewares.push(
643
- offset2(typeof this.floatingUIOptions.offset !== "boolean" ? this.floatingUIOptions.offset : void 0)
644
- );
645
- }
646
- if (this.floatingUIOptions.arrow) {
647
- middlewares.push(arrow2(this.floatingUIOptions.arrow));
648
- }
649
- if (this.floatingUIOptions.size) {
650
- middlewares.push(size2(typeof this.floatingUIOptions.size !== "boolean" ? this.floatingUIOptions.size : void 0));
651
- }
652
- if (this.floatingUIOptions.autoPlacement) {
653
- middlewares.push(
654
- autoPlacement2(
655
- typeof this.floatingUIOptions.autoPlacement !== "boolean" ? this.floatingUIOptions.autoPlacement : void 0
656
- )
657
- );
658
- }
659
- if (this.floatingUIOptions.hide) {
660
- middlewares.push(hide2(typeof this.floatingUIOptions.hide !== "boolean" ? this.floatingUIOptions.hide : void 0));
661
- }
662
- if (this.floatingUIOptions.inline) {
663
- middlewares.push(
664
- inline2(typeof this.floatingUIOptions.inline !== "boolean" ? this.floatingUIOptions.inline : void 0)
665
- );
666
- }
667
- return middlewares;
668
- }
669
- getShouldShow(oldState) {
670
- var _a;
671
- const { state } = this.view;
672
- const { selection } = state;
673
- const { ranges } = selection;
674
- const from = Math.min(...ranges.map((range) => range.$from.pos));
675
- const to = Math.max(...ranges.map((range) => range.$to.pos));
676
- const shouldShow = (_a = this.shouldShow) == null ? void 0 : _a.call(this, {
677
- editor: this.editor,
678
- view: this.view,
679
- state,
680
- oldState,
681
- from,
682
- to
683
- });
684
- return shouldShow;
685
- }
686
- updateOptions(newProps) {
687
- var _a;
688
- if (newProps.updateDelay !== void 0) {
689
- this.updateDelay = newProps.updateDelay;
690
- }
691
- if (newProps.resizeDelay !== void 0) {
692
- this.resizeDelay = newProps.resizeDelay;
693
- }
694
- if (newProps.appendTo !== void 0) {
695
- this.appendTo = newProps.appendTo;
696
- }
697
- if (newProps.shouldShow !== void 0) {
698
- if (newProps.shouldShow) {
699
- this.shouldShow = newProps.shouldShow;
700
- }
701
- }
702
- if (newProps.options !== void 0) {
703
- const newScrollTarget = (_a = newProps.options.scrollTarget) != null ? _a : window;
704
- if (newScrollTarget !== this.scrollTarget) {
705
- this.scrollTarget.removeEventListener("scroll", this.resizeHandler);
706
- this.scrollTarget = newScrollTarget;
707
- this.scrollTarget.addEventListener("scroll", this.resizeHandler);
708
- }
709
- this.floatingUIOptions = {
710
- ...this.floatingUIOptions,
711
- ...newProps.options
712
- };
713
- }
714
- }
715
- updatePosition() {
716
- const { selection } = this.editor.state;
717
- const domRect = posToDOMRect2(this.view, selection.from, selection.to);
718
- const virtualElement = {
719
- getBoundingClientRect: () => domRect,
720
- getClientRects: () => [domRect]
721
- };
722
- computePosition2(virtualElement, this.element, {
723
- placement: this.floatingUIOptions.placement,
724
- strategy: this.floatingUIOptions.strategy,
725
- middleware: this.middlewares
726
- }).then(({ x, y, strategy, middlewareData }) => {
727
- var _a, _b;
728
- if (((_a = middlewareData.hide) == null ? void 0 : _a.referenceHidden) || ((_b = middlewareData.hide) == null ? void 0 : _b.escaped)) {
729
- this.element.style.visibility = "hidden";
730
- return;
731
- }
732
- this.element.style.visibility = "visible";
733
- this.element.style.width = "max-content";
734
- this.element.style.position = strategy;
735
- this.element.style.left = `${x}px`;
736
- this.element.style.top = `${y}px`;
737
- if (this.isVisible && this.floatingUIOptions.onUpdate) {
738
- this.floatingUIOptions.onUpdate();
739
- }
740
- });
741
- }
742
- update(view, oldState) {
743
- const selectionChanged = !(oldState == null ? void 0 : oldState.selection.eq(view.state.selection));
744
- const docChanged = !(oldState == null ? void 0 : oldState.doc.eq(view.state.doc));
745
- this.updateHandler(view, selectionChanged, docChanged, oldState);
746
- }
747
- show() {
748
- var _a;
749
- if (this.isVisible) {
750
- return;
751
- }
752
- this.element.style.visibility = "visible";
753
- this.element.style.opacity = "1";
754
- const appendToElement = typeof this.appendTo === "function" ? this.appendTo() : this.appendTo;
755
- (_a = appendToElement != null ? appendToElement : this.view.dom.parentElement) == null ? void 0 : _a.appendChild(this.element);
756
- if (this.floatingUIOptions.onShow) {
757
- this.floatingUIOptions.onShow();
758
- }
759
- this.isVisible = true;
760
- }
761
- hide() {
762
- if (!this.isVisible) {
763
- return;
764
- }
765
- this.element.style.visibility = "hidden";
766
- this.element.style.opacity = "0";
767
- this.element.remove();
768
- if (this.floatingUIOptions.onHide) {
769
- this.floatingUIOptions.onHide();
770
- }
771
- this.isVisible = false;
772
- }
773
- destroy() {
774
- this.hide();
775
- this.element.removeEventListener("mousedown", this.mousedownHandler, { capture: true });
776
- window.removeEventListener("resize", this.resizeHandler);
777
- this.scrollTarget.removeEventListener("scroll", this.resizeHandler);
778
- this.editor.off("focus", this.focusHandler);
779
- this.editor.off("blur", this.blurHandler);
780
- this.editor.off("transaction", this.transactionHandler);
781
- if (this.floatingUIOptions.onDestroy) {
782
- this.floatingUIOptions.onDestroy();
783
- }
784
- }
785
- };
786
- var FloatingMenuPlugin = (options) => {
787
- return new Plugin2({
788
- key: typeof options.pluginKey === "string" ? new PluginKey2(options.pluginKey) : options.pluginKey,
789
- view: (view) => new FloatingMenuView({ view, ...options })
790
- });
791
- };
792
-
793
- // src/menus/FloatingMenu.ts
794
- import { defineComponent as defineComponent2, h as h2, onBeforeUnmount as onBeforeUnmount2, onMounted as onMounted2, ref as ref2 } from "vue";
795
- var FloatingMenu = defineComponent2({
796
- name: "FloatingMenu",
797
- inheritAttrs: false,
798
- props: {
799
- pluginKey: {
800
- // TODO: TypeScript breaks :(
801
- // type: [String, Object as PropType<Exclude<FloatingMenuPluginProps['pluginKey'], string>>],
802
- type: null,
803
- default: "floatingMenu"
804
- },
805
- editor: {
806
- type: Object,
807
- required: true
808
- },
809
- updateDelay: {
810
- type: Number,
811
- default: void 0
812
- },
813
- resizeDelay: {
814
- type: Number,
815
- default: void 0
816
- },
817
- options: {
818
- type: Object,
819
- default: () => ({})
820
- },
821
- appendTo: {
822
- type: [Object, Function],
823
- default: void 0
824
- },
825
- shouldShow: {
826
- type: Function,
827
- default: null
828
- }
829
- },
830
- setup(props, { slots, attrs }) {
831
- const root = ref2(null);
832
- onMounted2(() => {
833
- const { pluginKey, editor, updateDelay, resizeDelay, options, appendTo, shouldShow } = props;
834
- const el = root.value;
835
- if (!el) {
836
- return;
837
- }
838
- el.style.visibility = "hidden";
839
- el.style.position = "absolute";
840
- el.remove();
841
- editor.registerPlugin(
842
- FloatingMenuPlugin({
843
- pluginKey,
844
- editor,
845
- element: el,
846
- updateDelay,
847
- resizeDelay,
848
- options,
849
- appendTo,
850
- shouldShow
851
- })
852
- );
853
- });
854
- onBeforeUnmount2(() => {
855
- const { pluginKey, editor } = props;
856
- editor.unregisterPlugin(pluginKey);
857
- });
858
- return () => {
859
- var _a;
860
- return h2("div", { ref: root, ...attrs }, (_a = slots.default) == null ? void 0 : _a.call(slots));
861
- };
862
- }
863
- });
864
- export {
865
- BubbleMenu,
866
- FloatingMenu
867
- };
868
- //# sourceMappingURL=index.js.map