@underverse-ui/underverse 2.0.29 → 2.0.30

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 (35) hide show
  1. package/api-reference.json +1 -1
  2. package/dist/{EmojiPicker-NV3GQYWI.js → EmojiPicker-ISJ6RXYG.js} +4 -4
  3. package/dist/{chunk-LK6YWBI6.js → chunk-2P7TSXEE.js} +82 -25
  4. package/dist/chunk-2P7TSXEE.js.map +1 -0
  5. package/dist/{chunk-5QWYO527.js → chunk-37MHVJMV.js} +846 -90
  6. package/dist/chunk-37MHVJMV.js.map +1 -0
  7. package/dist/{chunk-XTZTUDRE.js → chunk-57BKIC6J.js} +711 -800
  8. package/dist/chunk-57BKIC6J.js.map +1 -0
  9. package/dist/{chunk-LRIRY4DG.js → chunk-5W63IHIN.js} +11 -3
  10. package/dist/chunk-5W63IHIN.js.map +1 -0
  11. package/dist/{chunk-F7MX3XXK.js → chunk-S4UHFRL3.js} +3 -3
  12. package/dist/{chunk-A4GUPKHM.js → chunk-ZP7F4ZD7.js} +63 -43
  13. package/dist/chunk-ZP7F4ZD7.js.map +1 -0
  14. package/dist/index.cjs +2225 -1311
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +55 -0
  17. package/dist/index.d.ts +55 -0
  18. package/dist/index.js +23 -10
  19. package/dist/index.js.map +1 -1
  20. package/dist/{menu-bar-AHG64PEB.js → menu-bar-DPCNNUX5.js} +193 -47
  21. package/dist/menu-bar-DPCNNUX5.js.map +1 -0
  22. package/dist/ueditor.cjs +9407 -8506
  23. package/dist/ueditor.cjs.map +1 -1
  24. package/dist/ueditor.d.cts +10 -0
  25. package/dist/ueditor.d.ts +10 -0
  26. package/dist/ueditor.js +4 -4
  27. package/package.json +2 -1
  28. package/dist/chunk-5QWYO527.js.map +0 -1
  29. package/dist/chunk-A4GUPKHM.js.map +0 -1
  30. package/dist/chunk-LK6YWBI6.js.map +0 -1
  31. package/dist/chunk-LRIRY4DG.js.map +0 -1
  32. package/dist/chunk-XTZTUDRE.js.map +0 -1
  33. package/dist/menu-bar-AHG64PEB.js.map +0 -1
  34. /package/dist/{EmojiPicker-NV3GQYWI.js.map → EmojiPicker-ISJ6RXYG.js.map} +0 -0
  35. /package/dist/{chunk-F7MX3XXK.js.map → chunk-S4UHFRL3.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  Modal_default
4
- } from "./chunk-LK6YWBI6.js";
4
+ } from "./chunk-2P7TSXEE.js";
5
5
  import {
6
6
  DEFAULT_TABLE_ROW_HEIGHT,
7
7
  DEFAULT_UEDITOR_IMAGE_MAX_FILE_SIZE,
@@ -18,25 +18,28 @@ import {
18
18
  UEDITOR_PROSEMIRROR_CLASS_NAME,
19
19
  applyEditorLink,
20
20
  clampResponsiveTableWidthBp,
21
- fileToDataUrl,
22
21
  formatBasisPointsAsPercentage,
23
22
  getTableAnchorPos,
24
23
  normalizeColumnRatios,
25
24
  parseColumnRatios,
26
25
  parsePercentageToBasisPoints,
27
26
  resolveResponsiveTableOffsetBp,
27
+ resolveUEditorImageFiles,
28
28
  sanitizeUEditorUrl,
29
+ trackEditorInsertionPosition,
29
30
  useDropdownMenuClose,
30
31
  useSharedEditorUiRenderState
31
- } from "./chunk-5QWYO527.js";
32
+ } from "./chunk-37MHVJMV.js";
32
33
  import {
33
34
  cn,
34
- useSmartTranslations
35
- } from "./chunk-A4GUPKHM.js";
35
+ resolveUEditorPortalContainer,
36
+ useSmartTranslations,
37
+ useUEditorPortalContainerGetter
38
+ } from "./chunk-ZP7F4ZD7.js";
36
39
  import "./chunk-NSBPE2FW.js";
37
40
 
38
41
  // src/components/UEditor/menu-bar.tsx
39
- import React, { useMemo, useRef, useState } from "react";
42
+ import React, { useEffect, useRef, useState } from "react";
40
43
  import {
41
44
  AlignCenter,
42
45
  AlignJustify,
@@ -71,6 +74,68 @@ import {
71
74
  } from "lucide-react";
72
75
 
73
76
  // src/components/UEditor/preview-html.ts
77
+ var BLOCKED_PREVIEW_ELEMENTS = /* @__PURE__ */ new Set(["SCRIPT", "IFRAME", "OBJECT", "EMBED", "LINK", "META", "BASE", "STYLE"]);
78
+ var UNSAFE_INLINE_STYLE_RE = /(?:url\s*\(|expression\s*\(|@import|-moz-binding)/i;
79
+ function isSafeUEditorSourceHtml(html, ownerDocument) {
80
+ const sourceDocument = ownerDocument ?? (typeof document !== "undefined" ? document : null);
81
+ if (!sourceDocument) return false;
82
+ const container = sourceDocument.createElement("div");
83
+ container.innerHTML = html;
84
+ for (const element of Array.from(container.querySelectorAll("*"))) {
85
+ if (BLOCKED_PREVIEW_ELEMENTS.has(element.tagName)) return false;
86
+ for (const attribute of Array.from(element.attributes)) {
87
+ const name = attribute.name.toLowerCase();
88
+ if (name.startsWith("on") || name === "srcdoc") return false;
89
+ }
90
+ const style = element.getAttribute("style");
91
+ if (style && UNSAFE_INLINE_STYLE_RE.test(style)) return false;
92
+ const isFileCard = element.getAttribute("data-type") === "file-card";
93
+ const urlAttributes = [
94
+ ["href", isFileCard ? "file" : "link"],
95
+ ["src", "image"],
96
+ ["data-src", isFileCard ? "file" : "image"],
97
+ ["data-url", "link"],
98
+ ["data-image", "image"]
99
+ ];
100
+ for (const [name, kind] of urlAttributes) {
101
+ if (element.hasAttribute(name) && !sanitizeUEditorUrl(element.getAttribute(name) ?? "", kind)) return false;
102
+ }
103
+ }
104
+ return true;
105
+ }
106
+ function sanitizePreviewContainer(container) {
107
+ for (const element of Array.from(container.querySelectorAll("*"))) {
108
+ if (BLOCKED_PREVIEW_ELEMENTS.has(element.tagName)) {
109
+ element.remove();
110
+ continue;
111
+ }
112
+ for (const attribute of Array.from(element.attributes)) {
113
+ const name = attribute.name.toLowerCase();
114
+ if (name.startsWith("on") || name === "srcdoc") {
115
+ element.removeAttribute(attribute.name);
116
+ }
117
+ }
118
+ const style = element.getAttribute("style");
119
+ if (style && UNSAFE_INLINE_STYLE_RE.test(style)) element.removeAttribute("style");
120
+ const isFileCard = element.getAttribute("data-type") === "file-card";
121
+ const urlAttributes = [
122
+ ["href", isFileCard ? "file" : "link"],
123
+ ["src", "image"],
124
+ ["data-src", isFileCard ? "file" : "image"],
125
+ ["data-url", "link"],
126
+ ["data-image", "image"]
127
+ ];
128
+ for (const [name, kind] of urlAttributes) {
129
+ if (!element.hasAttribute(name)) continue;
130
+ const safeUrl = sanitizeUEditorUrl(element.getAttribute(name) ?? "", kind);
131
+ if (safeUrl) element.setAttribute(name, safeUrl);
132
+ else element.removeAttribute(name);
133
+ }
134
+ if (element.tagName === "A" && element.getAttribute("target") === "_blank") {
135
+ element.setAttribute("rel", "noopener noreferrer");
136
+ }
137
+ }
138
+ }
74
139
  var DEFAULT_TABLE_COLUMN_WIDTH = 100;
75
140
  var TIPTAP_TABLE_MIN_COLUMN_WIDTH = 25;
76
141
  function parsePixelWidth(value) {
@@ -218,10 +283,12 @@ function normalizePreviewTable(table) {
218
283
  });
219
284
  });
220
285
  }
221
- function prepareUEditorPreviewHtml(html) {
222
- if (typeof document === "undefined" || !html) return html;
223
- const container = document.createElement("div");
286
+ function prepareUEditorPreviewHtml(html, ownerDocument) {
287
+ const previewDocument = ownerDocument ?? (typeof document !== "undefined" ? document : null);
288
+ if (!previewDocument || !html) return html;
289
+ const container = previewDocument.createElement("div");
224
290
  container.innerHTML = html;
291
+ sanitizePreviewContainer(container);
225
292
  container.querySelectorAll("table").forEach((table) => normalizePreviewTable(table));
226
293
  return container.innerHTML;
227
294
  }
@@ -289,13 +356,17 @@ function buildFileMenuItems(t, editor, { onSave, onExport }) {
289
356
  onExport();
290
357
  } else {
291
358
  const html = editor.getHTML();
292
- const blob = new Blob([`<!DOCTYPE html><html><body>${html}</body></html>`], { type: "text/html" });
293
- const url = URL.createObjectURL(blob);
294
- const a = document.createElement("a");
359
+ const editorDocument = editor.view.dom.ownerDocument;
360
+ const editorWindow = editorDocument.defaultView;
361
+ const BlobCtor = editorWindow?.Blob ?? Blob;
362
+ const URLApi = editorWindow?.URL ?? URL;
363
+ const blob = new BlobCtor([`<!DOCTYPE html><html><head><meta charset="utf-8"></head><body>${html}</body></html>`], { type: "text/html;charset=utf-8" });
364
+ const url = URLApi.createObjectURL(blob);
365
+ const a = editorDocument.createElement("a");
295
366
  a.href = url;
296
367
  a.download = "document.html";
297
368
  a.click();
298
- URL.revokeObjectURL(url);
369
+ editorWindow?.setTimeout(() => URLApi.revokeObjectURL(url), 0);
299
370
  }
300
371
  }
301
372
  }
@@ -325,29 +396,31 @@ function buildEditMenuItems(t, editor) {
325
396
  label: t("menubar.cut"),
326
397
  icon: Scissors,
327
398
  shortcut: t("menubar.cutShortcut"),
328
- onClick: () => document.execCommand("cut")
399
+ onClick: () => editor.view.dom.ownerDocument.execCommand("cut")
329
400
  },
330
401
  {
331
402
  type: "action",
332
403
  label: t("menubar.copy"),
333
404
  shortcut: t("menubar.copyShortcut"),
334
- onClick: () => document.execCommand("copy")
405
+ onClick: () => editor.view.dom.ownerDocument.execCommand("copy")
335
406
  },
336
407
  {
337
408
  type: "action",
338
409
  label: t("menubar.paste"),
339
410
  shortcut: t("menubar.pasteShortcut"),
340
- onClick: () => document.execCommand("paste")
411
+ onClick: () => editor.view.dom.ownerDocument.execCommand("paste")
341
412
  },
342
413
  {
343
414
  type: "action",
344
415
  label: t("menubar.pasteAsText"),
345
416
  onClick: async () => {
346
417
  try {
347
- const text = await navigator.clipboard.readText();
418
+ const clipboard = editor.view.dom.ownerDocument.defaultView?.navigator.clipboard;
419
+ if (!clipboard) throw new Error("Clipboard API is unavailable");
420
+ const text = await clipboard.readText();
348
421
  editor.chain().focus().insertContent(text).run();
349
422
  } catch {
350
- document.execCommand("paste");
423
+ editor.view.dom.ownerDocument.execCommand("paste");
351
424
  }
352
425
  }
353
426
  },
@@ -360,7 +433,7 @@ function buildEditMenuItems(t, editor) {
360
433
  }
361
434
  ];
362
435
  }
363
- function buildViewMenuItems(t, {
436
+ function buildViewMenuItems(t, editor, {
364
437
  containerRef,
365
438
  onSourceCode,
366
439
  openSourceDialog,
@@ -388,10 +461,11 @@ function buildViewMenuItems(t, {
388
461
  onClick: () => {
389
462
  const el = containerRef.current;
390
463
  if (!el) return;
391
- if (!document.fullscreenElement) {
464
+ const editorDocument = editor.view.dom.ownerDocument;
465
+ if (!editorDocument.fullscreenElement) {
392
466
  el.requestFullscreen?.();
393
467
  } else {
394
- document.exitFullscreen?.();
468
+ editorDocument.exitFullscreen?.();
395
469
  }
396
470
  }
397
471
  }
@@ -670,6 +744,8 @@ var MenuBar = ({
670
744
  imageInsertMode = "base64",
671
745
  maxImageFileSize = DEFAULT_UEDITOR_IMAGE_MAX_FILE_SIZE,
672
746
  allowedImageMimeTypes = DEFAULT_UEDITOR_IMAGE_MIME_TYPES,
747
+ onImageUploadError,
748
+ fallbackToDataUrl = true,
673
749
  onSave,
674
750
  onExport,
675
751
  onSourceCode,
@@ -678,22 +754,45 @@ var MenuBar = ({
678
754
  }) => {
679
755
  const t = useSmartTranslations("UEditor");
680
756
  useSharedEditorUiRenderState(editor);
757
+ const getPortalContainer = useUEditorPortalContainerGetter();
681
758
  const fileInputRef = useRef(null);
759
+ const sourceTextareaRef = useRef(null);
682
760
  const [showImageInput, setShowImageInput] = useState(false);
683
761
  const [showLinkInput, setShowLinkInput] = useState(false);
762
+ const [isUploadingImage, setIsUploadingImage] = useState(false);
763
+ const [imageUploadError, setImageUploadError] = useState(null);
684
764
  const [openMenuKey, setOpenMenuKey] = useState(null);
685
765
  const [showSourceDialog, setShowSourceDialog] = useState(false);
686
766
  const [sourceHtml, setSourceHtml] = useState("");
767
+ const [sourceError, setSourceError] = useState("");
768
+ const sourceErrorId = React.useId();
687
769
  const [showPreviewDialog, setShowPreviewDialog] = useState(false);
688
- const previewHtml = useMemo(
689
- () => showPreviewDialog ? prepareUEditorPreviewHtml(editor.getHTML()) : "",
690
- [editor, showPreviewDialog]
770
+ const [previewHtml, setPreviewHtml] = useState("");
771
+ const modalPortalContainer = resolveUEditorPortalContainer(
772
+ getPortalContainer,
773
+ void 0,
774
+ editor.view.dom.ownerDocument
691
775
  );
776
+ useEffect(() => {
777
+ if (!showPreviewDialog) return;
778
+ const updatePreview = () => {
779
+ if (!editor.isDestroyed) {
780
+ setPreviewHtml(prepareUEditorPreviewHtml(editor.getHTML(), editor.view.dom.ownerDocument));
781
+ }
782
+ };
783
+ updatePreview();
784
+ editor.on("update", updatePreview);
785
+ return () => {
786
+ editor.off("update", updatePreview);
787
+ };
788
+ }, [editor, showPreviewDialog]);
692
789
  const openSourceDialog = () => {
693
790
  setSourceHtml(editor.getHTML());
791
+ setSourceError("");
694
792
  setShowSourceDialog(true);
695
793
  };
696
794
  const openPreviewDialog = () => {
795
+ setPreviewHtml(prepareUEditorPreviewHtml(editor.getHTML(), editor.view.dom.ownerDocument));
697
796
  setShowPreviewDialog(true);
698
797
  };
699
798
  const handlePreview = () => {
@@ -701,13 +800,23 @@ var MenuBar = ({
701
800
  openPreviewDialog();
702
801
  };
703
802
  const applySourceHtml = () => {
704
- editor.chain().focus().setContent(sourceHtml).run();
705
- setShowSourceDialog(false);
803
+ const nextSourceHtml = sourceTextareaRef.current?.value ?? sourceHtml;
804
+ try {
805
+ if (!isSafeUEditorSourceHtml(nextSourceHtml, editor.view.dom.ownerDocument)) {
806
+ throw new Error("Unsafe source HTML");
807
+ }
808
+ editor.chain().focus().setContent(nextSourceHtml, { errorOnInvalidContent: true }).run();
809
+ setSourceError("");
810
+ setShowSourceDialog(false);
811
+ } catch {
812
+ setSourceError(t("menubar.invalidSource"));
813
+ }
706
814
  };
707
815
  const closeInsertMenu = () => {
708
816
  setOpenMenuKey(null);
709
817
  setShowImageInput(false);
710
818
  setShowLinkInput(false);
819
+ setImageUploadError(null);
711
820
  };
712
821
  const handleImageUrl = (url, alt) => {
713
822
  const safe = sanitizeUEditorUrl(url, "image");
@@ -718,21 +827,35 @@ var MenuBar = ({
718
827
  closeInsertMenu();
719
828
  };
720
829
  const handleImageFiles = async (files) => {
721
- if (!files?.length) return;
722
- for (const file of Array.from(files)) {
723
- if (!file.type.startsWith("image/")) continue;
724
- if (file.size > maxImageFileSize) continue;
725
- if (allowedImageMimeTypes.length > 0 && !allowedImageMimeTypes.includes(file.type)) continue;
726
- try {
727
- const src = imageInsertMode === "upload" && uploadImage ? await uploadImage(file) : await fileToDataUrl(file);
728
- const safe = sanitizeUEditorUrl(src, "image");
729
- if (!safe) continue;
730
- editor.chain().focus().setImage({ src: safe, alt: file.name }).run();
731
- editor.commands.createParagraphNear();
732
- } catch {
830
+ if (files.length === 0 || isUploadingImage) return;
831
+ setIsUploadingImage(true);
832
+ setImageUploadError(null);
833
+ const trackedPosition = trackEditorInsertionPosition(editor);
834
+ try {
835
+ const { images, hadError } = await resolveUEditorImageFiles(files, {
836
+ maxFileSize: maxImageFileSize,
837
+ allowedMimeTypes: allowedImageMimeTypes,
838
+ upload: uploadImage,
839
+ fallbackToDataUrl,
840
+ insertMode: imageInsertMode,
841
+ onError: onImageUploadError
842
+ });
843
+ if (!editor.isDestroyed && images.length > 0) {
844
+ const content = images.map((image) => ({
845
+ type: "image",
846
+ attrs: { src: image.src, alt: image.file.name }
847
+ }));
848
+ editor.commands.insertContentAt(trackedPosition.current, content, { updateSelection: false });
733
849
  }
850
+ if (hadError) {
851
+ setImageUploadError(t("imageInput.uploadError"));
852
+ } else {
853
+ closeInsertMenu();
854
+ }
855
+ } finally {
856
+ trackedPosition.stop();
857
+ setIsUploadingImage(false);
734
858
  }
735
- closeInsertMenu();
736
859
  };
737
860
  const handleInsertTable = (rows, cols) => {
738
861
  editor.chain().focus().insertTable({ rows, cols, withHeaderRow: true }).run();
@@ -751,12 +874,14 @@ var MenuBar = ({
751
874
  /* @__PURE__ */ jsx(
752
875
  DropdownMenuItem,
753
876
  {
754
- label: t("menubar.imageUpload"),
877
+ label: isUploadingImage ? t("imageInput.uploading") : t("menubar.imageUpload"),
755
878
  icon: Upload,
756
879
  onClick: () => fileInputRef.current?.click(),
757
- closeOnSelect: false
880
+ closeOnSelect: false,
881
+ disabled: isUploadingImage
758
882
  }
759
- )
883
+ ),
884
+ imageUploadError ? /* @__PURE__ */ jsx(DropdownMenuItem, { label: imageUploadError, disabled: true, destructive: true }) : null
760
885
  ] })
761
886
  },
762
887
  { type: "separator" },
@@ -837,7 +962,13 @@ var MenuBar = ({
837
962
  {
838
963
  key: "view",
839
964
  label: t("menubar.view"),
840
- items: buildViewMenuItems(t, { containerRef, onSourceCode, openSourceDialog, onPreview: handlePreview, openPreviewDialog })
965
+ items: buildViewMenuItems(t, editor, {
966
+ containerRef,
967
+ onSourceCode,
968
+ openSourceDialog,
969
+ onPreview: handlePreview,
970
+ openPreviewDialog
971
+ })
841
972
  },
842
973
  {
843
974
  key: "insert",
@@ -861,10 +992,14 @@ var MenuBar = ({
861
992
  accept: allowedImageMimeTypes.join(","),
862
993
  multiple: true,
863
994
  className: "hidden",
864
- onChange: (e) => handleImageFiles(e.target.files)
995
+ onChange: (e) => {
996
+ const files = Array.from(e.target.files ?? []);
997
+ e.target.value = "";
998
+ void handleImageFiles(files);
999
+ }
865
1000
  }
866
1001
  ),
867
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 border-b border-border/35 bg-muted/20 px-1.5 py-0.5", children: [
1002
+ /* @__PURE__ */ jsxs("nav", { "aria-label": t("toolbar.showMenuBar"), className: "flex items-center gap-0.5 border-b border-border/35 bg-muted/20 px-1.5 py-0.5", children: [
868
1003
  menus.map(({ key, label, items }) => /* @__PURE__ */ jsx(
869
1004
  DropdownMenu,
870
1005
  {
@@ -905,18 +1040,28 @@ var MenuBar = ({
905
1040
  onClose: () => setShowSourceDialog(false),
906
1041
  title: t("menubar.sourceCode"),
907
1042
  size: "lg",
1043
+ portalContainer: modalPortalContainer,
908
1044
  children: /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
909
1045
  /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: t("menubar.sourceCodeHint") }),
910
1046
  /* @__PURE__ */ jsx(
911
1047
  "textarea",
912
1048
  {
1049
+ ref: sourceTextareaRef,
913
1050
  "data-testid": "source-code-textarea",
1051
+ "aria-label": t("menubar.sourceCode"),
1052
+ name: "ueditor-source-html",
914
1053
  className: "w-full h-64 font-mono text-xs p-3 bg-muted rounded-lg border border-border resize-y focus:outline-none focus:ring-2 focus:ring-primary/20",
915
1054
  value: sourceHtml,
916
- onChange: (e) => setSourceHtml(e.target.value),
1055
+ onChange: (e) => {
1056
+ setSourceHtml(e.target.value);
1057
+ if (sourceError) setSourceError("");
1058
+ },
1059
+ "aria-invalid": Boolean(sourceError),
1060
+ "aria-describedby": sourceError ? sourceErrorId : void 0,
917
1061
  spellCheck: false
918
1062
  }
919
1063
  ),
1064
+ sourceError ? /* @__PURE__ */ jsx("p", { id: sourceErrorId, role: "alert", className: "text-xs text-destructive", children: sourceError }) : null,
920
1065
  /* @__PURE__ */ jsxs("div", { className: "flex gap-2 justify-end", children: [
921
1066
  /* @__PURE__ */ jsx(
922
1067
  "button",
@@ -947,6 +1092,7 @@ var MenuBar = ({
947
1092
  onClose: () => setShowPreviewDialog(false),
948
1093
  title: t("menubar.preview"),
949
1094
  size: "full",
1095
+ portalContainer: modalPortalContainer,
950
1096
  width: "min(1180px, calc(100vw - 2rem))",
951
1097
  height: "min(860px, calc(100vh - 2rem))",
952
1098
  className: "flex flex-col overflow-hidden rounded-xl md:rounded-2xl",
@@ -972,4 +1118,4 @@ var MenuBar = ({
972
1118
  export {
973
1119
  MenuBar
974
1120
  };
975
- //# sourceMappingURL=menu-bar-AHG64PEB.js.map
1121
+ //# sourceMappingURL=menu-bar-DPCNNUX5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/UEditor/menu-bar.tsx","../src/components/UEditor/preview-html.ts"],"sourcesContent":["\"use client\";\n\nimport React, { useEffect, useRef, useState } from \"react\";\nimport type { Editor } from \"@tiptap/core\";\nimport {\n AlignCenter,\n AlignJustify,\n AlignLeft,\n AlignRight,\n Bold as BoldIcon,\n Code as CodeIcon,\n Eye,\n FileCode,\n Heading1 as Heading1Icon,\n Heading2 as Heading2Icon,\n Heading3 as Heading3Icon,\n Image as ImageIcon,\n Italic as ItalicIcon,\n Link as LinkIcon,\n ListTodo,\n Maximize2,\n Quote as QuoteIcon,\n Redo as RedoIcon,\n Scissors,\n Strikethrough as StrikethroughIcon,\n Subscript as SubscriptIcon,\n Superscript as SuperscriptIcon,\n Table as TableIcon,\n Trash2,\n Underline as UnderlineIcon,\n Undo as UndoIcon,\n Square,\n CircleDot,\n CircleCheckBig,\n Upload,\n} from \"lucide-react\";\nimport { useSmartTranslations } from \"../../hooks/useSmartTranslations\";\nimport { cn } from \"../../utils/cn\";\nimport { DropdownMenu, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuSub, useDropdownMenuClose } from \"../DropdownMenu\";\nimport Modal from \"../Modal\";\nimport { ImageInput, LinkInput } from \"./inputs\";\nimport { applyEditorLink } from \"./link-commands\";\nimport { TableInsertGrid, getTableAnchorPos, useSharedEditorUiRenderState } from \"./toolbar\";\nimport { sanitizeUEditorUrl } from \"./url-safety\";\nimport { DEFAULT_UEDITOR_IMAGE_MAX_FILE_SIZE, DEFAULT_UEDITOR_IMAGE_MIME_TYPES } from \"./clipboard-images\";\nimport { UEDITOR_PROSEMIRROR_CLASS_NAME } from \"./editor-styles\";\nimport { isSafeUEditorSourceHtml, prepareUEditorPreviewHtml } from \"./preview-html\";\nimport { resolveUEditorPortalContainer, useUEditorPortalContainerGetter } from \"./portal-context\";\nimport { trackEditorInsertionPosition } from \"./async-insertion-position\";\nimport { resolveUEditorImageFiles } from \"./image-file-upload\";\n\n// ─── Types ──────────────────────────────────────────────────────────────────\n\ntype MenuAction = {\n type: \"action\";\n label: string;\n icon?: React.ComponentType<{ className?: string }>;\n shortcut?: string;\n onClick: () => void;\n disabled?: boolean;\n active?: boolean;\n destructive?: boolean;\n};\n\ntype MenuSeparator = { type: \"separator\" };\n\ntype MenuSub = {\n type: \"sub\";\n label: string;\n icon?: React.ComponentType<{ className?: string }>;\n items: MenuItemDef[];\n disabled?: boolean;\n};\n\ntype MenuCustom = { type: \"custom\"; key: string; render: () => React.ReactNode };\n\ntype MenuItemDef = MenuAction | MenuSeparator | MenuSub | MenuCustom;\n\n// ─── Render helper ──────────────────────────────────────────────────────────\n\nfunction MenuTableInsertGrid({\n insertLabel,\n previewTemplate,\n onInsert,\n}: {\n insertLabel: string;\n previewTemplate: string;\n onInsert: (rows: number, cols: number) => void;\n}) {\n const closeMenu = useDropdownMenuClose();\n\n return (\n <TableInsertGrid\n insertLabel={insertLabel}\n previewTemplate={previewTemplate}\n onInsert={(rows, cols) => {\n onInsert(rows, cols);\n closeMenu();\n }}\n />\n );\n}\n\nfunction renderMenuItems(items: MenuItemDef[]): React.ReactNode {\n return items.map((item, i) => {\n switch (item.type) {\n case \"separator\":\n return <DropdownMenuSeparator key={i} />;\n case \"action\":\n return (\n <DropdownMenuItem\n key={i}\n label={item.label}\n icon={item.icon}\n shortcut={item.shortcut}\n onClick={item.onClick}\n disabled={item.disabled}\n active={item.active}\n destructive={item.destructive}\n />\n );\n case \"sub\":\n return (\n <DropdownMenuSub key={i} label={item.label} icon={item.icon} disabled={item.disabled}>\n {renderMenuItems(item.items)}\n </DropdownMenuSub>\n );\n case \"custom\":\n return <React.Fragment key={item.key}>{item.render()}</React.Fragment>;\n }\n });\n}\n\n// ─── Menu builders ──────────────────────────────────────────────────────────\n\nfunction buildFileMenuItems(\n t: (k: string) => string,\n editor: Editor,\n { onSave, onExport }: { onSave?: () => void; onExport?: () => void },\n): MenuItemDef[] {\n return [\n {\n type: \"action\",\n label: t(\"menubar.save\"),\n shortcut: \"Ctrl+S\",\n onClick: () => onSave?.(),\n disabled: !onSave,\n },\n {\n type: \"action\",\n label: t(\"menubar.exportHtml\"),\n onClick: () => {\n if (onExport) {\n onExport();\n } else {\n // Default: download as HTML file\n const html = editor.getHTML();\n const editorDocument = editor.view.dom.ownerDocument;\n const editorWindow = editorDocument.defaultView;\n const BlobCtor = editorWindow?.Blob ?? Blob;\n const URLApi = editorWindow?.URL ?? URL;\n const blob = new BlobCtor([`<!DOCTYPE html><html><head><meta charset=\"utf-8\"></head><body>${html}</body></html>`], { type: \"text/html;charset=utf-8\" });\n const url = URLApi.createObjectURL(blob);\n const a = editorDocument.createElement(\"a\");\n a.href = url;\n a.download = \"document.html\";\n a.click();\n editorWindow?.setTimeout(() => URLApi.revokeObjectURL(url), 0);\n }\n },\n },\n ];\n}\n\nfunction buildEditMenuItems(t: (k: string) => string, editor: Editor): MenuItemDef[] {\n return [\n {\n type: \"action\",\n label: t(\"menubar.undo\"),\n icon: UndoIcon,\n shortcut: t(\"menubar.undoShortcut\"),\n onClick: () => editor.chain().focus().undo().run(),\n disabled: !editor.can().undo(),\n },\n {\n type: \"action\",\n label: t(\"menubar.redo\"),\n icon: RedoIcon,\n shortcut: t(\"menubar.redoShortcut\"),\n onClick: () => editor.chain().focus().redo().run(),\n disabled: !editor.can().redo(),\n },\n { type: \"separator\" },\n {\n type: \"action\",\n label: t(\"menubar.cut\"),\n icon: Scissors,\n shortcut: t(\"menubar.cutShortcut\"),\n onClick: () => editor.view.dom.ownerDocument.execCommand(\"cut\"),\n },\n {\n type: \"action\",\n label: t(\"menubar.copy\"),\n shortcut: t(\"menubar.copyShortcut\"),\n onClick: () => editor.view.dom.ownerDocument.execCommand(\"copy\"),\n },\n {\n type: \"action\",\n label: t(\"menubar.paste\"),\n shortcut: t(\"menubar.pasteShortcut\"),\n onClick: () => editor.view.dom.ownerDocument.execCommand(\"paste\"),\n },\n {\n type: \"action\",\n label: t(\"menubar.pasteAsText\"),\n onClick: async () => {\n try {\n const clipboard = editor.view.dom.ownerDocument.defaultView?.navigator.clipboard;\n if (!clipboard) throw new Error(\"Clipboard API is unavailable\");\n const text = await clipboard.readText();\n editor.chain().focus().insertContent(text).run();\n } catch {\n editor.view.dom.ownerDocument.execCommand(\"paste\");\n }\n },\n },\n { type: \"separator\" },\n {\n type: \"action\",\n label: t(\"menubar.selectAll\"),\n shortcut: t(\"menubar.selectAllShortcut\"),\n onClick: () => editor.chain().focus().selectAll().run(),\n },\n ];\n}\n\nfunction buildViewMenuItems(\n t: (k: string) => string,\n editor: Editor,\n {\n containerRef,\n onSourceCode,\n openSourceDialog,\n onPreview,\n openPreviewDialog,\n }: {\n containerRef: React.RefObject<HTMLElement | null>;\n onSourceCode?: () => void;\n openSourceDialog: () => void;\n onPreview?: () => void;\n openPreviewDialog: () => void;\n },\n): MenuItemDef[] {\n return [\n {\n type: \"action\",\n label: t(\"menubar.sourceCode\"),\n icon: FileCode,\n onClick: () => (onSourceCode ? onSourceCode() : openSourceDialog()),\n },\n {\n type: \"action\",\n label: t(\"menubar.preview\"),\n onClick: () => (onPreview ? onPreview() : openPreviewDialog()),\n },\n { type: \"separator\" },\n {\n type: \"action\",\n label: t(\"menubar.fullscreen\"),\n icon: Maximize2,\n shortcut: t(\"menubar.fullscreenShortcut\"),\n onClick: () => {\n const el = containerRef.current;\n if (!el) return;\n const editorDocument = editor.view.dom.ownerDocument;\n if (!editorDocument.fullscreenElement) {\n el.requestFullscreen?.();\n } else {\n editorDocument.exitFullscreen?.();\n }\n },\n },\n ];\n}\n\nfunction buildFormatMenuItems(t: (k: string) => string, editor: Editor): MenuItemDef[] {\n return [\n {\n type: \"action\",\n label: t(\"menubar.bold\"),\n icon: BoldIcon,\n shortcut: t(\"menubar.boldShortcut\"),\n active: editor.isActive(\"bold\"),\n onClick: () => editor.chain().focus().toggleBold().run(),\n },\n {\n type: \"action\",\n label: t(\"menubar.italic\"),\n icon: ItalicIcon,\n shortcut: t(\"menubar.italicShortcut\"),\n active: editor.isActive(\"italic\"),\n onClick: () => editor.chain().focus().toggleItalic().run(),\n },\n {\n type: \"action\",\n label: t(\"menubar.underline\"),\n icon: UnderlineIcon,\n shortcut: t(\"menubar.underlineShortcut\"),\n active: editor.isActive(\"underline\"),\n onClick: () => editor.chain().focus().toggleUnderline().run(),\n },\n {\n type: \"action\",\n label: t(\"menubar.strike\"),\n icon: StrikethroughIcon,\n active: editor.isActive(\"strike\"),\n onClick: () => editor.chain().focus().toggleStrike().run(),\n },\n {\n type: \"action\",\n label: t(\"menubar.superscript\"),\n icon: SuperscriptIcon,\n active: editor.isActive(\"superscript\"),\n onClick: () => editor.chain().focus().toggleSuperscript().run(),\n },\n {\n type: \"action\",\n label: t(\"menubar.subscript\"),\n icon: SubscriptIcon,\n active: editor.isActive(\"subscript\"),\n onClick: () => editor.chain().focus().toggleSubscript().run(),\n },\n {\n type: \"action\",\n label: t(\"menubar.code\"),\n icon: CodeIcon,\n active: editor.isActive(\"code\"),\n onClick: () => editor.chain().focus().toggleCode().run(),\n },\n { type: \"separator\" },\n {\n type: \"sub\",\n label: t(\"menubar.wrap\"),\n items: [\n {\n type: \"action\",\n label: t(\"menubar.paragraph\"),\n active: editor.isActive(\"paragraph\"),\n onClick: () => editor.chain().focus().setParagraph().run(),\n },\n {\n type: \"action\",\n label: t(\"menubar.heading1\"),\n icon: Heading1Icon,\n active: editor.isActive(\"heading\", { level: 1 }),\n onClick: () => editor.chain().focus().toggleHeading({ level: 1 }).run(),\n },\n {\n type: \"action\",\n label: t(\"menubar.heading2\"),\n icon: Heading2Icon,\n active: editor.isActive(\"heading\", { level: 2 }),\n onClick: () => editor.chain().focus().toggleHeading({ level: 2 }).run(),\n },\n {\n type: \"action\",\n label: t(\"menubar.heading3\"),\n icon: Heading3Icon,\n active: editor.isActive(\"heading\", { level: 3 }),\n onClick: () => editor.chain().focus().toggleHeading({ level: 3 }).run(),\n },\n { type: \"separator\" },\n {\n type: \"action\",\n label: t(\"menubar.blockquote\"),\n icon: QuoteIcon,\n active: editor.isActive(\"blockquote\"),\n onClick: () => editor.chain().focus().toggleBlockquote().run(),\n },\n {\n type: \"action\",\n label: t(\"menubar.codeBlock\"),\n icon: FileCode,\n active: editor.isActive(\"codeBlock\"),\n onClick: () => editor.chain().focus().toggleCodeBlock().run(),\n },\n {\n type: \"action\",\n label: t(\"menubar.taskList\"),\n icon: ListTodo,\n active: editor.isActive(\"taskList\"),\n onClick: () => editor.chain().focus().toggleTaskList().run(),\n },\n ],\n },\n {\n type: \"sub\",\n label: t(\"menubar.align\"),\n items: [\n {\n type: \"action\",\n label: t(\"menubar.alignLeft\"),\n icon: AlignLeft,\n active: editor.isActive({ textAlign: \"left\" }),\n onClick: () => editor.chain().focus().setTextAlign(\"left\").run(),\n },\n {\n type: \"action\",\n label: t(\"menubar.alignCenter\"),\n icon: AlignCenter,\n active: editor.isActive({ textAlign: \"center\" }),\n onClick: () => editor.chain().focus().setTextAlign(\"center\").run(),\n },\n {\n type: \"action\",\n label: t(\"menubar.alignRight\"),\n icon: AlignRight,\n active: editor.isActive({ textAlign: \"right\" }),\n onClick: () => editor.chain().focus().setTextAlign(\"right\").run(),\n },\n {\n type: \"action\",\n label: t(\"menubar.alignJustify\"),\n icon: AlignJustify,\n active: editor.isActive({ textAlign: \"justify\" }),\n onClick: () => editor.chain().focus().setTextAlign(\"justify\").run(),\n },\n ],\n },\n { type: \"separator\" },\n {\n type: \"action\",\n label: t(\"menubar.clearFormatting\"),\n onClick: () => editor.chain().focus().unsetAllMarks().clearNodes().run(),\n },\n ];\n}\n\nfunction buildToolsMenuItems(\n t: (k: string) => string,\n { onSourceCode, openSourceDialog }: { onSourceCode?: () => void; openSourceDialog: () => void },\n): MenuItemDef[] {\n return [\n {\n type: \"action\",\n label: t(\"menubar.sourceCode\"),\n icon: FileCode,\n onClick: () => (onSourceCode ? onSourceCode() : openSourceDialog()),\n },\n ];\n}\n\nfunction buildTableMenuItems(t: (k: string) => string, editor: Editor, onInsertTable: (rows: number, cols: number) => void): MenuItemDef[] {\n const inTable = getTableAnchorPos(editor) !== null;\n\n return [\n {\n type: \"sub\",\n label: t(\"menubar.insertTable\"),\n icon: TableIcon,\n items: [\n {\n type: \"custom\",\n key: \"table-insert-grid\",\n render: () => (\n <MenuTableInsertGrid\n insertLabel={t(\"tableMenu.insertTable\")}\n previewTemplate={t(\"tableMenu.gridPreview\")}\n onInsert={onInsertTable}\n />\n ),\n },\n ],\n },\n {\n type: \"action\",\n label: t(\"menubar.tableProperties\"),\n disabled: true,\n onClick: () => {},\n },\n {\n type: \"action\",\n label: t(\"menubar.deleteTable\"),\n icon: Trash2,\n destructive: true,\n disabled: !inTable,\n onClick: () => editor.chain().focus().deleteTable().run(),\n },\n { type: \"separator\" },\n {\n type: \"sub\",\n label: t(\"menubar.row\"),\n disabled: !inTable,\n items: [\n {\n type: \"action\",\n label: t(\"menubar.deleteRow\"),\n destructive: true,\n onClick: () => editor.chain().focus().deleteRow().run(),\n },\n ],\n },\n {\n type: \"sub\",\n label: t(\"menubar.column\"),\n disabled: !inTable,\n items: [\n {\n type: \"action\",\n label: t(\"menubar.deleteColumn\"),\n destructive: true,\n onClick: () => editor.chain().focus().deleteColumn().run(),\n },\n ],\n },\n {\n type: \"sub\",\n label: t(\"menubar.cell\"),\n disabled: !inTable,\n items: [\n {\n type: \"action\",\n label: t(\"menubar.mergeCells\"),\n onClick: () => editor.chain().focus().mergeCells().run(),\n disabled: !editor.can().mergeCells(),\n },\n {\n type: \"action\",\n label: t(\"menubar.splitCell\"),\n onClick: () => editor.chain().focus().splitCell().run(),\n disabled: !editor.can().splitCell(),\n },\n ],\n },\n ];\n}\n\n// ─── MenuBarTrigger ──────────────────────────────────────────────────────────\n\nconst MenuBarTrigger = React.forwardRef<HTMLButtonElement, React.ButtonHTMLAttributes<HTMLButtonElement>>(\n ({ children, className, ...props }, ref) => (\n <button\n ref={ref}\n type=\"button\"\n onMouseDown={(e) => e.preventDefault()}\n className={cn(\n \"px-2 py-0.5 rounded text-sm transition-colors cursor-pointer\",\n \"hover:bg-accent hover:text-accent-foreground\",\n \"focus:outline-none focus:bg-accent focus:text-accent-foreground\",\n className,\n )}\n {...props}\n >\n {children}\n </button>\n ),\n);\nMenuBarTrigger.displayName = \"MenuBarTrigger\";\n\n// ─── MenuBar ─────────────────────────────────────────────────────────────────\n\nexport interface MenuBarProps {\n editor: Editor;\n containerRef: React.RefObject<HTMLElement | null>;\n uploadImage?: (file: File) => Promise<string> | string;\n imageInsertMode?: \"base64\" | \"upload\";\n maxImageFileSize?: number;\n allowedImageMimeTypes?: string[];\n onImageUploadError?: (error: Error, file: File) => void;\n fallbackToDataUrl?: boolean;\n onSave?: () => void;\n onExport?: () => void;\n onSourceCode?: () => void;\n onPreview?: (html: string) => void | false;\n showPreviewButton?: boolean;\n}\n\nexport const MenuBar: React.FC<MenuBarProps> = ({\n editor,\n containerRef,\n uploadImage,\n imageInsertMode = \"base64\",\n maxImageFileSize = DEFAULT_UEDITOR_IMAGE_MAX_FILE_SIZE,\n allowedImageMimeTypes = DEFAULT_UEDITOR_IMAGE_MIME_TYPES,\n onImageUploadError,\n fallbackToDataUrl = true,\n onSave,\n onExport,\n onSourceCode,\n onPreview,\n showPreviewButton = true,\n}) => {\n const t = useSmartTranslations(\"UEditor\");\n useSharedEditorUiRenderState(editor);\n const getPortalContainer = useUEditorPortalContainerGetter();\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const sourceTextareaRef = useRef<HTMLTextAreaElement>(null);\n const [showImageInput, setShowImageInput] = useState(false);\n const [showLinkInput, setShowLinkInput] = useState(false);\n const [isUploadingImage, setIsUploadingImage] = useState(false);\n const [imageUploadError, setImageUploadError] = useState<string | null>(null);\n const [openMenuKey, setOpenMenuKey] = useState<string | null>(null);\n\n // Built-in source code dialog state\n const [showSourceDialog, setShowSourceDialog] = useState(false);\n const [sourceHtml, setSourceHtml] = useState(\"\");\n const [sourceError, setSourceError] = useState(\"\");\n const sourceErrorId = React.useId();\n\n // Built-in preview dialog state\n const [showPreviewDialog, setShowPreviewDialog] = useState(false);\n const [previewHtml, setPreviewHtml] = useState(\"\");\n const modalPortalContainer = resolveUEditorPortalContainer(\n getPortalContainer,\n undefined,\n editor.view.dom.ownerDocument,\n );\n useEffect(() => {\n if (!showPreviewDialog) return;\n const updatePreview = () => {\n if (!editor.isDestroyed) {\n setPreviewHtml(prepareUEditorPreviewHtml(editor.getHTML(), editor.view.dom.ownerDocument));\n }\n };\n updatePreview();\n editor.on(\"update\", updatePreview);\n return () => {\n editor.off(\"update\", updatePreview);\n };\n }, [editor, showPreviewDialog]);\n\n const openSourceDialog = () => {\n setSourceHtml(editor.getHTML());\n setSourceError(\"\");\n setShowSourceDialog(true);\n };\n\n const openPreviewDialog = () => {\n setPreviewHtml(prepareUEditorPreviewHtml(editor.getHTML(), editor.view.dom.ownerDocument));\n setShowPreviewDialog(true);\n };\n\n const handlePreview = () => {\n if (onPreview?.(editor.getHTML()) === false) return;\n openPreviewDialog();\n };\n\n const applySourceHtml = () => {\n const nextSourceHtml = sourceTextareaRef.current?.value ?? sourceHtml;\n try {\n if (!isSafeUEditorSourceHtml(nextSourceHtml, editor.view.dom.ownerDocument)) {\n throw new Error(\"Unsafe source HTML\");\n }\n editor.chain().focus().setContent(nextSourceHtml, { errorOnInvalidContent: true }).run();\n setSourceError(\"\");\n setShowSourceDialog(false);\n } catch {\n setSourceError(t(\"menubar.invalidSource\"));\n }\n };\n\n const closeInsertMenu = () => {\n setOpenMenuKey(null);\n setShowImageInput(false);\n setShowLinkInput(false);\n setImageUploadError(null);\n };\n\n const handleImageUrl = (url: string, alt?: string) => {\n const safe = sanitizeUEditorUrl(url, \"image\");\n if (safe) {\n editor.chain().focus().setImage({ src: safe, alt: alt ?? \"\" }).run();\n editor.commands.createParagraphNear();\n }\n closeInsertMenu();\n };\n\n const handleImageFiles = async (files: File[]) => {\n if (files.length === 0 || isUploadingImage) return;\n setIsUploadingImage(true);\n setImageUploadError(null);\n const trackedPosition = trackEditorInsertionPosition(editor);\n try {\n const { images, hadError } = await resolveUEditorImageFiles(files, {\n maxFileSize: maxImageFileSize,\n allowedMimeTypes: allowedImageMimeTypes,\n upload: uploadImage,\n fallbackToDataUrl,\n insertMode: imageInsertMode,\n onError: onImageUploadError,\n });\n\n if (!editor.isDestroyed && images.length > 0) {\n const content = images.map((image) => ({\n type: \"image\",\n attrs: { src: image.src, alt: image.file.name },\n }));\n editor.commands.insertContentAt(trackedPosition.current, content, { updateSelection: false });\n }\n\n if (hadError) {\n setImageUploadError(t(\"imageInput.uploadError\"));\n } else {\n closeInsertMenu();\n }\n } finally {\n trackedPosition.stop();\n setIsUploadingImage(false);\n }\n };\n\n const handleInsertTable = (rows: number, cols: number) => {\n editor.chain().focus().insertTable({ rows, cols, withHeaderRow: true }).run();\n // Close the Insert menu after inserting\n closeInsertMenu();\n };\n\n const handleLinkSubmit = (url: string) => {\n applyEditorLink(editor, url);\n closeInsertMenu();\n };\n\n const insertMenuItems: MenuItemDef[] = [\n {\n type: \"custom\",\n key: \"image\",\n render: () =>\n showImageInput ? (\n <ImageInput onSubmit={handleImageUrl} onCancel={() => setShowImageInput(false)} />\n ) : (\n <>\n <DropdownMenuItem label={t(\"menubar.image\")} icon={ImageIcon} onClick={() => setShowImageInput(true)} closeOnSelect={false} />\n <DropdownMenuItem\n label={isUploadingImage ? t(\"imageInput.uploading\") : t(\"menubar.imageUpload\")}\n icon={Upload}\n onClick={() => fileInputRef.current?.click()}\n closeOnSelect={false}\n disabled={isUploadingImage}\n />\n {imageUploadError ? <DropdownMenuItem label={imageUploadError} disabled destructive /> : null}\n </>\n ),\n },\n { type: \"separator\" },\n {\n type: \"custom\",\n key: \"link\",\n render: () =>\n showLinkInput ? (\n <LinkInput onSubmit={handleLinkSubmit} onCancel={() => setShowLinkInput(false)} initialUrl={editor.getAttributes(\"link\").href ?? \"\"} />\n ) : (\n <DropdownMenuItem\n label={t(\"menubar.link\")}\n icon={LinkIcon}\n shortcut={t(\"menubar.linkShortcut\")}\n onClick={() => setShowLinkInput(true)}\n closeOnSelect={false}\n />\n ),\n },\n { type: \"separator\" },\n {\n type: \"sub\",\n label: t(\"menubar.insertTable\"),\n icon: TableIcon,\n items: [\n {\n type: \"custom\",\n key: \"table-grid\",\n render: () => (\n <MenuTableInsertGrid\n insertLabel={t(\"tableMenu.insertTable\")}\n previewTemplate={t(\"tableMenu.gridPreview\")}\n onInsert={handleInsertTable}\n />\n ),\n },\n ],\n },\n { type: \"separator\" },\n {\n type: \"sub\",\n label: t(\"menubar.formFields\") || \"Form Fields\",\n icon: ListTodo,\n items: [\n {\n type: \"action\",\n label: t(\"menubar.formCheckbox\") || \"Form Checkbox\",\n icon: Square,\n onClick: () => editor.chain().focus().setFormCheckbox().run(),\n },\n {\n type: \"action\",\n label: t(\"slashCommand.roundCheckbox\") || \"Round Checkbox\",\n icon: CircleCheckBig,\n onClick: () => editor.chain().focus().setFormCheckbox({ variant: \"circle\" }).run(),\n },\n {\n type: \"action\",\n label: t(\"menubar.formRadio\") || \"Form Radio Button\",\n icon: CircleDot,\n onClick: () => editor.chain().focus().setFormRadio().run(),\n },\n ],\n },\n { type: \"separator\" },\n {\n type: \"action\",\n label: t(\"menubar.horizontalRule\"),\n onClick: () => editor.chain().focus().setHorizontalRule().run(),\n },\n ];\n\n const menus = [\n {\n key: \"file\",\n label: t(\"menubar.file\"),\n items: buildFileMenuItems(t, editor, { onSave, onExport }),\n },\n { key: \"edit\", label: t(\"menubar.edit\"), items: buildEditMenuItems(t, editor) },\n {\n key: \"view\",\n label: t(\"menubar.view\"),\n items: buildViewMenuItems(t, editor, {\n containerRef,\n onSourceCode,\n openSourceDialog,\n onPreview: handlePreview,\n openPreviewDialog,\n }),\n },\n {\n key: \"insert\",\n label: t(\"menubar.insert\"),\n items: insertMenuItems,\n },\n { key: \"format\", label: t(\"menubar.format\"), items: buildFormatMenuItems(t, editor) },\n {\n key: \"tools\",\n label: t(\"menubar.tools\"),\n items: buildToolsMenuItems(t, { onSourceCode, openSourceDialog }),\n },\n { key: \"table\", label: t(\"menubar.table\"), items: buildTableMenuItems(t, editor, handleInsertTable) },\n ];\n\n return (\n <>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept={allowedImageMimeTypes.join(\",\")}\n multiple\n className=\"hidden\"\n onChange={(e) => {\n const files = Array.from(e.target.files ?? []);\n e.target.value = \"\";\n void handleImageFiles(files);\n }}\n />\n\n <nav aria-label={t(\"toolbar.showMenuBar\")} className=\"flex items-center gap-0.5 border-b border-border/35 bg-muted/20 px-1.5 py-0.5\">\n {menus.map(({ key, label, items }) => (\n <DropdownMenu\n key={key}\n trigger={<MenuBarTrigger>{label}</MenuBarTrigger>}\n placement=\"bottom-start\"\n isOpen={openMenuKey === key}\n onOpenChange={(open) => {\n setOpenMenuKey((current) => open ? key : current === key ? null : current);\n if (key === \"insert\" && !open) {\n setShowImageInput(false);\n setShowLinkInput(false);\n }\n }}\n openOnHover\n >\n {renderMenuItems(items)}\n </DropdownMenu>\n ))}\n {showPreviewButton && (\n <button\n type=\"button\"\n onClick={handlePreview}\n aria-label={t(\"menubar.preview\")}\n title={t(\"menubar.preview\")}\n className={cn(\n \"ml-auto inline-flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition-colors\",\n \"hover:bg-accent hover:text-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1\",\n )}\n >\n <Eye className=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n )}\n </nav>\n\n {/* Built-in source code dialog */}\n <Modal\n isOpen={showSourceDialog}\n onClose={() => setShowSourceDialog(false)}\n title={t(\"menubar.sourceCode\")}\n size=\"lg\"\n portalContainer={modalPortalContainer}\n >\n <div className=\"space-y-3\">\n <p className=\"text-xs text-muted-foreground\">{t(\"menubar.sourceCodeHint\")}</p>\n <textarea\n ref={sourceTextareaRef}\n data-testid=\"source-code-textarea\"\n aria-label={t(\"menubar.sourceCode\")}\n name=\"ueditor-source-html\"\n className=\"w-full h-64 font-mono text-xs p-3 bg-muted rounded-lg border border-border resize-y focus:outline-none focus:ring-2 focus:ring-primary/20\"\n value={sourceHtml}\n onChange={(e) => {\n setSourceHtml(e.target.value);\n if (sourceError) setSourceError(\"\");\n }}\n aria-invalid={Boolean(sourceError)}\n aria-describedby={sourceError ? sourceErrorId : undefined}\n spellCheck={false}\n />\n {sourceError ? (\n <p id={sourceErrorId} role=\"alert\" className=\"text-xs text-destructive\">\n {sourceError}\n </p>\n ) : null}\n <div className=\"flex gap-2 justify-end\">\n <button\n type=\"button\"\n onClick={applySourceHtml}\n className=\"px-4 py-2 bg-primary text-primary-foreground rounded-lg text-sm hover:bg-primary/90 transition-colors\"\n >\n {t(\"menubar.applySource\")}\n </button>\n <button\n type=\"button\"\n onClick={() => setShowSourceDialog(false)}\n className=\"px-4 py-2 bg-muted rounded-lg text-sm hover:bg-accent transition-colors\"\n >\n {t(\"menubar.closeDialog\")}\n </button>\n </div>\n </div>\n </Modal>\n\n <Modal\n isOpen={showPreviewDialog}\n onClose={() => setShowPreviewDialog(false)}\n title={t(\"menubar.preview\")}\n size=\"full\"\n portalContainer={modalPortalContainer}\n width=\"min(1180px, calc(100vw - 2rem))\"\n height=\"min(860px, calc(100vh - 2rem))\"\n className=\"flex flex-col overflow-hidden rounded-xl md:rounded-2xl\"\n contentClassName=\"flex min-h-0 flex-1 overflow-hidden p-0\"\n >\n <div\n data-testid=\"preview-content\"\n className=\"min-h-0 flex-1 overflow-y-auto overscroll-contain\"\n >\n {editor.isEmpty ? (\n <p className=\"text-muted-foreground text-sm\">{t(\"menubar.previewEmpty\")}</p>\n ) : (\n <div\n className={UEDITOR_PROSEMIRROR_CLASS_NAME}\n dangerouslySetInnerHTML={{ __html: previewHtml }}\n />\n )}\n </div>\n </Modal>\n </>\n );\n};\n","import { DEFAULT_TABLE_ROW_HEIGHT, MIN_TABLE_ROW_HEIGHT } from \"./table-dom-utils\";\nimport {\n clampResponsiveTableWidthBp,\n formatBasisPointsAsPercentage,\n normalizeColumnRatios,\n parseColumnRatios,\n parsePercentageToBasisPoints,\n resolveResponsiveTableOffsetBp,\n TABLE_WIDTH_BASIS_POINTS,\n} from \"./table-width-model\";\nimport { sanitizeUEditorUrl } from \"./url-safety\";\n\nconst BLOCKED_PREVIEW_ELEMENTS = new Set([\"SCRIPT\", \"IFRAME\", \"OBJECT\", \"EMBED\", \"LINK\", \"META\", \"BASE\", \"STYLE\"]);\nconst UNSAFE_INLINE_STYLE_RE = /(?:url\\s*\\(|expression\\s*\\(|@import|-moz-binding)/i;\n\nexport function isSafeUEditorSourceHtml(html: string, ownerDocument?: Document | null) {\n const sourceDocument = ownerDocument ?? (typeof document !== \"undefined\" ? document : null);\n if (!sourceDocument) return false;\n const container = sourceDocument.createElement(\"div\");\n container.innerHTML = html;\n\n for (const element of Array.from(container.querySelectorAll<HTMLElement>(\"*\"))) {\n if (BLOCKED_PREVIEW_ELEMENTS.has(element.tagName)) return false;\n for (const attribute of Array.from(element.attributes)) {\n const name = attribute.name.toLowerCase();\n if (name.startsWith(\"on\") || name === \"srcdoc\") return false;\n }\n const style = element.getAttribute(\"style\");\n if (style && UNSAFE_INLINE_STYLE_RE.test(style)) return false;\n\n const isFileCard = element.getAttribute(\"data-type\") === \"file-card\";\n const urlAttributes: Array<[string, \"link\" | \"image\" | \"file\"]> = [\n [\"href\", isFileCard ? \"file\" : \"link\"],\n [\"src\", \"image\"],\n [\"data-src\", isFileCard ? \"file\" : \"image\"],\n [\"data-url\", \"link\"],\n [\"data-image\", \"image\"],\n ];\n for (const [name, kind] of urlAttributes) {\n if (element.hasAttribute(name) && !sanitizeUEditorUrl(element.getAttribute(name) ?? \"\", kind)) return false;\n }\n }\n return true;\n}\n\nfunction sanitizePreviewContainer(container: HTMLElement) {\n for (const element of Array.from(container.querySelectorAll<HTMLElement>(\"*\"))) {\n if (BLOCKED_PREVIEW_ELEMENTS.has(element.tagName)) {\n element.remove();\n continue;\n }\n\n for (const attribute of Array.from(element.attributes)) {\n const name = attribute.name.toLowerCase();\n if (name.startsWith(\"on\") || name === \"srcdoc\") {\n element.removeAttribute(attribute.name);\n }\n }\n\n const style = element.getAttribute(\"style\");\n if (style && UNSAFE_INLINE_STYLE_RE.test(style)) element.removeAttribute(\"style\");\n\n const isFileCard = element.getAttribute(\"data-type\") === \"file-card\";\n const urlAttributes: Array<[string, \"link\" | \"image\" | \"file\"]> = [\n [\"href\", isFileCard ? \"file\" : \"link\"],\n [\"src\", \"image\"],\n [\"data-src\", isFileCard ? \"file\" : \"image\"],\n [\"data-url\", \"link\"],\n [\"data-image\", \"image\"],\n ];\n for (const [name, kind] of urlAttributes) {\n if (!element.hasAttribute(name)) continue;\n const safeUrl = sanitizeUEditorUrl(element.getAttribute(name) ?? \"\", kind);\n if (safeUrl) element.setAttribute(name, safeUrl);\n else element.removeAttribute(name);\n }\n if (element.tagName === \"A\" && element.getAttribute(\"target\") === \"_blank\") {\n element.setAttribute(\"rel\", \"noopener noreferrer\");\n }\n }\n}\n\nconst DEFAULT_TABLE_COLUMN_WIDTH = 100;\nconst TIPTAP_TABLE_MIN_COLUMN_WIDTH = 25;\n\nfunction parsePixelWidth(value: string | null | undefined): number | null {\n if (!value) return null;\n const match = String(value).match(/(?:^|[\\s:])(\\d+(?:\\.\\d+)?)px\\b/i) ?? String(value).match(/^(\\d+(?:\\.\\d+)?)$/);\n if (!match) return null;\n const parsed = Number.parseFloat(match[1] ?? match[0]);\n return Number.isFinite(parsed) && parsed > 0 ? Math.round(parsed) : null;\n}\n\nfunction parseStyleWidth(style: CSSStyleDeclaration) {\n return parsePixelWidth(style.width) ?? parsePixelWidth(style.minWidth);\n}\n\nfunction parseStyleHeight(style: CSSStyleDeclaration) {\n return parsePixelWidth(style.height) ?? parsePixelWidth(style.minHeight);\n}\n\nfunction getCellColspan(cell: HTMLTableCellElement) {\n return Math.max(1, cell.colSpan || Number.parseInt(cell.getAttribute(\"colspan\") || \"1\", 10) || 1);\n}\n\nfunction getCellWidths(cell: HTMLTableCellElement): number[] | null {\n const dataColwidth = cell.getAttribute(\"data-colwidth\") || cell.getAttribute(\"colwidth\");\n if (dataColwidth) {\n const widths = dataColwidth\n .split(/[,\\s]+/)\n .map((part) => parsePixelWidth(part))\n .filter((width): width is number => typeof width === \"number\");\n if (widths.length > 0) return widths;\n }\n\n const width = parsePixelWidth(cell.getAttribute(\"width\")) ?? parseStyleWidth(cell.style);\n if (!width) return null;\n\n const colspan = getCellColspan(cell);\n return Array.from({ length: colspan }, () => Math.max(DEFAULT_TABLE_COLUMN_WIDTH, Math.round(width / colspan)));\n}\n\nfunction getColumnCount(table: HTMLTableElement) {\n const colCount = table.querySelectorAll(\"colgroup > col\").length;\n if (colCount > 0) return colCount;\n\n return Math.max(\n 0,\n ...Array.from(table.rows).map((row) =>\n Array.from(row.cells).reduce((count, cell) => count + getCellColspan(cell), 0),\n ),\n );\n}\n\nfunction resolveColumnWidths(table: HTMLTableElement) {\n const columnCount = getColumnCount(table);\n if (columnCount <= 0) return [];\n\n const widths = Array.from({ length: columnCount }, () => DEFAULT_TABLE_COLUMN_WIDTH);\n const cols = Array.from(table.querySelectorAll<HTMLTableColElement>(\"colgroup > col\"));\n\n cols.slice(0, columnCount).forEach((col, index) => {\n const width = parsePixelWidth(col.getAttribute(\"width\")) ?? parseStyleWidth(col.style);\n if (width && width > TIPTAP_TABLE_MIN_COLUMN_WIDTH) {\n widths[index] = width;\n }\n });\n\n Array.from(table.rows).forEach((row) => {\n let columnIndex = 0;\n Array.from(row.cells).forEach((cell) => {\n const cellWidths = getCellWidths(cell);\n if (cellWidths) {\n cellWidths.slice(0, getCellColspan(cell)).forEach((width, offset) => {\n if (width > TIPTAP_TABLE_MIN_COLUMN_WIDTH && columnIndex + offset < widths.length) {\n widths[columnIndex + offset] = width;\n }\n });\n }\n columnIndex += getCellColspan(cell);\n });\n });\n\n return widths;\n}\n\nfunction setStyleProperty(element: HTMLElement, property: string, value: string) {\n element.style.setProperty(property, value);\n}\n\nfunction resolveExplicitRowHeight(row: HTMLTableRowElement) {\n const explicitRowHeight = parsePixelWidth(row.getAttribute(\"data-row-height\")) ?? parseStyleHeight(row.style);\n if (explicitRowHeight) return Math.max(MIN_TABLE_ROW_HEIGHT, explicitRowHeight);\n\n const cellHeight = Array.from(row.cells).reduce((maxHeight, cell) => {\n const height = parsePixelWidth(cell.getAttribute(\"height\")) ?? parseStyleHeight(cell.style);\n return height ? Math.max(maxHeight, height) : maxHeight;\n }, 0);\n\n return cellHeight ? Math.max(MIN_TABLE_ROW_HEIGHT, cellHeight) : DEFAULT_TABLE_ROW_HEIGHT;\n}\n\nfunction normalizePreviewRowHeight(row: HTMLTableRowElement) {\n const rowHeight = resolveExplicitRowHeight(row);\n\n row.style.height = `${rowHeight}px`;\n row.style.minHeight = `${rowHeight}px`;\n\n Array.from(row.cells).forEach((cell) => {\n cell.style.height = `${rowHeight}px`;\n cell.style.minHeight = `${rowHeight}px`;\n });\n}\n\nfunction normalizePreviewTable(table: HTMLTableElement) {\n const widths = resolveColumnWidths(table);\n if (widths.length === 0) return;\n const storedMode = table.getAttribute(\"data-table-width-mode\");\n const responsive = storedMode === \"responsive\"\n || storedMode === \"full\"\n || parsePercentageToBasisPoints(table.style.width) !== null;\n const storedRatios = parseColumnRatios(table.getAttribute(\"data-table-column-ratios\"));\n const columnRatios = normalizeColumnRatios(\n storedRatios?.length === widths.length ? storedRatios : widths,\n widths.length,\n );\n const widthBp = responsive\n ? Number(table.getAttribute(\"data-table-width-bp\"))\n || parsePercentageToBasisPoints(table.getAttribute(\"data-table-width\") ?? table.style.width)\n || TABLE_WIDTH_BASIS_POINTS\n : TABLE_WIDTH_BASIS_POINTS;\n const safeWidthBp = clampResponsiveTableWidthBp(widthBp);\n const offsetBp = responsive\n ? Number(table.getAttribute(\"data-table-offset-bp\"))\n || parsePercentageToBasisPoints(table.getAttribute(\"data-table-offset\") ?? table.style.marginLeft)\n || 0\n : 0;\n const safeOffsetBp = resolveResponsiveTableOffsetBp(safeWidthBp, null, offsetBp);\n\n let colgroup = table.querySelector(\"colgroup\");\n if (!colgroup) {\n colgroup = document.createElement(\"colgroup\");\n table.insertBefore(colgroup, table.firstChild);\n }\n\n while (colgroup.children.length < widths.length) {\n colgroup.appendChild(document.createElement(\"col\"));\n }\n\n const tableWidth = widths.reduce((sum, width) => sum + width, 0);\n Array.from(colgroup.children).forEach((child, index) => {\n if (child.tagName.toLowerCase() !== \"col\") return;\n const col = child as HTMLTableColElement;\n if (index >= widths.length) {\n child.remove();\n return;\n }\n col.style.width = responsive ? formatBasisPointsAsPercentage(columnRatios[index]) : `${widths[index]}px`;\n col.style.minWidth = responsive ? \"\" : `${widths[index]}px`;\n col.setAttribute(\"width\", String(widths[index]));\n });\n\n setStyleProperty(table, \"width\", responsive ? formatBasisPointsAsPercentage(safeWidthBp) : `${tableWidth}px`);\n setStyleProperty(table, \"min-width\", responsive ? `${widths.length * TIPTAP_TABLE_MIN_COLUMN_WIDTH}px` : `${tableWidth}px`);\n setStyleProperty(table, \"table-layout\", \"fixed\");\n if (responsive) {\n table.setAttribute(\"data-table-width-mode\", \"responsive\");\n table.setAttribute(\"data-table-width-bp\", String(safeWidthBp));\n table.setAttribute(\"data-table-offset-bp\", String(safeOffsetBp));\n table.setAttribute(\"data-table-column-ratios\", columnRatios.join(\",\"));\n setStyleProperty(table, \"margin-left\", formatBasisPointsAsPercentage(safeOffsetBp));\n setStyleProperty(table, \"margin-right\", \"auto\");\n }\n\n Array.from(table.rows).forEach((row) => {\n let columnIndex = 0;\n normalizePreviewRowHeight(row);\n\n Array.from(row.cells).forEach((cell) => {\n const colspan = getCellColspan(cell);\n const cellWidth = widths.slice(columnIndex, columnIndex + colspan).reduce((sum, width) => sum + width, 0);\n const cellRatio = columnRatios.slice(columnIndex, columnIndex + colspan).reduce((sum, ratio) => sum + ratio, 0);\n if (cellWidth > 0) {\n cell.style.width = responsive ? formatBasisPointsAsPercentage(cellRatio) : `${cellWidth}px`;\n cell.style.minWidth = responsive ? \"\" : `${cellWidth}px`;\n }\n columnIndex += colspan;\n });\n });\n}\n\nexport function prepareUEditorPreviewHtml(html: string, ownerDocument?: Document | null) {\n const previewDocument = ownerDocument ?? (typeof document !== \"undefined\" ? document : null);\n if (!previewDocument || !html) return html;\n\n const container = previewDocument.createElement(\"div\");\n container.innerHTML = html;\n sanitizePreviewContainer(container);\n container.querySelectorAll(\"table\").forEach((table) => normalizePreviewTable(table));\n return container.innerHTML;\n}\n"],"mappings":"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","names":["width"]}