@harbour-enterprises/superdoc 0.14.0-next.2 → 0.14.0-next.21

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 (99) hide show
  1. package/dist/chunks/{eventemitter3-BrspJk8q.es.js → eventemitter3-BIPEy-pY.es.js} +1 -1
  2. package/dist/chunks/{eventemitter3-DfVviFzP.cjs → eventemitter3-DGnD-HK9.cjs} +1 -1
  3. package/dist/chunks/{index-Diu6UKHt.es.js → index-BvK-G6B1.es.js} +4 -4
  4. package/dist/chunks/{index-B4J7wgs6.cjs → index-CCRVYhTn.cjs} +2 -2
  5. package/dist/chunks/{index-Cdsq63Xq.cjs → index-CgJ5KVh6.cjs} +4 -4
  6. package/dist/chunks/{index-Hr3Um-Bg.es.js → index-oHslWah4.es.js} +2 -2
  7. package/dist/chunks/{jszip-DckFs3A7.es.js → jszip-CYDYUNnI.es.js} +1 -1
  8. package/dist/chunks/{jszip-BTAcmbVg.cjs → jszip-D5XoMX4C.cjs} +1 -1
  9. package/dist/chunks/{super-editor.es-C6TRTeBI.es.js → super-editor.es-Cu7C5Ezf.es.js} +3414 -2237
  10. package/dist/chunks/{super-editor.es-DFls-Ipj.cjs → super-editor.es-DM3LYkiV.cjs} +3402 -2225
  11. package/dist/chunks/{url-BIzg4y2i.cjs → url-BG1Z_Z2_.cjs} +2 -2
  12. package/dist/chunks/{url-CHayXMZH.es.js → url-Dvx6wrNT.es.js} +2 -2
  13. package/dist/chunks/{vue-Bi1uWinj.es.js → vue-lU0o_RlU.es.js} +35 -15
  14. package/dist/chunks/{vue-HIY1g7dm.cjs → vue-tQYF719J.cjs} +24 -4
  15. package/dist/chunks/{xml-js-BjqmFOSP.cjs → xml-js-BHJlXtfU.cjs} +13 -6
  16. package/dist/chunks/{xml-js-CfClL-1b.es.js → xml-js-DNISVjNF.es.js} +13 -6
  17. package/dist/composables/use-ai.d.ts +1 -3
  18. package/dist/composables/use-ai.d.ts.map +1 -1
  19. package/dist/core/SuperDoc.d.ts +5 -0
  20. package/dist/core/SuperDoc.d.ts.map +1 -1
  21. package/dist/helpers/floor.d.ts +2 -0
  22. package/dist/helpers/floor.d.ts.map +1 -0
  23. package/dist/stores/hrbr-fields-store.d.ts.map +1 -1
  24. package/dist/style.css +407 -291
  25. package/dist/super-editor/ai-writer.es.js +18 -33
  26. package/dist/super-editor/chunks/{converter-2R-ZXcMD.js → converter-BnCzxu5M.js} +1685 -1609
  27. package/dist/super-editor/chunks/{docx-zipper-D1Hg-x9a.js → docx-zipper-BPw_B6hI.js} +1 -1
  28. package/dist/super-editor/chunks/{editor-DYjOoB1N.js → editor-DD4MGOZb.js} +1788 -1251
  29. package/dist/super-editor/chunks/{toolbar-WyGfV3qj.js → toolbar-BCtZctWE.js} +33 -38
  30. package/dist/super-editor/components/cursor-helpers.d.ts +23 -0
  31. package/dist/super-editor/components/cursor-helpers.d.ts.map +1 -1
  32. package/dist/super-editor/components/slash-menu/constants.d.ts +64 -0
  33. package/dist/super-editor/components/slash-menu/constants.d.ts.map +1 -0
  34. package/dist/super-editor/components/slash-menu/menuItems.d.ts +35 -0
  35. package/dist/super-editor/components/slash-menu/menuItems.d.ts.map +1 -0
  36. package/dist/super-editor/components/slash-menu/utils.d.ts +10 -0
  37. package/dist/super-editor/components/slash-menu/utils.d.ts.map +1 -0
  38. package/dist/super-editor/components/toolbar/defaultItems.d.ts.map +1 -1
  39. package/dist/super-editor/components/toolbar/super-toolbar.d.ts.map +1 -1
  40. package/dist/super-editor/components/toolbar/toolbarIcons.d.ts +3 -12
  41. package/dist/super-editor/components/toolbar/toolbarTexts.d.ts +0 -11
  42. package/dist/super-editor/converter.es.js +1 -1
  43. package/dist/super-editor/core/Editor.d.ts +12 -4
  44. package/dist/super-editor/core/Editor.d.ts.map +1 -1
  45. package/dist/super-editor/core/InputRule.d.ts.map +1 -1
  46. package/dist/super-editor/core/commands/decreaseListIndent.d.ts.map +1 -1
  47. package/dist/super-editor/core/commands/deleteListItem.d.ts.map +1 -1
  48. package/dist/super-editor/core/commands/deleteSelection.d.ts +2 -0
  49. package/dist/super-editor/core/commands/deleteSelection.d.ts.map +1 -1
  50. package/dist/super-editor/core/commands/increaseListIndent.d.ts.map +1 -1
  51. package/dist/super-editor/core/commands/joinBackward.d.ts.map +1 -1
  52. package/dist/super-editor/core/commands/joinForward.d.ts.map +1 -1
  53. package/dist/super-editor/core/commands/splitListItem.d.ts.map +1 -1
  54. package/dist/super-editor/core/commands/toggleList.d.ts +5 -1
  55. package/dist/super-editor/core/commands/toggleList.d.ts.map +1 -1
  56. package/dist/super-editor/core/extensions/keymap.d.ts.map +1 -1
  57. package/dist/super-editor/core/helpers/list-numbering-helpers.d.ts +6 -5
  58. package/dist/super-editor/core/helpers/list-numbering-helpers.d.ts.map +1 -1
  59. package/dist/super-editor/core/super-converter/SuperConverter.d.ts.map +1 -1
  60. package/dist/super-editor/core/super-converter/exporter.d.ts.map +1 -1
  61. package/dist/super-editor/core/super-converter/v2/importer/annotationImporter.d.ts +1 -1
  62. package/dist/super-editor/core/super-converter/v2/importer/annotationImporter.d.ts.map +1 -1
  63. package/dist/super-editor/core/super-converter/v2/importer/hyperlinkImporter.d.ts.map +1 -1
  64. package/dist/super-editor/core/super-converter/v2/importer/listImporter.d.ts.map +1 -1
  65. package/dist/super-editor/core/super-converter/v2/importer/paragraphNodeImporter.d.ts.map +1 -1
  66. package/dist/super-editor/core/utilities/clipboardUtils.d.ts +27 -0
  67. package/dist/super-editor/core/utilities/clipboardUtils.d.ts.map +1 -0
  68. package/dist/super-editor/core/utilities/index.d.ts +1 -0
  69. package/dist/super-editor/docx-zipper.es.js +2 -2
  70. package/dist/super-editor/editor.es.js +3 -3
  71. package/dist/super-editor/extensions/ai/ai-plugin.d.ts.map +1 -1
  72. package/dist/super-editor/extensions/bullet-list/bullet-list.d.ts.map +1 -1
  73. package/dist/super-editor/extensions/field-annotation/fieldAnnotationHelpers/findRemovedFieldAnnotations.d.ts.map +1 -1
  74. package/dist/super-editor/extensions/index.d.ts.map +1 -1
  75. package/dist/super-editor/extensions/list-item/list-item.d.ts.map +1 -1
  76. package/dist/super-editor/extensions/noderesizer/noderesizer.d.ts +0 -3
  77. package/dist/super-editor/extensions/noderesizer/noderesizer.d.ts.map +1 -1
  78. package/dist/super-editor/extensions/ordered-list/helpers/orderedListSyncPlugin.d.ts.map +1 -1
  79. package/dist/super-editor/extensions/pagination/pagination-helpers.d.ts.map +1 -1
  80. package/dist/super-editor/extensions/pagination/pagination.d.ts.map +1 -1
  81. package/dist/super-editor/extensions/paragraph/paragraph.d.ts.map +1 -1
  82. package/dist/super-editor/extensions/slash-menu/index.d.ts +2 -0
  83. package/dist/super-editor/extensions/slash-menu/index.d.ts.map +1 -0
  84. package/dist/super-editor/extensions/slash-menu/slash-menu.d.ts +4 -0
  85. package/dist/super-editor/extensions/slash-menu/slash-menu.d.ts.map +1 -0
  86. package/dist/super-editor/extensions/table/table.d.ts.map +1 -1
  87. package/dist/super-editor/file-zipper.es.js +1 -1
  88. package/dist/super-editor/index.d.ts +1 -1
  89. package/dist/super-editor/index.d.ts.map +1 -1
  90. package/dist/super-editor/style.css +368 -261
  91. package/dist/super-editor/super-editor.es.js +1202 -608
  92. package/dist/super-editor/toolbar.es.js +2 -2
  93. package/dist/super-editor.cjs +3 -2
  94. package/dist/super-editor.es.js +15 -14
  95. package/dist/superdoc.cjs +89 -76
  96. package/dist/superdoc.es.js +141 -128
  97. package/dist/superdoc.umd.js +3716 -2509
  98. package/dist/superdoc.umd.js.map +1 -1
  99. package/package.json +2 -2
@@ -9,14 +9,14 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
9
9
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
10
10
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
11
11
  var _SuperToolbar_instances, initToolbarGroups_fn, _interceptedCommands, makeToolbarItems_fn, initDefaultFonts_fn, updateHighlightColors_fn, deactivateAll_fn, updateToolbarHistory_fn, runCommandWithArgumentOnly_fn;
12
- import { ab as getDefaultExportFromCjs, J as v4, ae as vClickOutside, T as TextSelection, a as Plugin } from "./chunks/converter-2R-ZXcMD.js";
13
- import { X } from "./chunks/converter-2R-ZXcMD.js";
14
- import { _ as _export_sfc, u as useHighContrastMode, a as getQuickFormatList, b as generateLinkedStyleString, f as findParentNode, c as getFileOpener, s as startImageUpload, d as getActiveFormatting, i as isInTable, e as undoDepth, r as redoDepth, E as Editor, h as getStarterExtensions, P as Placeholder, j as getRichTextExtensions, M as Mark, k as Extension, A as Attribute, N as Node } from "./chunks/editor-DYjOoB1N.js";
15
- import { o, C, T, m, q, p, l, n } from "./chunks/editor-DYjOoB1N.js";
16
- import { ref, onMounted, createElementBlock, openBlock, normalizeClass, unref, Fragment, renderList, createElementVNode, withModifiers, getCurrentInstance, computed, watch, createCommentVNode, withDirectives, withKeys, vModelText, createTextVNode, toDisplayString, normalizeStyle, createVNode, h, createApp, reactive, onUnmounted, shallowRef, onBeforeUnmount, createBlock } from "vue";
17
- import { t as toolbarIcons, s as sanitizeNumber, T as Toolbar, N as NSkeleton } from "./chunks/toolbar-WyGfV3qj.js";
12
+ import { ab as getDefaultExportFromCjs, J as v4, ae as vClickOutside, af as readFromClipboard, T as TextSelection, ag as serializeSelectionToClipboard, ah as writeToClipboard, a as Plugin } from "./chunks/converter-BnCzxu5M.js";
13
+ import { X } from "./chunks/converter-BnCzxu5M.js";
14
+ import { _ as _export_sfc, u as useHighContrastMode, a as getQuickFormatList, b as generateLinkedStyleString, f as findParentNode, c as getFileOpener, s as startImageUpload, d as getActiveFormatting, i as isInTable, e as undoDepth, r as redoDepth, S as SlashMenuPluginKey, E as Editor, h as getStarterExtensions, P as Placeholder, j as getRichTextExtensions, M as Mark, k as Extension, A as Attribute, N as Node } from "./chunks/editor-DD4MGOZb.js";
15
+ import { o, C, T, m, q, p, l, n } from "./chunks/editor-DD4MGOZb.js";
16
+ import { ref, onMounted, createElementBlock, openBlock, normalizeClass, unref, Fragment, renderList, createElementVNode, withModifiers, toDisplayString, createCommentVNode, normalizeStyle, computed, createTextVNode, createVNode, h, withDirectives, withKeys, vModelText, createApp, markRaw, watch, nextTick, onBeforeUnmount, reactive, onUnmounted, renderSlot, shallowRef, createBlock, withCtx, resolveDynamicComponent, normalizeProps, guardReactiveProps } from "vue";
17
+ import { t as toolbarIcons, s as sanitizeNumber, T as Toolbar, m as magicWandIcon, l as linkIconSvg, a as tableIconSvg, b as scissorsIconSvg, c as copyIconSvg, p as pasteIconSvg, N as NSkeleton } from "./chunks/toolbar-BCtZctWE.js";
18
18
  import AIWriter from "./ai-writer.es.js";
19
- import { D } from "./chunks/docx-zipper-D1Hg-x9a.js";
19
+ import { D } from "./chunks/docx-zipper-BPw_B6hI.js";
20
20
  import { createZip } from "./file-zipper.es.js";
21
21
  var eventemitter3 = { exports: {} };
22
22
  (function(module) {
@@ -177,28 +177,6 @@ var eventemitter3 = { exports: {} };
177
177
  })(eventemitter3);
178
178
  var eventemitter3Exports = eventemitter3.exports;
179
179
  const EventEmitter = /* @__PURE__ */ getDefaultExportFromCjs(eventemitter3Exports);
180
- function getScrollableParent(element) {
181
- let currentElement = element;
182
- while (currentElement) {
183
- const overflowY = window.getComputedStyle(currentElement).overflowY;
184
- if (/(auto|scroll)/.test(overflowY) && currentElement.scrollHeight > currentElement.clientHeight) {
185
- return currentElement;
186
- }
187
- currentElement = currentElement.parentElement;
188
- }
189
- return document.scrollingElement || document.documentElement;
190
- }
191
- function scrollToElement(targetElement, options = { behavior: "smooth", block: "start" }) {
192
- if (!targetElement) return;
193
- const container = getScrollableParent(targetElement);
194
- const containerRect = container.getBoundingClientRect();
195
- const targetRect = targetElement.getBoundingClientRect();
196
- const offsetTop = targetRect.top - containerRect.top + container.scrollTop;
197
- container.scrollTo({
198
- top: options.block === "start" ? offsetTop : offsetTop - container.clientHeight + targetElement.offsetHeight,
199
- behavior: options.behavior
200
- });
201
- }
202
180
  const useToolbarItem = (options) => {
203
181
  const types = ["button", "options", "separator", "dropdown", "overflow"];
204
182
  if (!types.includes(options.type)) {
@@ -327,8 +305,8 @@ const useToolbarItem = (options) => {
327
305
  onDeactivate
328
306
  };
329
307
  };
330
- const _hoisted_1$b = ["onClick", "innerHTML", "aria-label", "onKeydown"];
331
- const _sfc_main$c = {
308
+ const _hoisted_1$c = ["onClick", "innerHTML", "aria-label", "onKeydown"];
309
+ const _sfc_main$e = {
332
310
  __name: "AlignmentButtons",
333
311
  emits: ["select"],
334
312
  setup(__props, { emit: __emit }) {
@@ -413,183 +391,20 @@ const _sfc_main$c = {
413
391
  ref_key: "alignmentButtonsRefs",
414
392
  ref: alignmentButtonsRefs,
415
393
  onKeydown: withModifiers((event) => handleKeyDown(event, index), ["prevent"])
416
- }, null, 40, _hoisted_1$b);
394
+ }, null, 40, _hoisted_1$c);
417
395
  }), 64))
418
396
  ], 2);
419
397
  };
420
398
  }
421
399
  };
422
- const AlignmentButtons = /* @__PURE__ */ _export_sfc(_sfc_main$c, [["__scopeId", "data-v-3f28435a"]]);
423
- const _hoisted_1$a = {
424
- key: 0,
425
- class: "link-title"
426
- };
427
- const _hoisted_2$8 = {
428
- key: 1,
429
- class: "link-title"
430
- };
431
- const _hoisted_3$6 = {
432
- key: 2,
433
- class: "link-title"
434
- };
435
- const _hoisted_4$2 = { key: 3 };
436
- const _hoisted_5$2 = { class: "input-row" };
437
- const _hoisted_6$1 = ["innerHTML"];
438
- const _hoisted_7 = ["onKeydown"];
439
- const _hoisted_8 = ["innerHTML"];
440
- const _hoisted_9 = { class: "input-row link-buttons" };
441
- const _hoisted_10 = ["innerHTML"];
442
- const _hoisted_11 = {
443
- key: 4,
444
- class: "input-row go-to-anchor clickable"
445
- };
446
- const _sfc_main$b = {
447
- __name: "LinkInput",
448
- props: {
449
- initialText: {
450
- type: String,
451
- default: ""
452
- },
453
- href: {
454
- type: String,
455
- default: ""
456
- },
457
- showInput: {
458
- type: Boolean,
459
- default: true
460
- },
461
- showLink: {
462
- type: Boolean,
463
- default: true
464
- },
465
- goToAnchor: {
466
- type: Function,
467
- default: () => {
468
- }
469
- }
470
- },
471
- emits: ["submit", "cancel"],
472
- setup(__props, { emit: __emit }) {
473
- const emit = __emit;
474
- const props = __props;
475
- const { isHighContrastMode } = useHighContrastMode();
476
- const { proxy } = getCurrentInstance();
477
- const handleSubmit = () => {
478
- if (proxy?.$submit instanceof Function) proxy.$submit();
479
- if (rawUrl.value && validUrl.value) {
480
- emit("submit", { text: text.value, href: url.value });
481
- return;
482
- } else if (!rawUrl.value) {
483
- emit("submit", { text: text.value, href: null });
484
- return;
485
- }
486
- console.debug("[LinkInput] Invalid URL in handleSubmit");
487
- urlError.value = true;
488
- };
489
- const handleRemove = () => {
490
- emit("submit", { text: text.value, href: null });
491
- };
492
- const urlError = ref(false);
493
- const text = ref(props.initialText);
494
- const rawUrl = ref(props.href);
495
- const url = computed(() => {
496
- if (!rawUrl.value?.startsWith("http")) return "http://" + rawUrl.value;
497
- return rawUrl.value;
498
- });
499
- const validUrl = computed(() => {
500
- const urlSplit = url.value.split(".").filter(Boolean);
501
- return url.value.includes(".") && urlSplit.length > 1;
502
- });
503
- const getApplyText = computed(() => showApply.value ? "Apply" : "Remove");
504
- const isDisabled = computed(() => !validUrl.value);
505
- const showApply = computed(() => !showRemove.value);
506
- const showRemove = computed(() => props.href && !rawUrl.value);
507
- const isAnchor = computed(() => props.href.startsWith("#"));
508
- const openLink = () => {
509
- window.open(url.value, "_blank");
510
- };
511
- watch(
512
- () => props.href,
513
- (newVal) => {
514
- rawUrl.value = newVal;
515
- }
516
- );
517
- const focusInput = () => {
518
- const input = document.querySelector(".link-input-ctn input");
519
- if (!input) return;
520
- input.focus();
521
- };
522
- onMounted(() => {
523
- if (props.showInput) focusInput();
524
- });
525
- return (_ctx, _cache) => {
526
- return openBlock(), createElementBlock("div", {
527
- class: normalizeClass(["link-input-ctn", { "high-contrast": unref(isHighContrastMode) }])
528
- }, [
529
- !__props.href ? (openBlock(), createElementBlock("div", _hoisted_1$a, "Add link")) : isAnchor.value ? (openBlock(), createElementBlock("div", _hoisted_2$8, "Page anchor")) : (openBlock(), createElementBlock("div", _hoisted_3$6, "Edit link")),
530
- __props.showInput && !isAnchor.value ? (openBlock(), createElementBlock("div", _hoisted_4$2, [
531
- createElementVNode("div", _hoisted_5$2, [
532
- createElementVNode("div", {
533
- class: "input-icon",
534
- innerHTML: unref(toolbarIcons).linkInput
535
- }, null, 8, _hoisted_6$1),
536
- withDirectives(createElementVNode("input", {
537
- type: "text",
538
- name: "link",
539
- placeholder: "Type or paste a link",
540
- class: normalizeClass({ error: urlError.value }),
541
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => rawUrl.value = $event),
542
- onKeydown: [
543
- withKeys(withModifiers(handleSubmit, ["stop", "prevent"]), ["enter"]),
544
- _cache[1] || (_cache[1] = ($event) => urlError.value = false)
545
- ]
546
- }, null, 42, _hoisted_7), [
547
- [vModelText, rawUrl.value]
548
- ]),
549
- createElementVNode("div", {
550
- class: normalizeClass(["open-link-icon", { disabled: !validUrl.value }]),
551
- innerHTML: unref(toolbarIcons).openLink,
552
- onClick: openLink,
553
- "data-item": "btn-link-open"
554
- }, null, 10, _hoisted_8)
555
- ]),
556
- createElementVNode("div", _hoisted_9, [
557
- __props.href ? (openBlock(), createElementBlock("button", {
558
- key: 0,
559
- class: "remove-btn",
560
- onClick: handleRemove,
561
- "data-item": "btn-link-remove"
562
- }, [
563
- createElementVNode("div", {
564
- class: "remove-btn__icon",
565
- innerHTML: unref(toolbarIcons).removeLink
566
- }, null, 8, _hoisted_10),
567
- _cache[3] || (_cache[3] = createTextVNode(" Remove "))
568
- ])) : createCommentVNode("", true),
569
- showApply.value ? (openBlock(), createElementBlock("button", {
570
- key: 1,
571
- class: normalizeClass(["submit-btn", { "disable-btn": isDisabled.value }]),
572
- onClick: handleSubmit,
573
- "data-item": "btn-link-apply"
574
- }, toDisplayString(getApplyText.value), 3)) : createCommentVNode("", true)
575
- ])
576
- ])) : isAnchor.value ? (openBlock(), createElementBlock("div", _hoisted_11, [
577
- createElementVNode("a", {
578
- onClick: _cache[2] || (_cache[2] = withModifiers((...args) => __props.goToAnchor && __props.goToAnchor(...args), ["stop", "prevent"]))
579
- }, "Go to " + toDisplayString(__props.href.startsWith("#_") ? __props.href.substring(2) : __props.href), 1)
580
- ])) : createCommentVNode("", true)
581
- ], 2);
582
- };
583
- }
584
- };
585
- const LinkInput = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-64aa14bc"]]);
586
- const _hoisted_1$9 = ["onClick", "onKeydown"];
587
- const _hoisted_2$7 = { class: "document-mode-column icon-column" };
588
- const _hoisted_3$5 = ["innerHTML"];
589
- const _hoisted_4$1 = { class: "document-mode-column text-column" };
590
- const _hoisted_5$1 = { class: "document-mode-type" };
591
- const _hoisted_6 = { class: "document-mode-description" };
592
- const _sfc_main$a = {
400
+ const AlignmentButtons = /* @__PURE__ */ _export_sfc(_sfc_main$e, [["__scopeId", "data-v-3f28435a"]]);
401
+ const _hoisted_1$b = ["onClick", "onKeydown"];
402
+ const _hoisted_2$9 = { class: "document-mode-column icon-column" };
403
+ const _hoisted_3$7 = ["innerHTML"];
404
+ const _hoisted_4$3 = { class: "document-mode-column text-column" };
405
+ const _hoisted_5$2 = { class: "document-mode-type" };
406
+ const _hoisted_6$1 = { class: "document-mode-description" };
407
+ const _sfc_main$d = {
593
408
  __name: "DocumentMode",
594
409
  props: {
595
410
  options: {
@@ -653,29 +468,29 @@ const _sfc_main$a = {
653
468
  ref: documentModeRefs,
654
469
  onKeydown: withModifiers((event) => handleKeyDown(event, index), ["prevent"])
655
470
  }, [
656
- createElementVNode("div", _hoisted_2$7, [
471
+ createElementVNode("div", _hoisted_2$9, [
657
472
  createElementVNode("div", {
658
473
  class: "icon-column__icon",
659
474
  innerHTML: option.icon
660
- }, null, 8, _hoisted_3$5)
475
+ }, null, 8, _hoisted_3$7)
661
476
  ]),
662
- createElementVNode("div", _hoisted_4$1, [
663
- createElementVNode("div", _hoisted_5$1, toDisplayString(option.label), 1),
664
- createElementVNode("div", _hoisted_6, toDisplayString(option.description), 1)
477
+ createElementVNode("div", _hoisted_4$3, [
478
+ createElementVNode("div", _hoisted_5$2, toDisplayString(option.label), 1),
479
+ createElementVNode("div", _hoisted_6$1, toDisplayString(option.description), 1)
665
480
  ])
666
- ], 42, _hoisted_1$9);
481
+ ], 42, _hoisted_1$b);
667
482
  }), 256))
668
483
  ], 2);
669
484
  };
670
485
  }
671
486
  };
672
- const DocumentMode = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__scopeId", "data-v-7febe4d9"]]);
673
- const _hoisted_1$8 = {
487
+ const DocumentMode = /* @__PURE__ */ _export_sfc(_sfc_main$d, [["__scopeId", "data-v-7febe4d9"]]);
488
+ const _hoisted_1$a = {
674
489
  key: 0,
675
490
  class: "linked-style-buttons"
676
491
  };
677
- const _hoisted_2$6 = ["onClick", "onKeydown"];
678
- const _sfc_main$9 = {
492
+ const _hoisted_2$8 = ["onClick", "onKeydown"];
493
+ const _sfc_main$c = {
679
494
  __name: "LinkedStyle",
680
495
  props: {
681
496
  editor: {
@@ -729,7 +544,7 @@ const _sfc_main$9 = {
729
544
  styleRefs.value[0].focus();
730
545
  });
731
546
  return (_ctx, _cache) => {
732
- return props.editor ? (openBlock(), createElementBlock("div", _hoisted_1$8, [
547
+ return props.editor ? (openBlock(), createElementBlock("div", _hoisted_1$a, [
733
548
  (openBlock(true), createElementBlock(Fragment, null, renderList(unref(getQuickFormatList)(__props.editor), (style, index) => {
734
549
  return openBlock(), createElementBlock("div", {
735
550
  class: normalizeClass(["style-item", { "selected": __props.selectedOption === style.id }]),
@@ -744,18 +559,18 @@ const _sfc_main$9 = {
744
559
  style: normalizeStyle(unref(generateLinkedStyleString)(style, null, false)),
745
560
  "data-item": "btn-linkedStyles-option"
746
561
  }, toDisplayString(style.definition.attrs.name), 5)
747
- ], 42, _hoisted_2$6);
562
+ ], 42, _hoisted_2$8);
748
563
  }), 256))
749
564
  ])) : createCommentVNode("", true);
750
565
  };
751
566
  }
752
567
  };
753
- const LinkedStyle = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["__scopeId", "data-v-2cf079a2"]]);
754
- const _hoisted_1$7 = ["aria-label", "onClick", "onKeydown"];
755
- const _hoisted_2$5 = ["innerHTML"];
756
- const _hoisted_3$4 = ["innerHTML"];
568
+ const LinkedStyle = /* @__PURE__ */ _export_sfc(_sfc_main$c, [["__scopeId", "data-v-2cf079a2"]]);
569
+ const _hoisted_1$9 = ["aria-label", "onClick", "onKeydown"];
570
+ const _hoisted_2$7 = ["innerHTML"];
571
+ const _hoisted_3$6 = ["innerHTML"];
757
572
  const ROW_SIZE$1 = 7;
758
- const _sfc_main$8 = {
573
+ const _sfc_main$b = {
759
574
  __name: "IconGridRow",
760
575
  props: {
761
576
  icons: {
@@ -874,26 +689,26 @@ const _sfc_main$8 = {
874
689
  class: "option__icon",
875
690
  innerHTML: option.icon,
876
691
  style: normalizeStyle(option.style)
877
- }, null, 12, _hoisted_2$5),
692
+ }, null, 12, _hoisted_2$7),
878
693
  isActive.value(option) ? (openBlock(), createElementBlock("div", {
879
694
  key: 0,
880
695
  class: "option__check",
881
696
  innerHTML: unref(toolbarIcons).colorOptionCheck,
882
697
  style: normalizeStyle(getCheckStyle(option.value, optionIndex))
883
- }, null, 12, _hoisted_3$4)) : createCommentVNode("", true)
884
- ], 40, _hoisted_1$7);
698
+ }, null, 12, _hoisted_3$6)) : createCommentVNode("", true)
699
+ ], 40, _hoisted_1$9);
885
700
  }), 128))
886
701
  ]);
887
702
  }), 128);
888
703
  };
889
704
  }
890
705
  };
891
- const IconGridRow = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["__scopeId", "data-v-e89b7f5f"]]);
706
+ const IconGridRow = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__scopeId", "data-v-e89b7f5f"]]);
892
707
  const DropIcon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M320 512c53.2 0 101.4-21.6 136.1-56.6l-298.3-235C140 257.1 128 292.3 128 320c0 106 86 192 192 192zM505.2 370.7c4.4-16.2 6.8-33.1 6.8-50.7c0-91.2-130.2-262.3-166.6-308.3C339.4 4.2 330.5 0 320.9 0l-1.8 0c-9.6 0-18.5 4.2-24.5 11.7C277.8 33 240.7 81.3 205.8 136L38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L505.2 370.7zM224 336c0 44.2 35.8 80 80 80c8.8 0 16 7.2 16 16s-7.2 16-16 16c-61.9 0-112-50.1-112-112c0-8.8 7.2-16 16-16s16 7.2 16 16z"/></svg>\n';
893
- const _hoisted_1$6 = { class: "options-grid-wrap" };
894
- const _hoisted_2$4 = ["innerHTML"];
895
- const _hoisted_3$3 = { class: "option-grid-ctn" };
896
- const _sfc_main$7 = {
708
+ const _hoisted_1$8 = { class: "options-grid-wrap" };
709
+ const _hoisted_2$6 = ["innerHTML"];
710
+ const _hoisted_3$5 = { class: "option-grid-ctn" };
711
+ const _sfc_main$a = {
897
712
  __name: "IconGrid",
898
713
  props: {
899
714
  icons: {
@@ -920,7 +735,7 @@ const _sfc_main$7 = {
920
735
  emit("select", option);
921
736
  };
922
737
  return (_ctx, _cache) => {
923
- return openBlock(), createElementBlock("div", _hoisted_1$6, [
738
+ return openBlock(), createElementBlock("div", _hoisted_1$8, [
924
739
  __props.hasNoneIcon ? (openBlock(), createElementBlock("div", {
925
740
  key: 0,
926
741
  class: "none-option",
@@ -931,10 +746,10 @@ const _sfc_main$7 = {
931
746
  createElementVNode("span", {
932
747
  innerHTML: unref(DropIcon),
933
748
  class: "none-icon"
934
- }, null, 8, _hoisted_2$4),
749
+ }, null, 8, _hoisted_2$6),
935
750
  _cache[1] || (_cache[1] = createTextVNode(" None "))
936
751
  ])) : createCommentVNode("", true),
937
- createElementVNode("div", _hoisted_3$3, [
752
+ createElementVNode("div", _hoisted_3$5, [
938
753
  createVNode(IconGridRow, {
939
754
  icons: __props.icons,
940
755
  "active-color": __props.activeColor,
@@ -953,7 +768,7 @@ const _sfc_main$7 = {
953
768
  };
954
769
  }
955
770
  };
956
- const IconGrid = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-a00a9a3e"]]);
771
+ const IconGrid = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__scopeId", "data-v-a00a9a3e"]]);
957
772
  const closeDropdown$1 = (dropdown) => {
958
773
  dropdown.expand.value = false;
959
774
  };
@@ -1062,10 +877,10 @@ const icons = [
1062
877
  const getAvailableColorOptions = () => {
1063
878
  return icons.flat().map((item) => item.value);
1064
879
  };
1065
- const _hoisted_1$5 = ["data-cols", "data-rows", "onKeydown", "onClick"];
1066
- const _hoisted_2$3 = ["aria-valuetext"];
880
+ const _hoisted_1$7 = ["data-cols", "data-rows", "onKeydown", "onClick"];
881
+ const _hoisted_2$5 = ["aria-valuetext"];
1067
882
  const ROW_SIZE = 5;
1068
- const _sfc_main$6 = {
883
+ const _sfc_main$9 = {
1069
884
  __name: "TableGrid",
1070
885
  emits: ["select", "clickoutside"],
1071
886
  setup(__props, { emit: __emit }) {
@@ -1181,7 +996,7 @@ const _sfc_main$6 = {
1181
996
  ref: tableGridItems,
1182
997
  onKeydown: withModifiers((event) => handleKeyDown(event, n2, i), ["prevent"]),
1183
998
  onClick: withModifiers(($event) => handleClick({ cols: n2, rows: i }), ["stop", "prevent"])
1184
- }, null, 40, _hoisted_1$5);
999
+ }, null, 40, _hoisted_1$7);
1185
1000
  }), 64))
1186
1001
  ], 64);
1187
1002
  }), 64))
@@ -1189,59 +1004,17 @@ const _sfc_main$6 = {
1189
1004
  createElementVNode("div", {
1190
1005
  class: "toolbar-table-grid-value",
1191
1006
  "aria-valuetext": `${selectedRows.value} x ${selectedCols.value}`
1192
- }, toDisplayString(selectedRows.value) + " x " + toDisplayString(selectedCols.value), 9, _hoisted_2$3)
1007
+ }, toDisplayString(selectedRows.value) + " x " + toDisplayString(selectedCols.value), 9, _hoisted_2$5)
1193
1008
  ], 2);
1194
1009
  };
1195
1010
  }
1196
1011
  };
1197
- const TableGrid = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__scopeId", "data-v-3e1154b8"]]);
1198
- const _hoisted_1$4 = { class: "toolbar-table-actions" };
1199
- const _hoisted_2$2 = ["onClick", "data-item", "ariaLabel"];
1200
- const _hoisted_3$2 = { class: "toolbar-table-actions__icon" };
1201
- const _hoisted_4 = ["innerHTML"];
1202
- const _hoisted_5 = { class: "toolbar-table-actions__label" };
1203
- const _sfc_main$5 = {
1204
- __name: "TableActions",
1205
- props: {
1206
- options: {
1207
- type: Array
1208
- }
1209
- },
1210
- emits: ["select"],
1211
- setup(__props, { emit: __emit }) {
1212
- const emit = __emit;
1213
- const handleClick = (item) => {
1214
- emit("select", { command: item.command });
1215
- };
1216
- return (_ctx, _cache) => {
1217
- return openBlock(), createElementBlock("div", _hoisted_1$4, [
1218
- (openBlock(true), createElementBlock(Fragment, null, renderList(__props.options, (option) => {
1219
- return openBlock(), createElementBlock("div", {
1220
- class: normalizeClass(["toolbar-table-actions__item", { "toolbar-table-actions__item--border": option.bottomBorder }]),
1221
- onClick: ($event) => handleClick(option),
1222
- "data-item": option.props?.["data-item"] || "",
1223
- ariaLabel: option.props?.ariaLabel,
1224
- role: "menuitem"
1225
- }, [
1226
- createElementVNode("div", _hoisted_3$2, [
1227
- createElementVNode("div", {
1228
- class: "toolbar-table-actions__icon-wrapper",
1229
- innerHTML: option.icon
1230
- }, null, 8, _hoisted_4)
1231
- ]),
1232
- createElementVNode("div", _hoisted_5, toDisplayString(option.label), 1)
1233
- ], 10, _hoisted_2$2);
1234
- }), 256))
1235
- ]);
1236
- };
1237
- }
1238
- };
1239
- const TableActions = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-f82e859a"]]);
1012
+ const TableGrid = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["__scopeId", "data-v-3e1154b8"]]);
1240
1013
  const checkIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M438.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L160 338.7 393.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"/></svg>\n';
1241
- const _hoisted_1$3 = { class: "search-input-ctn" };
1242
- const _hoisted_2$1 = { class: "row" };
1243
- const _hoisted_3$1 = ["onKeydown"];
1244
- const _sfc_main$4 = {
1014
+ const _hoisted_1$6 = { class: "search-input-ctn" };
1015
+ const _hoisted_2$4 = { class: "row" };
1016
+ const _hoisted_3$4 = ["onKeydown"];
1017
+ const _sfc_main$8 = {
1245
1018
  __name: "SearchInput",
1246
1019
  props: {
1247
1020
  searchRef: {
@@ -1256,8 +1029,8 @@ const _sfc_main$4 = {
1256
1029
  emit("submit", { value: searchValue.value });
1257
1030
  };
1258
1031
  return (_ctx, _cache) => {
1259
- return openBlock(), createElementBlock("div", _hoisted_1$3, [
1260
- createElementVNode("div", _hoisted_2$1, [
1032
+ return openBlock(), createElementBlock("div", _hoisted_1$6, [
1033
+ createElementVNode("div", _hoisted_2$4, [
1261
1034
  withDirectives(createElementVNode("input", {
1262
1035
  ref: __props.searchRef,
1263
1036
  "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => searchValue.value = $event),
@@ -1266,7 +1039,7 @@ const _sfc_main$4 = {
1266
1039
  name: "search",
1267
1040
  placeholder: "Type search string",
1268
1041
  onKeydown: withKeys(withModifiers(handleSubmit, ["stop", "prevent"]), ["enter"])
1269
- }, null, 40, _hoisted_3$1), [
1042
+ }, null, 40, _hoisted_3$4), [
1270
1043
  [vModelText, searchValue.value]
1271
1044
  ])
1272
1045
  ]),
@@ -1280,7 +1053,7 @@ const _sfc_main$4 = {
1280
1053
  };
1281
1054
  }
1282
1055
  };
1283
- const SearchInput = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-af870fbd"]]);
1056
+ const SearchInput = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["__scopeId", "data-v-af870fbd"]]);
1284
1057
  const TOOLBAR_FONTS = [
1285
1058
  {
1286
1059
  label: "Georgia",
@@ -1423,7 +1196,7 @@ const makeDefaultItems = ({
1423
1196
  labelAttr: "fontSize",
1424
1197
  tooltip: toolbarTexts2.fontSize,
1425
1198
  hasCaret: true,
1426
- hasInlineTextInput: false,
1199
+ hasInlineTextInput: true,
1427
1200
  inlineTextInputVisible: true,
1428
1201
  suppressActiveHighlight: true,
1429
1202
  isWide: true,
@@ -1562,62 +1335,6 @@ const makeDefaultItems = ({
1562
1335
  })
1563
1336
  ]);
1564
1337
  };
1565
- const link = useToolbarItem({
1566
- type: "dropdown",
1567
- name: "link",
1568
- markName: "link",
1569
- icon: toolbarIcons2.link,
1570
- tooltip: toolbarTexts2.link,
1571
- attributes: {
1572
- ariaLabel: "Link dropdown"
1573
- },
1574
- options: [
1575
- {
1576
- type: "render",
1577
- key: "linkDropdown",
1578
- render: () => renderLinkDropdown(link)
1579
- }
1580
- ],
1581
- onActivate: ({ href }) => {
1582
- if (href) link.attributes.value = { href };
1583
- else link.attributes.value = {};
1584
- link.expand.value = true;
1585
- },
1586
- onDeactivate: () => {
1587
- link.attributes.value = {};
1588
- link.expand.value = false;
1589
- }
1590
- });
1591
- function renderLinkDropdown(link2) {
1592
- const handleSubmit = ({ href }) => {
1593
- closeDropdown(link2);
1594
- link2.attributes.value.link = { href };
1595
- const itemWithCommand = { ...link2, command: "toggleLink" };
1596
- superToolbar.emitCommand({ item: itemWithCommand, argument: { href, text: "" } });
1597
- if (!href) link2.active.value = false;
1598
- };
1599
- return h("div", {}, [
1600
- h(LinkInput, {
1601
- onSubmit: handleSubmit,
1602
- href: link2.attributes.value.href,
1603
- goToAnchor: () => {
1604
- closeDropdown(link2);
1605
- if (!superToolbar.activeEditor || !link2.attributes.value?.href) return;
1606
- const anchorName = link2.attributes.value?.href?.slice(1);
1607
- const container = superToolbar.activeEditor.element;
1608
- const anchor = container.querySelector(`a[name='${anchorName}']`);
1609
- if (anchor) scrollToElement(anchor);
1610
- }
1611
- })
1612
- ]);
1613
- }
1614
- const linkInput = useToolbarItem({
1615
- type: "options",
1616
- name: "linkInput",
1617
- command: "toggleLink"
1618
- });
1619
- link.childItem = linkInput;
1620
- linkInput.parentItem = link;
1621
1338
  const image = useToolbarItem({
1622
1339
  type: "button",
1623
1340
  name: "image",
@@ -1660,171 +1377,41 @@ const makeDefaultItems = ({
1660
1377
  })
1661
1378
  ]);
1662
1379
  }
1663
- const tableActionsItem = useToolbarItem({
1380
+ const alignment2 = useToolbarItem({
1664
1381
  type: "dropdown",
1665
- name: "tableActions",
1666
- command: "executeTableCommand",
1667
- icon: toolbarIcons2.tableActions,
1668
- hideLabel: true,
1669
- disabled: true,
1382
+ name: "textAlign",
1383
+ tooltip: toolbarTexts2.textAlign,
1384
+ icon: toolbarIcons2.alignLeft,
1385
+ command: "setTextAlign",
1386
+ hasCaret: true,
1387
+ markName: "textAlign",
1388
+ labelAttr: "textAlign",
1389
+ suppressActiveHighlight: true,
1670
1390
  attributes: {
1671
- ariaLabel: "Table actions"
1391
+ ariaLabel: "Text align"
1672
1392
  },
1673
1393
  options: [
1674
1394
  {
1675
1395
  type: "render",
1676
- render: () => renderTableActions(tableActionsItem)
1677
- }
1678
- ]
1679
- });
1680
- const tableActionsOptions = [
1681
- {
1682
- label: toolbarTexts2.addRowBefore,
1683
- command: "addRowBefore",
1684
- icon: toolbarIcons2.addRowBefore,
1685
- props: {
1686
- "data-item": "btn-tableActions-option",
1687
- ariaLabel: "Add row before"
1688
- }
1689
- },
1690
- {
1691
- label: toolbarTexts2.addRowAfter,
1692
- command: "addRowAfter",
1693
- icon: toolbarIcons2.addRowAfter,
1694
- props: {
1695
- "data-item": "btn-tableActions-option",
1696
- ariaLabel: "Add row after"
1697
- }
1698
- },
1699
- {
1700
- label: toolbarTexts2.addColumnBefore,
1701
- command: "addColumnBefore",
1702
- icon: toolbarIcons2.addColumnBefore,
1703
- props: {
1704
- "data-item": "btn-tableActions-option",
1705
- ariaLabel: "Add column before"
1396
+ render: () => {
1397
+ const handleSelect = (e) => {
1398
+ closeDropdown(alignment2);
1399
+ const buttonWithCommand = { ...alignment2, command: "setTextAlign" };
1400
+ buttonWithCommand.command = "setTextAlign";
1401
+ superToolbar.emitCommand({ item: buttonWithCommand, argument: e });
1402
+ setAlignmentIcon(alignment2, e);
1403
+ };
1404
+ return h("div", {}, [
1405
+ h(AlignmentButtons, {
1406
+ onSelect: handleSelect
1407
+ })
1408
+ ]);
1409
+ },
1410
+ key: "alignment"
1706
1411
  }
1707
- },
1708
- {
1709
- label: toolbarTexts2.addColumnAfter,
1710
- command: "addColumnAfter",
1711
- icon: toolbarIcons2.addColumnAfter,
1712
- bottomBorder: true,
1713
- props: {
1714
- "data-item": "btn-tableActions-option",
1715
- ariaLabel: "Add column after"
1716
- }
1717
- },
1718
- {
1719
- label: toolbarTexts2.deleteRow,
1720
- command: "deleteRow",
1721
- icon: toolbarIcons2.deleteRow,
1722
- props: {
1723
- "data-item": "btn-tableActions-option",
1724
- ariaLabel: "Delete row"
1725
- }
1726
- },
1727
- {
1728
- label: toolbarTexts2.deleteColumn,
1729
- command: "deleteColumn",
1730
- icon: toolbarIcons2.deleteColumn,
1731
- props: {
1732
- "data-item": "btn-tableActions-option",
1733
- ariaLabel: "Delete column"
1734
- }
1735
- },
1736
- {
1737
- label: toolbarTexts2.deleteTable,
1738
- command: "deleteTable",
1739
- icon: toolbarIcons2.deleteTable,
1740
- props: {
1741
- "data-item": "btn-tableActions-option",
1742
- ariaLabel: "Delete table"
1743
- }
1744
- },
1745
- {
1746
- label: toolbarTexts2.transparentBorders,
1747
- command: "deleteCellAndTableBorders",
1748
- icon: toolbarIcons2.deleteBorders,
1749
- bottomBorder: true,
1750
- props: {
1751
- "data-item": "btn-tableActions-option",
1752
- ariaLabel: "Delete cell and table borders"
1753
- }
1754
- },
1755
- {
1756
- label: toolbarTexts2.mergeCells,
1757
- command: "mergeCells",
1758
- icon: toolbarIcons2.mergeCells,
1759
- props: {
1760
- "data-item": "btn-tableActions-option",
1761
- ariaLabel: "Merge cells"
1762
- }
1763
- },
1764
- {
1765
- label: toolbarTexts2.splitCell,
1766
- command: "splitCell",
1767
- icon: toolbarIcons2.splitCell,
1768
- props: {
1769
- "data-item": "btn-tableActions-option",
1770
- ariaLabel: "Split cells"
1771
- }
1772
- },
1773
- {
1774
- label: toolbarTexts2.fixTables,
1775
- command: "fixTables",
1776
- icon: toolbarIcons2.fixTables,
1777
- props: {
1778
- "data-item": "btn-tableActions-option",
1779
- ariaLabel: "Fix tables"
1780
- }
1781
- }
1782
- ];
1783
- function renderTableActions(tableActionsItem2) {
1784
- return h(TableActions, {
1785
- options: tableActionsOptions,
1786
- onSelect: (event) => {
1787
- closeDropdown(tableActionsItem2);
1788
- const { command } = event;
1789
- superToolbar.emitCommand({ item: tableActionsItem2, argument: { command } });
1790
- }
1791
- });
1792
- }
1793
- const alignment2 = useToolbarItem({
1794
- type: "dropdown",
1795
- name: "textAlign",
1796
- tooltip: toolbarTexts2.textAlign,
1797
- icon: toolbarIcons2.alignLeft,
1798
- command: "setTextAlign",
1799
- hasCaret: true,
1800
- markName: "textAlign",
1801
- labelAttr: "textAlign",
1802
- suppressActiveHighlight: true,
1803
- attributes: {
1804
- ariaLabel: "Text align"
1805
- },
1806
- options: [
1807
- {
1808
- type: "render",
1809
- render: () => {
1810
- const handleSelect = (e) => {
1811
- closeDropdown(alignment2);
1812
- const buttonWithCommand = { ...alignment2, command: "setTextAlign" };
1813
- buttonWithCommand.command = "setTextAlign";
1814
- superToolbar.emitCommand({ item: buttonWithCommand, argument: e });
1815
- setAlignmentIcon(alignment2, e);
1816
- };
1817
- return h("div", {}, [
1818
- h(AlignmentButtons, {
1819
- onSelect: handleSelect
1820
- })
1821
- ]);
1822
- },
1823
- key: "alignment"
1824
- }
1825
- ],
1826
- onActivate: ({ textAlign }) => {
1827
- setAlignmentIcon(alignment2, textAlign);
1412
+ ],
1413
+ onActivate: ({ textAlign }) => {
1414
+ setAlignmentIcon(alignment2, textAlign);
1828
1415
  },
1829
1416
  onDeactivate: () => {
1830
1417
  setAlignmentIcon(alignment2, "left");
@@ -2245,10 +1832,8 @@ const makeDefaultItems = ({
2245
1832
  colorButton,
2246
1833
  highlight,
2247
1834
  separator,
2248
- link,
2249
1835
  image,
2250
1836
  tableItem,
2251
- tableActionsItem,
2252
1837
  separator,
2253
1838
  alignment2,
2254
1839
  bulletedList,
@@ -2338,17 +1923,6 @@ const toolbarTexts = {
2338
1923
  link: "Link",
2339
1924
  image: "Image",
2340
1925
  table: "Insert table",
2341
- addRowBefore: "Insert row above",
2342
- addRowAfter: "Insert row below",
2343
- addColumnBefore: "Insert column left",
2344
- addColumnAfter: "Insert column right",
2345
- deleteRow: "Delete row",
2346
- deleteColumn: "Delete column",
2347
- deleteTable: "Delete table",
2348
- transparentBorders: "Transparent borders",
2349
- mergeCells: "Merge cells",
2350
- splitCell: "Split cell",
2351
- fixTables: "Fix tables",
2352
1926
  textAlign: "Alignment",
2353
1927
  bulletList: "Bullet list",
2354
1928
  numberedList: "Numbered list",
@@ -2603,35 +2177,6 @@ class SuperToolbar extends EventEmitter {
2603
2177
  }
2604
2178
  this.updateToolbarState();
2605
2179
  },
2606
- /**
2607
- * Toggles link formatting and updates cursor position
2608
- * @param {Object} params - Command parameters
2609
- * @param {CommandItem} params.item - The command item
2610
- * @param {*} params.argument - Command arguments
2611
- * @returns {void}
2612
- */
2613
- toggleLink: ({ item, argument }) => {
2614
- let command = item.command;
2615
- if (command in this.activeEditor.commands) {
2616
- this.activeEditor.commands[command](argument);
2617
- const { view } = this.activeEditor;
2618
- let { selection } = view.state;
2619
- if (this.activeEditor.options.isHeaderOrFooter) {
2620
- selection = this.activeEditor.options.lastSelection;
2621
- }
2622
- const endPos = selection.$to.pos;
2623
- const newSelection = new TextSelection(view.state.doc.resolve(endPos));
2624
- const tr = view.state.tr.setSelection(newSelection);
2625
- const state = view.state.apply(tr);
2626
- view.updateState(state);
2627
- if (!this.activeEditor.options.isHeaderOrFooter) {
2628
- setTimeout(() => {
2629
- view.focus();
2630
- }, 100);
2631
- }
2632
- }
2633
- this.updateToolbarState();
2634
- },
2635
2180
  /**
2636
2181
  * Inserts a table into the document
2637
2182
  * @param {Object} params - Command parameters
@@ -3020,76 +2565,1019 @@ runCommandWithArgumentOnly_fn = function({ item, argument, noArgumentCallback =
3020
2565
  this.updateToolbarState();
3021
2566
  }
3022
2567
  };
3023
- function adjustPaginationBreaks(editorElem, editor) {
3024
- if (!editorElem.value || !editor?.value?.options?.scale) return;
3025
- const zoom = editor.value.options.scale;
3026
- const bounds = editorElem.value.getBoundingClientRect();
3027
- const breakNodes = editorElem.value.querySelectorAll(".pagination-break-wrapper");
3028
- let firstLeft;
3029
- breakNodes.forEach((node) => {
3030
- const nodeBounds = node.getBoundingClientRect();
3031
- const left = (nodeBounds.left - bounds.left) / zoom * -1 + 1;
3032
- if (!firstLeft) firstLeft = left;
3033
- if (left !== firstLeft) {
3034
- const diff = left - firstLeft;
3035
- node.style.transform = `translateX(${diff}px)`;
2568
+ const plusIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 144L48 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l144 0 0 144c0 17.7 14.3 32 32 32s32-14.3 32-32l0-144 144 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-144 0 0-144z"/></svg>';
2569
+ const trashIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M135.2 17.7C140.6 6.8 151.7 0 163.8 0L284.2 0c12.1 0 23.2 6.8 28.6 17.7L320 32l96 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L32 96C14.3 96 0 81.7 0 64S14.3 32 32 32l96 0 7.2-14.3zM32 128l384 0 0 320c0 35.3-28.7 64-64 64L96 512c-35.3 0-64-28.7-64-64l0-320zm96 64c-8.8 0-16 7.2-16 16l0 224c0 8.8 7.2 16 16 16s16-7.2 16-16l0-224c0-8.8-7.2-16-16-16zm96 0c-8.8 0-16 7.2-16 16l0 224c0 8.8 7.2 16 16 16s16-7.2 16-16l0-224c0-8.8-7.2-16-16-16zm96 0c-8.8 0-16 7.2-16 16l0 224c0 8.8 7.2 16 16 16s16-7.2 16-16l0-224c0-8.8-7.2-16-16-16z"/></svg>';
2570
+ const wrenchIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M352 320c88.4 0 160-71.6 160-160c0-15.3-2.2-30.1-6.2-44.2c-3.1-10.8-16.4-13.2-24.3-5.3l-76.8 76.8c-3 3-7.1 4.7-11.3 4.7L336 192c-8.8 0-16-7.2-16-16l0-57.4c0-4.2 1.7-8.3 4.7-11.3l76.8-76.8c7.9-7.9 5.4-21.2-5.3-24.3C382.1 2.2 367.3 0 352 0C263.6 0 192 71.6 192 160c0 19.1 3.4 37.5 9.5 54.5L19.9 396.1C7.2 408.8 0 426.1 0 444.1C0 481.6 30.4 512 67.9 512c18 0 35.3-7.2 48-19.9L297.5 310.5c17 6.2 35.4 9.5 54.5 9.5zM80 408a24 24 0 1 1 0 48 24 24 0 1 1 0-48z"/></svg>';
2571
+ const borderNoneIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M32 480a32 32 0 1 1 0-64 32 32 0 1 1 0 64zm96-64a32 32 0 1 1 0 64 32 32 0 1 1 0-64zm0-384a32 32 0 1 1 0 64 32 32 0 1 1 0-64zm0 256a32 32 0 1 1 0-64 32 32 0 1 1 0 64zM320 416a32 32 0 1 1 0 64 32 32 0 1 1 0-64zm0-320a32 32 0 1 1 0-64 32 32 0 1 1 0 64zm0 128a32 32 0 1 1 0 64 32 32 0 1 1 0-64zM224 480a32 32 0 1 1 0-64 32 32 0 1 1 0 64zm0-448a32 32 0 1 1 0 64 32 32 0 1 1 0-64zm0 256a32 32 0 1 1 0-64 32 32 0 1 1 0 64zM416 416a32 32 0 1 1 0 64 32 32 0 1 1 0-64zm0-384a32 32 0 1 1 0 64 32 32 0 1 1 0-64zM32 96a32 32 0 1 1 0-64 32 32 0 1 1 0 64zM416 224a32 32 0 1 1 0 64 32 32 0 1 1 0-64zM32 288a32 32 0 1 1 0-64 32 32 0 1 1 0 64zm192 32a32 32 0 1 1 0 64 32 32 0 1 1 0-64zm192 64a32 32 0 1 1 0-64 32 32 0 1 1 0 64zM32 320a32 32 0 1 1 0 64 32 32 0 1 1 0-64zM416 192a32 32 0 1 1 0-64 32 32 0 1 1 0 64zM32 128a32 32 0 1 1 0 64 32 32 0 1 1 0-64zm192 64a32 32 0 1 1 0-64 32 32 0 1 1 0 64z"/></svg>';
2572
+ const arrowsLeftRightIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M406.6 374.6l96-96c12.5-12.5 12.5-32.8 0-45.3l-96-96c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L402.7 224l-293.5 0 41.4-41.4c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-96 96c-12.5 12.5-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 288l293.5 0-41.4 41.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0z"/></svg>';
2573
+ const arrowsToDotIconSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M256 0c17.7 0 32 14.3 32 32l0 32 32 0c12.9 0 24.6 7.8 29.6 19.8s2.2 25.7-6.9 34.9l-64 64c-12.5 12.5-32.8 12.5-45.3 0l-64-64c-9.2-9.2-11.9-22.9-6.9-34.9s16.6-19.8 29.6-19.8l32 0 0-32c0-17.7 14.3-32 32-32zM169.4 393.4l64-64c12.5-12.5 32.8-12.5 45.3 0l64 64c9.2 9.2 11.9 22.9 6.9 34.9s-16.6 19.8-29.6 19.8l-32 0 0 32c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-32-32 0c-12.9 0-24.6-7.8-29.6-19.8s-2.2-25.7 6.9-34.9zM32 224l32 0 0-32c0-12.9 7.8-24.6 19.8-29.6s25.7-2.2 34.9 6.9l64 64c12.5 12.5 12.5 32.8 0 45.3l-64 64c-9.2 9.2-22.9 11.9-34.9 6.9s-19.8-16.6-19.8-29.6l0-32-32 0c-17.7 0-32-14.3-32-32s14.3-32 32-32zm297.4 54.6c-12.5-12.5-12.5-32.8 0-45.3l64-64c9.2-9.2 22.9-11.9 34.9-6.9s19.8 16.6 19.8 29.6l0 32 32 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-32 0 0 32c0 12.9-7.8 24.6-19.8 29.6s-25.7 2.2-34.9-6.9l-64-64zM256 224a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/></svg>';
2574
+ const ICONS = {
2575
+ addRowBefore: plusIconSvg,
2576
+ addRowAfter: plusIconSvg,
2577
+ addColumnBefore: plusIconSvg,
2578
+ addColumnAfter: plusIconSvg,
2579
+ deleteRow: trashIconSvg,
2580
+ deleteColumn: trashIconSvg,
2581
+ deleteTable: trashIconSvg,
2582
+ deleteBorders: borderNoneIconSvg,
2583
+ mergeCells: arrowsToDotIconSvg,
2584
+ splitCell: arrowsLeftRightIconSvg,
2585
+ fixTables: wrenchIconSvg,
2586
+ ai: magicWandIcon,
2587
+ link: linkIconSvg,
2588
+ table: tableIconSvg,
2589
+ cut: scissorsIconSvg,
2590
+ copy: copyIconSvg,
2591
+ paste: pasteIconSvg
2592
+ };
2593
+ const TEXTS = {
2594
+ addRowBefore: "Insert row above",
2595
+ addRowAfter: "Insert row below",
2596
+ addColumnBefore: "Insert column left",
2597
+ addColumnAfter: "Insert column right",
2598
+ deleteRow: "Delete row",
2599
+ deleteColumn: "Delete column",
2600
+ deleteTable: "Delete table",
2601
+ transparentBorders: "Transparent borders",
2602
+ mergeCells: "Merge cells",
2603
+ splitCell: "Split cell",
2604
+ fixTables: "Fix tables",
2605
+ insertText: "Insert text",
2606
+ replaceText: "Replace text",
2607
+ insertLink: "Insert link",
2608
+ insertTable: "Insert table",
2609
+ editTable: "Edit table",
2610
+ cut: "Cut",
2611
+ copy: "Copy",
2612
+ paste: "Paste"
2613
+ };
2614
+ const tableActionsOptions = [
2615
+ {
2616
+ label: TEXTS.addRowBefore,
2617
+ command: "addRowBefore",
2618
+ icon: ICONS.addRowBefore,
2619
+ props: {
2620
+ "data-item": "btn-tableActions-option",
2621
+ ariaLabel: "Add row before"
3036
2622
  }
3037
- });
3038
- }
3039
- const onMarginClickCursorChange = (event, editor) => {
3040
- const y = event.clientY;
3041
- const x = event.clientX;
3042
- const { view } = editor;
3043
- const editorRect = view.dom.getBoundingClientRect();
3044
- let coords = {
3045
- left: 0,
3046
- top: y
2623
+ },
2624
+ {
2625
+ label: TEXTS.addRowAfter,
2626
+ command: "addRowAfter",
2627
+ icon: ICONS.addRowAfter,
2628
+ props: {
2629
+ "data-item": "btn-tableActions-option",
2630
+ ariaLabel: "Add row after"
2631
+ }
2632
+ },
2633
+ {
2634
+ label: TEXTS.addColumnBefore,
2635
+ command: "addColumnBefore",
2636
+ icon: ICONS.addColumnBefore,
2637
+ props: {
2638
+ "data-item": "btn-tableActions-option",
2639
+ ariaLabel: "Add column before"
2640
+ }
2641
+ },
2642
+ {
2643
+ label: TEXTS.addColumnAfter,
2644
+ command: "addColumnAfter",
2645
+ icon: ICONS.addColumnAfter,
2646
+ bottomBorder: true,
2647
+ props: {
2648
+ "data-item": "btn-tableActions-option",
2649
+ ariaLabel: "Add column after"
2650
+ }
2651
+ },
2652
+ {
2653
+ label: TEXTS.deleteRow,
2654
+ command: "deleteRow",
2655
+ icon: ICONS.deleteRow,
2656
+ props: {
2657
+ "data-item": "btn-tableActions-option",
2658
+ ariaLabel: "Delete row"
2659
+ }
2660
+ },
2661
+ {
2662
+ label: TEXTS.deleteColumn,
2663
+ command: "deleteColumn",
2664
+ icon: ICONS.deleteColumn,
2665
+ props: {
2666
+ "data-item": "btn-tableActions-option",
2667
+ ariaLabel: "Delete column"
2668
+ }
2669
+ },
2670
+ {
2671
+ label: TEXTS.deleteTable,
2672
+ command: "deleteTable",
2673
+ icon: ICONS.deleteTable,
2674
+ props: {
2675
+ "data-item": "btn-tableActions-option",
2676
+ ariaLabel: "Delete table"
2677
+ }
2678
+ },
2679
+ {
2680
+ label: TEXTS.transparentBorders,
2681
+ command: "deleteCellAndTableBorders",
2682
+ icon: ICONS.deleteBorders,
2683
+ bottomBorder: true,
2684
+ props: {
2685
+ "data-item": "btn-tableActions-option",
2686
+ ariaLabel: "Delete cell and table borders"
2687
+ }
2688
+ },
2689
+ {
2690
+ label: TEXTS.mergeCells,
2691
+ command: "mergeCells",
2692
+ icon: ICONS.mergeCells,
2693
+ props: {
2694
+ "data-item": "btn-tableActions-option",
2695
+ ariaLabel: "Merge cells"
2696
+ }
2697
+ },
2698
+ {
2699
+ label: TEXTS.splitCell,
2700
+ command: "splitCell",
2701
+ icon: ICONS.splitCell,
2702
+ props: {
2703
+ "data-item": "btn-tableActions-option",
2704
+ ariaLabel: "Split cells"
2705
+ }
2706
+ },
2707
+ {
2708
+ label: TEXTS.fixTables,
2709
+ command: "fixTables",
2710
+ icon: ICONS.fixTables,
2711
+ props: {
2712
+ "data-item": "btn-tableActions-option",
2713
+ ariaLabel: "Fix tables"
2714
+ }
2715
+ }
2716
+ ];
2717
+ const TRIGGERS = {
2718
+ slash: "slash",
2719
+ click: "click"
2720
+ };
2721
+ const getPropsByItemId = (itemId, props) => {
2722
+ const editor = props.editor;
2723
+ const baseProps = {
2724
+ editor: markRaw(props.editor)
3047
2725
  };
3048
- let isRightMargin = false;
3049
- if (x > editorRect.right) {
3050
- coords.left = editorRect.left + editorRect.width - 1;
3051
- isRightMargin = true;
3052
- } else if (x < editorRect.left) {
3053
- coords.left = editorRect.left;
2726
+ switch (itemId) {
2727
+ case "insert-text":
2728
+ const { state } = editor.view;
2729
+ const { from, to, empty } = state.selection;
2730
+ const selectedText = !empty ? state.doc.textBetween(from, to) : "";
2731
+ return {
2732
+ ...baseProps,
2733
+ selectedText,
2734
+ handleClose: props.closePopover || (() => null),
2735
+ apiKey: editor.options?.aiApiKey,
2736
+ endpoint: editor.options?.aiEndpoint
2737
+ };
2738
+ case "insert-link":
2739
+ return baseProps;
2740
+ case "insert-table":
2741
+ return {
2742
+ ...baseProps,
2743
+ onSelect: ({ rows, cols }) => {
2744
+ editor.commands.insertTable({ rows, cols });
2745
+ props.closePopover();
2746
+ }
2747
+ };
2748
+ case "edit-table":
2749
+ return {
2750
+ ...baseProps,
2751
+ options: tableActionsOptions,
2752
+ onSelect: ({ command }) => {
2753
+ if (editor.commands[command]) {
2754
+ editor.commands[command]();
2755
+ }
2756
+ props.closePopover();
2757
+ }
2758
+ };
2759
+ case "copy":
2760
+ case "paste":
2761
+ return {
2762
+ ...baseProps
2763
+ // These actions don't need additional props
2764
+ };
2765
+ default:
2766
+ return baseProps;
3054
2767
  }
3055
- const pos = view.posAtCoords(coords)?.pos;
3056
- if (pos) {
3057
- let cursorPos = pos;
3058
- if (isRightMargin) {
3059
- const $pos = view.state.doc.resolve(pos);
3060
- const charOffset = $pos.textOffset;
3061
- const node = view.state.doc.nodeAt(pos);
3062
- const text = node?.text;
3063
- const charAtPos = text?.charAt(charOffset);
3064
- cursorPos = node?.isText && charAtPos !== " " ? pos - 1 : pos;
3065
- }
3066
- const transaction = view.state.tr.setSelection(
3067
- TextSelection.create(view.state.doc, cursorPos)
3068
- );
3069
- view.dispatch(transaction);
3070
- view.focus();
2768
+ };
2769
+ async function getEditorContext(editor, event) {
2770
+ const { view } = editor;
2771
+ const { state } = view;
2772
+ const { from, to, empty } = state.selection;
2773
+ const selectedText = !empty ? state.doc.textBetween(from, to) : "";
2774
+ let pos = null;
2775
+ let node = null;
2776
+ if (event) {
2777
+ const coords = { left: event.clientX, top: event.clientY };
2778
+ pos = view.posAtCoords(coords)?.pos ?? null;
2779
+ node = pos !== null ? state.doc.nodeAt(pos) : null;
2780
+ } else {
2781
+ pos = from;
2782
+ node = state.doc.nodeAt(pos);
3071
2783
  }
2784
+ const clipboardContent = await readFromClipboard(state);
2785
+ return {
2786
+ editor,
2787
+ selectedText,
2788
+ pos,
2789
+ node,
2790
+ event,
2791
+ clipboardContent
2792
+ };
2793
+ }
2794
+ const _hoisted_1$5 = {
2795
+ key: 0,
2796
+ class: "link-title"
3072
2797
  };
3073
- const _hoisted_1$2 = { class: "numbering" };
3074
- const MIN_WIDTH = 200;
3075
- const alignment = "flex-end";
3076
- const _sfc_main$3 = {
3077
- __name: "Ruler",
2798
+ const _hoisted_2$3 = {
2799
+ key: 1,
2800
+ class: "link-title"
2801
+ };
2802
+ const _hoisted_3$3 = {
2803
+ key: 2,
2804
+ class: "link-title"
2805
+ };
2806
+ const _hoisted_4$2 = { key: 3 };
2807
+ const _hoisted_5$1 = { class: "input-row" };
2808
+ const _hoisted_6 = ["innerHTML"];
2809
+ const _hoisted_7 = ["onKeydown"];
2810
+ const _hoisted_8 = ["innerHTML"];
2811
+ const _hoisted_9 = { class: "input-row link-buttons" };
2812
+ const _hoisted_10 = ["innerHTML"];
2813
+ const _hoisted_11 = {
2814
+ key: 4,
2815
+ class: "input-row go-to-anchor clickable"
2816
+ };
2817
+ const _sfc_main$7 = {
2818
+ __name: "LinkInput",
3078
2819
  props: {
3079
- orientation: {
3080
- type: String,
3081
- default: "horizontal"
2820
+ showInput: {
2821
+ type: Boolean,
2822
+ default: true
3082
2823
  },
3083
- length: {
3084
- type: Number,
3085
- default: 0
2824
+ showLink: {
2825
+ type: Boolean,
2826
+ default: true
2827
+ },
2828
+ goToAnchor: {
2829
+ type: Function,
2830
+ default: () => {
2831
+ }
3086
2832
  },
3087
2833
  editor: {
3088
2834
  type: Object,
3089
2835
  required: true
3090
- }
3091
- },
3092
- emits: ["margin-change"],
2836
+ },
2837
+ closePopover: {
2838
+ type: Function,
2839
+ default: () => {
2840
+ }
2841
+ }
2842
+ },
2843
+ setup(__props) {
2844
+ const props = __props;
2845
+ const { isHighContrastMode } = useHighContrastMode();
2846
+ const urlError = ref(false);
2847
+ const getSelectedText = () => {
2848
+ if (!props.editor || !props.editor.state) return "";
2849
+ const { state } = props.editor;
2850
+ const { from, to } = state.selection;
2851
+ return state.doc.textBetween(from, to, " ");
2852
+ };
2853
+ const getLinkHrefAtSelection = () => {
2854
+ if (!props.editor || !props.editor.state) return "";
2855
+ const { state } = props.editor;
2856
+ const { schema, selection } = state;
2857
+ const linkMark = schema.marks.link;
2858
+ if (!linkMark) return "";
2859
+ let href = "";
2860
+ const { $from, empty } = selection;
2861
+ if (empty) {
2862
+ const marks = state.storedMarks || $from.marks();
2863
+ const link = marks.find((mark) => mark.type === linkMark);
2864
+ if (link) href = link.attrs.href;
2865
+ } else {
2866
+ state.doc.nodesBetween(selection.from, selection.to, (node) => {
2867
+ if (node.marks) {
2868
+ const link = node.marks.find((mark) => mark.type === linkMark);
2869
+ if (link) href = link.attrs.href;
2870
+ }
2871
+ });
2872
+ }
2873
+ return href || "";
2874
+ };
2875
+ const text = ref("");
2876
+ const rawUrl = ref("");
2877
+ const isAnchor = ref(false);
2878
+ const url = computed(() => {
2879
+ if (!rawUrl.value?.startsWith("http")) return "http://" + rawUrl.value;
2880
+ return rawUrl.value;
2881
+ });
2882
+ const validUrl = computed(() => {
2883
+ const urlSplit = url.value.split(".").filter(Boolean);
2884
+ return url.value.includes(".") && urlSplit.length > 1;
2885
+ });
2886
+ const isEditing = computed(() => !isAnchor.value && !!getLinkHrefAtSelection());
2887
+ const getApplyText = computed(() => showApply.value ? "Apply" : "Remove");
2888
+ const isDisabled = computed(() => !validUrl.value);
2889
+ const showApply = computed(() => !showRemove.value);
2890
+ const showRemove = computed(() => rawUrl.value === "" && getLinkHrefAtSelection());
2891
+ const openLink = () => {
2892
+ window.open(url.value, "_blank");
2893
+ };
2894
+ const updateFromEditor = () => {
2895
+ text.value = getSelectedText();
2896
+ rawUrl.value = getLinkHrefAtSelection();
2897
+ };
2898
+ watch(
2899
+ () => props.editor?.state?.selection,
2900
+ () => {
2901
+ updateFromEditor();
2902
+ },
2903
+ { immediate: true }
2904
+ );
2905
+ const focusInput = () => {
2906
+ const input = document.querySelector(".link-input-ctn input");
2907
+ if (!input) return;
2908
+ input.focus();
2909
+ };
2910
+ onMounted(() => {
2911
+ updateFromEditor();
2912
+ isAnchor.value = rawUrl.value.startsWith("#");
2913
+ if (props.showInput) focusInput();
2914
+ });
2915
+ const handleSubmit = () => {
2916
+ if (rawUrl.value && validUrl.value) {
2917
+ if (props.editor && props.editor.commands && props.editor.commands.toggleLink) {
2918
+ props.editor.commands.toggleLink({ href: url.value, text: text.value });
2919
+ const { view } = props.editor;
2920
+ let { selection } = view.state;
2921
+ const endPos = selection.$to.pos;
2922
+ const tr = view.state.tr.setSelection(new TextSelection(view.state.doc.resolve(endPos)));
2923
+ const state = view.state.apply(tr);
2924
+ view.updateState(state);
2925
+ setTimeout(() => {
2926
+ view.focus();
2927
+ }, 100);
2928
+ }
2929
+ props.closePopover();
2930
+ return;
2931
+ } else if (!rawUrl.value) {
2932
+ if (props.editor && props.editor.commands && props.editor.commands.unsetLink) {
2933
+ props.editor.commands.unsetLink();
2934
+ }
2935
+ props.closePopover();
2936
+ return;
2937
+ }
2938
+ urlError.value = true;
2939
+ };
2940
+ const handleRemove = () => {
2941
+ if (props.editor && props.editor.commands && props.editor.commands.unsetLink) {
2942
+ props.editor.commands.unsetLink();
2943
+ props.closePopover();
2944
+ }
2945
+ };
2946
+ return (_ctx, _cache) => {
2947
+ return openBlock(), createElementBlock("div", {
2948
+ class: normalizeClass(["link-input-ctn", { "high-contrast": unref(isHighContrastMode) }])
2949
+ }, [
2950
+ isAnchor.value ? (openBlock(), createElementBlock("div", _hoisted_1$5, "Page anchor")) : isEditing.value ? (openBlock(), createElementBlock("div", _hoisted_2$3, "Edit link")) : (openBlock(), createElementBlock("div", _hoisted_3$3, "Add link")),
2951
+ __props.showInput && !isAnchor.value ? (openBlock(), createElementBlock("div", _hoisted_4$2, [
2952
+ createElementVNode("div", _hoisted_5$1, [
2953
+ createElementVNode("div", {
2954
+ class: "input-icon",
2955
+ innerHTML: unref(toolbarIcons).linkInput
2956
+ }, null, 8, _hoisted_6),
2957
+ withDirectives(createElementVNode("input", {
2958
+ type: "text",
2959
+ name: "link",
2960
+ placeholder: "Type or paste a link",
2961
+ class: normalizeClass({ error: urlError.value }),
2962
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => rawUrl.value = $event),
2963
+ onKeydown: [
2964
+ withKeys(withModifiers(handleSubmit, ["stop", "prevent"]), ["enter"]),
2965
+ _cache[1] || (_cache[1] = ($event) => urlError.value = false)
2966
+ ]
2967
+ }, null, 42, _hoisted_7), [
2968
+ [vModelText, rawUrl.value]
2969
+ ]),
2970
+ createElementVNode("div", {
2971
+ class: normalizeClass(["open-link-icon", { disabled: !validUrl.value }]),
2972
+ innerHTML: unref(toolbarIcons).openLink,
2973
+ onClick: openLink,
2974
+ "data-item": "btn-link-open"
2975
+ }, null, 10, _hoisted_8)
2976
+ ]),
2977
+ createElementVNode("div", _hoisted_9, [
2978
+ rawUrl.value ? (openBlock(), createElementBlock("button", {
2979
+ key: 0,
2980
+ class: "remove-btn",
2981
+ onClick: handleRemove,
2982
+ "data-item": "btn-link-remove"
2983
+ }, [
2984
+ createElementVNode("div", {
2985
+ class: "remove-btn__icon",
2986
+ innerHTML: unref(toolbarIcons).removeLink
2987
+ }, null, 8, _hoisted_10),
2988
+ _cache[3] || (_cache[3] = createTextVNode(" Remove "))
2989
+ ])) : createCommentVNode("", true),
2990
+ showApply.value ? (openBlock(), createElementBlock("button", {
2991
+ key: 1,
2992
+ class: normalizeClass(["submit-btn", { "disable-btn": isDisabled.value }]),
2993
+ onClick: handleSubmit,
2994
+ "data-item": "btn-link-apply"
2995
+ }, toDisplayString(getApplyText.value), 3)) : createCommentVNode("", true)
2996
+ ])
2997
+ ])) : isAnchor.value ? (openBlock(), createElementBlock("div", _hoisted_11, [
2998
+ createElementVNode("a", {
2999
+ onClick: _cache[2] || (_cache[2] = withModifiers((...args) => __props.goToAnchor && __props.goToAnchor(...args), ["stop", "prevent"]))
3000
+ }, "Go to " + toDisplayString(rawUrl.value.startsWith("#_") ? rawUrl.value.substring(2) : rawUrl.value), 1)
3001
+ ])) : createCommentVNode("", true)
3002
+ ], 2);
3003
+ };
3004
+ }
3005
+ };
3006
+ const LinkInput = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-2632571a"]]);
3007
+ const onMarginClickCursorChange = (event, editor) => {
3008
+ const y = event.clientY;
3009
+ const x = event.clientX;
3010
+ const { view } = editor;
3011
+ const editorRect = view.dom.getBoundingClientRect();
3012
+ let coords = {
3013
+ left: 0,
3014
+ top: y
3015
+ };
3016
+ let isRightMargin = false;
3017
+ if (x > editorRect.right) {
3018
+ coords.left = editorRect.left + editorRect.width - 1;
3019
+ isRightMargin = true;
3020
+ } else if (x < editorRect.left) {
3021
+ coords.left = editorRect.left;
3022
+ }
3023
+ const pos = view.posAtCoords(coords)?.pos;
3024
+ if (pos) {
3025
+ let cursorPos = pos;
3026
+ if (isRightMargin) {
3027
+ const $pos = view.state.doc.resolve(pos);
3028
+ const charOffset = $pos.textOffset;
3029
+ const node = view.state.doc.nodeAt(pos);
3030
+ const text = node?.text;
3031
+ const charAtPos = text?.charAt(charOffset);
3032
+ cursorPos = node?.isText && charAtPos !== " " ? pos - 1 : pos;
3033
+ }
3034
+ const transaction = view.state.tr.setSelection(
3035
+ TextSelection.create(view.state.doc, cursorPos)
3036
+ );
3037
+ view.dispatch(transaction);
3038
+ view.focus();
3039
+ }
3040
+ };
3041
+ const checkNodeSpecificClicks = (editor, event, popoverControls) => {
3042
+ if (!editor) return;
3043
+ if (selectionHasNodeOrMark(editor.view.state, "link", { requireEnds: true })) {
3044
+ popoverControls.component = LinkInput;
3045
+ popoverControls.position = {
3046
+ left: `${event.clientX - editor.element.getBoundingClientRect().left}px`,
3047
+ top: `${event.clientY - editor.element.getBoundingClientRect().top + 15}px`
3048
+ };
3049
+ popoverControls.props = {
3050
+ showInput: true
3051
+ };
3052
+ popoverControls.visible = true;
3053
+ }
3054
+ };
3055
+ function selectionHasNodeOrMark(state, name, options = {}) {
3056
+ const { requireEnds = false } = options;
3057
+ const $from = state.selection.$from;
3058
+ const $to = state.selection.$to;
3059
+ if (requireEnds) {
3060
+ for (let d = $from.depth; d > 0; d--) {
3061
+ if ($from.node(d).type.name === name) {
3062
+ return true;
3063
+ }
3064
+ }
3065
+ for (let d = $to.depth; d > 0; d--) {
3066
+ if ($to.node(d).type.name === name) {
3067
+ return true;
3068
+ }
3069
+ }
3070
+ } else {
3071
+ for (let d = $from.depth; d > 0; d--) {
3072
+ if ($from.node(d).type.name === name) {
3073
+ return true;
3074
+ }
3075
+ }
3076
+ }
3077
+ const markType = state.schema.marks[name];
3078
+ if (markType) {
3079
+ const { from, to, empty } = state.selection;
3080
+ if (requireEnds) {
3081
+ const fromMarks = markType.isInSet($from.marks());
3082
+ const toMarks = markType.isInSet($to.marks());
3083
+ if (fromMarks || toMarks) {
3084
+ return true;
3085
+ }
3086
+ if (empty && markType.isInSet(state.storedMarks || $from.marks())) {
3087
+ return true;
3088
+ }
3089
+ } else {
3090
+ if (empty) {
3091
+ if (markType.isInSet(state.storedMarks || $from.marks())) {
3092
+ return true;
3093
+ }
3094
+ } else {
3095
+ let hasMark = false;
3096
+ state.doc.nodesBetween(from, to, (node) => {
3097
+ if (markType.isInSet(node.marks)) {
3098
+ hasMark = true;
3099
+ return false;
3100
+ }
3101
+ });
3102
+ if (hasMark) return true;
3103
+ }
3104
+ }
3105
+ }
3106
+ return false;
3107
+ }
3108
+ function moveCursorToMouseEvent(event, editor) {
3109
+ const { view } = editor;
3110
+ const coords = { left: event.clientX, top: event.clientY };
3111
+ const pos = view.posAtCoords(coords)?.pos;
3112
+ if (typeof pos === "number") {
3113
+ const tr = view.state.tr.setSelection(
3114
+ TextSelection.create(view.state.doc, pos)
3115
+ );
3116
+ view.dispatch(tr);
3117
+ view.focus();
3118
+ }
3119
+ }
3120
+ const _hoisted_1$4 = { class: "toolbar-table-actions" };
3121
+ const _hoisted_2$2 = ["onClick", "data-item", "ariaLabel"];
3122
+ const _hoisted_3$2 = { class: "toolbar-table-actions__icon" };
3123
+ const _hoisted_4$1 = ["innerHTML"];
3124
+ const _hoisted_5 = { class: "toolbar-table-actions__label" };
3125
+ const _sfc_main$6 = {
3126
+ __name: "TableActions",
3127
+ props: {
3128
+ options: {
3129
+ type: Array
3130
+ }
3131
+ },
3132
+ emits: ["select"],
3133
+ setup(__props, { emit: __emit }) {
3134
+ const emit = __emit;
3135
+ const handleClick = (item) => {
3136
+ emit("select", { command: item.command });
3137
+ };
3138
+ return (_ctx, _cache) => {
3139
+ return openBlock(), createElementBlock("div", _hoisted_1$4, [
3140
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.options, (option) => {
3141
+ return openBlock(), createElementBlock("div", {
3142
+ class: normalizeClass(["toolbar-table-actions__item", { "toolbar-table-actions__item--border": option.bottomBorder }]),
3143
+ onClick: ($event) => handleClick(option),
3144
+ "data-item": option.props?.["data-item"] || "",
3145
+ ariaLabel: option.props?.ariaLabel,
3146
+ role: "menuitem"
3147
+ }, [
3148
+ createElementVNode("div", _hoisted_3$2, [
3149
+ createElementVNode("div", {
3150
+ class: "toolbar-table-actions__icon-wrapper",
3151
+ innerHTML: option.icon
3152
+ }, null, 8, _hoisted_4$1)
3153
+ ]),
3154
+ createElementVNode("div", _hoisted_5, toDisplayString(option.label), 1)
3155
+ ], 10, _hoisted_2$2);
3156
+ }), 256))
3157
+ ]);
3158
+ };
3159
+ }
3160
+ };
3161
+ const TableActions = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__scopeId", "data-v-f82e859a"]]);
3162
+ const isModuleEnabled = (editorOptions, moduleName) => {
3163
+ switch (moduleName) {
3164
+ case "ai":
3165
+ return !!editorOptions?.isAiEnabled;
3166
+ default:
3167
+ return true;
3168
+ }
3169
+ };
3170
+ function getItems(context) {
3171
+ const { editor, selectedText, trigger, clipboardContent } = context;
3172
+ const isInTable2 = selectionHasNodeOrMark(editor.view.state, "table", { requireEnds: true });
3173
+ const sections = [
3174
+ {
3175
+ id: "ai-content",
3176
+ items: [
3177
+ {
3178
+ id: "insert-text",
3179
+ label: selectedText ? TEXTS.replaceText : TEXTS.insertText,
3180
+ icon: ICONS.ai,
3181
+ component: AIWriter,
3182
+ action: (editor2) => {
3183
+ if (editor2?.commands && typeof editor2.commands?.insertAiMark === "function") {
3184
+ editor2.commands.insertAiMark();
3185
+ }
3186
+ },
3187
+ allowedTriggers: [TRIGGERS.slash, TRIGGERS.click],
3188
+ requiresModule: "ai"
3189
+ }
3190
+ ]
3191
+ },
3192
+ {
3193
+ id: "general",
3194
+ items: [
3195
+ {
3196
+ id: "insert-link",
3197
+ label: TEXTS.insertLink,
3198
+ icon: ICONS.link,
3199
+ component: LinkInput,
3200
+ allowedTriggers: [TRIGGERS.click]
3201
+ },
3202
+ {
3203
+ id: "insert-table",
3204
+ label: TEXTS.insertTable,
3205
+ icon: ICONS.table,
3206
+ component: TableGrid,
3207
+ allowedTriggers: [TRIGGERS.slash, TRIGGERS.click]
3208
+ },
3209
+ {
3210
+ id: "edit-table",
3211
+ label: TEXTS.editTable,
3212
+ icon: ICONS.table,
3213
+ component: TableActions,
3214
+ allowedTriggers: [TRIGGERS.slash, TRIGGERS.click],
3215
+ requiresTableParent: true
3216
+ }
3217
+ ]
3218
+ },
3219
+ {
3220
+ id: "clipboard",
3221
+ items: [
3222
+ {
3223
+ id: "cut",
3224
+ label: TEXTS.cut,
3225
+ icon: ICONS.cut,
3226
+ action: async (editor2) => {
3227
+ const { state, dispatch } = editor2.view;
3228
+ const { htmlString, text } = serializeSelectionToClipboard(state);
3229
+ await writeToClipboard({ htmlString, text });
3230
+ const { from, to } = state.selection;
3231
+ dispatch(state.tr.delete(from, to));
3232
+ },
3233
+ allowedTriggers: [TRIGGERS.click],
3234
+ requiresSelection: true
3235
+ },
3236
+ {
3237
+ id: "copy",
3238
+ label: TEXTS.copy,
3239
+ icon: ICONS.copy,
3240
+ action: async (editor2) => {
3241
+ const { state } = editor2.view;
3242
+ const { htmlString, text } = serializeSelectionToClipboard(state);
3243
+ await writeToClipboard({ htmlString, text });
3244
+ },
3245
+ allowedTriggers: [TRIGGERS.click],
3246
+ requiresSelection: true
3247
+ },
3248
+ {
3249
+ id: "paste",
3250
+ label: TEXTS.paste,
3251
+ icon: ICONS.paste,
3252
+ action: async (editor2) => {
3253
+ try {
3254
+ const clipboardData = await navigator.clipboard.read();
3255
+ const event = new ClipboardEvent("paste", {
3256
+ clipboardData: new DataTransfer(),
3257
+ bubbles: true,
3258
+ cancelable: true
3259
+ });
3260
+ for (const item of clipboardData) {
3261
+ for (const type of item.types) {
3262
+ const blob = await item.getType(type);
3263
+ event.clipboardData.setData(type, await blob.text());
3264
+ }
3265
+ }
3266
+ editor2.view.dom.dispatchEvent(event);
3267
+ } catch (error) {
3268
+ console.warn("Failed to paste:", error);
3269
+ }
3270
+ },
3271
+ allowedTriggers: [TRIGGERS.click, TRIGGERS.slash],
3272
+ requiresClipboard: true
3273
+ }
3274
+ ]
3275
+ }
3276
+ ];
3277
+ const filteredSections = sections.map((section) => {
3278
+ const filteredItems = section.items.filter((item) => {
3279
+ if (item.requiresModule && !isModuleEnabled(editor?.options, item.requiresModule)) return false;
3280
+ if (item.requiresSelection && !selectedText) return false;
3281
+ if (!item.allowedTriggers.includes(trigger)) return false;
3282
+ if (item.requiresClipboard && !clipboardContent) return false;
3283
+ if (item.requiresTableParent && !isInTable2 || item.id === "insert-table" && isInTable2) return false;
3284
+ return true;
3285
+ });
3286
+ return {
3287
+ ...section,
3288
+ items: filteredItems
3289
+ };
3290
+ }).filter((section) => section.items.length > 0);
3291
+ return filteredSections;
3292
+ }
3293
+ const _hoisted_1$3 = { class: "slash-menu-items" };
3294
+ const _hoisted_2$1 = {
3295
+ key: 0,
3296
+ class: "slash-menu-divider",
3297
+ tabindex: "0"
3298
+ };
3299
+ const _hoisted_3$1 = ["onClick"];
3300
+ const _hoisted_4 = ["innerHTML"];
3301
+ const _sfc_main$5 = {
3302
+ __name: "SlashMenu",
3303
+ props: {
3304
+ editor: {
3305
+ type: Object,
3306
+ required: true
3307
+ },
3308
+ openPopover: {
3309
+ type: Function,
3310
+ required: true
3311
+ },
3312
+ closePopover: {
3313
+ type: Function,
3314
+ required: true
3315
+ }
3316
+ },
3317
+ setup(__props) {
3318
+ const props = __props;
3319
+ const searchInput = ref(null);
3320
+ const searchQuery = ref("");
3321
+ const isOpen = ref(false);
3322
+ const menuPosition = ref({ left: "0px", top: "0px" });
3323
+ const menuRef = ref(null);
3324
+ const sections = ref([]);
3325
+ const selectedId = ref(null);
3326
+ const flattenedItems = computed(() => {
3327
+ const items = [];
3328
+ sections.value.forEach((section) => {
3329
+ section.items.forEach((item) => {
3330
+ items.push(item);
3331
+ });
3332
+ });
3333
+ return items;
3334
+ });
3335
+ const filteredItems = computed(() => {
3336
+ if (!searchQuery.value) {
3337
+ return flattenedItems.value;
3338
+ }
3339
+ return flattenedItems.value.filter(
3340
+ (item) => item.label?.toLowerCase().includes(searchQuery.value.toLowerCase())
3341
+ );
3342
+ });
3343
+ const filteredSections = computed(() => {
3344
+ if (!searchQuery.value) {
3345
+ return sections.value;
3346
+ }
3347
+ return [{
3348
+ id: "search-results",
3349
+ items: filteredItems.value
3350
+ }];
3351
+ });
3352
+ watch(isOpen, (open) => {
3353
+ if (open) {
3354
+ nextTick(() => {
3355
+ if (searchInput.value) {
3356
+ searchInput.value.focus();
3357
+ }
3358
+ });
3359
+ }
3360
+ });
3361
+ watch(flattenedItems, (newItems) => {
3362
+ if (newItems.length > 0) {
3363
+ selectedId.value = newItems[0].id;
3364
+ }
3365
+ });
3366
+ const handleGlobalKeyDown = (event) => {
3367
+ if (event.key === "Escape") {
3368
+ event.preventDefault();
3369
+ event.stopPropagation();
3370
+ closeMenu();
3371
+ props.editor?.view?.focus();
3372
+ return;
3373
+ }
3374
+ if (isOpen.value && (event.target === searchInput.value || menuRef.value && menuRef.value.contains(event.target))) {
3375
+ const currentItems = filteredItems.value;
3376
+ const currentIndex = currentItems.findIndex((item) => item.id === selectedId.value);
3377
+ switch (event.key) {
3378
+ case "ArrowDown": {
3379
+ event.preventDefault();
3380
+ if (currentIndex < currentItems.length - 1) {
3381
+ selectedId.value = currentItems[currentIndex + 1].id;
3382
+ }
3383
+ break;
3384
+ }
3385
+ case "ArrowUp": {
3386
+ event.preventDefault();
3387
+ if (currentIndex > 0) {
3388
+ selectedId.value = currentItems[currentIndex - 1].id;
3389
+ }
3390
+ break;
3391
+ }
3392
+ case "Enter": {
3393
+ event.preventDefault();
3394
+ const selectedItem = currentItems.find((item) => item.id === selectedId.value);
3395
+ if (selectedItem) {
3396
+ executeCommand(selectedItem);
3397
+ }
3398
+ break;
3399
+ }
3400
+ }
3401
+ }
3402
+ };
3403
+ const handleGlobalOutsideClick = (event) => {
3404
+ if (isOpen.value && menuRef.value && !menuRef.value.contains(event.target)) {
3405
+ moveCursorToMouseEvent(event, props.editor);
3406
+ closeMenu({ restoreCursor: false });
3407
+ }
3408
+ };
3409
+ const handleRightClick = async (event) => {
3410
+ if (event.ctrlKey) {
3411
+ return;
3412
+ }
3413
+ event.preventDefault();
3414
+ props.editor.view.dispatch(
3415
+ props.editor.view.state.tr.setMeta(SlashMenuPluginKey, {
3416
+ type: "open",
3417
+ pos: props.editor.view.state.selection.from,
3418
+ clientX: event.clientX,
3419
+ clientY: event.clientY
3420
+ })
3421
+ );
3422
+ searchQuery.value = "";
3423
+ const context = await getEditorContext(props.editor, event);
3424
+ sections.value = getItems({ ...context, trigger: "click" });
3425
+ selectedId.value = flattenedItems.value[0]?.id || null;
3426
+ };
3427
+ const executeCommand = async (item) => {
3428
+ if (props.editor) {
3429
+ item.action ? await item.action(props.editor) : null;
3430
+ if (item.component) {
3431
+ menuRef.value;
3432
+ const componentProps = getPropsByItemId(item.id, props);
3433
+ props.openPopover(markRaw(item.component), componentProps, { left: menuPosition.value.left, top: menuPosition.value.top });
3434
+ closeMenu({ restoreCursor: false });
3435
+ } else {
3436
+ const shouldRestoreCursor = item.id !== "paste";
3437
+ closeMenu({ restoreCursor: shouldRestoreCursor });
3438
+ }
3439
+ }
3440
+ };
3441
+ const closeMenu = (options = { restoreCursor: true }) => {
3442
+ if (props.editor?.view) {
3443
+ const pluginState = SlashMenuPluginKey.getState(props.editor.view.state);
3444
+ const { anchorPos } = pluginState;
3445
+ props.editor.view.dispatch(
3446
+ props.editor.view.state.tr.setMeta(SlashMenuPluginKey, {
3447
+ type: "close"
3448
+ })
3449
+ );
3450
+ if (options.restoreCursor && anchorPos !== null) {
3451
+ const tr = props.editor.view.state.tr.setSelection(
3452
+ props.editor.view.state.selection.constructor.near(
3453
+ props.editor.view.state.doc.resolve(anchorPos)
3454
+ )
3455
+ );
3456
+ props.editor.view.dispatch(tr);
3457
+ props.editor.view.focus();
3458
+ }
3459
+ isOpen.value = false;
3460
+ searchQuery.value = "";
3461
+ sections.value = [];
3462
+ }
3463
+ };
3464
+ onMounted(() => {
3465
+ if (!props.editor) return;
3466
+ document.addEventListener("keydown", handleGlobalKeyDown);
3467
+ document.addEventListener("mousedown", handleGlobalOutsideClick);
3468
+ props.editor.on("slashMenu:open", async (event) => {
3469
+ isOpen.value = true;
3470
+ menuPosition.value = event.menuPosition;
3471
+ searchQuery.value = "";
3472
+ const context = await getEditorContext(props.editor);
3473
+ sections.value = getItems({ ...context, trigger: "slash" });
3474
+ selectedId.value = flattenedItems.value[0]?.id || null;
3475
+ });
3476
+ props.editor.view.dom.addEventListener("contextmenu", handleRightClick);
3477
+ props.editor.on("slashMenu:close", () => {
3478
+ isOpen.value = false;
3479
+ searchQuery.value = "";
3480
+ });
3481
+ });
3482
+ onBeforeUnmount(() => {
3483
+ document.removeEventListener("keydown", handleGlobalKeyDown);
3484
+ document.removeEventListener("mousedown", handleGlobalOutsideClick);
3485
+ if (props.editor) {
3486
+ try {
3487
+ props.editor.off("slashMenu:open");
3488
+ props.editor.off("slashMenu:close");
3489
+ props.editor.view.dom.removeEventListener("contextmenu", handleRightClick);
3490
+ } catch (error) {
3491
+ }
3492
+ }
3493
+ });
3494
+ return (_ctx, _cache) => {
3495
+ return isOpen.value ? (openBlock(), createElementBlock("div", {
3496
+ key: 0,
3497
+ ref_key: "menuRef",
3498
+ ref: menuRef,
3499
+ class: "slash-menu",
3500
+ style: normalizeStyle(menuPosition.value),
3501
+ onMousedown: _cache[2] || (_cache[2] = withModifiers(() => {
3502
+ }, ["stop"]))
3503
+ }, [
3504
+ withDirectives(createElementVNode("input", {
3505
+ ref_key: "searchInput",
3506
+ ref: searchInput,
3507
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => searchQuery.value = $event),
3508
+ type: "text",
3509
+ class: "slash-menu-hidden-input",
3510
+ onKeydown: [
3511
+ handleGlobalKeyDown,
3512
+ _cache[1] || (_cache[1] = withModifiers(() => {
3513
+ }, ["stop"]))
3514
+ ]
3515
+ }, null, 544), [
3516
+ [vModelText, searchQuery.value]
3517
+ ]),
3518
+ createElementVNode("div", _hoisted_1$3, [
3519
+ (openBlock(true), createElementBlock(Fragment, null, renderList(filteredSections.value, (section, sectionIndex) => {
3520
+ return openBlock(), createElementBlock(Fragment, {
3521
+ key: section.id
3522
+ }, [
3523
+ sectionIndex > 0 && section.items.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_2$1)) : createCommentVNode("", true),
3524
+ (openBlock(true), createElementBlock(Fragment, null, renderList(section.items, (item) => {
3525
+ return openBlock(), createElementBlock("div", {
3526
+ key: item.id,
3527
+ class: normalizeClass(["slash-menu-item", { "is-selected": item.id === selectedId.value }]),
3528
+ onClick: ($event) => executeCommand(item)
3529
+ }, [
3530
+ item.icon ? (openBlock(), createElementBlock("span", {
3531
+ key: 0,
3532
+ class: "slash-menu-item-icon",
3533
+ innerHTML: item.icon
3534
+ }, null, 8, _hoisted_4)) : createCommentVNode("", true),
3535
+ createElementVNode("span", null, toDisplayString(item.label), 1)
3536
+ ], 10, _hoisted_3$1);
3537
+ }), 128))
3538
+ ], 64);
3539
+ }), 128))
3540
+ ])
3541
+ ], 36)) : createCommentVNode("", true);
3542
+ };
3543
+ }
3544
+ };
3545
+ function adjustPaginationBreaks(editorElem, editor) {
3546
+ if (!editorElem.value || !editor?.value?.options?.scale) return;
3547
+ const zoom = editor.value.options.scale;
3548
+ const bounds = editorElem.value.getBoundingClientRect();
3549
+ const breakNodes = editorElem.value.querySelectorAll(".pagination-break-wrapper");
3550
+ let firstLeft;
3551
+ breakNodes.forEach((node) => {
3552
+ const nodeBounds = node.getBoundingClientRect();
3553
+ const left = (nodeBounds.left - bounds.left) / zoom * -1 + 1;
3554
+ if (!firstLeft) firstLeft = left;
3555
+ if (left !== firstLeft) {
3556
+ const diff = left - firstLeft;
3557
+ node.style.transform = `translateX(${diff}px)`;
3558
+ }
3559
+ });
3560
+ }
3561
+ const _hoisted_1$2 = { class: "numbering" };
3562
+ const MIN_WIDTH = 200;
3563
+ const alignment = "flex-end";
3564
+ const _sfc_main$4 = {
3565
+ __name: "Ruler",
3566
+ props: {
3567
+ orientation: {
3568
+ type: String,
3569
+ default: "horizontal"
3570
+ },
3571
+ length: {
3572
+ type: Number,
3573
+ default: 0
3574
+ },
3575
+ editor: {
3576
+ type: Object,
3577
+ required: true
3578
+ }
3579
+ },
3580
+ emits: ["margin-change"],
3093
3581
  setup(__props, { emit: __emit }) {
3094
3582
  const emit = __emit;
3095
3583
  const props = __props;
@@ -3278,7 +3766,73 @@ const _sfc_main$3 = {
3278
3766
  };
3279
3767
  }
3280
3768
  };
3281
- const Ruler = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-ad77036c"]]);
3769
+ const Ruler = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-ad77036c"]]);
3770
+ const _sfc_main$3 = {
3771
+ __name: "GenericPopover",
3772
+ props: {
3773
+ editor: { type: Object, required: true },
3774
+ styles: { type: Object, default: () => ({}) },
3775
+ visible: { type: Boolean, default: false },
3776
+ position: { type: Object, default: () => ({ left: "0px", top: "0px" }) }
3777
+ },
3778
+ emits: ["close"],
3779
+ setup(__props, { emit: __emit }) {
3780
+ const props = __props;
3781
+ const emit = __emit;
3782
+ const popover = ref(null);
3783
+ function handleClickOutside(event) {
3784
+ if (popover.value && !popover.value.contains(event.target)) {
3785
+ emit("close");
3786
+ }
3787
+ moveCursorToMouseEvent(event, props.editor);
3788
+ }
3789
+ function handleEscape(event) {
3790
+ if (event.key === "Escape") {
3791
+ emit("close");
3792
+ }
3793
+ }
3794
+ watch(() => props.visible, (val) => {
3795
+ if (val) {
3796
+ document.addEventListener("mousedown", handleClickOutside);
3797
+ document.addEventListener("keydown", handleEscape);
3798
+ } else {
3799
+ document.removeEventListener("mousedown", handleClickOutside);
3800
+ document.removeEventListener("keydown", handleEscape);
3801
+ }
3802
+ });
3803
+ onMounted(() => {
3804
+ if (props.visible) {
3805
+ document.addEventListener("mousedown", handleClickOutside);
3806
+ document.addEventListener("keydown", handleEscape);
3807
+ }
3808
+ });
3809
+ onBeforeUnmount(() => {
3810
+ document.removeEventListener("mousedown", handleClickOutside);
3811
+ document.removeEventListener("keydown", handleEscape);
3812
+ });
3813
+ const derivedStyles = computed(() => ({
3814
+ left: props.position.left,
3815
+ top: props.position.top,
3816
+ ...props.styles
3817
+ }));
3818
+ return (_ctx, _cache) => {
3819
+ return __props.visible ? (openBlock(), createElementBlock("div", {
3820
+ key: 0,
3821
+ class: "generic-popover",
3822
+ style: normalizeStyle(derivedStyles.value),
3823
+ ref_key: "popover",
3824
+ ref: popover,
3825
+ onMousedown: _cache[0] || (_cache[0] = withModifiers(() => {
3826
+ }, ["stop"])),
3827
+ onClick: _cache[1] || (_cache[1] = withModifiers(() => {
3828
+ }, ["stop"]))
3829
+ }, [
3830
+ renderSlot(_ctx.$slots, "default", {}, void 0, true)
3831
+ ], 36)) : createCommentVNode("", true);
3832
+ };
3833
+ }
3834
+ };
3835
+ const GenericPopover = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-93a6abe9"]]);
3282
3836
  const _hoisted_1$1 = { class: "super-editor-container" };
3283
3837
  const _hoisted_2 = {
3284
3838
  key: 1,
@@ -3321,6 +3875,24 @@ const _sfc_main$2 = {
3321
3875
  const editor = shallowRef(null);
3322
3876
  const editorWrapper = ref(null);
3323
3877
  const editorElem = ref(null);
3878
+ const popoverControls = reactive({
3879
+ visible: false,
3880
+ position: { left: "0px", top: "0px" },
3881
+ component: null,
3882
+ props: {}
3883
+ });
3884
+ const closePopover = () => {
3885
+ popoverControls.visible = false;
3886
+ popoverControls.component = null;
3887
+ popoverControls.props = {};
3888
+ editor.value.view.focus();
3889
+ };
3890
+ const openPopover = (component, props2, position) => {
3891
+ popoverControls.component = component;
3892
+ popoverControls.props = props2;
3893
+ popoverControls.position = position;
3894
+ popoverControls.visible = true;
3895
+ };
3324
3896
  let dataPollTimeout;
3325
3897
  const stopPolling = () => {
3326
3898
  clearTimeout(dataPollTimeout);
@@ -3417,6 +3989,9 @@ const _sfc_main$2 = {
3417
3989
  if (!isInsideEditor && editor.value.isEditable) {
3418
3990
  editor.value.view?.focus();
3419
3991
  }
3992
+ if (isInsideEditor && editor.value.isEditable) {
3993
+ checkNodeSpecificClicks(editor.value, event, popoverControls);
3994
+ }
3420
3995
  };
3421
3996
  onMounted(() => {
3422
3997
  initializeData();
@@ -3459,7 +4034,14 @@ const _sfc_main$2 = {
3459
4034
  ref: editorElem,
3460
4035
  class: "editor-element super-editor__element",
3461
4036
  role: "presentation"
3462
- }, null, 512)
4037
+ }, null, 512),
4038
+ editorReady.value && editor.value ? (openBlock(), createBlock(_sfc_main$5, {
4039
+ key: 0,
4040
+ editor: editor.value,
4041
+ popoverControls,
4042
+ openPopover,
4043
+ closePopover
4044
+ }, null, 8, ["editor", "popoverControls"])) : createCommentVNode("", true)
3463
4045
  ], 544),
3464
4046
  !editorReady.value ? (openBlock(), createElementBlock("div", _hoisted_2, [
3465
4047
  createElementVNode("div", _hoisted_3, [
@@ -3505,12 +4087,23 @@ const _sfc_main$2 = {
3505
4087
  text: "",
3506
4088
  style: { "width": "70%" }
3507
4089
  })
3508
- ])) : createCommentVNode("", true)
4090
+ ])) : createCommentVNode("", true),
4091
+ createVNode(GenericPopover, {
4092
+ editor: editor.value ?? {},
4093
+ visible: popoverControls.visible,
4094
+ position: popoverControls.position,
4095
+ onClose: closePopover
4096
+ }, {
4097
+ default: withCtx(() => [
4098
+ (openBlock(), createBlock(resolveDynamicComponent(popoverControls.component), normalizeProps(guardReactiveProps({ ...popoverControls.props, editor: editor.value, closePopover })), null, 16))
4099
+ ]),
4100
+ _: 1
4101
+ }, 8, ["editor", "visible", "position"])
3509
4102
  ]);
3510
4103
  };
3511
4104
  }
3512
4105
  };
3513
- const SuperEditor = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-4b700df1"]]);
4106
+ const SuperEditor = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-b71313e5"]]);
3514
4107
  const _sfc_main$1 = {
3515
4108
  __name: "BasicUpload",
3516
4109
  emits: ["file-change"],
@@ -3637,6 +4230,7 @@ export {
3637
4230
  D as DocxZipper,
3638
4231
  Editor,
3639
4232
  Extensions,
4233
+ _sfc_main$5 as SlashMenu,
3640
4234
  X as SuperConverter,
3641
4235
  SuperEditor,
3642
4236
  SuperInput,