@underverse-ui/underverse 1.0.137 → 1.0.138

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.
package/dist/index.js CHANGED
@@ -770,7 +770,13 @@ var en_default = {
770
770
  dividerDesc: "Visual divider",
771
771
  table: "Table",
772
772
  tableDesc: "Add a table",
773
- noResults: "No matching blocks found"
773
+ noResults: "No matching blocks found",
774
+ callout: "Callout",
775
+ calloutDesc: "Highlight key info with a callout block",
776
+ bookmark: "Bookmark Card",
777
+ bookmarkDesc: "Embed a link as a bookmark card",
778
+ fileCard: "File Attachment",
779
+ fileCardDesc: "Upload a file card attachment"
774
780
  },
775
781
  floatingMenu: {
776
782
  addBlock: "Add block"
@@ -831,7 +837,28 @@ var en_default = {
831
837
  alignLeft: "Align Table Left",
832
838
  alignCenter: "Align Table Center",
833
839
  alignRight: "Align Table Right",
834
- cellBackground: "Cell Background"
840
+ cellBackground: "Cell Background",
841
+ cellBorder: "Cell Border",
842
+ borderStyle: "Border Style",
843
+ borderWidth: "Border Width",
844
+ borderColor: "Border Color",
845
+ clearBorder: "Clear Border",
846
+ done: "Done"
847
+ },
848
+ callout: {
849
+ selectEmoji: "Select Emoji",
850
+ backgroundColor: "Background Color"
851
+ },
852
+ bookmark: {
853
+ clickToOpenNewTab: "Click to open this link in a new tab.",
854
+ clickToOpenLink: "Click to open link.",
855
+ noDescription: "No description available.",
856
+ failedToLoad: "Failed to load link preview. Click to open link."
857
+ },
858
+ fileCard: {
859
+ unnamed: "Unnamed file",
860
+ uploading: "(Uploading...)",
861
+ uploadFailed: "Upload failed"
835
862
  }
836
863
  }
837
864
  };
@@ -1042,7 +1069,13 @@ var vi_default = {
1042
1069
  dividerDesc: "\u0110\u01B0\u1EDDng k\u1EBB ngang",
1043
1070
  table: "B\u1EA3ng",
1044
1071
  tableDesc: "Th\xEAm b\u1EA3ng",
1045
- noResults: "Kh\xF4ng t\xECm th\u1EA5y kh\u1ED1i ph\xF9 h\u1EE3p"
1072
+ noResults: "Kh\xF4ng t\xECm th\u1EA5y kh\u1ED1i ph\xF9 h\u1EE3p",
1073
+ callout: "H\u1ED9p th\xF4ng tin",
1074
+ calloutDesc: "L\xE0m n\u1ED5i b\u1EADt th\xF4ng tin ch\xEDnh b\u1EB1ng h\u1ED9p ch\xFA th\xEDch",
1075
+ bookmark: "Th\u1EBB li\xEAn k\u1EBFt",
1076
+ bookmarkDesc: "Nh\xFAng m\u1ED9t li\xEAn k\u1EBFt d\u01B0\u1EDBi d\u1EA1ng th\u1EBB xem tr\u01B0\u1EDBc",
1077
+ fileCard: "T\u1EC7p \u0111\xEDnh k\xE8m",
1078
+ fileCardDesc: "T\u1EA3i l\xEAn t\u1EC7p tin \u0111\xEDnh k\xE8m"
1046
1079
  },
1047
1080
  floatingMenu: {
1048
1081
  addBlock: "Th\xEAm kh\u1ED1i"
@@ -1103,7 +1136,28 @@ var vi_default = {
1103
1136
  alignLeft: "C\u0103n b\u1EA3ng tr\xE1i",
1104
1137
  alignCenter: "C\u0103n b\u1EA3ng gi\u1EEFa",
1105
1138
  alignRight: "C\u0103n b\u1EA3ng ph\u1EA3i",
1106
- cellBackground: "M\xE0u n\u1EC1n \xF4"
1139
+ cellBackground: "M\xE0u n\u1EC1n \xF4",
1140
+ cellBorder: "Vi\u1EC1n \xF4",
1141
+ borderStyle: "Ki\u1EC3u vi\u1EC1n",
1142
+ borderWidth: "\u0110\u1ED9 d\xE0y vi\u1EC1n",
1143
+ borderColor: "M\xE0u vi\u1EC1n",
1144
+ clearBorder: "X\xF3a vi\u1EC1n",
1145
+ done: "Xong"
1146
+ },
1147
+ callout: {
1148
+ selectEmoji: "Ch\u1ECDn Bi\u1EC3u t\u01B0\u1EE3ng",
1149
+ backgroundColor: "M\xE0u n\u1EC1n"
1150
+ },
1151
+ bookmark: {
1152
+ clickToOpenNewTab: "B\u1EA5m \u0111\u1EC3 m\u1EDF li\xEAn k\u1EBFt n\xE0y trong tab m\u1EDBi.",
1153
+ clickToOpenLink: "B\u1EA5m \u0111\u1EC3 m\u1EDF li\xEAn k\u1EBFt.",
1154
+ noDescription: "Kh\xF4ng c\xF3 m\xF4 t\u1EA3.",
1155
+ failedToLoad: "T\u1EA3i b\u1EA3n xem tr\u01B0\u1EDBc th\u1EA5t b\u1EA1i. B\u1EA5m \u0111\u1EC3 m\u1EDF li\xEAn k\u1EBFt."
1156
+ },
1157
+ fileCard: {
1158
+ unnamed: "T\u1EC7p kh\xF4ng t\xEAn",
1159
+ uploading: "(\u0110ang t\u1EA3i l\xEAn...)",
1160
+ uploadFailed: "T\u1EA3i l\xEAn th\u1EA5t b\u1EA1i"
1107
1161
  }
1108
1162
  }
1109
1163
  };
@@ -1313,7 +1367,13 @@ var ko_default = {
1313
1367
  divider: "\uAD6C\uBD84\uC120",
1314
1368
  dividerDesc: "\uC2DC\uAC01\uC801 \uAD6C\uBD84\uC120",
1315
1369
  table: "\uD45C",
1316
- tableDesc: "\uD45C \uCD94\uAC00"
1370
+ tableDesc: "\uD45C \uCD94\uAC00",
1371
+ callout: "\uCF5C\uC544\uC6C3",
1372
+ calloutDesc: "\uC911\uC694\uD55C \uC815\uBCF4\uB97C \uCF5C\uC544\uC6C3 \uBE14\uB85D\uC73C\uB85C \uAC15\uC870\uD569\uB2C8\uB2E4",
1373
+ bookmark: "\uBD81\uB9C8\uD06C \uCE74\uB4DC",
1374
+ bookmarkDesc: "\uB9C1\uD06C\uB97C \uBD81\uB9C8\uD06C \uCE74\uB4DC\uB85C \uC0BD\uC785\uD569\uB2C8\uB2E4",
1375
+ fileCard: "\uD30C\uC77C \uCCA8\uBD80",
1376
+ fileCardDesc: "\uD30C\uC77C \uCE74\uB4DC \uCCA8\uBD80 \uD30C\uC77C\uC744 \uC5C5\uB85C\uB4DC\uD569\uB2C8\uB2E4"
1317
1377
  },
1318
1378
  floatingMenu: {
1319
1379
  addBlock: "\uBE14\uB85D \uCD94\uAC00"
@@ -1374,7 +1434,28 @@ var ko_default = {
1374
1434
  alignLeft: "\uD45C \uC67C\uCABD \uC815\uB82C",
1375
1435
  alignCenter: "\uD45C \uAC00\uC6B4\uB370 \uC815\uB82C",
1376
1436
  alignRight: "\uD45C \uC624\uB978\uCABD \uC815\uB82C",
1377
- cellBackground: "\uC140 \uBC30\uACBD\uC0C9"
1437
+ cellBackground: "\uC140 \uBC30\uACBD\uC0C9",
1438
+ cellBorder: "\uC140 \uD14C\uB450\uB9AC",
1439
+ borderStyle: "\uD14C\uB450\uB9AC \uC2A4\uD0C0\uC77C",
1440
+ borderWidth: "\uD14C\uB450\uB9AC \uB450\uAED8",
1441
+ borderColor: "\uD14C\uB450\uB9AC \uC0C9\uC0C1",
1442
+ clearBorder: "\uD14C\uB450\uB9AC \uC9C0\uC6B0\uAE30",
1443
+ done: "\uC644\uB8CC"
1444
+ },
1445
+ callout: {
1446
+ selectEmoji: "\uC774\uBAA8\uC9C0 \uC120\uD0DD",
1447
+ backgroundColor: "\uBC30\uACBD \uC0C9\uC0C1"
1448
+ },
1449
+ bookmark: {
1450
+ clickToOpenNewTab: "\uD074\uB9AD\uD558\uC5EC \uC774 \uB9C1\uD06C\uB97C \uC0C8 \uD0ED\uC5D0\uC11C \uC5FD\uB2C8\uB2E4.",
1451
+ clickToOpenLink: "\uD074\uB9AD\uD558\uC5EC \uB9C1\uD06C\uB97C \uC5FD\uB2C8\uB2E4.",
1452
+ noDescription: "\uC124\uBA85\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
1453
+ failedToLoad: "\uB9C1\uD06C \uBBF8\uB9AC\uBCF4\uAE30\uB97C \uBD88\uB7EC\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uD074\uB9AD\uD558\uC5EC \uB9C1\uD06C\uB97C \uC5FD\uB2C8\uB2E4."
1454
+ },
1455
+ fileCard: {
1456
+ unnamed: "\uC774\uB984 \uC5C6\uB294 \uD30C\uC77C",
1457
+ uploading: "(\uC5C5\uB85C\uB4DC \uC911...)",
1458
+ uploadFailed: "\uC5C5\uB85C\uB4DC \uC2E4\uD328"
1378
1459
  }
1379
1460
  }
1380
1461
  };
@@ -1584,7 +1665,13 @@ var ja_default = {
1584
1665
  divider: "\u533A\u5207\u308A\u7DDA",
1585
1666
  dividerDesc: "\u8996\u899A\u7684\u306A\u533A\u5207\u308A\u7DDA",
1586
1667
  table: "\u8868",
1587
- tableDesc: "\u8868\u3092\u8FFD\u52A0"
1668
+ tableDesc: "\u8868\u3092\u8FFD\u52A0",
1669
+ callout: "\u30B3\u30FC\u30EB\u30A2\u30A6\u30C8",
1670
+ calloutDesc: "\u91CD\u8981\u306A\u60C5\u5831\u3092\u30B3\u30FC\u30EB\u30A2\u30A6\u30C8\u30D6\u30ED\u30C3\u30AF\u3067\u5F37\u8ABF\u3057\u307E\u3059",
1671
+ bookmark: "\u30D6\u30C3\u30AF\u30DE\u30FC\u30AF\u30AB\u30FC\u30C9",
1672
+ bookmarkDesc: "\u30EA\u30F3\u30AF\u3092\u30D6\u30C3\u30AF\u30DE\u30FC\u30AF\u30AB\u30FC\u30C9\u3068\u3057\u3066\u57CB\u3081\u8FBC\u307F\u307E\u3059",
1673
+ fileCard: "\u30D5\u30A1\u30A4\u30EB\u6DFB\u4ED8",
1674
+ fileCardDesc: "\u30D5\u30A1\u30A4\u30EB\u30AB\u30FC\u30C9\u306E\u6DFB\u4ED8\u30D5\u30A1\u30A4\u30EB\u3092\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u3057\u307E\u3059"
1588
1675
  },
1589
1676
  floatingMenu: {
1590
1677
  addBlock: "\u30D6\u30ED\u30C3\u30AF\u3092\u8FFD\u52A0"
@@ -1645,7 +1732,28 @@ var ja_default = {
1645
1732
  alignLeft: "\u8868\u3092\u5DE6\u5BC4\u305B",
1646
1733
  alignCenter: "\u8868\u3092\u4E2D\u592E\u63C3\u3048",
1647
1734
  alignRight: "\u8868\u3092\u53F3\u5BC4\u305B",
1648
- cellBackground: "\u30BB\u30EB\u80CC\u666F\u8272"
1735
+ cellBackground: "\u30BB\u30EB\u80CC\u666F\u8272",
1736
+ cellBorder: "\u30BB\u30EB\u306E\u67A0\u7DDA",
1737
+ borderStyle: "\u67A0\u7DDA\u30B9\u30BF\u30A4\u30EB",
1738
+ borderWidth: "\u67A0\u7DDA\u306E\u592A\u3055",
1739
+ borderColor: "\u67A0\u7DDA\u306E\u8272",
1740
+ clearBorder: "\u67A0\u7DDA\u3092\u30AF\u30EA\u30A2",
1741
+ done: "\u5B8C\u4E86"
1742
+ },
1743
+ callout: {
1744
+ selectEmoji: "\u7D75\u6587\u5B57\u3092\u9078\u629E",
1745
+ backgroundColor: "\u80CC\u666F\u8272"
1746
+ },
1747
+ bookmark: {
1748
+ clickToOpenNewTab: "\u30AF\u30EA\u30C3\u30AF\u3057\u3066\u3053\u306E\u30EA\u30F3\u30AF\u3092\u65B0\u3057\u3044\u30BF\u30D6\u3067\u958B\u304F\u3002",
1749
+ clickToOpenLink: "\u30AF\u30EA\u30C3\u30AF\u3057\u3066\u30EA\u30F3\u30AF\u3092\u958B\u304F\u3002",
1750
+ noDescription: "\u8AAC\u660E\u306F\u3042\u308A\u307E\u305B\u3093\u3002",
1751
+ failedToLoad: "\u30D7\u30EC\u30D3\u30E5\u30FC\u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002\u30AF\u30EA\u30C3\u30AF\u3057\u3066\u30EA\u30F3\u30AF\u3092\u958B\u304F\u3002"
1752
+ },
1753
+ fileCard: {
1754
+ unnamed: "\u540D\u524D\u306A\u3057\u30D5\u30A1\u30A4\u30EB",
1755
+ uploading: "(\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u4E2D...)",
1756
+ uploadFailed: "\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u5931\u6557"
1649
1757
  }
1650
1758
  }
1651
1759
  };
@@ -24158,11 +24266,11 @@ function useLocale2() {
24158
24266
  }
24159
24267
 
24160
24268
  // src/components/UEditor/UEditor.tsx
24161
- import React78, { useEffect as useEffect36, useImperativeHandle as useImperativeHandle3, useMemo as useMemo24, useRef as useRef35 } from "react";
24269
+ import React81, { useEffect as useEffect38, useImperativeHandle as useImperativeHandle3, useMemo as useMemo24, useRef as useRef36 } from "react";
24162
24270
  import { useEditor, EditorContent } from "@tiptap/react";
24163
24271
 
24164
24272
  // src/components/UEditor/extensions.ts
24165
- import { mergeAttributes as mergeAttributes2 } from "@tiptap/core";
24273
+ import { mergeAttributes as mergeAttributes5 } from "@tiptap/core";
24166
24274
  import Document from "@tiptap/extension-document";
24167
24275
  import Paragraph from "@tiptap/extension-paragraph";
24168
24276
  import Text from "@tiptap/extension-text";
@@ -24178,6 +24286,604 @@ import TaskList from "@tiptap/extension-task-list";
24178
24286
  import TaskItem from "@tiptap/extension-task-item";
24179
24287
  import Blockquote from "@tiptap/extension-blockquote";
24180
24288
  import Code from "@tiptap/extension-code";
24289
+ import { wrappingInputRule } from "@tiptap/core";
24290
+ import { ReactNodeViewRenderer as ReactNodeViewRenderer5 } from "@tiptap/react";
24291
+
24292
+ // src/components/UEditor/callout.ts
24293
+ import { Node as Node2, mergeAttributes } from "@tiptap/core";
24294
+ import { ReactNodeViewRenderer } from "@tiptap/react";
24295
+
24296
+ // src/components/UEditor/CalloutView.tsx
24297
+ import { NodeViewWrapper, NodeViewContent } from "@tiptap/react";
24298
+
24299
+ // src/components/UEditor/emoji-picker.tsx
24300
+ import { jsx as jsx75 } from "react/jsx-runtime";
24301
+ var EmojiPicker2 = ({ onSelect }) => {
24302
+ return /* @__PURE__ */ jsx75(EmojiPicker, { onEmojiSelect: onSelect, chrome: "embedded" });
24303
+ };
24304
+
24305
+ // src/components/UEditor/CalloutView.tsx
24306
+ import { jsx as jsx76, jsxs as jsxs62 } from "react/jsx-runtime";
24307
+ var CALLOUT_COLORS = [
24308
+ { name: "Gray", color: "var(--muted)" },
24309
+ { name: "Blue", color: "color-mix(in oklch, var(--info) 15%, transparent)" },
24310
+ { name: "Green", color: "color-mix(in oklch, var(--success) 15%, transparent)" },
24311
+ { name: "Yellow", color: "color-mix(in oklch, var(--warning) 15%, transparent)" },
24312
+ { name: "Red", color: "color-mix(in oklch, var(--destructive) 15%, transparent)" }
24313
+ ];
24314
+ var CalloutView = ({ node, updateAttributes, selected }) => {
24315
+ const t = useSmartTranslations("UEditor");
24316
+ const currentEmoji = node.attrs.emoji ?? "\u{1F4A1}";
24317
+ const currentBgColor = node.attrs.backgroundColor ?? "var(--muted)";
24318
+ return /* @__PURE__ */ jsxs62(
24319
+ NodeViewWrapper,
24320
+ {
24321
+ className: cn(
24322
+ "flex items-start gap-4 rounded-xl border p-4 my-4 transition-all duration-200 border-border/50",
24323
+ selected && "ring-2 ring-primary/45 border-primary/20 shadow-sm"
24324
+ ),
24325
+ style: { backgroundColor: currentBgColor },
24326
+ children: [
24327
+ /* @__PURE__ */ jsx76("div", { className: "flex items-center justify-center select-none", contentEditable: false, children: /* @__PURE__ */ jsx76(
24328
+ Popover,
24329
+ {
24330
+ placement: "bottom-start",
24331
+ trigger: /* @__PURE__ */ jsx76(
24332
+ "button",
24333
+ {
24334
+ type: "button",
24335
+ className: "flex items-center justify-center text-2xl h-9 w-9 hover:bg-muted-foreground/10 active:scale-95 rounded-lg transition-all focus:outline-none",
24336
+ children: currentEmoji
24337
+ }
24338
+ ),
24339
+ children: /* @__PURE__ */ jsxs62("div", { className: "flex flex-col gap-3 w-64 max-h-[360px] overflow-y-auto p-1", children: [
24340
+ /* @__PURE__ */ jsx76("div", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider px-1", children: t("callout.selectEmoji") }),
24341
+ /* @__PURE__ */ jsx76("div", { className: "h-44 overflow-y-auto border border-border/40 rounded-lg", children: /* @__PURE__ */ jsx76(EmojiPicker2, { onSelect: (emoji) => updateAttributes({ emoji }) }) }),
24342
+ /* @__PURE__ */ jsxs62("div", { className: "border-t border-border/50 pt-2 mt-1", children: [
24343
+ /* @__PURE__ */ jsx76("div", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider px-1 mb-2", children: t("callout.backgroundColor") }),
24344
+ /* @__PURE__ */ jsx76("div", { className: "flex flex-wrap gap-2 px-1", children: CALLOUT_COLORS.map((col) => /* @__PURE__ */ jsx76(
24345
+ "button",
24346
+ {
24347
+ type: "button",
24348
+ title: col.name,
24349
+ onClick: () => updateAttributes({ backgroundColor: col.color }),
24350
+ className: cn(
24351
+ "h-6 w-6 rounded-full border transition-all active:scale-90 hover:scale-105",
24352
+ currentBgColor === col.color ? "border-primary ring-2 ring-primary/30" : "border-border/60"
24353
+ ),
24354
+ style: { backgroundColor: col.color }
24355
+ },
24356
+ col.name
24357
+ )) })
24358
+ ] })
24359
+ ] })
24360
+ }
24361
+ ) }),
24362
+ /* @__PURE__ */ jsx76(NodeViewContent, { className: "min-w-0 flex-1 outline-none" })
24363
+ ]
24364
+ }
24365
+ );
24366
+ };
24367
+
24368
+ // src/components/UEditor/callout.ts
24369
+ var Callout = Node2.create({
24370
+ name: "callout",
24371
+ group: "block",
24372
+ content: "block+",
24373
+ defining: true,
24374
+ addOptions() {
24375
+ return {
24376
+ HTMLAttributes: {}
24377
+ };
24378
+ },
24379
+ addAttributes() {
24380
+ return {
24381
+ emoji: {
24382
+ default: "\u{1F4A1}",
24383
+ parseHTML: (element) => element.getAttribute("data-emoji") || "\u{1F4A1}",
24384
+ renderHTML: (attributes) => ({
24385
+ "data-emoji": attributes.emoji
24386
+ })
24387
+ },
24388
+ backgroundColor: {
24389
+ default: "var(--muted)",
24390
+ parseHTML: (element) => element.getAttribute("data-background-color") || element.style.backgroundColor || "var(--muted)",
24391
+ renderHTML: (attributes) => ({
24392
+ "data-background-color": attributes.backgroundColor,
24393
+ style: `background-color: ${attributes.backgroundColor}`
24394
+ })
24395
+ }
24396
+ };
24397
+ },
24398
+ parseHTML() {
24399
+ return [
24400
+ {
24401
+ tag: 'div[data-type="callout"]'
24402
+ }
24403
+ ];
24404
+ },
24405
+ renderHTML({ HTMLAttributes }) {
24406
+ return [
24407
+ "div",
24408
+ mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, { "data-type": "callout" }),
24409
+ 0
24410
+ ];
24411
+ },
24412
+ addNodeView() {
24413
+ return ReactNodeViewRenderer(CalloutView);
24414
+ },
24415
+ addCommands() {
24416
+ return {
24417
+ setCallout: (attributes) => ({ commands }) => {
24418
+ return commands.wrapIn(this.name, attributes);
24419
+ }
24420
+ };
24421
+ }
24422
+ });
24423
+
24424
+ // src/components/UEditor/bookmark.ts
24425
+ import { Node as Node3, mergeAttributes as mergeAttributes2 } from "@tiptap/core";
24426
+ import { ReactNodeViewRenderer as ReactNodeViewRenderer2 } from "@tiptap/react";
24427
+
24428
+ // src/components/UEditor/BookmarkView.tsx
24429
+ import { useEffect as useEffect31, useState as useState42 } from "react";
24430
+ import { NodeViewWrapper as NodeViewWrapper2 } from "@tiptap/react";
24431
+ import { ExternalLink as ExternalLink2, Globe as Globe2 } from "lucide-react";
24432
+ import { jsx as jsx77, jsxs as jsxs63 } from "react/jsx-runtime";
24433
+ var BookmarkView = ({ node, updateAttributes, selected, editor }) => {
24434
+ const t = useSmartTranslations("UEditor");
24435
+ const { url, title, description, image, publisher } = node.attrs;
24436
+ const [loading2, setLoading] = useState42(false);
24437
+ const [error, setError] = useState42(false);
24438
+ useEffect31(() => {
24439
+ if (title) return;
24440
+ let active = true;
24441
+ const safeUpdateAttributes = (attrs) => {
24442
+ Promise.resolve().then(() => {
24443
+ if (active && editor && !editor.isDestroyed) {
24444
+ updateAttributes(attrs);
24445
+ }
24446
+ });
24447
+ };
24448
+ const extension = editor.extensionManager.extensions.find((e) => e.name === "bookmark");
24449
+ const fetchMetadata = extension?.options?.fetchMetadata;
24450
+ if (!fetchMetadata) {
24451
+ try {
24452
+ const hostname = new URL(url).hostname;
24453
+ safeUpdateAttributes({
24454
+ title: hostname || url,
24455
+ description: t("bookmark.clickToOpenNewTab"),
24456
+ publisher: hostname
24457
+ });
24458
+ } catch {
24459
+ safeUpdateAttributes({
24460
+ title: url,
24461
+ description: t("bookmark.clickToOpenLink"),
24462
+ publisher: ""
24463
+ });
24464
+ }
24465
+ return;
24466
+ }
24467
+ setLoading(true);
24468
+ setError(false);
24469
+ fetchMetadata(url).then((meta) => {
24470
+ if (!active) return;
24471
+ safeUpdateAttributes({
24472
+ title: meta.title || new URL(url).hostname || url,
24473
+ description: meta.description || t("bookmark.noDescription"),
24474
+ image: meta.image || "",
24475
+ publisher: meta.publisher || new URL(url).hostname || ""
24476
+ });
24477
+ setLoading(false);
24478
+ }).catch(() => {
24479
+ if (!active) return;
24480
+ setError(true);
24481
+ setLoading(false);
24482
+ try {
24483
+ const hostname = new URL(url).hostname;
24484
+ safeUpdateAttributes({
24485
+ title: hostname || url,
24486
+ description: t("bookmark.failedToLoad"),
24487
+ publisher: hostname
24488
+ });
24489
+ } catch {
24490
+ safeUpdateAttributes({
24491
+ title: url,
24492
+ description: t("bookmark.clickToOpenLink"),
24493
+ publisher: ""
24494
+ });
24495
+ }
24496
+ });
24497
+ return () => {
24498
+ active = false;
24499
+ };
24500
+ }, [url, title, editor, updateAttributes, t]);
24501
+ const handleOpenLink = (e) => {
24502
+ e.preventDefault();
24503
+ e.stopPropagation();
24504
+ window.open(url, "_blank", "noopener,noreferrer");
24505
+ };
24506
+ const displayPublisher = publisher || (() => {
24507
+ try {
24508
+ return new URL(url).hostname;
24509
+ } catch {
24510
+ return "";
24511
+ }
24512
+ })();
24513
+ return /* @__PURE__ */ jsx77(
24514
+ NodeViewWrapper2,
24515
+ {
24516
+ className: cn(
24517
+ "my-4 block overflow-hidden rounded-xl border border-border/60 bg-muted/20 hover:bg-muted/30 transition-all duration-200 cursor-pointer select-none",
24518
+ selected && "ring-2 ring-primary/45 border-primary/20 shadow-sm"
24519
+ ),
24520
+ onClick: handleOpenLink,
24521
+ children: loading2 ? /* @__PURE__ */ jsxs63("div", { className: "flex items-center justify-between p-4 gap-4 animate-pulse", children: [
24522
+ /* @__PURE__ */ jsxs63("div", { className: "flex-1 flex flex-col gap-2", children: [
24523
+ /* @__PURE__ */ jsx77("div", { className: "h-4 w-1/3 bg-muted-foreground/20 rounded" }),
24524
+ /* @__PURE__ */ jsx77("div", { className: "h-5 w-3/4 bg-muted-foreground/20 rounded" }),
24525
+ /* @__PURE__ */ jsx77("div", { className: "h-4 w-5/6 bg-muted-foreground/20 rounded" })
24526
+ ] }),
24527
+ /* @__PURE__ */ jsx77("div", { className: "h-20 w-32 bg-muted-foreground/20 rounded-lg flex-shrink-0" })
24528
+ ] }) : /* @__PURE__ */ jsxs63("div", { className: "flex flex-col sm:flex-row items-stretch justify-between min-h-[100px]", children: [
24529
+ /* @__PURE__ */ jsxs63("div", { className: "flex-1 p-4 flex flex-col justify-between gap-1 min-w-0", children: [
24530
+ /* @__PURE__ */ jsxs63("div", { className: "flex flex-col gap-1 min-w-0", children: [
24531
+ /* @__PURE__ */ jsxs63("span", { className: "text-xs text-muted-foreground font-medium flex items-center gap-1.5 truncate", children: [
24532
+ /* @__PURE__ */ jsx77(Globe2, { className: "h-3 w-3 flex-shrink-0" }),
24533
+ displayPublisher
24534
+ ] }),
24535
+ /* @__PURE__ */ jsx77("h4", { className: "text-sm font-semibold text-foreground line-clamp-1 break-all", children: title || url }),
24536
+ /* @__PURE__ */ jsx77("p", { className: "text-xs text-muted-foreground line-clamp-2 leading-relaxed", children: description })
24537
+ ] }),
24538
+ /* @__PURE__ */ jsxs63("span", { className: "text-[11px] text-primary/80 font-mono mt-2 truncate flex items-center gap-1", children: [
24539
+ url,
24540
+ /* @__PURE__ */ jsx77(ExternalLink2, { className: "h-3 w-3 flex-shrink-0" })
24541
+ ] })
24542
+ ] }),
24543
+ image && /* @__PURE__ */ jsx77("div", { className: "relative w-full sm:w-44 h-32 sm:h-auto flex-shrink-0 bg-muted overflow-hidden border-t sm:border-t-0 sm:border-l border-border/50", children: /* @__PURE__ */ jsx77(
24544
+ "img",
24545
+ {
24546
+ src: image,
24547
+ alt: title || "Link preview image",
24548
+ className: "absolute inset-0 w-full h-full object-cover transition-opacity duration-300",
24549
+ onError: (e) => {
24550
+ e.currentTarget.style.display = "none";
24551
+ }
24552
+ }
24553
+ ) })
24554
+ ] })
24555
+ }
24556
+ );
24557
+ };
24558
+
24559
+ // src/components/UEditor/bookmark.ts
24560
+ import { Plugin, PluginKey } from "@tiptap/pm/state";
24561
+ var URL_REGEX = /^(https?:\/\/[^\s]+)$/i;
24562
+ var Bookmark = Node3.create({
24563
+ name: "bookmark",
24564
+ group: "block",
24565
+ atom: true,
24566
+ addOptions() {
24567
+ return {
24568
+ fetchMetadata: void 0,
24569
+ HTMLAttributes: {}
24570
+ };
24571
+ },
24572
+ addAttributes() {
24573
+ return {
24574
+ url: {
24575
+ default: "",
24576
+ parseHTML: (element) => element.getAttribute("href") || element.getAttribute("data-url") || "",
24577
+ renderHTML: (attributes) => ({
24578
+ href: attributes.url,
24579
+ "data-url": attributes.url
24580
+ })
24581
+ },
24582
+ title: {
24583
+ default: "",
24584
+ parseHTML: (element) => element.getAttribute("data-title") || "",
24585
+ renderHTML: (attributes) => ({
24586
+ "data-title": attributes.title
24587
+ })
24588
+ },
24589
+ description: {
24590
+ default: "",
24591
+ parseHTML: (element) => element.getAttribute("data-description") || "",
24592
+ renderHTML: (attributes) => ({
24593
+ "data-description": attributes.description
24594
+ })
24595
+ },
24596
+ image: {
24597
+ default: "",
24598
+ parseHTML: (element) => element.getAttribute("data-image") || "",
24599
+ renderHTML: (attributes) => ({
24600
+ "data-image": attributes.image
24601
+ })
24602
+ },
24603
+ publisher: {
24604
+ default: "",
24605
+ parseHTML: (element) => element.getAttribute("data-publisher") || "",
24606
+ renderHTML: (attributes) => ({
24607
+ "data-publisher": attributes.publisher
24608
+ })
24609
+ }
24610
+ };
24611
+ },
24612
+ parseHTML() {
24613
+ return [
24614
+ {
24615
+ tag: 'div[data-type="bookmark"]'
24616
+ },
24617
+ {
24618
+ tag: 'a[data-type="bookmark"]'
24619
+ }
24620
+ ];
24621
+ },
24622
+ renderHTML({ HTMLAttributes }) {
24623
+ return [
24624
+ "div",
24625
+ mergeAttributes2(this.options.HTMLAttributes, HTMLAttributes, { "data-type": "bookmark" })
24626
+ ];
24627
+ },
24628
+ addNodeView() {
24629
+ return ReactNodeViewRenderer2(BookmarkView);
24630
+ },
24631
+ addCommands() {
24632
+ return {
24633
+ setBookmark: (attributes) => ({ commands }) => {
24634
+ return commands.insertContent({
24635
+ type: this.name,
24636
+ attrs: attributes
24637
+ });
24638
+ }
24639
+ };
24640
+ },
24641
+ addProseMirrorPlugins() {
24642
+ const editor = this.editor;
24643
+ return [
24644
+ new Plugin({
24645
+ key: new PluginKey("bookmarkPaste"),
24646
+ props: {
24647
+ handlePaste(view, event) {
24648
+ if (!event || !event.clipboardData) return false;
24649
+ const text = event.clipboardData.getData("text/plain")?.trim();
24650
+ if (!text || !URL_REGEX.test(text)) return false;
24651
+ const { selection } = view.state;
24652
+ const parent = selection.$from.parent;
24653
+ console.log("DEBUG handlePaste name:", parent.type.name, "size:", parent.content.size);
24654
+ const isEmptyParagraph = parent.type.name === "paragraph" && parent.content.size === 0;
24655
+ if (isEmptyParagraph) {
24656
+ event.preventDefault();
24657
+ editor.chain().focus().insertContent({
24658
+ type: "bookmark",
24659
+ attrs: { url: text }
24660
+ }).run();
24661
+ return true;
24662
+ }
24663
+ return false;
24664
+ }
24665
+ }
24666
+ })
24667
+ ];
24668
+ }
24669
+ });
24670
+
24671
+ // src/components/UEditor/file-card.ts
24672
+ import { Node as Node4, mergeAttributes as mergeAttributes3 } from "@tiptap/core";
24673
+ import { ReactNodeViewRenderer as ReactNodeViewRenderer3 } from "@tiptap/react";
24674
+
24675
+ // src/components/UEditor/FileCardView.tsx
24676
+ import { useEffect as useEffect32, useState as useState43, useRef as useRef27 } from "react";
24677
+ import { NodeViewWrapper as NodeViewWrapper3 } from "@tiptap/react";
24678
+ import { Download as Download2, File as LucideFile, FileText as FileText2, Image as Image3, Music, Video } from "lucide-react";
24679
+ import { jsx as jsx78, jsxs as jsxs64 } from "react/jsx-runtime";
24680
+ function formatBytes(bytes, decimals = 1) {
24681
+ if (!bytes || bytes <= 0) return "0 Bytes";
24682
+ const k = 1024;
24683
+ const dm = decimals < 0 ? 0 : decimals;
24684
+ const sizes = ["Bytes", "KB", "MB", "GB"];
24685
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
24686
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
24687
+ }
24688
+ function getFileIcon2(type) {
24689
+ const mime = (type || "").toLowerCase();
24690
+ if (mime.includes("pdf")) return FileText2;
24691
+ if (mime.startsWith("image/")) return Image3;
24692
+ if (mime.startsWith("audio/")) return Music;
24693
+ if (mime.startsWith("video/")) return Video;
24694
+ return LucideFile;
24695
+ }
24696
+ function dataURLtoFile(dataurl, filename, mimeType) {
24697
+ try {
24698
+ const arr = dataurl.split(",");
24699
+ if (arr.length < 2) return null;
24700
+ const mimeMatch = arr[0].match(/:(.*?);/);
24701
+ const mime = mimeMatch ? mimeMatch[1] : mimeType || "application/octet-stream";
24702
+ const base64Data = arr[arr.length - 1].replace(/\s+/g, "");
24703
+ let bytes;
24704
+ if (typeof Buffer !== "undefined") {
24705
+ bytes = new Uint8Array(Buffer.from(base64Data, "base64"));
24706
+ } else {
24707
+ const binaryString = atob(base64Data);
24708
+ const len = binaryString.length;
24709
+ bytes = new Uint8Array(len);
24710
+ for (let i = 0; i < len; i++) {
24711
+ bytes[i] = binaryString.charCodeAt(i);
24712
+ }
24713
+ }
24714
+ return new File([bytes], filename, { type: mime });
24715
+ } catch (e) {
24716
+ console.error("Error converting data URI to file:", e);
24717
+ return null;
24718
+ }
24719
+ }
24720
+ var FileCardView = ({ node, selected, editor, updateAttributes }) => {
24721
+ const t = useSmartTranslations("UEditor");
24722
+ const { src, fileName, fileSize, fileType } = node.attrs;
24723
+ const FileIcon = getFileIcon2(fileType);
24724
+ const [uploadError, setUploadError] = useState43(null);
24725
+ const uploadAttemptedRef = useRef27(false);
24726
+ useEffect32(() => {
24727
+ if (!src || !src.startsWith("data:")) {
24728
+ return;
24729
+ }
24730
+ const extension = editor?.extensionManager?.extensions?.find((e) => e.name === "fileCard");
24731
+ const uploadFn = extension?.options?.upload;
24732
+ if (!uploadFn || uploadAttemptedRef.current || !updateAttributes) {
24733
+ return;
24734
+ }
24735
+ uploadAttemptedRef.current = true;
24736
+ setUploadError(null);
24737
+ const runUpload = async () => {
24738
+ try {
24739
+ const file = dataURLtoFile(src, fileName || "file", fileType);
24740
+ if (!file) {
24741
+ throw new Error("Failed to parse file data");
24742
+ }
24743
+ const resolvedUrl = await uploadFn(file);
24744
+ Promise.resolve().then(() => {
24745
+ if (editor && !editor.isDestroyed) {
24746
+ updateAttributes({ src: resolvedUrl });
24747
+ }
24748
+ });
24749
+ } catch (err) {
24750
+ console.error("File upload failed:", err);
24751
+ setUploadError(err?.message || "Upload failed");
24752
+ uploadAttemptedRef.current = false;
24753
+ }
24754
+ };
24755
+ void runUpload();
24756
+ }, [src, fileName, fileType, editor, updateAttributes]);
24757
+ const handleDownload = (e) => {
24758
+ e.preventDefault();
24759
+ e.stopPropagation();
24760
+ if (!src) return;
24761
+ const link = document.createElement("a");
24762
+ link.href = src;
24763
+ link.download = fileName || "download";
24764
+ document.body.appendChild(link);
24765
+ link.click();
24766
+ document.body.removeChild(link);
24767
+ };
24768
+ const isUploading = (src || "").startsWith("data:");
24769
+ return /* @__PURE__ */ jsxs64(
24770
+ NodeViewWrapper3,
24771
+ {
24772
+ className: cn(
24773
+ "my-4 flex items-center justify-between rounded-xl border border-border/60 bg-card p-4 hover:bg-muted/15 transition-all duration-200 cursor-pointer select-none",
24774
+ selected && "ring-2 ring-primary/45 border-primary/20 shadow-sm"
24775
+ ),
24776
+ onClick: handleDownload,
24777
+ children: [
24778
+ /* @__PURE__ */ jsxs64("div", { className: "flex items-center gap-3.5 min-w-0", children: [
24779
+ /* @__PURE__ */ jsx78("div", { className: "flex h-11 w-11 items-center justify-center rounded-lg bg-primary/10 text-primary flex-shrink-0", children: /* @__PURE__ */ jsx78(FileIcon, { className: "h-6 w-6" }) }),
24780
+ /* @__PURE__ */ jsxs64("div", { className: "min-w-0", children: [
24781
+ /* @__PURE__ */ jsx78("div", { className: "text-sm font-semibold text-foreground truncate break-all", children: fileName || t("fileCard.unnamed") }),
24782
+ /* @__PURE__ */ jsxs64("div", { className: "text-xs text-muted-foreground flex items-center gap-2 mt-0.5", children: [
24783
+ fileSize ? /* @__PURE__ */ jsx78("span", { children: formatBytes(fileSize) }) : null,
24784
+ isUploading && /* @__PURE__ */ jsx78("span", { className: cn(
24785
+ "font-medium truncate max-w-[200px]",
24786
+ uploadError ? "text-destructive" : "text-primary animate-pulse"
24787
+ ), children: uploadError ? `${t("fileCard.uploadFailed") || "T\u1EA3i l\xEAn th\u1EA5t b\u1EA1i"}: ${uploadError}` : t("fileCard.uploading") })
24788
+ ] })
24789
+ ] })
24790
+ ] }),
24791
+ src && /* @__PURE__ */ jsx78(
24792
+ "button",
24793
+ {
24794
+ type: "button",
24795
+ onClick: handleDownload,
24796
+ className: "flex h-8 w-8 items-center justify-center rounded-lg border border-border bg-background text-muted-foreground hover:text-foreground hover:bg-muted active:scale-95 transition-all focus:outline-none",
24797
+ children: /* @__PURE__ */ jsx78(Download2, { className: "h-4 w-4" })
24798
+ }
24799
+ )
24800
+ ]
24801
+ }
24802
+ );
24803
+ };
24804
+
24805
+ // src/components/UEditor/file-card.ts
24806
+ var FileCard = Node4.create({
24807
+ name: "fileCard",
24808
+ group: "block",
24809
+ atom: true,
24810
+ addOptions() {
24811
+ return {
24812
+ HTMLAttributes: {},
24813
+ upload: void 0
24814
+ };
24815
+ },
24816
+ addAttributes() {
24817
+ return {
24818
+ src: {
24819
+ default: "",
24820
+ parseHTML: (element) => element.getAttribute("href") || element.getAttribute("data-src") || "",
24821
+ renderHTML: (attributes) => ({
24822
+ href: attributes.src,
24823
+ "data-src": attributes.src
24824
+ })
24825
+ },
24826
+ fileName: {
24827
+ default: "",
24828
+ parseHTML: (element) => element.getAttribute("data-file-name") || "",
24829
+ renderHTML: (attributes) => ({
24830
+ "data-file-name": attributes.fileName
24831
+ })
24832
+ },
24833
+ fileSize: {
24834
+ default: null,
24835
+ parseHTML: (element) => {
24836
+ const val = element.getAttribute("data-file-size");
24837
+ return val ? Number(val) : null;
24838
+ },
24839
+ renderHTML: (attributes) => {
24840
+ if (attributes.fileSize === null || attributes.fileSize === void 0) return {};
24841
+ return {
24842
+ "data-file-size": attributes.fileSize
24843
+ };
24844
+ }
24845
+ },
24846
+ fileType: {
24847
+ default: "",
24848
+ parseHTML: (element) => element.getAttribute("data-file-type") || "",
24849
+ renderHTML: (attributes) => ({
24850
+ "data-file-type": attributes.fileType
24851
+ })
24852
+ }
24853
+ };
24854
+ },
24855
+ parseHTML() {
24856
+ return [
24857
+ {
24858
+ tag: 'div[data-type="file-card"]'
24859
+ },
24860
+ {
24861
+ tag: 'a[data-type="file-card"]'
24862
+ }
24863
+ ];
24864
+ },
24865
+ renderHTML({ HTMLAttributes }) {
24866
+ return [
24867
+ "div",
24868
+ mergeAttributes3(this.options.HTMLAttributes, HTMLAttributes, { "data-type": "file-card" })
24869
+ ];
24870
+ },
24871
+ addNodeView() {
24872
+ return ReactNodeViewRenderer3(FileCardView);
24873
+ },
24874
+ addCommands() {
24875
+ return {
24876
+ setFileCard: (attributes) => ({ commands }) => {
24877
+ return commands.insertContent({
24878
+ type: this.name,
24879
+ attrs: attributes
24880
+ });
24881
+ }
24882
+ };
24883
+ }
24884
+ });
24885
+
24886
+ // src/components/UEditor/extensions.ts
24181
24887
  import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
24182
24888
  import History2 from "@tiptap/extension-history";
24183
24889
  import Link from "@tiptap/extension-link";
@@ -24198,7 +24904,7 @@ import { common, createLowlight } from "lowlight";
24198
24904
  import { Extension } from "@tiptap/core";
24199
24905
  import Suggestion from "@tiptap/suggestion";
24200
24906
  import { ReactRenderer } from "@tiptap/react";
24201
- import React68, { forwardRef as forwardRef14, useEffect as useEffect31, useImperativeHandle, useRef as useRef27 } from "react";
24907
+ import React70, { forwardRef as forwardRef14, useEffect as useEffect33, useImperativeHandle, useRef as useRef28 } from "react";
24202
24908
  import {
24203
24909
  FileCode as FileCode2,
24204
24910
  Heading1,
@@ -24210,7 +24916,10 @@ import {
24210
24916
  Minus,
24211
24917
  Quote,
24212
24918
  Table as Table2,
24213
- Type
24919
+ Type,
24920
+ Info as Info3,
24921
+ Bookmark as BookmarkIcon,
24922
+ Paperclip
24214
24923
  } from "lucide-react";
24215
24924
 
24216
24925
  // src/components/UEditor/tippy-interop.ts
@@ -24233,7 +24942,7 @@ function destroyTippyInstance(instance) {
24233
24942
  }
24234
24943
 
24235
24944
  // src/components/UEditor/slash-command.tsx
24236
- import { jsx as jsx75, jsxs as jsxs62 } from "react/jsx-runtime";
24945
+ import { jsx as jsx79, jsxs as jsxs65 } from "react/jsx-runtime";
24237
24946
  var DEFAULT_MESSAGES = {
24238
24947
  noResults: "No results",
24239
24948
  basicBlocks: "Basic Blocks",
@@ -24258,12 +24967,18 @@ var DEFAULT_MESSAGES = {
24258
24967
  divider: "Divider",
24259
24968
  dividerDesc: "Visually divide blocks",
24260
24969
  table: "Table",
24261
- tableDesc: "Insert a table"
24970
+ tableDesc: "Insert a table",
24971
+ callout: "Callout",
24972
+ calloutDesc: "Highlight key info with a callout block",
24973
+ bookmark: "Bookmark Card",
24974
+ bookmarkDesc: "Embed a link as a bookmark card",
24975
+ fileCard: "File Attachment",
24976
+ fileCardDesc: "Upload a file card attachment"
24262
24977
  };
24263
24978
  function useResettingIndex2(resetToken) {
24264
- const [state, setState] = React68.useState({ resetToken, index: 0 });
24979
+ const [state, setState] = React70.useState({ resetToken, index: 0 });
24265
24980
  const selectedIndex = Object.is(state.resetToken, resetToken) ? state.index : 0;
24266
- const setSelectedIndex = React68.useCallback((nextIndex) => {
24981
+ const setSelectedIndex = React70.useCallback((nextIndex) => {
24267
24982
  setState((prev) => {
24268
24983
  const prevIndex = Object.is(prev.resetToken, resetToken) ? prev.index : 0;
24269
24984
  return {
@@ -24300,10 +25015,16 @@ function buildSlashCommandMessages(translate) {
24300
25015
  quoteDesc: translate("slashCommand.quoteDesc"),
24301
25016
  codeBlock: translate("slashCommand.codeBlock"),
24302
25017
  codeBlockDesc: translate("slashCommand.codeBlockDesc"),
24303
- divider: translate("slashCommand.divider"),
24304
- dividerDesc: translate("slashCommand.dividerDesc"),
24305
- table: translate("slashCommand.table"),
24306
- tableDesc: translate("slashCommand.tableDesc")
25018
+ divider: translate("slashCommand.divider") || "Divider",
25019
+ dividerDesc: translate("slashCommand.dividerDesc") || "Visually divide blocks",
25020
+ table: translate("slashCommand.table") || "Table",
25021
+ tableDesc: translate("slashCommand.tableDesc") || "Insert a table",
25022
+ callout: translate("slashCommand.callout") || "Callout",
25023
+ calloutDesc: translate("slashCommand.calloutDesc") || "Highlight key info with a callout block",
25024
+ bookmark: translate("slashCommand.bookmark") || "Bookmark Card",
25025
+ bookmarkDesc: translate("slashCommand.bookmarkDesc") || "Embed a link as a bookmark card",
25026
+ fileCard: translate("slashCommand.fileCard") || "File Attachment",
25027
+ fileCardDesc: translate("slashCommand.fileCardDesc") || "Upload a file card attachment"
24307
25028
  };
24308
25029
  }
24309
25030
  function buildSlashCommandItems({
@@ -24399,18 +25120,64 @@ function buildSlashCommandItems({
24399
25120
  command: run(({ editor, range }) => {
24400
25121
  getCommandChain(editor, range).insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run();
24401
25122
  })
25123
+ },
25124
+ {
25125
+ icon: Info3,
25126
+ title: messages.callout || "Callout",
25127
+ description: messages.calloutDesc || "Highlight key info with a callout block",
25128
+ command: run(({ editor, range }) => {
25129
+ getCommandChain(editor, range).setCallout().run();
25130
+ })
25131
+ },
25132
+ {
25133
+ icon: BookmarkIcon,
25134
+ title: messages.bookmark || "Bookmark Card",
25135
+ description: messages.bookmarkDesc || "Embed a link as a bookmark card",
25136
+ command: run(({ editor, range }) => {
25137
+ const url = window.prompt("Enter URL for bookmark:");
25138
+ if (url) {
25139
+ getCommandChain(editor, range).setBookmark({ url }).run();
25140
+ }
25141
+ })
25142
+ },
25143
+ {
25144
+ icon: Paperclip,
25145
+ title: messages.fileCard || "File Attachment",
25146
+ description: messages.fileCardDesc || "Upload a file card attachment",
25147
+ command: run(({ editor, range }) => {
25148
+ const input = document.createElement("input");
25149
+ input.type = "file";
25150
+ input.onchange = async () => {
25151
+ const file = input.files?.[0];
25152
+ if (!file) return;
25153
+ const reader = new FileReader();
25154
+ reader.onload = () => {
25155
+ const dataUrl = reader.result;
25156
+ getCommandChain(editor, range).setFileCard({
25157
+ src: dataUrl,
25158
+ fileName: file.name,
25159
+ fileSize: file.size,
25160
+ fileType: file.type
25161
+ }).run();
25162
+ };
25163
+ reader.readAsDataURL(file);
25164
+ };
25165
+ input.click();
25166
+ })
24402
25167
  }
24403
25168
  ].filter((item) => item.title.toLowerCase().includes(query.toLowerCase()));
24404
25169
  }
24405
25170
  var SlashCommandList = forwardRef14((props, ref) => {
24406
25171
  const [selectedIndex, setSelectedIndex] = useResettingIndex2(props.items);
24407
- const listRef = useRef27(null);
24408
- useEffect31(() => {
25172
+ const listRef = useRef28(null);
25173
+ useEffect33(() => {
24409
25174
  const selectedElement = listRef.current?.querySelector(`[data-index="${selectedIndex}"]`);
24410
25175
  selectedElement?.scrollIntoView({ block: "nearest" });
24411
25176
  }, [selectedIndex, props.items]);
24412
25177
  useImperativeHandle(ref, () => ({
24413
- onKeyDown: ({ event }) => {
25178
+ onKeyDown: (keyProps) => {
25179
+ if (!keyProps || !keyProps.event) return false;
25180
+ const { event } = keyProps;
24414
25181
  if (props.items.length === 0) {
24415
25182
  return false;
24416
25183
  }
@@ -24433,11 +25200,11 @@ var SlashCommandList = forwardRef14((props, ref) => {
24433
25200
  }
24434
25201
  }));
24435
25202
  if (props.items.length === 0) {
24436
- return /* @__PURE__ */ jsx75("div", { className: "w-72 p-4 text-center text-sm text-muted-foreground", children: props.messages.noResults });
25203
+ return /* @__PURE__ */ jsx79("div", { className: "w-72 p-4 text-center text-sm text-muted-foreground", children: props.messages.noResults });
24437
25204
  }
24438
- return /* @__PURE__ */ jsxs62("div", { ref: listRef, className: "w-72 max-h-80 overflow-y-auto bg-card border border-border/50 rounded-2xl shadow-lg", children: [
24439
- /* @__PURE__ */ jsx75("div", { className: "px-3 py-2 border-b", children: /* @__PURE__ */ jsx75("span", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: props.messages.basicBlocks }) }),
24440
- /* @__PURE__ */ jsx75("div", { className: "p-1", children: props.items.map((item, index) => /* @__PURE__ */ jsxs62(
25205
+ return /* @__PURE__ */ jsxs65("div", { ref: listRef, className: "w-72 max-h-80 overflow-y-auto bg-card border border-border/50 rounded-2xl shadow-lg", children: [
25206
+ /* @__PURE__ */ jsx79("div", { className: "px-3 py-2 border-b", children: /* @__PURE__ */ jsx79("span", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: props.messages.basicBlocks }) }),
25207
+ /* @__PURE__ */ jsx79("div", { className: "p-1", children: props.items.map((item, index) => /* @__PURE__ */ jsxs65(
24441
25208
  "button",
24442
25209
  {
24443
25210
  type: "button",
@@ -24449,19 +25216,19 @@ var SlashCommandList = forwardRef14((props, ref) => {
24449
25216
  selectedIndex === index ? "bg-accent" : "hover:bg-accent/50"
24450
25217
  ),
24451
25218
  children: [
24452
- /* @__PURE__ */ jsx75(
25219
+ /* @__PURE__ */ jsx79(
24453
25220
  "div",
24454
25221
  {
24455
25222
  className: cn(
24456
25223
  "flex items-center justify-center w-10 h-10 rounded-lg mr-3 transition-colors",
24457
25224
  selectedIndex === index ? "bg-primary/10" : "bg-muted/50 group-hover:bg-muted"
24458
25225
  ),
24459
- children: /* @__PURE__ */ jsx75(item.icon, { className: cn("w-5 h-5", selectedIndex === index ? "text-primary" : "text-muted-foreground") })
25226
+ children: /* @__PURE__ */ jsx79(item.icon, { className: cn("w-5 h-5", selectedIndex === index ? "text-primary" : "text-muted-foreground") })
24460
25227
  }
24461
25228
  ),
24462
- /* @__PURE__ */ jsxs62("div", { className: "text-left", children: [
24463
- /* @__PURE__ */ jsx75("div", { className: cn("text-sm font-medium", selectedIndex === index && "text-primary"), children: item.title }),
24464
- /* @__PURE__ */ jsx75("div", { className: "text-xs text-muted-foreground", children: item.description })
25229
+ /* @__PURE__ */ jsxs65("div", { className: "text-left", children: [
25230
+ /* @__PURE__ */ jsx79("div", { className: cn("text-sm font-medium", selectedIndex === index && "text-primary"), children: item.title }),
25231
+ /* @__PURE__ */ jsx79("div", { className: "text-xs text-muted-foreground", children: item.description })
24465
25232
  ] })
24466
25233
  ]
24467
25234
  },
@@ -24526,6 +25293,7 @@ var SlashCommand = Extension.create({
24526
25293
  });
24527
25294
  },
24528
25295
  onKeyDown(props) {
25296
+ if (!props || !props.event) return false;
24529
25297
  const popupInstance = getFirstTippyInstance(popup);
24530
25298
  if (props.event.key === "Escape") {
24531
25299
  hideTippyInstance(popupInstance);
@@ -24546,7 +25314,7 @@ var SlashCommand = Extension.create({
24546
25314
 
24547
25315
  // src/components/UEditor/clipboard-images.ts
24548
25316
  import { Extension as Extension2 } from "@tiptap/core";
24549
- import { Plugin } from "@tiptap/pm/state";
25317
+ import { Plugin as Plugin2 } from "@tiptap/pm/state";
24550
25318
 
24551
25319
  // src/components/UEditor/url-safety.ts
24552
25320
  var LINK_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:", "mailto:", "tel:"]);
@@ -24659,10 +25427,10 @@ var ClipboardImages = Extension2.create({
24659
25427
  }
24660
25428
  };
24661
25429
  return [
24662
- new Plugin({
25430
+ new Plugin2({
24663
25431
  props: {
24664
25432
  handlePaste: (_view, event) => {
24665
- if (!(event instanceof ClipboardEvent)) return false;
25433
+ if (!event || !event.clipboardData) return false;
24666
25434
  const files = getImageFiles(event.clipboardData);
24667
25435
  if (files.length === 0) return false;
24668
25436
  event.preventDefault();
@@ -24689,14 +25457,14 @@ var ClipboardImages = Extension2.create({
24689
25457
  import { Extension as Extension3 } from "@tiptap/core";
24690
25458
  import Suggestion2 from "@tiptap/suggestion";
24691
25459
  import { ReactRenderer as ReactRenderer2 } from "@tiptap/react";
24692
- import { PluginKey } from "@tiptap/pm/state";
24693
- import React69, { forwardRef as forwardRef15, useImperativeHandle as useImperativeHandle2 } from "react";
25460
+ import { PluginKey as PluginKey2 } from "@tiptap/pm/state";
25461
+ import React71, { forwardRef as forwardRef15, useImperativeHandle as useImperativeHandle2 } from "react";
24694
25462
  import { Smile as Smile2 } from "lucide-react";
24695
- import { jsx as jsx76, jsxs as jsxs63 } from "react/jsx-runtime";
25463
+ import { jsx as jsx80, jsxs as jsxs66 } from "react/jsx-runtime";
24696
25464
  function useResettingIndex3(resetToken) {
24697
- const [state, setState] = React69.useState({ resetToken, index: 0 });
25465
+ const [state, setState] = React71.useState({ resetToken, index: 0 });
24698
25466
  const selectedIndex = Object.is(state.resetToken, resetToken) ? state.index : 0;
24699
- const setSelectedIndex = React69.useCallback((nextIndex) => {
25467
+ const setSelectedIndex = React71.useCallback((nextIndex) => {
24700
25468
  setState((prev) => {
24701
25469
  const prevIndex = Object.is(prev.resetToken, resetToken) ? prev.index : 0;
24702
25470
  return {
@@ -24712,7 +25480,9 @@ var EmojiList = forwardRef15((props, ref) => {
24712
25480
  const [selectedIndex, setSelectedIndex] = useResettingIndex3(props.items);
24713
25481
  const showingCountLabel = formatEmojiCountLabel(t("emojiSuggestion.showingCount"), 64, props.items.length);
24714
25482
  useImperativeHandle2(ref, () => ({
24715
- onKeyDown: ({ event }) => {
25483
+ onKeyDown: (keyProps) => {
25484
+ if (!keyProps || !keyProps.event) return false;
25485
+ const { event } = keyProps;
24716
25486
  if (event.key === "ArrowUp") {
24717
25487
  setSelectedIndex((prev) => (prev + props.items.length - 1) % props.items.length);
24718
25488
  return true;
@@ -24740,15 +25510,15 @@ var EmojiList = forwardRef15((props, ref) => {
24740
25510
  }
24741
25511
  }));
24742
25512
  if (props.items.length === 0) {
24743
- return /* @__PURE__ */ jsx76("div", { className: "w-80 p-4 text-center text-sm text-muted-foreground bg-card border border-border/50 rounded-2xl shadow-lg", children: t("emojiSuggestion.noResults") });
25513
+ return /* @__PURE__ */ jsx80("div", { className: "w-80 p-4 text-center text-sm text-muted-foreground bg-card border border-border/50 rounded-2xl shadow-lg", children: t("emojiSuggestion.noResults") });
24744
25514
  }
24745
- return /* @__PURE__ */ jsxs63("div", { className: "w-80 max-h-80 overflow-y-auto bg-card border border-border/50 rounded-2xl shadow-lg", children: [
24746
- /* @__PURE__ */ jsx76("div", { className: "px-3 py-2 border-b bg-muted/30", children: /* @__PURE__ */ jsxs63("div", { className: "flex items-center gap-2", children: [
24747
- /* @__PURE__ */ jsx76(Smile2, { className: "w-4 h-4 text-primary" }),
24748
- /* @__PURE__ */ jsx76("span", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: t("emojiSuggestion.title") })
25515
+ return /* @__PURE__ */ jsxs66("div", { className: "w-80 max-h-80 overflow-y-auto bg-card border border-border/50 rounded-2xl shadow-lg", children: [
25516
+ /* @__PURE__ */ jsx80("div", { className: "px-3 py-2 border-b bg-muted/30", children: /* @__PURE__ */ jsxs66("div", { className: "flex items-center gap-2", children: [
25517
+ /* @__PURE__ */ jsx80(Smile2, { className: "w-4 h-4 text-primary" }),
25518
+ /* @__PURE__ */ jsx80("span", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: t("emojiSuggestion.title") })
24749
25519
  ] }) }),
24750
- /* @__PURE__ */ jsxs63("div", { className: "p-3", children: [
24751
- /* @__PURE__ */ jsx76("div", { className: "grid grid-cols-8 gap-1", children: props.items.slice(0, 64).map((item, index) => /* @__PURE__ */ jsx76(
25520
+ /* @__PURE__ */ jsxs66("div", { className: "p-3", children: [
25521
+ /* @__PURE__ */ jsx80("div", { className: "grid grid-cols-8 gap-1", children: props.items.slice(0, 64).map((item, index) => /* @__PURE__ */ jsx80(
24752
25522
  EmojiGridButton,
24753
25523
  {
24754
25524
  emoji: item.emoji,
@@ -24759,7 +25529,7 @@ var EmojiList = forwardRef15((props, ref) => {
24759
25529
  },
24760
25530
  item.name
24761
25531
  )) }),
24762
- props.items.length > 64 && /* @__PURE__ */ jsx76("div", { className: "mt-2 text-xs text-center text-muted-foreground", children: showingCountLabel })
25532
+ props.items.length > 64 && /* @__PURE__ */ jsx80("div", { className: "mt-2 text-xs text-center text-muted-foreground", children: showingCountLabel })
24763
25533
  ] })
24764
25534
  ] });
24765
25535
  });
@@ -24781,7 +25551,7 @@ var EmojiSuggestion = Extension3.create({
24781
25551
  Suggestion2({
24782
25552
  editor: this.editor,
24783
25553
  char: ":",
24784
- pluginKey: new PluginKey("emojiSuggestion"),
25554
+ pluginKey: new PluginKey2("emojiSuggestion"),
24785
25555
  command: ({ editor, range, props }) => {
24786
25556
  editor.chain().focus().deleteRange(range).insertContent(props.emoji).run();
24787
25557
  },
@@ -24819,6 +25589,7 @@ var EmojiSuggestion = Extension3.create({
24819
25589
  });
24820
25590
  },
24821
25591
  onKeyDown(props) {
25592
+ if (!props || !props.event) return false;
24822
25593
  const popupInstance = getFirstTippyInstance(popup);
24823
25594
  if (props.event.key === "Escape") {
24824
25595
  hideTippyInstance(popupInstance);
@@ -24839,7 +25610,7 @@ var EmojiSuggestion = Extension3.create({
24839
25610
 
24840
25611
  // src/components/UEditor/placeholder.ts
24841
25612
  import { Extension as Extension4, isNodeEmpty } from "@tiptap/core";
24842
- import { Plugin as Plugin2, PluginKey as PluginKey2 } from "@tiptap/pm/state";
25613
+ import { Plugin as Plugin3, PluginKey as PluginKey3 } from "@tiptap/pm/state";
24843
25614
  import { Decoration, DecorationSet } from "@tiptap/pm/view";
24844
25615
  var UEditorPlaceholder = Extension4.create({
24845
25616
  name: "placeholder",
@@ -24858,8 +25629,8 @@ var UEditorPlaceholder = Extension4.create({
24858
25629
  addProseMirrorPlugins() {
24859
25630
  const dataAttribute = `data-${this.options.dataAttribute}`;
24860
25631
  return [
24861
- new Plugin2({
24862
- key: new PluginKey2("placeholder"),
25632
+ new Plugin3({
25633
+ key: new PluginKey3("placeholder"),
24863
25634
  props: {
24864
25635
  decorations: ({ doc, selection }) => {
24865
25636
  const active = this.editor.isEditable || !this.options.showOnlyWhenEditable;
@@ -24911,11 +25682,11 @@ var UEditorPlaceholder = Extension4.create({
24911
25682
  });
24912
25683
 
24913
25684
  // src/components/UEditor/resizable-image.tsx
24914
- import { useEffect as useEffect32, useRef as useRef28, useState as useState42 } from "react";
24915
- import Image3 from "@tiptap/extension-image";
24916
- import { mergeAttributes } from "@tiptap/core";
24917
- import { NodeViewWrapper, ReactNodeViewRenderer } from "@tiptap/react";
24918
- import { jsx as jsx77, jsxs as jsxs64 } from "react/jsx-runtime";
25685
+ import { useEffect as useEffect34, useRef as useRef29, useState as useState44 } from "react";
25686
+ import Image4 from "@tiptap/extension-image";
25687
+ import { mergeAttributes as mergeAttributes4 } from "@tiptap/core";
25688
+ import { NodeViewWrapper as NodeViewWrapper4, ReactNodeViewRenderer as ReactNodeViewRenderer4 } from "@tiptap/react";
25689
+ import { jsx as jsx81, jsxs as jsxs67 } from "react/jsx-runtime";
24919
25690
  var MIN_IMAGE_SIZE_PX = 40;
24920
25691
  var AXIS_LOCK_THRESHOLD_PX = 4;
24921
25692
  var IMAGE_LAYOUTS = /* @__PURE__ */ new Set(["block", "left", "right"]);
@@ -24960,17 +25731,17 @@ function getImageLayoutStyles(layout) {
24960
25731
  }
24961
25732
  function ResizableImageNodeView(props) {
24962
25733
  const { node, selected, updateAttributes, editor, getPos } = props;
24963
- const wrapperRef = useRef28(null);
24964
- const imgRef = useRef28(null);
24965
- const [isHovered, setIsHovered] = useState42(false);
24966
- const [isResizing, setIsResizing] = useState42(false);
25734
+ const wrapperRef = useRef29(null);
25735
+ const imgRef = useRef29(null);
25736
+ const [isHovered, setIsHovered] = useState44(false);
25737
+ const [isResizing, setIsResizing] = useState44(false);
24967
25738
  const widthAttr = toNullableNumber(node.attrs["width"]);
24968
25739
  const heightAttr = toNullableNumber(node.attrs["height"]);
24969
25740
  const textAlign = String(node.attrs["textAlign"] ?? "");
24970
25741
  const imageLayout = parseImageLayout(node.attrs["imageLayout"]);
24971
25742
  const preserveAspectByDefault = imageLayout === "left" || imageLayout === "right";
24972
- const dragStateRef = useRef28(null);
24973
- useEffect32(() => {
25743
+ const dragStateRef = useRef29(null);
25744
+ useEffect34(() => {
24974
25745
  const img = imgRef.current;
24975
25746
  if (!img) return;
24976
25747
  img.style.width = widthAttr ? `${widthAttr}px` : "";
@@ -25066,8 +25837,8 @@ function ResizableImageNodeView(props) {
25066
25837
  const showHandle = selected || isHovered || isResizing;
25067
25838
  const wrapperAlignClass = imageLayout === "block" ? textAlign === "center" ? "mx-auto" : textAlign === "right" ? "ml-auto" : textAlign === "justify" ? "mx-auto" : "" : "";
25068
25839
  const wrapperLayoutClass = imageLayout === "left" ? "float-left mr-4 mb-3 mt-1 clear-none max-w-[min(45%,20rem)]" : imageLayout === "right" ? "float-right ml-4 mb-3 mt-1 clear-none max-w-[min(45%,20rem)]" : "w-fit";
25069
- return /* @__PURE__ */ jsxs64(
25070
- NodeViewWrapper,
25840
+ return /* @__PURE__ */ jsxs67(
25841
+ NodeViewWrapper4,
25071
25842
  {
25072
25843
  as: "div",
25073
25844
  ref: wrapperRef,
@@ -25081,7 +25852,7 @@ function ResizableImageNodeView(props) {
25081
25852
  },
25082
25853
  contentEditable: false,
25083
25854
  children: [
25084
- /* @__PURE__ */ jsx77(
25855
+ /* @__PURE__ */ jsx81(
25085
25856
  "img",
25086
25857
  {
25087
25858
  ref: imgRef,
@@ -25100,7 +25871,7 @@ function ResizableImageNodeView(props) {
25100
25871
  }
25101
25872
  }
25102
25873
  ),
25103
- showHandle && /* @__PURE__ */ jsx77(
25874
+ showHandle && /* @__PURE__ */ jsx81(
25104
25875
  "div",
25105
25876
  {
25106
25877
  "aria-hidden": "true",
@@ -25120,7 +25891,7 @@ function ResizableImageNodeView(props) {
25120
25891
  }
25121
25892
  );
25122
25893
  }
25123
- var ResizableImage = Image3.extend({
25894
+ var ResizableImage = Image4.extend({
25124
25895
  addAttributes() {
25125
25896
  const parentAttrs = this.parent?.() ?? {};
25126
25897
  return {
@@ -25165,10 +25936,10 @@ var ResizableImage = Image3.extend({
25165
25936
  };
25166
25937
  },
25167
25938
  renderHTML({ HTMLAttributes }) {
25168
- return ["img", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)];
25939
+ return ["img", mergeAttributes4(this.options.HTMLAttributes, HTMLAttributes)];
25169
25940
  },
25170
25941
  addNodeView() {
25171
- return ReactNodeViewRenderer(ResizableImageNodeView);
25942
+ return ReactNodeViewRenderer4(ResizableImageNodeView);
25172
25943
  }
25173
25944
  }).configure({
25174
25945
  allowBase64: true,
@@ -25358,7 +26129,7 @@ var letter_spacing_default = LetterSpacing;
25358
26129
 
25359
26130
  // src/components/UEditor/table-align.ts
25360
26131
  import { Table as Table3 } from "@tiptap/extension-table";
25361
- import { Plugin as Plugin3 } from "@tiptap/pm/state";
26132
+ import { Plugin as Plugin4 } from "@tiptap/pm/state";
25362
26133
 
25363
26134
  // src/components/UEditor/table-dom-utils.ts
25364
26135
  var MIN_TABLE_ROW_HEIGHT = 36;
@@ -25600,7 +26371,7 @@ var UEditorTable = Table3.extend({
25600
26371
  addProseMirrorPlugins() {
25601
26372
  return [
25602
26373
  ...this.parent?.() ?? [],
25603
- new Plugin3({
26374
+ new Plugin4({
25604
26375
  appendTransaction(_transactions, _oldState, newState) {
25605
26376
  const { doc, schema } = newState;
25606
26377
  const paragraphType = schema.nodes.paragraph;
@@ -25619,6 +26390,121 @@ var UEditorTable = Table3.extend({
25619
26390
  });
25620
26391
  var table_align_default = UEditorTable;
25621
26392
 
26393
+ // src/components/UEditor/CodeBlockView.tsx
26394
+ import React73, { useState as useState45 } from "react";
26395
+ import { NodeViewWrapper as NodeViewWrapper5, NodeViewContent as NodeViewContent2 } from "@tiptap/react";
26396
+ import { Check as Check10, Copy as Copy2, ChevronDown as ChevronDown7 } from "lucide-react";
26397
+ import { Fragment as Fragment27, jsx as jsx82, jsxs as jsxs68 } from "react/jsx-runtime";
26398
+ var LANGUAGES = [
26399
+ { label: "Plain Text", value: "text" },
26400
+ { label: "JavaScript", value: "javascript" },
26401
+ { label: "TypeScript", value: "typescript" },
26402
+ { label: "HTML", value: "html" },
26403
+ { label: "CSS", value: "css" },
26404
+ { label: "Python", value: "python" },
26405
+ { label: "Go", value: "go" },
26406
+ { label: "Rust", value: "rust" },
26407
+ { label: "C++", value: "cpp" },
26408
+ { label: "Java", value: "java" },
26409
+ { label: "SQL", value: "sql" },
26410
+ { label: "JSON", value: "json" },
26411
+ { label: "YAML", value: "yaml" },
26412
+ { label: "Shell", value: "bash" }
26413
+ ];
26414
+ var CodeBlockView = ({
26415
+ node,
26416
+ updateAttributes,
26417
+ extension
26418
+ }) => {
26419
+ const [copied, setCopied] = useState45(false);
26420
+ const [isDropdownOpen, setIsDropdownOpen] = useState45(false);
26421
+ const timeoutRef = React73.useRef(null);
26422
+ const currentLangValue = node.attrs.language || "text";
26423
+ const currentLangLabel = LANGUAGES.find((lang) => lang.value === currentLangValue)?.label || "Plain Text";
26424
+ React73.useEffect(() => {
26425
+ return () => {
26426
+ if (timeoutRef.current) {
26427
+ clearTimeout(timeoutRef.current);
26428
+ }
26429
+ };
26430
+ }, []);
26431
+ const handleCopy = async () => {
26432
+ try {
26433
+ await navigator.clipboard.writeText(node.textContent);
26434
+ setCopied(true);
26435
+ if (timeoutRef.current) {
26436
+ clearTimeout(timeoutRef.current);
26437
+ }
26438
+ timeoutRef.current = setTimeout(() => {
26439
+ setCopied(false);
26440
+ }, 2e3);
26441
+ } catch (err) {
26442
+ console.error("Failed to copy code text: ", err);
26443
+ }
26444
+ };
26445
+ return /* @__PURE__ */ jsxs68(NodeViewWrapper5, { className: "group/code relative my-4 rounded-xl border border-border/60 bg-muted/40 p-4 font-mono text-sm shadow-sm overflow-visible", children: [
26446
+ /* @__PURE__ */ jsxs68(
26447
+ "div",
26448
+ {
26449
+ className: "absolute right-3 top-3 z-10 flex items-center gap-1.5 opacity-0 group-hover/code:opacity-100 focus-within:opacity-100 transition-opacity duration-200 select-none",
26450
+ contentEditable: false,
26451
+ children: [
26452
+ /* @__PURE__ */ jsxs68("div", { className: "relative", children: [
26453
+ /* @__PURE__ */ jsxs68(
26454
+ "button",
26455
+ {
26456
+ type: "button",
26457
+ onClick: () => setIsDropdownOpen(!isDropdownOpen),
26458
+ className: "flex items-center gap-1.5 rounded-lg border border-border bg-background px-2.5 py-1 text-xs text-muted-foreground hover:text-foreground hover:bg-muted active:scale-95 transition-all focus:outline-none",
26459
+ children: [
26460
+ currentLangLabel,
26461
+ /* @__PURE__ */ jsx82(ChevronDown7, { className: "h-3 w-3" })
26462
+ ]
26463
+ }
26464
+ ),
26465
+ isDropdownOpen && /* @__PURE__ */ jsxs68(Fragment27, { children: [
26466
+ /* @__PURE__ */ jsx82(
26467
+ "div",
26468
+ {
26469
+ className: "fixed inset-0 z-20",
26470
+ onClick: () => setIsDropdownOpen(false)
26471
+ }
26472
+ ),
26473
+ /* @__PURE__ */ jsx82("div", { className: "absolute right-0 mt-1 max-h-56 w-36 overflow-y-auto rounded-lg border border-border/50 bg-popover p-1 shadow-lg z-30 [scrollbar-width:thin] animate-in fade-in-0 zoom-in-95", children: LANGUAGES.map((lang) => /* @__PURE__ */ jsx82(
26474
+ "button",
26475
+ {
26476
+ type: "button",
26477
+ onClick: () => {
26478
+ updateAttributes({ language: lang.value });
26479
+ setIsDropdownOpen(false);
26480
+ },
26481
+ className: cn(
26482
+ "w-full rounded-md px-2 py-1.5 text-left text-xs transition-colors focus:outline-none",
26483
+ currentLangValue === lang.value ? "bg-primary/10 text-primary font-semibold" : "text-foreground hover:bg-muted"
26484
+ ),
26485
+ children: lang.label
26486
+ },
26487
+ lang.value
26488
+ )) })
26489
+ ] })
26490
+ ] }),
26491
+ /* @__PURE__ */ jsx82(
26492
+ "button",
26493
+ {
26494
+ type: "button",
26495
+ onClick: handleCopy,
26496
+ className: "flex h-7 w-7 items-center justify-center rounded-lg border border-border bg-background text-muted-foreground hover:text-foreground hover:bg-muted active:scale-95 transition-all focus:outline-none",
26497
+ title: "Copy code",
26498
+ children: copied ? /* @__PURE__ */ jsx82(Check10, { className: "h-3.5 w-3.5 text-success animate-in fade-in-0 zoom-in-75" }) : /* @__PURE__ */ jsx82(Copy2, { className: "h-3.5 w-3.5" })
26499
+ }
26500
+ )
26501
+ ]
26502
+ }
26503
+ ),
26504
+ /* @__PURE__ */ jsx82("pre", { className: "m-0 overflow-x-auto [scrollbar-width:thin] pt-4 sm:pt-0", children: /* @__PURE__ */ jsx82("code", { className: "bg-transparent! text-foreground!", children: /* @__PURE__ */ jsx82(NodeViewContent2, {}) }) })
26505
+ ] });
26506
+ };
26507
+
25622
26508
  // src/components/UEditor/extensions.ts
25623
26509
  var CustomTableCell = TableCell2.extend({
25624
26510
  addAttributes() {
@@ -25635,16 +26521,54 @@ var CustomTableCell = TableCell2.extend({
25635
26521
  "data-background-color": attributes.backgroundColor
25636
26522
  };
25637
26523
  }
26524
+ },
26525
+ borderColor: {
26526
+ default: null,
26527
+ parseHTML: (element) => element.style.borderColor || element.getAttribute("data-border-color") || null,
26528
+ renderHTML: (attributes) => {
26529
+ if (!attributes.borderColor) return {};
26530
+ return {
26531
+ "data-border-color": attributes.borderColor
26532
+ };
26533
+ }
26534
+ },
26535
+ borderStyle: {
26536
+ default: null,
26537
+ parseHTML: (element) => element.style.borderStyle || element.getAttribute("data-border-style") || null,
26538
+ renderHTML: (attributes) => {
26539
+ if (!attributes.borderStyle) return {};
26540
+ return {
26541
+ "data-border-style": attributes.borderStyle
26542
+ };
26543
+ }
26544
+ },
26545
+ borderWidth: {
26546
+ default: null,
26547
+ parseHTML: (element) => element.style.borderWidth || element.getAttribute("data-border-width") || null,
26548
+ renderHTML: (attributes) => {
26549
+ if (!attributes.borderWidth) return {};
26550
+ return {
26551
+ "data-border-width": attributes.borderWidth
26552
+ };
26553
+ }
25638
26554
  }
25639
26555
  };
25640
26556
  },
25641
26557
  renderHTML({ HTMLAttributes }) {
25642
26558
  const style = HTMLAttributes.style || "";
25643
26559
  const bg = HTMLAttributes["data-background-color"];
25644
- const mergedStyle = bg ? `${style}; background-color: ${bg}`.replace(/^;/, "") : style;
26560
+ const borderColor = HTMLAttributes["data-border-color"];
26561
+ const borderStyle = HTMLAttributes["data-border-style"];
26562
+ const borderWidth = HTMLAttributes["data-border-width"];
26563
+ let mergedStyle = style;
26564
+ if (bg) mergedStyle += `; background-color: ${bg}`;
26565
+ if (borderColor) mergedStyle += `; border-color: ${borderColor}`;
26566
+ if (borderStyle) mergedStyle += `; border-style: ${borderStyle}`;
26567
+ if (borderWidth) mergedStyle += `; border-width: ${borderWidth}`;
26568
+ mergedStyle = mergedStyle.replace(/^;/, "").trim();
25645
26569
  return [
25646
26570
  "td",
25647
- mergeAttributes2(this.options.HTMLAttributes, HTMLAttributes, mergedStyle ? { style: mergedStyle } : {}),
26571
+ mergeAttributes5(this.options.HTMLAttributes, HTMLAttributes, mergedStyle ? { style: mergedStyle } : {}),
25648
26572
  0
25649
26573
  ];
25650
26574
  }
@@ -25664,31 +26588,94 @@ var CustomTableHeader = TableHeader2.extend({
25664
26588
  "data-background-color": attributes.backgroundColor
25665
26589
  };
25666
26590
  }
26591
+ },
26592
+ borderColor: {
26593
+ default: null,
26594
+ parseHTML: (element) => element.style.borderColor || element.getAttribute("data-border-color") || null,
26595
+ renderHTML: (attributes) => {
26596
+ if (!attributes.borderColor) return {};
26597
+ return {
26598
+ "data-border-color": attributes.borderColor
26599
+ };
26600
+ }
26601
+ },
26602
+ borderStyle: {
26603
+ default: null,
26604
+ parseHTML: (element) => element.style.borderStyle || element.getAttribute("data-border-style") || null,
26605
+ renderHTML: (attributes) => {
26606
+ if (!attributes.borderStyle) return {};
26607
+ return {
26608
+ "data-border-style": attributes.borderStyle
26609
+ };
26610
+ }
26611
+ },
26612
+ borderWidth: {
26613
+ default: null,
26614
+ parseHTML: (element) => element.style.borderWidth || element.getAttribute("data-border-width") || null,
26615
+ renderHTML: (attributes) => {
26616
+ if (!attributes.borderWidth) return {};
26617
+ return {
26618
+ "data-border-width": attributes.borderWidth
26619
+ };
26620
+ }
25667
26621
  }
25668
26622
  };
25669
26623
  },
25670
26624
  renderHTML({ HTMLAttributes }) {
25671
26625
  const style = HTMLAttributes.style || "";
25672
26626
  const bg = HTMLAttributes["data-background-color"];
25673
- const mergedStyle = bg ? `${style}; background-color: ${bg}`.replace(/^;/, "") : style;
26627
+ const borderColor = HTMLAttributes["data-border-color"];
26628
+ const borderStyle = HTMLAttributes["data-border-style"];
26629
+ const borderWidth = HTMLAttributes["data-border-width"];
26630
+ let mergedStyle = style;
26631
+ if (bg) mergedStyle += `; background-color: ${bg}`;
26632
+ if (borderColor) mergedStyle += `; border-color: ${borderColor}`;
26633
+ if (borderStyle) mergedStyle += `; border-style: ${borderStyle}`;
26634
+ if (borderWidth) mergedStyle += `; border-width: ${borderWidth}`;
26635
+ mergedStyle = mergedStyle.replace(/^;/, "").trim();
25674
26636
  return [
25675
26637
  "th",
25676
- mergeAttributes2(this.options.HTMLAttributes, HTMLAttributes, mergedStyle ? { style: mergedStyle } : {}),
26638
+ mergeAttributes5(this.options.HTMLAttributes, HTMLAttributes, mergedStyle ? { style: mergedStyle } : {}),
25677
26639
  0
25678
26640
  ];
25679
26641
  }
25680
26642
  });
26643
+ var CustomTaskList = TaskList.extend({
26644
+ addInputRules() {
26645
+ return [
26646
+ wrappingInputRule({
26647
+ find: /^\s*(\[ \]|\[\])\s$/,
26648
+ type: this.type
26649
+ }),
26650
+ wrappingInputRule({
26651
+ find: /^\s*(-\s*\[ \]|-\s*\[\])\s$/,
26652
+ type: this.type
26653
+ }),
26654
+ wrappingInputRule({
26655
+ find: /^\s*(\*\s*\[ \]|-\s*\[\])\s$/,
26656
+ type: this.type
26657
+ })
26658
+ ];
26659
+ }
26660
+ });
25681
26661
  var lowlight = createLowlight(common);
26662
+ var CustomCodeBlockLowlight = CodeBlockLowlight.extend({
26663
+ addNodeView() {
26664
+ return ReactNodeViewRenderer5(CodeBlockView);
26665
+ }
26666
+ });
25682
26667
  function buildUEditorExtensions({
25683
26668
  placeholder,
25684
26669
  translate,
25685
26670
  maxCharacters,
25686
26671
  uploadImage,
26672
+ uploadFile,
25687
26673
  imageInsertMode = "base64",
25688
26674
  maxImageFileSize,
25689
26675
  allowedImageMimeTypes,
25690
26676
  fallbackToDataUrl,
25691
- editable = true
26677
+ editable = true,
26678
+ fetchMetadata
25692
26679
  }) {
25693
26680
  return [
25694
26681
  Document,
@@ -25718,7 +26705,7 @@ function buildUEditorExtensions({
25718
26705
  class: "pl-1"
25719
26706
  }
25720
26707
  }),
25721
- TaskList,
26708
+ CustomTaskList,
25722
26709
  TaskItem.configure({
25723
26710
  nested: true
25724
26711
  }),
@@ -25732,7 +26719,7 @@ function buildUEditorExtensions({
25732
26719
  class: "px-1.5 py-0.5 rounded bg-muted font-mono text-sm"
25733
26720
  }
25734
26721
  }),
25735
- CodeBlockLowlight.configure({
26722
+ CustomCodeBlockLowlight.configure({
25736
26723
  lowlight,
25737
26724
  HTMLAttributes: {
25738
26725
  class: "rounded-lg border border-border/60 bg-muted/40 text-foreground p-4 font-mono text-sm overflow-x-auto"
@@ -25809,12 +26796,19 @@ function buildUEditorExtensions({
25809
26796
  SlashCommand.configure({
25810
26797
  messages: buildSlashCommandMessages(translate)
25811
26798
  }),
25812
- EmojiSuggestion
26799
+ EmojiSuggestion,
26800
+ Callout,
26801
+ Bookmark.configure({
26802
+ fetchMetadata
26803
+ }),
26804
+ FileCard.configure({
26805
+ upload: uploadFile
26806
+ })
25813
26807
  ];
25814
26808
  }
25815
26809
 
25816
26810
  // src/components/UEditor/toolbar.tsx
25817
- import React73, { useRef as useRef31, useState as useState44 } from "react";
26811
+ import React76, { useRef as useRef32, useState as useState47 } from "react";
25818
26812
  import { useEditorState } from "@tiptap/react";
25819
26813
  import {
25820
26814
  AlignCenter,
@@ -25827,7 +26821,7 @@ import {
25827
26821
  ArrowUp,
25828
26822
  Baseline,
25829
26823
  Bold as BoldIcon,
25830
- ChevronDown as ChevronDown7,
26824
+ ChevronDown as ChevronDown8,
25831
26825
  ChevronsUpDown,
25832
26826
  Code as CodeIcon,
25833
26827
  FileCode as FileCode3,
@@ -25856,14 +26850,14 @@ import {
25856
26850
  } from "lucide-react";
25857
26851
 
25858
26852
  // src/components/UEditor/colors.tsx
25859
- import { useMemo as useMemo22, useRef as useRef29 } from "react";
25860
- import { Check as Check10, Highlighter, Palette as Palette2, Paintbrush } from "lucide-react";
25861
- import { jsx as jsx78, jsxs as jsxs65 } from "react/jsx-runtime";
26853
+ import { useMemo as useMemo22, useRef as useRef30 } from "react";
26854
+ import { Check as Check11, Highlighter, Palette as Palette2, Paintbrush, Grid as Grid2 } from "lucide-react";
26855
+ import { jsx as jsx83, jsxs as jsxs69 } from "react/jsx-runtime";
25862
26856
  var TextColorIcon = ({ color }) => {
25863
26857
  const underlineColor = color && color !== "inherit" ? color : "currentColor";
25864
- return /* @__PURE__ */ jsxs65("span", { className: "relative flex h-5 w-5 items-center justify-center leading-none", children: [
25865
- /* @__PURE__ */ jsx78("span", { className: "text-[15px] font-semibold leading-none", children: "A" }),
25866
- /* @__PURE__ */ jsx78(
26858
+ return /* @__PURE__ */ jsxs69("span", { className: "relative flex h-5 w-5 items-center justify-center leading-none", children: [
26859
+ /* @__PURE__ */ jsx83("span", { className: "text-[15px] font-semibold leading-none", children: "A" }),
26860
+ /* @__PURE__ */ jsx83(
25867
26861
  "span",
25868
26862
  {
25869
26863
  "aria-hidden": "true",
@@ -25875,9 +26869,9 @@ var TextColorIcon = ({ color }) => {
25875
26869
  };
25876
26870
  var HighlightColorIcon = ({ color }) => {
25877
26871
  const underlineColor = color || "currentColor";
25878
- return /* @__PURE__ */ jsxs65("span", { className: "relative flex h-5 w-5 items-center justify-center leading-none", children: [
25879
- /* @__PURE__ */ jsx78(Highlighter, { className: "h-4 w-4" }),
25880
- /* @__PURE__ */ jsx78(
26872
+ return /* @__PURE__ */ jsxs69("span", { className: "relative flex h-5 w-5 items-center justify-center leading-none", children: [
26873
+ /* @__PURE__ */ jsx83(Highlighter, { className: "h-4 w-4" }),
26874
+ /* @__PURE__ */ jsx83(
25881
26875
  "span",
25882
26876
  {
25883
26877
  "aria-hidden": "true",
@@ -25889,9 +26883,23 @@ var HighlightColorIcon = ({ color }) => {
25889
26883
  };
25890
26884
  var CellBgColorIcon = ({ color }) => {
25891
26885
  const underlineColor = color && color !== "inherit" ? color : "currentColor";
25892
- return /* @__PURE__ */ jsxs65("span", { className: "relative flex h-5 w-5 items-center justify-center leading-none", children: [
25893
- /* @__PURE__ */ jsx78(Paintbrush, { className: "h-4 w-4" }),
25894
- /* @__PURE__ */ jsx78(
26886
+ return /* @__PURE__ */ jsxs69("span", { className: "relative flex h-5 w-5 items-center justify-center leading-none", children: [
26887
+ /* @__PURE__ */ jsx83(Paintbrush, { className: "h-4 w-4" }),
26888
+ /* @__PURE__ */ jsx83(
26889
+ "span",
26890
+ {
26891
+ "aria-hidden": "true",
26892
+ className: "absolute bottom-0 left-1/2 h-0.5 w-4 -translate-x-1/2 rounded-full",
26893
+ style: { backgroundColor: underlineColor }
26894
+ }
26895
+ )
26896
+ ] });
26897
+ };
26898
+ var CellBorderIcon = ({ color }) => {
26899
+ const underlineColor = color && color !== "inherit" ? color : "currentColor";
26900
+ return /* @__PURE__ */ jsxs69("span", { className: "relative flex h-5 w-5 items-center justify-center leading-none", children: [
26901
+ /* @__PURE__ */ jsx83(Grid2, { className: "h-4 w-4" }),
26902
+ /* @__PURE__ */ jsx83(
25895
26903
  "span",
25896
26904
  {
25897
26905
  "aria-hidden": "true",
@@ -26012,12 +27020,12 @@ var EditorColorPalette = ({
26012
27020
  label
26013
27021
  }) => {
26014
27022
  const t = useSmartTranslations("UEditor");
26015
- const colorInputRef = useRef29(null);
27023
+ const colorInputRef = useRef30(null);
26016
27024
  const automaticColor = colors[0]?.color ?? "";
26017
27025
  const paletteColors = colors.slice(1);
26018
- return /* @__PURE__ */ jsxs65("div", { className: "w-56 p-2", children: [
26019
- /* @__PURE__ */ jsx78("span", { className: "px-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: label }),
26020
- /* @__PURE__ */ jsxs65(
27026
+ return /* @__PURE__ */ jsxs69("div", { className: "w-56 p-2", children: [
27027
+ /* @__PURE__ */ jsx83("span", { className: "px-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: label }),
27028
+ /* @__PURE__ */ jsxs69(
26021
27029
  "button",
26022
27030
  {
26023
27031
  type: "button",
@@ -26029,12 +27037,12 @@ var EditorColorPalette = ({
26029
27037
  currentColor === automaticColor ? "border-primary text-primary" : "border-transparent text-foreground"
26030
27038
  ),
26031
27039
  children: [
26032
- /* @__PURE__ */ jsx78("span", { className: "flex h-5 w-5 items-center justify-center rounded border border-border bg-background", children: currentColor === automaticColor && /* @__PURE__ */ jsx78(Check10, { className: "h-3.5 w-3.5" }) }),
26033
- /* @__PURE__ */ jsx78("span", { className: "flex-1 text-center", children: t("colors.automatic") })
27040
+ /* @__PURE__ */ jsx83("span", { className: "flex h-5 w-5 items-center justify-center rounded border border-border bg-background", children: currentColor === automaticColor && /* @__PURE__ */ jsx83(Check11, { className: "h-3.5 w-3.5" }) }),
27041
+ /* @__PURE__ */ jsx83("span", { className: "flex-1 text-center", children: t("colors.automatic") })
26034
27042
  ]
26035
27043
  }
26036
27044
  ),
26037
- /* @__PURE__ */ jsx78("div", { className: "mt-2 grid grid-cols-8 gap-1", children: paletteColors.map((c) => /* @__PURE__ */ jsx78(Tooltip, { placement: "top", content: /* @__PURE__ */ jsx78("span", { className: "text-xs font-medium", children: c.name }), children: /* @__PURE__ */ jsx78(
27045
+ /* @__PURE__ */ jsx83("div", { className: "mt-2 grid grid-cols-8 gap-1", children: paletteColors.map((c) => /* @__PURE__ */ jsx83(Tooltip, { placement: "top", content: /* @__PURE__ */ jsx83("span", { className: "text-xs font-medium", children: c.name }), children: /* @__PURE__ */ jsx83(
26038
27046
  "button",
26039
27047
  {
26040
27048
  type: "button",
@@ -26046,10 +27054,10 @@ var EditorColorPalette = ({
26046
27054
  currentColor === c.color ? "border-primary ring-2 ring-primary/25" : "border-border/70"
26047
27055
  ),
26048
27056
  style: { backgroundColor: c.color || "transparent" },
26049
- children: currentColor === c.color && /* @__PURE__ */ jsx78("span", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsx78(Check10, { className: "h-3.5 w-3.5 text-white drop-shadow-[0_1px_1px_rgba(0,0,0,0.8)]" }) })
27057
+ children: currentColor === c.color && /* @__PURE__ */ jsx83("span", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsx83(Check11, { className: "h-3.5 w-3.5 text-white drop-shadow-[0_1px_1px_rgba(0,0,0,0.8)]" }) })
26050
27058
  }
26051
27059
  ) }, `${c.name}-${c.color}`)) }),
26052
- /* @__PURE__ */ jsxs65(
27060
+ /* @__PURE__ */ jsxs69(
26053
27061
  "button",
26054
27062
  {
26055
27063
  type: "button",
@@ -26057,7 +27065,7 @@ var EditorColorPalette = ({
26057
27065
  onClick: () => colorInputRef.current?.click(),
26058
27066
  className: "mt-3 flex h-9 w-full items-center gap-3 rounded-md px-2 text-sm text-foreground transition-colors hover:bg-muted",
26059
27067
  children: [
26060
- /* @__PURE__ */ jsx78(
27068
+ /* @__PURE__ */ jsx83(
26061
27069
  "span",
26062
27070
  {
26063
27071
  "aria-hidden": "true",
@@ -26067,9 +27075,9 @@ var EditorColorPalette = ({
26067
27075
  }
26068
27076
  }
26069
27077
  ),
26070
- /* @__PURE__ */ jsx78("span", { className: "flex-1 text-center", children: t("colors.moreColors") }),
26071
- /* @__PURE__ */ jsx78(Palette2, { className: "h-4 w-4 text-muted-foreground" }),
26072
- /* @__PURE__ */ jsx78(
27078
+ /* @__PURE__ */ jsx83("span", { className: "flex-1 text-center", children: t("colors.moreColors") }),
27079
+ /* @__PURE__ */ jsx83(Palette2, { className: "h-4 w-4 text-muted-foreground" }),
27080
+ /* @__PURE__ */ jsx83(
26073
27081
  "input",
26074
27082
  {
26075
27083
  ref: colorInputRef,
@@ -26177,9 +27185,9 @@ function deleteSelectedImage(editor) {
26177
27185
  }
26178
27186
 
26179
27187
  // src/components/UEditor/inputs.tsx
26180
- import { useEffect as useEffect33, useRef as useRef30, useState as useState43 } from "react";
26181
- import { Check as Check11, X as X18 } from "lucide-react";
26182
- import { jsx as jsx79, jsxs as jsxs66 } from "react/jsx-runtime";
27188
+ import { useEffect as useEffect35, useRef as useRef31, useState as useState46 } from "react";
27189
+ import { Check as Check12, X as X18 } from "lucide-react";
27190
+ import { jsx as jsx84, jsxs as jsxs70 } from "react/jsx-runtime";
26183
27191
  function normalizeUrl(raw) {
26184
27192
  return sanitizeUEditorUrl(raw, "link");
26185
27193
  }
@@ -26189,9 +27197,9 @@ var LinkInput = ({
26189
27197
  initialUrl = ""
26190
27198
  }) => {
26191
27199
  const t = useSmartTranslations("UEditor");
26192
- const [url, setUrl] = useState43(initialUrl);
26193
- const inputRef = useRef30(null);
26194
- useEffect33(() => {
27200
+ const [url, setUrl] = useState46(initialUrl);
27201
+ const inputRef = useRef31(null);
27202
+ useEffect35(() => {
26195
27203
  inputRef.current?.focus();
26196
27204
  inputRef.current?.select();
26197
27205
  }, []);
@@ -26200,8 +27208,8 @@ var LinkInput = ({
26200
27208
  const normalized = normalizeUrl(url);
26201
27209
  if (normalized) onSubmit(normalized);
26202
27210
  };
26203
- return /* @__PURE__ */ jsxs66("form", { onSubmit: handleSubmit, className: "flex items-center gap-2 p-2", children: [
26204
- /* @__PURE__ */ jsx79(
27211
+ return /* @__PURE__ */ jsxs70("form", { onSubmit: handleSubmit, className: "flex items-center gap-2 p-2", children: [
27212
+ /* @__PURE__ */ jsx84(
26205
27213
  "input",
26206
27214
  {
26207
27215
  ref: inputRef,
@@ -26212,16 +27220,16 @@ var LinkInput = ({
26212
27220
  className: "flex-1 px-3 py-2 text-sm bg-muted/50 border-0 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/20"
26213
27221
  }
26214
27222
  ),
26215
- /* @__PURE__ */ jsx79("button", { type: "submit", className: "p-2 rounded-lg bg-primary text-primary-foreground hover:bg-primary/90 transition-colors", children: /* @__PURE__ */ jsx79(Check11, { className: "w-4 h-4" }) }),
26216
- /* @__PURE__ */ jsx79("button", { type: "button", onClick: onCancel, className: "p-2 rounded-lg hover:bg-muted transition-colors text-muted-foreground", children: /* @__PURE__ */ jsx79(X18, { className: "w-4 h-4" }) })
27223
+ /* @__PURE__ */ jsx84("button", { type: "submit", className: "p-2 rounded-lg bg-primary text-primary-foreground hover:bg-primary/90 transition-colors", children: /* @__PURE__ */ jsx84(Check12, { className: "w-4 h-4" }) }),
27224
+ /* @__PURE__ */ jsx84("button", { type: "button", onClick: onCancel, className: "p-2 rounded-lg hover:bg-muted transition-colors text-muted-foreground", children: /* @__PURE__ */ jsx84(X18, { className: "w-4 h-4" }) })
26217
27225
  ] });
26218
27226
  };
26219
27227
  var ImageInput = ({ onSubmit, onCancel }) => {
26220
27228
  const t = useSmartTranslations("UEditor");
26221
- const [url, setUrl] = useState43("");
26222
- const [alt, setAlt] = useState43("");
26223
- const inputRef = useRef30(null);
26224
- useEffect33(() => {
27229
+ const [url, setUrl] = useState46("");
27230
+ const [alt, setAlt] = useState46("");
27231
+ const inputRef = useRef31(null);
27232
+ useEffect35(() => {
26225
27233
  inputRef.current?.focus();
26226
27234
  }, []);
26227
27235
  const handleSubmit = (e) => {
@@ -26231,10 +27239,10 @@ var ImageInput = ({ onSubmit, onCancel }) => {
26231
27239
  onSubmit(safeUrl, alt);
26232
27240
  }
26233
27241
  };
26234
- return /* @__PURE__ */ jsxs66("form", { onSubmit: handleSubmit, className: "p-3 space-y-3", children: [
26235
- /* @__PURE__ */ jsxs66("div", { children: [
26236
- /* @__PURE__ */ jsx79("label", { className: "text-xs font-medium text-muted-foreground", children: t("imageInput.urlLabel") }),
26237
- /* @__PURE__ */ jsx79(
27242
+ return /* @__PURE__ */ jsxs70("form", { onSubmit: handleSubmit, className: "p-3 space-y-3", children: [
27243
+ /* @__PURE__ */ jsxs70("div", { children: [
27244
+ /* @__PURE__ */ jsx84("label", { className: "text-xs font-medium text-muted-foreground", children: t("imageInput.urlLabel") }),
27245
+ /* @__PURE__ */ jsx84(
26238
27246
  "input",
26239
27247
  {
26240
27248
  ref: inputRef,
@@ -26246,9 +27254,9 @@ var ImageInput = ({ onSubmit, onCancel }) => {
26246
27254
  }
26247
27255
  )
26248
27256
  ] }),
26249
- /* @__PURE__ */ jsxs66("div", { children: [
26250
- /* @__PURE__ */ jsx79("label", { className: "text-xs font-medium text-muted-foreground", children: t("imageInput.altLabel") }),
26251
- /* @__PURE__ */ jsx79(
27257
+ /* @__PURE__ */ jsxs70("div", { children: [
27258
+ /* @__PURE__ */ jsx84("label", { className: "text-xs font-medium text-muted-foreground", children: t("imageInput.altLabel") }),
27259
+ /* @__PURE__ */ jsx84(
26252
27260
  "input",
26253
27261
  {
26254
27262
  type: "text",
@@ -26259,8 +27267,8 @@ var ImageInput = ({ onSubmit, onCancel }) => {
26259
27267
  }
26260
27268
  )
26261
27269
  ] }),
26262
- /* @__PURE__ */ jsxs66("div", { className: "flex gap-2", children: [
26263
- /* @__PURE__ */ jsx79(
27270
+ /* @__PURE__ */ jsxs70("div", { className: "flex gap-2", children: [
27271
+ /* @__PURE__ */ jsx84(
26264
27272
  "button",
26265
27273
  {
26266
27274
  type: "submit",
@@ -26269,29 +27277,29 @@ var ImageInput = ({ onSubmit, onCancel }) => {
26269
27277
  children: t("imageInput.addBtn")
26270
27278
  }
26271
27279
  ),
26272
- /* @__PURE__ */ jsx79("button", { type: "button", onClick: onCancel, className: "px-4 py-2 rounded-lg hover:bg-muted transition-colors text-muted-foreground", children: t("imageInput.cancelBtn") })
27280
+ /* @__PURE__ */ jsx84("button", { type: "button", onClick: onCancel, className: "px-4 py-2 rounded-lg hover:bg-muted transition-colors text-muted-foreground", children: t("imageInput.cancelBtn") })
26273
27281
  ] })
26274
27282
  ] });
26275
27283
  };
26276
27284
 
26277
- // src/components/UEditor/emoji-picker.tsx
26278
- import { jsx as jsx80 } from "react/jsx-runtime";
26279
- var EmojiPicker2 = ({ onSelect }) => {
26280
- return /* @__PURE__ */ jsx80(EmojiPicker, { onEmojiSelect: onSelect, chrome: "embedded" });
26281
- };
26282
-
26283
27285
  // src/components/UEditor/typography-options.ts
26284
27286
  function normalizeStyleValue(value) {
26285
27287
  return typeof value === "string" ? value.trim().replace(/^['"]|['"]$/g, "") : "";
26286
27288
  }
26287
27289
  function getDefaultFontFamilies(t) {
26288
27290
  return [
26289
- { label: "Inter", value: "Inter, ui-sans-serif, system-ui, sans-serif" },
26290
- { label: "System UI", value: "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" },
26291
- { label: "Georgia", value: "Georgia, 'Times New Roman', serif" },
26292
- { label: "Palatino", value: "'Palatino Linotype', Palatino, Georgia, serif" },
26293
- { label: "Times", value: "'Times New Roman', Times, serif" },
26294
- { label: "JetBrains Mono", value: "'JetBrains Mono', 'Fira Code', 'SFMono-Regular', Consolas, monospace" }
27291
+ { label: "Inter", value: '"Inter", "Noto Sans", "Noto Sans CJK KR", "Noto Sans CJK JP", "Segoe UI", sans-serif' },
27292
+ { label: "System UI", value: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif' },
27293
+ { label: "Roboto", value: '"Roboto", "Noto Sans", "Apple SD Gothic Neo", "Hiragino Kaku Gothic ProN", sans-serif' },
27294
+ { label: "Lexend", value: '"Lexend", "Be Vietnam Pro", "Segoe UI", sans-serif' },
27295
+ { label: "Montserrat", value: '"Montserrat", "Segoe UI", sans-serif' },
27296
+ { label: "Lora", value: '"Lora", "Georgia", "Times New Roman", "Nanum Myeongjo", "BIZ UDPMincho", serif' },
27297
+ { label: "Playfair Display", value: '"Playfair Display", "Times New Roman", "Nanum Myeongjo", serif' },
27298
+ { label: "Georgia", value: 'Georgia, "Nanum Myeongjo", "Batang", "Times New Roman", serif' },
27299
+ { label: "Times New Roman", value: '"Times New Roman", Times, "BIZ UDPMincho", serif' },
27300
+ { label: "Meiryo (JA)", value: '"Meiryo", "Hiragino Sans", "Noto Sans JP", sans-serif' },
27301
+ { label: "Apple SD Gothic Neo (KO)", value: '"Apple SD Gothic Neo", "Malgun Gothic", "Noto Sans KR", sans-serif' },
27302
+ { label: "JetBrains Mono", value: '"JetBrains Mono", "Fira Code", "SFMono-Regular", Consolas, "Noto Sans Mono CJK KR", "Noto Sans Mono CJK JP", monospace' }
26295
27303
  ];
26296
27304
  }
26297
27305
  function getDefaultFontSizes() {
@@ -26334,7 +27342,7 @@ function getDefaultLetterSpacings() {
26334
27342
  }
26335
27343
 
26336
27344
  // src/components/UEditor/toolbar.tsx
26337
- import { Fragment as Fragment27, jsx as jsx81, jsxs as jsxs67 } from "react/jsx-runtime";
27345
+ import { Fragment as Fragment28, jsx as jsx85, jsxs as jsxs71 } from "react/jsx-runtime";
26338
27346
  function getTableAnchorPos(editor) {
26339
27347
  const tableInfo = findTableNodeInfoFromState(editor.state);
26340
27348
  if (tableInfo) return editor.state.selection.from;
@@ -26364,8 +27372,8 @@ function fileToDataUrl2(file) {
26364
27372
  function formatTableInsertLabel(template, rows, cols) {
26365
27373
  return template.replace("{rows}", String(rows)).replace("{cols}", String(cols));
26366
27374
  }
26367
- var ToolbarButton = React73.forwardRef(({ onClick, onMouseDown, active, disabled, children, title, className }, ref) => {
26368
- const button = /* @__PURE__ */ jsx81(
27375
+ var ToolbarButton = React76.forwardRef(({ onClick, onMouseDown, active, disabled, children, title, className }, ref) => {
27376
+ const button = /* @__PURE__ */ jsx85(
26369
27377
  "button",
26370
27378
  {
26371
27379
  ref,
@@ -26390,28 +27398,28 @@ var ToolbarButton = React73.forwardRef(({ onClick, onMouseDown, active, disabled
26390
27398
  }
26391
27399
  );
26392
27400
  if (title) {
26393
- return /* @__PURE__ */ jsx81(Tooltip, { content: title, placement: "top", delay: { open: 200, close: 0 }, children: button });
27401
+ return /* @__PURE__ */ jsx85(Tooltip, { content: title, placement: "top", delay: { open: 200, close: 0 }, children: button });
26394
27402
  }
26395
27403
  return button;
26396
27404
  });
26397
27405
  ToolbarButton.displayName = "ToolbarButton";
26398
- var ToolbarDivider = () => /* @__PURE__ */ jsx81("div", { className: "mx-0.5 h-5 w-px bg-border/60" });
27406
+ var ToolbarDivider = () => /* @__PURE__ */ jsx85("div", { className: "mx-0.5 h-5 w-px bg-border/60" });
26399
27407
  var TableInsertGrid = ({
26400
27408
  insertLabel,
26401
27409
  previewTemplate,
26402
27410
  onInsert
26403
27411
  }) => {
26404
- const [selection, setSelection] = React73.useState({ rows: 3, cols: 3 });
27412
+ const [selection, setSelection] = React76.useState({ rows: 3, cols: 3 });
26405
27413
  const maxRows = 8;
26406
27414
  const maxCols = 8;
26407
- return /* @__PURE__ */ jsxs67("div", { className: "mb-2 rounded-xl border border-border/60 bg-muted/20 p-2", children: [
26408
- /* @__PURE__ */ jsx81("div", { className: "mb-2 text-sm font-medium text-foreground", children: formatTableInsertLabel(previewTemplate, selection.rows, selection.cols) }),
26409
- /* @__PURE__ */ jsx81("div", { className: "grid grid-cols-8 gap-1", onMouseLeave: () => setSelection((prev) => prev), children: Array.from({ length: maxRows }).map(
27415
+ return /* @__PURE__ */ jsxs71("div", { className: "mb-2 rounded-xl border border-border/60 bg-muted/20 p-2", children: [
27416
+ /* @__PURE__ */ jsx85("div", { className: "mb-2 text-sm font-medium text-foreground", children: formatTableInsertLabel(previewTemplate, selection.rows, selection.cols) }),
27417
+ /* @__PURE__ */ jsx85("div", { className: "grid grid-cols-8 gap-1", onMouseLeave: () => setSelection((prev) => prev), children: Array.from({ length: maxRows }).map(
26410
27418
  (_, rowIndex) => Array.from({ length: maxCols }).map((__, colIndex) => {
26411
27419
  const rows = rowIndex + 1;
26412
27420
  const cols = colIndex + 1;
26413
27421
  const active = rows <= selection.rows && cols <= selection.cols;
26414
- return /* @__PURE__ */ jsx81(
27422
+ return /* @__PURE__ */ jsx85(
26415
27423
  "button",
26416
27424
  {
26417
27425
  type: "button",
@@ -26429,7 +27437,7 @@ var TableInsertGrid = ({
26429
27437
  );
26430
27438
  })
26431
27439
  ) }),
26432
- /* @__PURE__ */ jsx81("div", { className: "mt-2 text-xs text-muted-foreground", children: insertLabel })
27440
+ /* @__PURE__ */ jsx85("div", { className: "mt-2 text-xs text-muted-foreground", children: insertLabel })
26433
27441
  ] });
26434
27442
  };
26435
27443
  var EditorToolbar = ({
@@ -26450,13 +27458,13 @@ var EditorToolbar = ({
26450
27458
  selector: ({ transactionNumber }) => transactionNumber
26451
27459
  });
26452
27460
  const { textColors, highlightColors } = useEditorColors();
26453
- const [showImageInput, setShowImageInput] = useState44(false);
26454
- const [showLinkInput, setShowLinkInput] = useState44(false);
26455
- const [isTableMenuOpen, setIsTableMenuOpen] = useState44(false);
26456
- const tableCommandAnchorPosRef = useRef31(null);
26457
- const fileInputRef = useRef31(null);
26458
- const [isUploadingImage, setIsUploadingImage] = useState44(false);
26459
- const [imageUploadError, setImageUploadError] = useState44(null);
27461
+ const [showImageInput, setShowImageInput] = useState47(false);
27462
+ const [showLinkInput, setShowLinkInput] = useState47(false);
27463
+ const [isTableMenuOpen, setIsTableMenuOpen] = useState47(false);
27464
+ const tableCommandAnchorPosRef = useRef32(null);
27465
+ const fileInputRef = useRef32(null);
27466
+ const [isUploadingImage, setIsUploadingImage] = useState47(false);
27467
+ const [imageUploadError, setImageUploadError] = useState47(null);
26460
27468
  const isImageSelected = editor.isActive("image");
26461
27469
  const imageAttrs = editor.getAttributes("image");
26462
27470
  const tableAnchorPos = getTableAnchorPos(editor);
@@ -26475,10 +27483,10 @@ var EditorToolbar = ({
26475
27483
  const currentHighlightColor = normalizeStyleValue(editor.getAttributes("highlight").color) || "";
26476
27484
  const currentLineHeight = normalizeStyleValue(textStyleAttrs.lineHeight);
26477
27485
  const currentLetterSpacing = normalizeStyleValue(textStyleAttrs.letterSpacing);
26478
- const availableFontFamilies = React73.useMemo(() => fontFamilies ?? getDefaultFontFamilies(t), [fontFamilies, t]);
26479
- const availableFontSizes = React73.useMemo(() => fontSizes ?? getDefaultFontSizes(), [fontSizes]);
26480
- const availableLineHeights = React73.useMemo(() => lineHeights ?? getDefaultLineHeights(), [lineHeights]);
26481
- const availableLetterSpacings = React73.useMemo(() => letterSpacings ?? getDefaultLetterSpacings(), [letterSpacings]);
27486
+ const availableFontFamilies = React76.useMemo(() => fontFamilies ?? getDefaultFontFamilies(t), [fontFamilies, t]);
27487
+ const availableFontSizes = React76.useMemo(() => fontSizes ?? getDefaultFontSizes(), [fontSizes]);
27488
+ const availableLineHeights = React76.useMemo(() => lineHeights ?? getDefaultLineHeights(), [lineHeights]);
27489
+ const availableLetterSpacings = React76.useMemo(() => letterSpacings ?? getDefaultLetterSpacings(), [letterSpacings]);
26482
27490
  const currentFontFamilyDisplayValue = currentFontFamily.split(",")[0]?.trim() ?? currentFontFamily;
26483
27491
  const currentFontFamilyLabel = availableFontFamilies.find((option) => normalizeStyleValue(option.value) === currentFontFamily)?.label ?? (currentFontFamilyDisplayValue || t("toolbar.fontDefault"));
26484
27492
  const currentFontSizeLabel = availableFontSizes.find((option) => normalizeStyleValue(option.value) === currentFontSize)?.label ?? t("toolbar.sizeDefault");
@@ -26507,32 +27515,32 @@ var EditorToolbar = ({
26507
27515
  setIsUploadingImage(false);
26508
27516
  };
26509
27517
  if (variant === "minimal") {
26510
- return /* @__PURE__ */ jsxs67("div", { className: "flex items-center gap-1 border-b border-border/35 bg-muted/30 p-2", children: [
26511
- /* @__PURE__ */ jsx81(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ jsx81(BoldIcon, { className: "w-4 h-4" }) }),
26512
- /* @__PURE__ */ jsx81(ToolbarButton, { onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic"), title: t("toolbar.italic"), children: /* @__PURE__ */ jsx81(ItalicIcon, { className: "w-4 h-4" }) }),
26513
- /* @__PURE__ */ jsx81(
27518
+ return /* @__PURE__ */ jsxs71("div", { className: "flex items-center gap-1 border-b border-border/35 bg-muted/30 p-2", children: [
27519
+ /* @__PURE__ */ jsx85(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ jsx85(BoldIcon, { className: "w-4 h-4" }) }),
27520
+ /* @__PURE__ */ jsx85(ToolbarButton, { onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic"), title: t("toolbar.italic"), children: /* @__PURE__ */ jsx85(ItalicIcon, { className: "w-4 h-4" }) }),
27521
+ /* @__PURE__ */ jsx85(
26514
27522
  ToolbarButton,
26515
27523
  {
26516
27524
  onClick: () => editor.chain().focus().toggleBulletList().run(),
26517
27525
  active: editor.isActive("bulletList"),
26518
27526
  title: t("toolbar.bulletList"),
26519
- children: /* @__PURE__ */ jsx81(ListIcon, { className: "w-4 h-4" })
27527
+ children: /* @__PURE__ */ jsx85(ListIcon, { className: "w-4 h-4" })
26520
27528
  }
26521
27529
  )
26522
27530
  ] });
26523
27531
  }
26524
- return /* @__PURE__ */ jsxs67("div", { className: "flex flex-wrap items-center gap-0.5 border-b border-border/35 bg-linear-to-r from-muted/25 to-transparent p-1.5", children: [
26525
- /* @__PURE__ */ jsxs67(
27532
+ return /* @__PURE__ */ jsxs71("div", { className: "flex flex-wrap items-center gap-0.5 border-b border-border/35 bg-linear-to-r from-muted/25 to-transparent p-1.5", children: [
27533
+ /* @__PURE__ */ jsxs71(
26526
27534
  DropdownMenu,
26527
27535
  {
26528
- trigger: /* @__PURE__ */ jsxs67(ToolbarButton, { onClick: () => {
27536
+ trigger: /* @__PURE__ */ jsxs71(ToolbarButton, { onClick: () => {
26529
27537
  }, title: t("toolbar.fontFamily"), className: "px-1.5 w-auto gap-0.5", children: [
26530
- /* @__PURE__ */ jsx81(Baseline, { className: "w-4 h-4" }),
26531
- /* @__PURE__ */ jsx81(ChevronDown7, { className: "h-3 w-3 text-muted-foreground" })
27538
+ /* @__PURE__ */ jsx85(Baseline, { className: "w-4 h-4" }),
27539
+ /* @__PURE__ */ jsx85(ChevronDown8, { className: "h-3 w-3 text-muted-foreground" })
26532
27540
  ] }),
26533
27541
  contentClassName: "max-h-80 overflow-y-auto min-w-56 p-2",
26534
27542
  children: [
26535
- /* @__PURE__ */ jsx81(
27543
+ /* @__PURE__ */ jsx85(
26536
27544
  DropdownMenuItem,
26537
27545
  {
26538
27546
  icon: Type2,
@@ -26541,7 +27549,7 @@ var EditorToolbar = ({
26541
27549
  active: !currentFontFamily
26542
27550
  }
26543
27551
  ),
26544
- availableFontFamilies.map((option) => /* @__PURE__ */ jsx81(
27552
+ availableFontFamilies.map((option) => /* @__PURE__ */ jsx85(
26545
27553
  DropdownMenuItem,
26546
27554
  {
26547
27555
  label: option.label,
@@ -26554,20 +27562,20 @@ var EditorToolbar = ({
26554
27562
  ]
26555
27563
  }
26556
27564
  ),
26557
- /* @__PURE__ */ jsxs67(
27565
+ /* @__PURE__ */ jsxs71(
26558
27566
  DropdownMenu,
26559
27567
  {
26560
- trigger: /* @__PURE__ */ jsxs67(ToolbarButton, { onClick: () => {
27568
+ trigger: /* @__PURE__ */ jsxs71(ToolbarButton, { onClick: () => {
26561
27569
  }, title: t("toolbar.fontSize"), className: "px-1.5 w-auto gap-0.5", children: [
26562
- /* @__PURE__ */ jsxs67("div", { className: "flex items-center gap-0.5", children: [
26563
- /* @__PURE__ */ jsx81(ChevronsUpDown, { className: "h-3 w-3 text-muted-foreground", strokeWidth: 2.5 }),
26564
- /* @__PURE__ */ jsx81("span", { className: "text-xs font-bold leading-none", children: "A" })
27570
+ /* @__PURE__ */ jsxs71("div", { className: "flex items-center gap-0.5", children: [
27571
+ /* @__PURE__ */ jsx85(ChevronsUpDown, { className: "h-3 w-3 text-muted-foreground", strokeWidth: 2.5 }),
27572
+ /* @__PURE__ */ jsx85("span", { className: "text-xs font-bold leading-none", children: "A" })
26565
27573
  ] }),
26566
- /* @__PURE__ */ jsx81(ChevronDown7, { className: "h-3 w-3 text-muted-foreground" })
27574
+ /* @__PURE__ */ jsx85(ChevronDown8, { className: "h-3 w-3 text-muted-foreground" })
26567
27575
  ] }),
26568
27576
  contentClassName: "max-h-80 overflow-y-auto min-w-32 p-2",
26569
27577
  children: [
26570
- /* @__PURE__ */ jsx81(
27578
+ /* @__PURE__ */ jsx85(
26571
27579
  DropdownMenuItem,
26572
27580
  {
26573
27581
  icon: Type2,
@@ -26576,7 +27584,7 @@ var EditorToolbar = ({
26576
27584
  active: !currentFontSize
26577
27585
  }
26578
27586
  ),
26579
- availableFontSizes.map((option) => /* @__PURE__ */ jsx81(
27587
+ availableFontSizes.map((option) => /* @__PURE__ */ jsx85(
26580
27588
  DropdownMenuItem,
26581
27589
  {
26582
27590
  label: option.label,
@@ -26588,17 +27596,17 @@ var EditorToolbar = ({
26588
27596
  ]
26589
27597
  }
26590
27598
  ),
26591
- /* @__PURE__ */ jsxs67(
27599
+ /* @__PURE__ */ jsxs71(
26592
27600
  DropdownMenu,
26593
27601
  {
26594
27602
  contentClassName: "p-1",
26595
- trigger: /* @__PURE__ */ jsxs67(ToolbarButton, { onClick: () => {
27603
+ trigger: /* @__PURE__ */ jsxs71(ToolbarButton, { onClick: () => {
26596
27604
  }, title: t("toolbar.textStyle"), className: "px-1.5 w-auto gap-0.5", children: [
26597
- /* @__PURE__ */ jsx81(Type2, { className: "w-4 h-4" }),
26598
- /* @__PURE__ */ jsx81(ChevronDown7, { className: "h-3 w-3 text-muted-foreground" })
27605
+ /* @__PURE__ */ jsx85(Type2, { className: "w-4 h-4" }),
27606
+ /* @__PURE__ */ jsx85(ChevronDown8, { className: "h-3 w-3 text-muted-foreground" })
26599
27607
  ] }),
26600
27608
  children: [
26601
- /* @__PURE__ */ jsx81(
27609
+ /* @__PURE__ */ jsx85(
26602
27610
  DropdownMenuItem,
26603
27611
  {
26604
27612
  icon: Type2,
@@ -26607,7 +27615,7 @@ var EditorToolbar = ({
26607
27615
  active: editor.isActive("paragraph")
26608
27616
  }
26609
27617
  ),
26610
- /* @__PURE__ */ jsx81(
27618
+ /* @__PURE__ */ jsx85(
26611
27619
  DropdownMenuItem,
26612
27620
  {
26613
27621
  icon: Heading1Icon,
@@ -26617,7 +27625,7 @@ var EditorToolbar = ({
26617
27625
  shortcut: "Ctrl+Alt+1"
26618
27626
  }
26619
27627
  ),
26620
- /* @__PURE__ */ jsx81(
27628
+ /* @__PURE__ */ jsx85(
26621
27629
  DropdownMenuItem,
26622
27630
  {
26623
27631
  icon: Heading2Icon,
@@ -26627,7 +27635,7 @@ var EditorToolbar = ({
26627
27635
  shortcut: "Ctrl+Alt+2"
26628
27636
  }
26629
27637
  ),
26630
- /* @__PURE__ */ jsx81(
27638
+ /* @__PURE__ */ jsx85(
26631
27639
  DropdownMenuItem,
26632
27640
  {
26633
27641
  icon: Heading3Icon,
@@ -26640,17 +27648,17 @@ var EditorToolbar = ({
26640
27648
  ]
26641
27649
  }
26642
27650
  ),
26643
- /* @__PURE__ */ jsxs67(
27651
+ /* @__PURE__ */ jsxs71(
26644
27652
  DropdownMenu,
26645
27653
  {
26646
- trigger: /* @__PURE__ */ jsxs67(ToolbarButton, { onClick: () => {
27654
+ trigger: /* @__PURE__ */ jsxs71(ToolbarButton, { onClick: () => {
26647
27655
  }, title: t("toolbar.lineHeight"), className: "gap-0.5", children: [
26648
- /* @__PURE__ */ jsx81(ArrowUp, { className: "w-3 h-3" }),
26649
- /* @__PURE__ */ jsx81(ArrowDown, { className: "w-3 h-3" })
27656
+ /* @__PURE__ */ jsx85(ArrowUp, { className: "w-3 h-3" }),
27657
+ /* @__PURE__ */ jsx85(ArrowDown, { className: "w-3 h-3" })
26650
27658
  ] }),
26651
27659
  contentClassName: "max-h-72 overflow-y-auto p-1",
26652
27660
  children: [
26653
- /* @__PURE__ */ jsx81(
27661
+ /* @__PURE__ */ jsx85(
26654
27662
  DropdownMenuItem,
26655
27663
  {
26656
27664
  icon: Type2,
@@ -26659,7 +27667,7 @@ var EditorToolbar = ({
26659
27667
  active: !currentLineHeight
26660
27668
  }
26661
27669
  ),
26662
- availableLineHeights.map((option) => /* @__PURE__ */ jsx81(
27670
+ availableLineHeights.map((option) => /* @__PURE__ */ jsx85(
26663
27671
  DropdownMenuItem,
26664
27672
  {
26665
27673
  label: option.label,
@@ -26671,17 +27679,17 @@ var EditorToolbar = ({
26671
27679
  ]
26672
27680
  }
26673
27681
  ),
26674
- /* @__PURE__ */ jsxs67(
27682
+ /* @__PURE__ */ jsxs71(
26675
27683
  DropdownMenu,
26676
27684
  {
26677
- trigger: /* @__PURE__ */ jsxs67(ToolbarButton, { onClick: () => {
27685
+ trigger: /* @__PURE__ */ jsxs71(ToolbarButton, { onClick: () => {
26678
27686
  }, title: t("toolbar.letterSpacing"), className: "gap-0.5", children: [
26679
- /* @__PURE__ */ jsx81(ArrowLeft, { className: "w-3 h-3" }),
26680
- /* @__PURE__ */ jsx81(ArrowRight, { className: "w-3 h-3" })
27687
+ /* @__PURE__ */ jsx85(ArrowLeft, { className: "w-3 h-3" }),
27688
+ /* @__PURE__ */ jsx85(ArrowRight, { className: "w-3 h-3" })
26681
27689
  ] }),
26682
27690
  contentClassName: "max-h-72 overflow-y-auto p-1",
26683
27691
  children: [
26684
- /* @__PURE__ */ jsx81(
27692
+ /* @__PURE__ */ jsx85(
26685
27693
  DropdownMenuItem,
26686
27694
  {
26687
27695
  icon: Type2,
@@ -26690,7 +27698,7 @@ var EditorToolbar = ({
26690
27698
  active: !currentLetterSpacing
26691
27699
  }
26692
27700
  ),
26693
- availableLetterSpacings.map((option) => /* @__PURE__ */ jsx81(
27701
+ availableLetterSpacings.map((option) => /* @__PURE__ */ jsx85(
26694
27702
  DropdownMenuItem,
26695
27703
  {
26696
27704
  label: option.label,
@@ -26702,44 +27710,44 @@ var EditorToolbar = ({
26702
27710
  ]
26703
27711
  }
26704
27712
  ),
26705
- /* @__PURE__ */ jsx81(ToolbarDivider, {}),
26706
- /* @__PURE__ */ jsx81(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ jsx81(BoldIcon, { className: "w-4 h-4" }) }),
26707
- /* @__PURE__ */ jsx81(ToolbarButton, { onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic"), title: t("toolbar.italic"), children: /* @__PURE__ */ jsx81(ItalicIcon, { className: "w-4 h-4" }) }),
26708
- /* @__PURE__ */ jsx81(
27713
+ /* @__PURE__ */ jsx85(ToolbarDivider, {}),
27714
+ /* @__PURE__ */ jsx85(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ jsx85(BoldIcon, { className: "w-4 h-4" }) }),
27715
+ /* @__PURE__ */ jsx85(ToolbarButton, { onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic"), title: t("toolbar.italic"), children: /* @__PURE__ */ jsx85(ItalicIcon, { className: "w-4 h-4" }) }),
27716
+ /* @__PURE__ */ jsx85(
26709
27717
  ToolbarButton,
26710
27718
  {
26711
27719
  onClick: () => editor.chain().focus().toggleUnderline().run(),
26712
27720
  active: editor.isActive("underline"),
26713
27721
  title: t("toolbar.underline"),
26714
- children: /* @__PURE__ */ jsx81(UnderlineIcon, { className: "w-4 h-4" })
27722
+ children: /* @__PURE__ */ jsx85(UnderlineIcon, { className: "w-4 h-4" })
26715
27723
  }
26716
27724
  ),
26717
- /* @__PURE__ */ jsx81(ToolbarButton, { onClick: () => editor.chain().focus().toggleStrike().run(), active: editor.isActive("strike"), title: t("toolbar.strike"), children: /* @__PURE__ */ jsx81(StrikethroughIcon, { className: "w-4 h-4" }) }),
26718
- /* @__PURE__ */ jsx81(ToolbarButton, { onClick: () => editor.chain().focus().toggleCode().run(), active: editor.isActive("code"), title: t("toolbar.code"), children: /* @__PURE__ */ jsx81(CodeIcon, { className: "w-4 h-4" }) }),
26719
- /* @__PURE__ */ jsx81(
27725
+ /* @__PURE__ */ jsx85(ToolbarButton, { onClick: () => editor.chain().focus().toggleStrike().run(), active: editor.isActive("strike"), title: t("toolbar.strike"), children: /* @__PURE__ */ jsx85(StrikethroughIcon, { className: "w-4 h-4" }) }),
27726
+ /* @__PURE__ */ jsx85(ToolbarButton, { onClick: () => editor.chain().focus().toggleCode().run(), active: editor.isActive("code"), title: t("toolbar.code"), children: /* @__PURE__ */ jsx85(CodeIcon, { className: "w-4 h-4" }) }),
27727
+ /* @__PURE__ */ jsx85(
26720
27728
  ToolbarButton,
26721
27729
  {
26722
27730
  onClick: () => editor.chain().focus().toggleSubscript().run(),
26723
27731
  active: editor.isActive("subscript"),
26724
27732
  title: t("toolbar.subscript"),
26725
- children: /* @__PURE__ */ jsx81(SubscriptIcon, { className: "w-4 h-4" })
27733
+ children: /* @__PURE__ */ jsx85(SubscriptIcon, { className: "w-4 h-4" })
26726
27734
  }
26727
27735
  ),
26728
- /* @__PURE__ */ jsx81(
27736
+ /* @__PURE__ */ jsx85(
26729
27737
  ToolbarButton,
26730
27738
  {
26731
27739
  onClick: () => editor.chain().focus().toggleSuperscript().run(),
26732
27740
  active: editor.isActive("superscript"),
26733
27741
  title: t("toolbar.superscript"),
26734
- children: /* @__PURE__ */ jsx81(SuperscriptIcon, { className: "w-4 h-4" })
27742
+ children: /* @__PURE__ */ jsx85(SuperscriptIcon, { className: "w-4 h-4" })
26735
27743
  }
26736
27744
  ),
26737
- /* @__PURE__ */ jsx81(
27745
+ /* @__PURE__ */ jsx85(
26738
27746
  DropdownMenu,
26739
27747
  {
26740
27748
  contentClassName: "min-w-72",
26741
- trigger: /* @__PURE__ */ jsx81(ToolbarButton, { onClick: () => setShowLinkInput(!editor.isActive("link")), active: editor.isActive("link"), title: t("toolbar.link"), children: /* @__PURE__ */ jsx81(LinkIcon, { className: "w-4 h-4" }) }),
26742
- children: showLinkInput ? /* @__PURE__ */ jsx81(
27749
+ trigger: /* @__PURE__ */ jsx85(ToolbarButton, { onClick: () => setShowLinkInput(!editor.isActive("link")), active: editor.isActive("link"), title: t("toolbar.link"), children: /* @__PURE__ */ jsx85(LinkIcon, { className: "w-4 h-4" }) }),
27750
+ children: showLinkInput ? /* @__PURE__ */ jsx85(
26743
27751
  LinkInput,
26744
27752
  {
26745
27753
  initialUrl: String(editor.getAttributes("link").href ?? ""),
@@ -26749,9 +27757,9 @@ var EditorToolbar = ({
26749
27757
  },
26750
27758
  onCancel: () => setShowLinkInput(false)
26751
27759
  }
26752
- ) : /* @__PURE__ */ jsxs67(Fragment27, { children: [
26753
- /* @__PURE__ */ jsx81(DropdownMenuItem, { icon: LinkIcon, label: t("toolbar.link"), onClick: () => setShowLinkInput(true), active: editor.isActive("link") }),
26754
- /* @__PURE__ */ jsx81(
27760
+ ) : /* @__PURE__ */ jsxs71(Fragment28, { children: [
27761
+ /* @__PURE__ */ jsx85(DropdownMenuItem, { icon: LinkIcon, label: t("toolbar.link"), onClick: () => setShowLinkInput(true), active: editor.isActive("link") }),
27762
+ /* @__PURE__ */ jsx85(
26755
27763
  DropdownMenuItem,
26756
27764
  {
26757
27765
  icon: Trash22,
@@ -26764,16 +27772,16 @@ var EditorToolbar = ({
26764
27772
  ] })
26765
27773
  }
26766
27774
  ),
26767
- /* @__PURE__ */ jsx81(ToolbarDivider, {}),
26768
- /* @__PURE__ */ jsx81(
27775
+ /* @__PURE__ */ jsx85(ToolbarDivider, {}),
27776
+ /* @__PURE__ */ jsx85(
26769
27777
  DropdownMenu,
26770
27778
  {
26771
- trigger: /* @__PURE__ */ jsxs67(ToolbarButton, { onClick: () => {
27779
+ trigger: /* @__PURE__ */ jsxs71(ToolbarButton, { onClick: () => {
26772
27780
  }, title: t("colors.textColor"), children: [
26773
- /* @__PURE__ */ jsx81(TextColorIcon, { color: currentTextColor }),
26774
- /* @__PURE__ */ jsx81(ChevronDown7, { className: "w-3 h-3" })
27781
+ /* @__PURE__ */ jsx85(TextColorIcon, { color: currentTextColor }),
27782
+ /* @__PURE__ */ jsx85(ChevronDown8, { className: "w-3 h-3" })
26775
27783
  ] }),
26776
- children: /* @__PURE__ */ jsx81(
27784
+ children: /* @__PURE__ */ jsx85(
26777
27785
  EditorColorPalette,
26778
27786
  {
26779
27787
  colors: textColors,
@@ -26790,15 +27798,15 @@ var EditorToolbar = ({
26790
27798
  )
26791
27799
  }
26792
27800
  ),
26793
- /* @__PURE__ */ jsx81(
27801
+ /* @__PURE__ */ jsx85(
26794
27802
  DropdownMenu,
26795
27803
  {
26796
- trigger: /* @__PURE__ */ jsxs67(ToolbarButton, { onClick: () => {
27804
+ trigger: /* @__PURE__ */ jsxs71(ToolbarButton, { onClick: () => {
26797
27805
  }, active: editor.isActive("highlight"), title: t("colors.highlight"), children: [
26798
- /* @__PURE__ */ jsx81(HighlightColorIcon, { color: currentHighlightColor }),
26799
- /* @__PURE__ */ jsx81(ChevronDown7, { className: "w-3 h-3" })
27806
+ /* @__PURE__ */ jsx85(HighlightColorIcon, { color: currentHighlightColor }),
27807
+ /* @__PURE__ */ jsx85(ChevronDown8, { className: "w-3 h-3" })
26800
27808
  ] }),
26801
- children: /* @__PURE__ */ jsx81(
27809
+ children: /* @__PURE__ */ jsx85(
26802
27810
  EditorColorPalette,
26803
27811
  {
26804
27812
  colors: highlightColors,
@@ -26815,14 +27823,14 @@ var EditorToolbar = ({
26815
27823
  )
26816
27824
  }
26817
27825
  ),
26818
- /* @__PURE__ */ jsx81(ToolbarDivider, {}),
26819
- /* @__PURE__ */ jsx81(
27826
+ /* @__PURE__ */ jsx85(ToolbarDivider, {}),
27827
+ /* @__PURE__ */ jsx85(
26820
27828
  DropdownMenu,
26821
27829
  {
26822
27830
  contentClassName: "p-0 overflow-hidden",
26823
- trigger: /* @__PURE__ */ jsx81(ToolbarButton, { onClick: () => {
26824
- }, title: t("toolbar.emoji"), children: /* @__PURE__ */ jsx81(Smile3, { className: "w-4 h-4" }) }),
26825
- children: /* @__PURE__ */ jsx81(
27831
+ trigger: /* @__PURE__ */ jsx85(ToolbarButton, { onClick: () => {
27832
+ }, title: t("toolbar.emoji"), children: /* @__PURE__ */ jsx85(Smile3, { className: "w-4 h-4" }) }),
27833
+ children: /* @__PURE__ */ jsx85(
26826
27834
  EmojiPicker2,
26827
27835
  {
26828
27836
  onSelect: (emoji) => {
@@ -26832,17 +27840,17 @@ var EditorToolbar = ({
26832
27840
  )
26833
27841
  }
26834
27842
  ),
26835
- /* @__PURE__ */ jsx81(ToolbarDivider, {}),
26836
- /* @__PURE__ */ jsxs67(
27843
+ /* @__PURE__ */ jsx85(ToolbarDivider, {}),
27844
+ /* @__PURE__ */ jsxs71(
26837
27845
  DropdownMenu,
26838
27846
  {
26839
- trigger: /* @__PURE__ */ jsxs67(ToolbarButton, { onClick: () => {
27847
+ trigger: /* @__PURE__ */ jsxs71(ToolbarButton, { onClick: () => {
26840
27848
  }, title: t("toolbar.alignment"), children: [
26841
- /* @__PURE__ */ jsx81(AlignLeft, { className: "w-4 h-4" }),
26842
- /* @__PURE__ */ jsx81(ChevronDown7, { className: "w-3 h-3" })
27849
+ /* @__PURE__ */ jsx85(AlignLeft, { className: "w-4 h-4" }),
27850
+ /* @__PURE__ */ jsx85(ChevronDown8, { className: "w-3 h-3" })
26843
27851
  ] }),
26844
27852
  children: [
26845
- /* @__PURE__ */ jsx81(
27853
+ /* @__PURE__ */ jsx85(
26846
27854
  DropdownMenuItem,
26847
27855
  {
26848
27856
  icon: AlignLeft,
@@ -26851,7 +27859,7 @@ var EditorToolbar = ({
26851
27859
  active: editor.isActive({ textAlign: "left" })
26852
27860
  }
26853
27861
  ),
26854
- /* @__PURE__ */ jsx81(
27862
+ /* @__PURE__ */ jsx85(
26855
27863
  DropdownMenuItem,
26856
27864
  {
26857
27865
  icon: AlignCenter,
@@ -26860,7 +27868,7 @@ var EditorToolbar = ({
26860
27868
  active: editor.isActive({ textAlign: "center" })
26861
27869
  }
26862
27870
  ),
26863
- /* @__PURE__ */ jsx81(
27871
+ /* @__PURE__ */ jsx85(
26864
27872
  DropdownMenuItem,
26865
27873
  {
26866
27874
  icon: AlignRight,
@@ -26869,7 +27877,7 @@ var EditorToolbar = ({
26869
27877
  active: editor.isActive({ textAlign: "right" })
26870
27878
  }
26871
27879
  ),
26872
- /* @__PURE__ */ jsx81(
27880
+ /* @__PURE__ */ jsx85(
26873
27881
  DropdownMenuItem,
26874
27882
  {
26875
27883
  icon: AlignJustify,
@@ -26881,17 +27889,17 @@ var EditorToolbar = ({
26881
27889
  ]
26882
27890
  }
26883
27891
  ),
26884
- /* @__PURE__ */ jsx81(ToolbarDivider, {}),
26885
- /* @__PURE__ */ jsxs67(
27892
+ /* @__PURE__ */ jsx85(ToolbarDivider, {}),
27893
+ /* @__PURE__ */ jsxs71(
26886
27894
  DropdownMenu,
26887
27895
  {
26888
- trigger: /* @__PURE__ */ jsxs67(ToolbarButton, { onClick: () => {
27896
+ trigger: /* @__PURE__ */ jsxs71(ToolbarButton, { onClick: () => {
26889
27897
  }, title: t("toolbar.bulletList"), children: [
26890
- /* @__PURE__ */ jsx81(ListIcon, { className: "w-4 h-4" }),
26891
- /* @__PURE__ */ jsx81(ChevronDown7, { className: "w-3 h-3" })
27898
+ /* @__PURE__ */ jsx85(ListIcon, { className: "w-4 h-4" }),
27899
+ /* @__PURE__ */ jsx85(ChevronDown8, { className: "w-3 h-3" })
26892
27900
  ] }),
26893
27901
  children: [
26894
- /* @__PURE__ */ jsx81(
27902
+ /* @__PURE__ */ jsx85(
26895
27903
  DropdownMenuItem,
26896
27904
  {
26897
27905
  icon: ListIcon,
@@ -26901,7 +27909,7 @@ var EditorToolbar = ({
26901
27909
  shortcut: "Ctrl+Shift+8"
26902
27910
  }
26903
27911
  ),
26904
- /* @__PURE__ */ jsx81(
27912
+ /* @__PURE__ */ jsx85(
26905
27913
  DropdownMenuItem,
26906
27914
  {
26907
27915
  icon: ListOrderedIcon,
@@ -26911,7 +27919,7 @@ var EditorToolbar = ({
26911
27919
  shortcut: "Ctrl+Shift+7"
26912
27920
  }
26913
27921
  ),
26914
- /* @__PURE__ */ jsx81(
27922
+ /* @__PURE__ */ jsx85(
26915
27923
  DropdownMenuItem,
26916
27924
  {
26917
27925
  icon: ListTodo2,
@@ -26924,16 +27932,16 @@ var EditorToolbar = ({
26924
27932
  ]
26925
27933
  }
26926
27934
  ),
26927
- /* @__PURE__ */ jsxs67(
27935
+ /* @__PURE__ */ jsxs71(
26928
27936
  DropdownMenu,
26929
27937
  {
26930
- trigger: /* @__PURE__ */ jsxs67(ToolbarButton, { onClick: () => {
27938
+ trigger: /* @__PURE__ */ jsxs71(ToolbarButton, { onClick: () => {
26931
27939
  }, title: t("toolbar.quote"), children: [
26932
- /* @__PURE__ */ jsx81(QuoteIcon, { className: "w-4 h-4" }),
26933
- /* @__PURE__ */ jsx81(ChevronDown7, { className: "w-3 h-3" })
27940
+ /* @__PURE__ */ jsx85(QuoteIcon, { className: "w-4 h-4" }),
27941
+ /* @__PURE__ */ jsx85(ChevronDown8, { className: "w-3 h-3" })
26934
27942
  ] }),
26935
27943
  children: [
26936
- /* @__PURE__ */ jsx81(
27944
+ /* @__PURE__ */ jsx85(
26937
27945
  DropdownMenuItem,
26938
27946
  {
26939
27947
  icon: QuoteIcon,
@@ -26943,7 +27951,7 @@ var EditorToolbar = ({
26943
27951
  shortcut: "Ctrl+Shift+B"
26944
27952
  }
26945
27953
  ),
26946
- /* @__PURE__ */ jsx81(
27954
+ /* @__PURE__ */ jsx85(
26947
27955
  DropdownMenuItem,
26948
27956
  {
26949
27957
  icon: FileCode3,
@@ -26956,15 +27964,15 @@ var EditorToolbar = ({
26956
27964
  ]
26957
27965
  }
26958
27966
  ),
26959
- /* @__PURE__ */ jsx81(
27967
+ /* @__PURE__ */ jsx85(
26960
27968
  DropdownMenu,
26961
27969
  {
26962
- trigger: /* @__PURE__ */ jsxs67(ToolbarButton, { onClick: () => {
27970
+ trigger: /* @__PURE__ */ jsxs71(ToolbarButton, { onClick: () => {
26963
27971
  }, title: t("toolbar.image"), children: [
26964
- /* @__PURE__ */ jsx81(ImageIcon2, { className: "w-4 h-4" }),
26965
- /* @__PURE__ */ jsx81(ChevronDown7, { className: "w-3 h-3" })
27972
+ /* @__PURE__ */ jsx85(ImageIcon2, { className: "w-4 h-4" }),
27973
+ /* @__PURE__ */ jsx85(ChevronDown8, { className: "w-3 h-3" })
26966
27974
  ] }),
26967
- children: showImageInput ? /* @__PURE__ */ jsx81(
27975
+ children: showImageInput ? /* @__PURE__ */ jsx85(
26968
27976
  ImageInput,
26969
27977
  {
26970
27978
  onSubmit: (url, alt) => {
@@ -26973,9 +27981,9 @@ var EditorToolbar = ({
26973
27981
  },
26974
27982
  onCancel: () => setShowImageInput(false)
26975
27983
  }
26976
- ) : /* @__PURE__ */ jsxs67(Fragment27, { children: [
26977
- /* @__PURE__ */ jsx81(DropdownMenuItem, { icon: LinkIcon, label: t("imageInput.addFromUrl"), onClick: () => setShowImageInput(true) }),
26978
- /* @__PURE__ */ jsx81(
27984
+ ) : /* @__PURE__ */ jsxs71(Fragment28, { children: [
27985
+ /* @__PURE__ */ jsx85(DropdownMenuItem, { icon: LinkIcon, label: t("imageInput.addFromUrl"), onClick: () => setShowImageInput(true) }),
27986
+ /* @__PURE__ */ jsx85(
26979
27987
  DropdownMenuItem,
26980
27988
  {
26981
27989
  icon: Upload3,
@@ -26984,8 +27992,8 @@ var EditorToolbar = ({
26984
27992
  onClick: () => fileInputRef.current?.click()
26985
27993
  }
26986
27994
  ),
26987
- imageUploadError && /* @__PURE__ */ jsx81(DropdownMenuItem, { label: imageUploadError, disabled: true, destructive: true }),
26988
- /* @__PURE__ */ jsx81(
27995
+ imageUploadError && /* @__PURE__ */ jsx85(DropdownMenuItem, { label: imageUploadError, disabled: true, destructive: true }),
27996
+ /* @__PURE__ */ jsx85(
26989
27997
  "input",
26990
27998
  {
26991
27999
  ref: fileInputRef,
@@ -27000,8 +28008,8 @@ var EditorToolbar = ({
27000
28008
  }
27001
28009
  }
27002
28010
  ),
27003
- /* @__PURE__ */ jsx81("div", { className: "my-1 border-t" }),
27004
- /* @__PURE__ */ jsx81(
28011
+ /* @__PURE__ */ jsx85("div", { className: "my-1 border-t" }),
28012
+ /* @__PURE__ */ jsx85(
27005
28013
  DropdownMenuItem,
27006
28014
  {
27007
28015
  icon: AlignCenter,
@@ -27011,7 +28019,7 @@ var EditorToolbar = ({
27011
28019
  disabled: !isImageSelected
27012
28020
  }
27013
28021
  ),
27014
- /* @__PURE__ */ jsx81(
28022
+ /* @__PURE__ */ jsx85(
27015
28023
  DropdownMenuItem,
27016
28024
  {
27017
28025
  icon: AlignLeft,
@@ -27021,7 +28029,7 @@ var EditorToolbar = ({
27021
28029
  disabled: !isImageSelected
27022
28030
  }
27023
28031
  ),
27024
- /* @__PURE__ */ jsx81(
28032
+ /* @__PURE__ */ jsx85(
27025
28033
  DropdownMenuItem,
27026
28034
  {
27027
28035
  icon: AlignRight,
@@ -27031,8 +28039,8 @@ var EditorToolbar = ({
27031
28039
  disabled: !isImageSelected
27032
28040
  }
27033
28041
  ),
27034
- /* @__PURE__ */ jsx81("div", { className: "my-1 border-t" }),
27035
- /* @__PURE__ */ jsx81(
28042
+ /* @__PURE__ */ jsx85("div", { className: "my-1 border-t" }),
28043
+ /* @__PURE__ */ jsx85(
27036
28044
  DropdownMenuItem,
27037
28045
  {
27038
28046
  label: t("toolbar.imageWidthSm"),
@@ -27041,7 +28049,7 @@ var EditorToolbar = ({
27041
28049
  disabled: !isImageSelected
27042
28050
  }
27043
28051
  ),
27044
- /* @__PURE__ */ jsx81(
28052
+ /* @__PURE__ */ jsx85(
27045
28053
  DropdownMenuItem,
27046
28054
  {
27047
28055
  label: t("toolbar.imageWidthMd"),
@@ -27050,7 +28058,7 @@ var EditorToolbar = ({
27050
28058
  disabled: !isImageSelected
27051
28059
  }
27052
28060
  ),
27053
- /* @__PURE__ */ jsx81(
28061
+ /* @__PURE__ */ jsx85(
27054
28062
  DropdownMenuItem,
27055
28063
  {
27056
28064
  label: t("toolbar.imageWidthLg"),
@@ -27059,8 +28067,8 @@ var EditorToolbar = ({
27059
28067
  disabled: !isImageSelected
27060
28068
  }
27061
28069
  ),
27062
- /* @__PURE__ */ jsx81("div", { className: "my-1 border-t" }),
27063
- /* @__PURE__ */ jsx81(
28070
+ /* @__PURE__ */ jsx85("div", { className: "my-1 border-t" }),
28071
+ /* @__PURE__ */ jsx85(
27064
28072
  DropdownMenuItem,
27065
28073
  {
27066
28074
  icon: RotateCcw2,
@@ -27069,7 +28077,7 @@ var EditorToolbar = ({
27069
28077
  disabled: !isImageSelected
27070
28078
  }
27071
28079
  ),
27072
- /* @__PURE__ */ jsx81(
28080
+ /* @__PURE__ */ jsx85(
27073
28081
  DropdownMenuItem,
27074
28082
  {
27075
28083
  icon: Trash22,
@@ -27082,7 +28090,7 @@ var EditorToolbar = ({
27082
28090
  ] })
27083
28091
  }
27084
28092
  ),
27085
- /* @__PURE__ */ jsxs67(
28093
+ /* @__PURE__ */ jsxs71(
27086
28094
  DropdownMenu,
27087
28095
  {
27088
28096
  isOpen: isTableMenuOpen,
@@ -27090,14 +28098,14 @@ var EditorToolbar = ({
27090
28098
  setIsTableMenuOpen(open);
27091
28099
  tableCommandAnchorPosRef.current = open ? getTableAnchorPos(editor) : null;
27092
28100
  },
27093
- trigger: /* @__PURE__ */ jsxs67(ToolbarButton, { onClick: () => {
28101
+ trigger: /* @__PURE__ */ jsxs71(ToolbarButton, { onClick: () => {
27094
28102
  }, title: t("toolbar.table"), children: [
27095
- /* @__PURE__ */ jsx81(TableIcon, { className: "w-4 h-4" }),
27096
- /* @__PURE__ */ jsx81(ChevronDown7, { className: "w-3 h-3" })
28103
+ /* @__PURE__ */ jsx85(TableIcon, { className: "w-4 h-4" }),
28104
+ /* @__PURE__ */ jsx85(ChevronDown8, { className: "w-3 h-3" })
27097
28105
  ] }),
27098
28106
  contentClassName: "p-2 min-w-56",
27099
28107
  children: [
27100
- /* @__PURE__ */ jsx81(
28108
+ /* @__PURE__ */ jsx85(
27101
28109
  TableInsertGrid,
27102
28110
  {
27103
28111
  insertLabel: t("tableMenu.insertTable"),
@@ -27108,8 +28116,8 @@ var EditorToolbar = ({
27108
28116
  }
27109
28117
  }
27110
28118
  ),
27111
- /* @__PURE__ */ jsx81("div", { className: "my-1 border-t" }),
27112
- /* @__PURE__ */ jsx81(
28119
+ /* @__PURE__ */ jsx85("div", { className: "my-1 border-t" }),
28120
+ /* @__PURE__ */ jsx85(
27113
28121
  DropdownMenuItem,
27114
28122
  {
27115
28123
  icon: AlignLeft,
@@ -27119,7 +28127,7 @@ var EditorToolbar = ({
27119
28127
  disabled: !hasTableContext
27120
28128
  }
27121
28129
  ),
27122
- /* @__PURE__ */ jsx81(
28130
+ /* @__PURE__ */ jsx85(
27123
28131
  DropdownMenuItem,
27124
28132
  {
27125
28133
  icon: AlignCenter,
@@ -27129,7 +28137,7 @@ var EditorToolbar = ({
27129
28137
  disabled: !hasTableContext
27130
28138
  }
27131
28139
  ),
27132
- /* @__PURE__ */ jsx81(
28140
+ /* @__PURE__ */ jsx85(
27133
28141
  DropdownMenuItem,
27134
28142
  {
27135
28143
  icon: AlignRight,
@@ -27139,8 +28147,8 @@ var EditorToolbar = ({
27139
28147
  disabled: !hasTableContext
27140
28148
  }
27141
28149
  ),
27142
- /* @__PURE__ */ jsx81("div", { className: "my-1 border-t" }),
27143
- /* @__PURE__ */ jsx81(
28150
+ /* @__PURE__ */ jsx85("div", { className: "my-1 border-t" }),
28151
+ /* @__PURE__ */ jsx85(
27144
28152
  DropdownMenuItem,
27145
28153
  {
27146
28154
  icon: ArrowLeft,
@@ -27149,7 +28157,7 @@ var EditorToolbar = ({
27149
28157
  disabled: !hasTableContext || !editor.can().addColumnBefore()
27150
28158
  }
27151
28159
  ),
27152
- /* @__PURE__ */ jsx81(
28160
+ /* @__PURE__ */ jsx85(
27153
28161
  DropdownMenuItem,
27154
28162
  {
27155
28163
  icon: ArrowDown,
@@ -27158,7 +28166,7 @@ var EditorToolbar = ({
27158
28166
  disabled: !hasTableContext || !editor.can().addColumnAfter()
27159
28167
  }
27160
28168
  ),
27161
- /* @__PURE__ */ jsx81(
28169
+ /* @__PURE__ */ jsx85(
27162
28170
  DropdownMenuItem,
27163
28171
  {
27164
28172
  icon: ArrowUp,
@@ -27167,7 +28175,7 @@ var EditorToolbar = ({
27167
28175
  disabled: !hasTableContext || !editor.can().addRowBefore()
27168
28176
  }
27169
28177
  ),
27170
- /* @__PURE__ */ jsx81(
28178
+ /* @__PURE__ */ jsx85(
27171
28179
  DropdownMenuItem,
27172
28180
  {
27173
28181
  icon: ArrowRight,
@@ -27176,8 +28184,8 @@ var EditorToolbar = ({
27176
28184
  disabled: !hasTableContext || !editor.can().addRowAfter()
27177
28185
  }
27178
28186
  ),
27179
- /* @__PURE__ */ jsx81("div", { className: "my-1 border-t" }),
27180
- /* @__PURE__ */ jsx81(
28187
+ /* @__PURE__ */ jsx85("div", { className: "my-1 border-t" }),
28188
+ /* @__PURE__ */ jsx85(
27181
28189
  DropdownMenuItem,
27182
28190
  {
27183
28191
  icon: TableIcon,
@@ -27186,7 +28194,7 @@ var EditorToolbar = ({
27186
28194
  disabled: !hasTableContext || !editor.can().toggleHeaderRow()
27187
28195
  }
27188
28196
  ),
27189
- /* @__PURE__ */ jsx81(
28197
+ /* @__PURE__ */ jsx85(
27190
28198
  DropdownMenuItem,
27191
28199
  {
27192
28200
  icon: TableIcon,
@@ -27195,8 +28203,8 @@ var EditorToolbar = ({
27195
28203
  disabled: !hasTableContext || !editor.can().toggleHeaderColumn()
27196
28204
  }
27197
28205
  ),
27198
- /* @__PURE__ */ jsx81("div", { className: "my-1 border-t" }),
27199
- /* @__PURE__ */ jsx81(
28206
+ /* @__PURE__ */ jsx85("div", { className: "my-1 border-t" }),
28207
+ /* @__PURE__ */ jsx85(
27200
28208
  DropdownMenuItem,
27201
28209
  {
27202
28210
  icon: Trash22,
@@ -27205,7 +28213,7 @@ var EditorToolbar = ({
27205
28213
  disabled: !hasTableContext || !editor.can().deleteColumn()
27206
28214
  }
27207
28215
  ),
27208
- /* @__PURE__ */ jsx81(
28216
+ /* @__PURE__ */ jsx85(
27209
28217
  DropdownMenuItem,
27210
28218
  {
27211
28219
  icon: Trash22,
@@ -27214,7 +28222,7 @@ var EditorToolbar = ({
27214
28222
  disabled: !hasTableContext || !editor.can().deleteRow()
27215
28223
  }
27216
28224
  ),
27217
- /* @__PURE__ */ jsx81(
28225
+ /* @__PURE__ */ jsx85(
27218
28226
  DropdownMenuItem,
27219
28227
  {
27220
28228
  icon: Trash22,
@@ -27226,14 +28234,14 @@ var EditorToolbar = ({
27226
28234
  ]
27227
28235
  }
27228
28236
  ),
27229
- /* @__PURE__ */ jsx81(ToolbarDivider, {}),
27230
- /* @__PURE__ */ jsx81(ToolbarButton, { onClick: () => editor.chain().focus().undo().run(), disabled: !editor.can().undo(), title: t("toolbar.undo"), children: /* @__PURE__ */ jsx81(UndoIcon, { className: "w-4 h-4" }) }),
27231
- /* @__PURE__ */ jsx81(ToolbarButton, { onClick: () => editor.chain().focus().redo().run(), disabled: !editor.can().redo(), title: t("toolbar.redo"), children: /* @__PURE__ */ jsx81(RedoIcon, { className: "w-4 h-4" }) })
28237
+ /* @__PURE__ */ jsx85(ToolbarDivider, {}),
28238
+ /* @__PURE__ */ jsx85(ToolbarButton, { onClick: () => editor.chain().focus().undo().run(), disabled: !editor.can().undo(), title: t("toolbar.undo"), children: /* @__PURE__ */ jsx85(UndoIcon, { className: "w-4 h-4" }) }),
28239
+ /* @__PURE__ */ jsx85(ToolbarButton, { onClick: () => editor.chain().focus().redo().run(), disabled: !editor.can().redo(), title: t("toolbar.redo"), children: /* @__PURE__ */ jsx85(RedoIcon, { className: "w-4 h-4" }) })
27232
28240
  ] });
27233
28241
  };
27234
28242
 
27235
28243
  // src/components/UEditor/menus.tsx
27236
- import { useCallback as useCallback22, useEffect as useEffect34, useMemo as useMemo23, useRef as useRef32, useState as useState45 } from "react";
28244
+ import { useCallback as useCallback22, useEffect as useEffect36, useMemo as useMemo23, useRef as useRef33, useState as useState48 } from "react";
27237
28245
  import { useEditorState as useEditorState2 } from "@tiptap/react";
27238
28246
  import { isInTable as isSelectionInTable, setCellAttr } from "@tiptap/pm/tables";
27239
28247
  import { createPortal as createPortal8 } from "react-dom";
@@ -27242,7 +28250,7 @@ import {
27242
28250
  AlignLeft as AlignLeft2,
27243
28251
  AlignRight as AlignRight2,
27244
28252
  Bold as BoldIcon2,
27245
- ChevronDown as ChevronDown8,
28253
+ ChevronDown as ChevronDown9,
27246
28254
  Code as CodeIcon2,
27247
28255
  Italic as ItalicIcon2,
27248
28256
  Link as LinkIcon2,
@@ -27254,7 +28262,10 @@ import {
27254
28262
  Trash2 as Trash23,
27255
28263
  Type as Type3,
27256
28264
  Underline as UnderlineIcon2,
27257
- Strikethrough as StrikethroughIcon2
28265
+ Strikethrough as StrikethroughIcon2,
28266
+ Edit2,
28267
+ Unlink,
28268
+ ExternalLink as ExternalLink3
27258
28269
  } from "lucide-react";
27259
28270
 
27260
28271
  // src/components/UEditor/table-cell-commands.ts
@@ -27481,13 +28492,13 @@ function expandTableFromCell(editor, activeCellPos, rows, columns) {
27481
28492
  }
27482
28493
 
27483
28494
  // src/components/UEditor/menus.tsx
27484
- import { Fragment as Fragment28, jsx as jsx82, jsxs as jsxs68 } from "react/jsx-runtime";
28495
+ import { Fragment as Fragment29, jsx as jsx86, jsxs as jsxs72 } from "react/jsx-runtime";
27485
28496
  var FloatingSlashCommandMenu = ({ editor, onClose }) => {
27486
28497
  const t = useSmartTranslations("UEditor");
27487
28498
  const messages = useMemo23(() => buildSlashCommandMessages(t), [t]);
27488
28499
  const items = useMemo23(() => buildSlashCommandItems({ query: "", messages }), [messages]);
27489
- const listRef = useRef32(null);
27490
- useEffect34(() => {
28500
+ const listRef = useRef33(null);
28501
+ useEffect36(() => {
27491
28502
  const handleKeyDown2 = (event) => {
27492
28503
  if (event.key === "Escape") {
27493
28504
  event.preventDefault();
@@ -27502,7 +28513,7 @@ var FloatingSlashCommandMenu = ({ editor, onClose }) => {
27502
28513
  document.addEventListener("keydown", handleKeyDown2);
27503
28514
  return () => document.removeEventListener("keydown", handleKeyDown2);
27504
28515
  }, [onClose]);
27505
- return /* @__PURE__ */ jsx82(
28516
+ return /* @__PURE__ */ jsx86(
27506
28517
  SlashCommandList,
27507
28518
  {
27508
28519
  ref: listRef,
@@ -27517,19 +28528,19 @@ var FloatingSlashCommandMenu = ({ editor, onClose }) => {
27517
28528
  };
27518
28529
  var FloatingMenuContent = ({ editor }) => {
27519
28530
  const t = useSmartTranslations("UEditor");
27520
- const [showCommands, setShowCommands] = useState45(false);
28531
+ const [showCommands, setShowCommands] = useState48(false);
27521
28532
  if (showCommands) {
27522
- return /* @__PURE__ */ jsx82(FloatingSlashCommandMenu, { editor, onClose: () => setShowCommands(false) });
28533
+ return /* @__PURE__ */ jsx86(FloatingSlashCommandMenu, { editor, onClose: () => setShowCommands(false) });
27523
28534
  }
27524
- return /* @__PURE__ */ jsxs68(
28535
+ return /* @__PURE__ */ jsxs72(
27525
28536
  "button",
27526
28537
  {
27527
28538
  type: "button",
27528
28539
  onClick: () => setShowCommands(true),
27529
28540
  className: "flex items-center gap-1 px-2 py-1.5 rounded-lg hover:bg-accent transition-all group",
27530
28541
  children: [
27531
- /* @__PURE__ */ jsx82(Plus3, { className: "w-4 h-4 text-muted-foreground group-hover:text-foreground" }),
27532
- /* @__PURE__ */ jsx82("span", { className: "text-sm text-muted-foreground group-hover:text-foreground", children: t("floatingMenu.addBlock") })
28542
+ /* @__PURE__ */ jsx86(Plus3, { className: "w-4 h-4 text-muted-foreground group-hover:text-foreground" }),
28543
+ /* @__PURE__ */ jsx86("span", { className: "text-sm text-muted-foreground group-hover:text-foreground", children: t("floatingMenu.addBlock") })
27533
28544
  ]
27534
28545
  }
27535
28546
  );
@@ -27548,7 +28559,8 @@ var BubbleMenuContent = ({
27548
28559
  editor,
27549
28560
  onKeepOpenChange,
27550
28561
  fontSizes,
27551
- lineHeights
28562
+ lineHeights,
28563
+ initialShowLinkInput = false
27552
28564
  }) => {
27553
28565
  const t = useSmartTranslations("UEditor");
27554
28566
  useEditorState2({
@@ -27556,11 +28568,14 @@ var BubbleMenuContent = ({
27556
28568
  selector: ({ transactionNumber }) => transactionNumber
27557
28569
  });
27558
28570
  const { textColors, highlightColors } = useEditorColors();
27559
- const [showLinkInput, setShowLinkInput] = useState45(false);
27560
- const [activeColorPalette, setActiveColorPalette] = useState45(null);
27561
- const [showTypographyPanel, setShowTypographyPanel] = useState45(false);
27562
- const [showFontSizeOptions, setShowFontSizeOptions] = useState45(false);
27563
- const [fontSizeDraft, setFontSizeDraft] = useState45("");
28571
+ const [showLinkInput, setShowLinkInput] = useState48(initialShowLinkInput);
28572
+ const [activeColorPalette, setActiveColorPalette] = useState48(null);
28573
+ useEffect36(() => {
28574
+ setShowLinkInput(initialShowLinkInput);
28575
+ }, [initialShowLinkInput]);
28576
+ const [showTypographyPanel, setShowTypographyPanel] = useState48(false);
28577
+ const [showFontSizeOptions, setShowFontSizeOptions] = useState48(false);
28578
+ const [fontSizeDraft, setFontSizeDraft] = useState48("");
27564
28579
  const isImageSelected = editor.isActive("image");
27565
28580
  const imageAttrs = editor.getAttributes("image");
27566
28581
  const imageLayout = imageAttrs.imageLayout === "left" || imageAttrs.imageLayout === "right" ? imageAttrs.imageLayout : "block";
@@ -27582,7 +28597,7 @@ var BubbleMenuContent = ({
27582
28597
  () => (lineHeights ?? getDefaultLineHeights()).filter((option) => ["1.2", "1.5", "1.75"].includes(option.value)),
27583
28598
  [lineHeights]
27584
28599
  );
27585
- useEffect34(() => {
28600
+ useEffect36(() => {
27586
28601
  setFontSizeDraft(currentFontSize.replace(/px$/i, ""));
27587
28602
  }, [currentFontSize]);
27588
28603
  const applyFontSizeDraft = () => {
@@ -27597,10 +28612,10 @@ var BubbleMenuContent = ({
27597
28612
  editor.chain().focus().setFontSize(`${clamped}px`).run();
27598
28613
  setFontSizeDraft(String(clamped));
27599
28614
  };
27600
- useEffect34(() => {
28615
+ useEffect36(() => {
27601
28616
  onKeepOpenChange?.(showLinkInput);
27602
28617
  }, [onKeepOpenChange, showLinkInput]);
27603
- useEffect34(() => {
28618
+ useEffect36(() => {
27604
28619
  if (!showLinkInput) return;
27605
28620
  const close2 = () => setShowLinkInput(false);
27606
28621
  editor.on("selectionUpdate", close2);
@@ -27611,7 +28626,7 @@ var BubbleMenuContent = ({
27611
28626
  };
27612
28627
  }, [editor, showLinkInput]);
27613
28628
  if (showLinkInput) {
27614
- return /* @__PURE__ */ jsx82(
28629
+ return /* @__PURE__ */ jsx86(
27615
28630
  LinkInput,
27616
28631
  {
27617
28632
  initialUrl: editor.getAttributes("link").href || "",
@@ -27630,7 +28645,115 @@ var BubbleMenuContent = ({
27630
28645
  if (activeColorPalette) {
27631
28646
  const isTextPalette = activeColorPalette === "text";
27632
28647
  const isHighlightPalette = activeColorPalette === "highlight";
27633
- return /* @__PURE__ */ jsx82("div", { className: "w-56", children: /* @__PURE__ */ jsx82(
28648
+ if (activeColorPalette === "cell-border") {
28649
+ const currentBorderStyle = editor.getAttributes("tableCell").borderStyle || editor.getAttributes("tableHeader").borderStyle || "solid";
28650
+ const currentBorderWidth = editor.getAttributes("tableCell").borderWidth || editor.getAttributes("tableHeader").borderWidth || "1px";
28651
+ const currentBorderColor = editor.getAttributes("tableCell").borderColor || editor.getAttributes("tableHeader").borderColor || "currentColor";
28652
+ return /* @__PURE__ */ jsxs72("div", { className: "flex flex-col gap-2 p-2 w-56 text-sm", children: [
28653
+ /* @__PURE__ */ jsx86("div", { className: "font-semibold text-xs text-muted-foreground uppercase tracking-wider mb-1", children: t("tableMenu.cellBorder") || "Cell Borders" }),
28654
+ /* @__PURE__ */ jsxs72("div", { className: "flex flex-col gap-1", children: [
28655
+ /* @__PURE__ */ jsx86("label", { className: "text-xs text-muted-foreground", children: t("tableMenu.borderStyle") || "Border Style" }),
28656
+ /* @__PURE__ */ jsxs72(
28657
+ "select",
28658
+ {
28659
+ className: "flex h-8 w-full rounded-md border border-input bg-background px-2 py-1 text-xs ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
28660
+ value: currentBorderStyle,
28661
+ onChange: (e) => {
28662
+ const style = e.target.value;
28663
+ editor.chain().focus().setCellAttribute("borderStyle", style).run();
28664
+ },
28665
+ children: [
28666
+ /* @__PURE__ */ jsx86("option", { value: "solid", children: "Solid" }),
28667
+ /* @__PURE__ */ jsx86("option", { value: "dashed", children: "Dashed" }),
28668
+ /* @__PURE__ */ jsx86("option", { value: "dotted", children: "Dotted" }),
28669
+ /* @__PURE__ */ jsx86("option", { value: "double", children: "Double" }),
28670
+ /* @__PURE__ */ jsx86("option", { value: "none", children: "None" })
28671
+ ]
28672
+ }
28673
+ )
28674
+ ] }),
28675
+ /* @__PURE__ */ jsxs72("div", { className: "flex flex-col gap-1", children: [
28676
+ /* @__PURE__ */ jsx86("label", { className: "text-xs text-muted-foreground", children: t("tableMenu.borderWidth") || "Border Width" }),
28677
+ /* @__PURE__ */ jsxs72(
28678
+ "select",
28679
+ {
28680
+ className: "flex h-8 w-full rounded-md border border-input bg-background px-2 py-1 text-xs ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
28681
+ value: currentBorderWidth,
28682
+ onChange: (e) => {
28683
+ const width = e.target.value;
28684
+ editor.chain().focus().setCellAttribute("borderWidth", width).run();
28685
+ },
28686
+ children: [
28687
+ /* @__PURE__ */ jsx86("option", { value: "1px", children: "1px" }),
28688
+ /* @__PURE__ */ jsx86("option", { value: "2px", children: "2px" }),
28689
+ /* @__PURE__ */ jsx86("option", { value: "3px", children: "3px" }),
28690
+ /* @__PURE__ */ jsx86("option", { value: "4px", children: "4px" })
28691
+ ]
28692
+ }
28693
+ )
28694
+ ] }),
28695
+ /* @__PURE__ */ jsxs72(
28696
+ "button",
28697
+ {
28698
+ type: "button",
28699
+ onClick: () => setActiveColorPalette("cell-border-color"),
28700
+ className: "flex items-center justify-between w-full h-8 px-2 rounded-md border border-input hover:bg-accent text-xs",
28701
+ children: [
28702
+ /* @__PURE__ */ jsx86("span", { children: t("tableMenu.borderColor") || "Border Color" }),
28703
+ /* @__PURE__ */ jsx86(
28704
+ "span",
28705
+ {
28706
+ className: "w-4 h-4 rounded-full border border-border",
28707
+ style: {
28708
+ backgroundColor: currentBorderColor
28709
+ }
28710
+ }
28711
+ )
28712
+ ]
28713
+ }
28714
+ ),
28715
+ /* @__PURE__ */ jsxs72("div", { className: "flex items-center justify-between gap-2 mt-2 pt-2 border-t border-border", children: [
28716
+ /* @__PURE__ */ jsx86(
28717
+ "button",
28718
+ {
28719
+ type: "button",
28720
+ onClick: () => {
28721
+ editor.chain().focus().setCellAttribute("borderColor", null).setCellAttribute("borderStyle", null).setCellAttribute("borderWidth", null).run();
28722
+ setActiveColorPalette(null);
28723
+ },
28724
+ className: "text-xs text-destructive hover:underline",
28725
+ children: t("tableMenu.clearBorder") || "Clear Border"
28726
+ }
28727
+ ),
28728
+ /* @__PURE__ */ jsx86(
28729
+ "button",
28730
+ {
28731
+ type: "button",
28732
+ onClick: () => setActiveColorPalette(null),
28733
+ className: "text-xs font-medium text-primary hover:underline",
28734
+ children: t("tableMenu.done") || "Done"
28735
+ }
28736
+ )
28737
+ ] })
28738
+ ] });
28739
+ }
28740
+ if (activeColorPalette === "cell-border-color") {
28741
+ const currentBorderColor = normalizeStyleValue(editor.getAttributes("tableCell").borderColor || editor.getAttributes("tableHeader").borderColor) || "";
28742
+ return /* @__PURE__ */ jsx86("div", { className: "w-56", children: /* @__PURE__ */ jsx86(
28743
+ EditorColorPalette,
28744
+ {
28745
+ colors: highlightColors,
28746
+ currentColor: currentBorderColor,
28747
+ onSelect: (color) => {
28748
+ const value = color || null;
28749
+ editor.chain().focus().setCellAttribute("borderColor", value).run();
28750
+ setActiveColorPalette("cell-border");
28751
+ },
28752
+ label: t("tableMenu.borderColor") || "Border Color"
28753
+ }
28754
+ ) });
28755
+ }
28756
+ return /* @__PURE__ */ jsx86("div", { className: "w-56", children: /* @__PURE__ */ jsx86(
27634
28757
  EditorColorPalette,
27635
28758
  {
27636
28759
  colors: isTextPalette ? textColors : highlightColors,
@@ -27658,32 +28781,32 @@ var BubbleMenuContent = ({
27658
28781
  ) });
27659
28782
  }
27660
28783
  if (isImageSelected) {
27661
- return /* @__PURE__ */ jsxs68("div", { className: "flex items-center gap-0.5 p-1", children: [
27662
- /* @__PURE__ */ jsx82(ToolbarButton, { onClick: () => applyImageLayout(editor, "block"), active: imageLayout === "block", title: t("toolbar.imageLayoutBlock"), children: /* @__PURE__ */ jsx82(AlignCenter2, { className: "w-4 h-4" }) }),
27663
- /* @__PURE__ */ jsx82(ToolbarButton, { onClick: () => applyImageLayout(editor, "left"), active: imageLayout === "left", title: t("toolbar.imageLayoutLeft"), children: /* @__PURE__ */ jsx82(AlignLeft2, { className: "w-4 h-4" }) }),
27664
- /* @__PURE__ */ jsx82(ToolbarButton, { onClick: () => applyImageLayout(editor, "right"), active: imageLayout === "right", title: t("toolbar.imageLayoutRight"), children: /* @__PURE__ */ jsx82(AlignRight2, { className: "w-4 h-4" }) }),
27665
- /* @__PURE__ */ jsx82("div", { className: "w-px h-6 bg-border/50 mx-1" }),
27666
- /* @__PURE__ */ jsx82(ToolbarButton, { onClick: () => applyImageWidthPreset(editor, "sm"), active: imageWidthPreset === "sm", title: t("toolbar.imageWidthSm"), children: /* @__PURE__ */ jsx82("span", { className: "text-[10px] font-semibold", children: "S" }) }),
27667
- /* @__PURE__ */ jsx82(ToolbarButton, { onClick: () => applyImageWidthPreset(editor, "md"), active: imageWidthPreset === "md", title: t("toolbar.imageWidthMd"), children: /* @__PURE__ */ jsx82("span", { className: "text-[10px] font-semibold", children: "M" }) }),
27668
- /* @__PURE__ */ jsx82(ToolbarButton, { onClick: () => applyImageWidthPreset(editor, "lg"), active: imageWidthPreset === "lg", title: t("toolbar.imageWidthLg"), children: /* @__PURE__ */ jsx82("span", { className: "text-[10px] font-semibold", children: "L" }) }),
27669
- /* @__PURE__ */ jsx82("div", { className: "w-px h-6 bg-border/50 mx-1" }),
27670
- /* @__PURE__ */ jsx82(ToolbarButton, { onClick: () => resetImageSize(editor), title: t("toolbar.imageResetSize"), children: /* @__PURE__ */ jsx82(RotateCcw3, { className: "w-4 h-4" }) }),
27671
- /* @__PURE__ */ jsx82(
28784
+ return /* @__PURE__ */ jsxs72("div", { className: "flex items-center gap-0.5 p-1", children: [
28785
+ /* @__PURE__ */ jsx86(ToolbarButton, { onClick: () => applyImageLayout(editor, "block"), active: imageLayout === "block", title: t("toolbar.imageLayoutBlock"), children: /* @__PURE__ */ jsx86(AlignCenter2, { className: "w-4 h-4" }) }),
28786
+ /* @__PURE__ */ jsx86(ToolbarButton, { onClick: () => applyImageLayout(editor, "left"), active: imageLayout === "left", title: t("toolbar.imageLayoutLeft"), children: /* @__PURE__ */ jsx86(AlignLeft2, { className: "w-4 h-4" }) }),
28787
+ /* @__PURE__ */ jsx86(ToolbarButton, { onClick: () => applyImageLayout(editor, "right"), active: imageLayout === "right", title: t("toolbar.imageLayoutRight"), children: /* @__PURE__ */ jsx86(AlignRight2, { className: "w-4 h-4" }) }),
28788
+ /* @__PURE__ */ jsx86("div", { className: "w-px h-6 bg-border/50 mx-1" }),
28789
+ /* @__PURE__ */ jsx86(ToolbarButton, { onClick: () => applyImageWidthPreset(editor, "sm"), active: imageWidthPreset === "sm", title: t("toolbar.imageWidthSm"), children: /* @__PURE__ */ jsx86("span", { className: "text-[10px] font-semibold", children: "S" }) }),
28790
+ /* @__PURE__ */ jsx86(ToolbarButton, { onClick: () => applyImageWidthPreset(editor, "md"), active: imageWidthPreset === "md", title: t("toolbar.imageWidthMd"), children: /* @__PURE__ */ jsx86("span", { className: "text-[10px] font-semibold", children: "M" }) }),
28791
+ /* @__PURE__ */ jsx86(ToolbarButton, { onClick: () => applyImageWidthPreset(editor, "lg"), active: imageWidthPreset === "lg", title: t("toolbar.imageWidthLg"), children: /* @__PURE__ */ jsx86("span", { className: "text-[10px] font-semibold", children: "L" }) }),
28792
+ /* @__PURE__ */ jsx86("div", { className: "w-px h-6 bg-border/50 mx-1" }),
28793
+ /* @__PURE__ */ jsx86(ToolbarButton, { onClick: () => resetImageSize(editor), title: t("toolbar.imageResetSize"), children: /* @__PURE__ */ jsx86(RotateCcw3, { className: "w-4 h-4" }) }),
28794
+ /* @__PURE__ */ jsx86(
27672
28795
  ToolbarButton,
27673
28796
  {
27674
28797
  onClick: () => deleteSelectedImage(editor),
27675
28798
  title: t("toolbar.imageDelete"),
27676
28799
  className: "text-destructive hover:text-destructive",
27677
- children: /* @__PURE__ */ jsx82(Trash23, { className: "w-4 h-4" })
28800
+ children: /* @__PURE__ */ jsx86(Trash23, { className: "w-4 h-4" })
27678
28801
  }
27679
28802
  )
27680
28803
  ] });
27681
28804
  }
27682
28805
  if (showTypographyPanel) {
27683
- return /* @__PURE__ */ jsxs68("div", { className: "w-72 p-2", children: [
27684
- /* @__PURE__ */ jsxs68("div", { className: "mb-2 flex items-center justify-between gap-2", children: [
27685
- /* @__PURE__ */ jsx82("span", { className: "px-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: t("toolbar.textStyle") }),
27686
- /* @__PURE__ */ jsx82(
28806
+ return /* @__PURE__ */ jsxs72("div", { className: "w-72 p-2", children: [
28807
+ /* @__PURE__ */ jsxs72("div", { className: "mb-2 flex items-center justify-between gap-2", children: [
28808
+ /* @__PURE__ */ jsx86("span", { className: "px-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: t("toolbar.textStyle") }),
28809
+ /* @__PURE__ */ jsx86(
27687
28810
  "button",
27688
28811
  {
27689
28812
  type: "button",
@@ -27693,11 +28816,11 @@ var BubbleMenuContent = ({
27693
28816
  }
27694
28817
  )
27695
28818
  ] }),
27696
- /* @__PURE__ */ jsxs68("div", { className: "space-y-2", children: [
27697
- /* @__PURE__ */ jsxs68("div", { children: [
27698
- /* @__PURE__ */ jsx82("div", { className: "mb-1 px-1 text-[11px] font-medium text-muted-foreground", children: t("toolbar.fontSize") }),
27699
- /* @__PURE__ */ jsxs68("div", { className: "flex h-9 items-center overflow-hidden rounded-md border border-border/60 bg-muted/40", children: [
27700
- /* @__PURE__ */ jsx82(
28819
+ /* @__PURE__ */ jsxs72("div", { className: "space-y-2", children: [
28820
+ /* @__PURE__ */ jsxs72("div", { children: [
28821
+ /* @__PURE__ */ jsx86("div", { className: "mb-1 px-1 text-[11px] font-medium text-muted-foreground", children: t("toolbar.fontSize") }),
28822
+ /* @__PURE__ */ jsxs72("div", { className: "flex h-9 items-center overflow-hidden rounded-md border border-border/60 bg-muted/40", children: [
28823
+ /* @__PURE__ */ jsx86(
27701
28824
  "input",
27702
28825
  {
27703
28826
  type: "number",
@@ -27721,8 +28844,8 @@ var BubbleMenuContent = ({
27721
28844
  className: "h-full min-w-0 flex-1 bg-transparent px-2 text-center text-sm font-semibold text-foreground outline-none [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
27722
28845
  }
27723
28846
  ),
27724
- /* @__PURE__ */ jsx82("span", { className: "border-l border-border/50 px-2 text-[11px] text-muted-foreground", children: "px" }),
27725
- /* @__PURE__ */ jsx82(
28847
+ /* @__PURE__ */ jsx86("span", { className: "border-l border-border/50 px-2 text-[11px] text-muted-foreground", children: "px" }),
28848
+ /* @__PURE__ */ jsx86(
27726
28849
  "button",
27727
28850
  {
27728
28851
  type: "button",
@@ -27732,12 +28855,12 @@ var BubbleMenuContent = ({
27732
28855
  "flex h-full w-9 items-center justify-center border-l border-border/50 transition-colors hover:bg-muted",
27733
28856
  showFontSizeOptions && "bg-primary/10 text-primary"
27734
28857
  ),
27735
- children: /* @__PURE__ */ jsx82(ChevronDown8, { className: "h-4 w-4" })
28858
+ children: /* @__PURE__ */ jsx86(ChevronDown9, { className: "h-4 w-4" })
27736
28859
  }
27737
28860
  )
27738
28861
  ] }),
27739
- showFontSizeOptions && /* @__PURE__ */ jsxs68("div", { className: "mt-1 grid grid-cols-4 gap-1", children: [
27740
- /* @__PURE__ */ jsx82(
28862
+ showFontSizeOptions && /* @__PURE__ */ jsxs72("div", { className: "mt-1 grid grid-cols-4 gap-1", children: [
28863
+ /* @__PURE__ */ jsx86(
27741
28864
  "button",
27742
28865
  {
27743
28866
  type: "button",
@@ -27752,7 +28875,7 @@ var BubbleMenuContent = ({
27752
28875
  children: "A"
27753
28876
  }
27754
28877
  ),
27755
- quickFontSizes.map((option) => /* @__PURE__ */ jsx82(
28878
+ quickFontSizes.map((option) => /* @__PURE__ */ jsx86(
27756
28879
  "button",
27757
28880
  {
27758
28881
  type: "button",
@@ -27770,10 +28893,10 @@ var BubbleMenuContent = ({
27770
28893
  ))
27771
28894
  ] })
27772
28895
  ] }),
27773
- /* @__PURE__ */ jsxs68("div", { children: [
27774
- /* @__PURE__ */ jsx82("div", { className: "mb-1 px-1 text-[11px] font-medium text-muted-foreground", children: t("toolbar.lineHeight") }),
27775
- /* @__PURE__ */ jsxs68("div", { className: "grid grid-cols-4 gap-1", children: [
27776
- /* @__PURE__ */ jsx82(
28896
+ /* @__PURE__ */ jsxs72("div", { children: [
28897
+ /* @__PURE__ */ jsx86("div", { className: "mb-1 px-1 text-[11px] font-medium text-muted-foreground", children: t("toolbar.lineHeight") }),
28898
+ /* @__PURE__ */ jsxs72("div", { className: "grid grid-cols-4 gap-1", children: [
28899
+ /* @__PURE__ */ jsx86(
27777
28900
  "button",
27778
28901
  {
27779
28902
  type: "button",
@@ -27785,7 +28908,7 @@ var BubbleMenuContent = ({
27785
28908
  children: "LH"
27786
28909
  }
27787
28910
  ),
27788
- quickLineHeights.map((option) => /* @__PURE__ */ jsx82(
28911
+ quickLineHeights.map((option) => /* @__PURE__ */ jsx86(
27789
28912
  "button",
27790
28913
  {
27791
28914
  type: "button",
@@ -27800,8 +28923,8 @@ var BubbleMenuContent = ({
27800
28923
  ))
27801
28924
  ] })
27802
28925
  ] }),
27803
- /* @__PURE__ */ jsxs68("div", { className: "grid grid-cols-2 gap-1 border-t border-border/40 pt-2", children: [
27804
- /* @__PURE__ */ jsxs68(
28926
+ /* @__PURE__ */ jsxs72("div", { className: "grid grid-cols-2 gap-1 border-t border-border/40 pt-2", children: [
28927
+ /* @__PURE__ */ jsxs72(
27805
28928
  "button",
27806
28929
  {
27807
28930
  type: "button",
@@ -27811,12 +28934,12 @@ var BubbleMenuContent = ({
27811
28934
  editor.isActive("subscript") ? "bg-primary/10 text-primary" : "bg-muted/40 text-foreground"
27812
28935
  ),
27813
28936
  children: [
27814
- /* @__PURE__ */ jsx82(SubscriptIcon2, { className: "h-4 w-4" }),
28937
+ /* @__PURE__ */ jsx86(SubscriptIcon2, { className: "h-4 w-4" }),
27815
28938
  t("toolbar.subscript")
27816
28939
  ]
27817
28940
  }
27818
28941
  ),
27819
- /* @__PURE__ */ jsxs68(
28942
+ /* @__PURE__ */ jsxs72(
27820
28943
  "button",
27821
28944
  {
27822
28945
  type: "button",
@@ -27826,7 +28949,7 @@ var BubbleMenuContent = ({
27826
28949
  editor.isActive("superscript") ? "bg-primary/10 text-primary" : "bg-muted/40 text-foreground"
27827
28950
  ),
27828
28951
  children: [
27829
- /* @__PURE__ */ jsx82(SuperscriptIcon2, { className: "h-4 w-4" }),
28952
+ /* @__PURE__ */ jsx86(SuperscriptIcon2, { className: "h-4 w-4" }),
27830
28953
  t("toolbar.superscript")
27831
28954
  ]
27832
28955
  }
@@ -27835,22 +28958,22 @@ var BubbleMenuContent = ({
27835
28958
  ] })
27836
28959
  ] });
27837
28960
  }
27838
- return /* @__PURE__ */ jsxs68("div", { className: "flex items-center gap-0.5 p-1", children: [
27839
- /* @__PURE__ */ jsx82(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ jsx82(BoldIcon2, { className: "w-4 h-4" }) }),
27840
- /* @__PURE__ */ jsx82(ToolbarButton, { onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic"), title: t("toolbar.italic"), children: /* @__PURE__ */ jsx82(ItalicIcon2, { className: "w-4 h-4" }) }),
27841
- /* @__PURE__ */ jsx82(
28961
+ return /* @__PURE__ */ jsxs72("div", { className: "flex items-center gap-0.5 p-1", children: [
28962
+ /* @__PURE__ */ jsx86(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ jsx86(BoldIcon2, { className: "w-4 h-4" }) }),
28963
+ /* @__PURE__ */ jsx86(ToolbarButton, { onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic"), title: t("toolbar.italic"), children: /* @__PURE__ */ jsx86(ItalicIcon2, { className: "w-4 h-4" }) }),
28964
+ /* @__PURE__ */ jsx86(
27842
28965
  ToolbarButton,
27843
28966
  {
27844
28967
  onClick: () => editor.chain().focus().toggleUnderline().run(),
27845
28968
  active: editor.isActive("underline"),
27846
28969
  title: t("toolbar.underline"),
27847
- children: /* @__PURE__ */ jsx82(UnderlineIcon2, { className: "w-4 h-4" })
28970
+ children: /* @__PURE__ */ jsx86(UnderlineIcon2, { className: "w-4 h-4" })
27848
28971
  }
27849
28972
  ),
27850
- /* @__PURE__ */ jsx82(ToolbarButton, { onClick: () => editor.chain().focus().toggleStrike().run(), active: editor.isActive("strike"), title: t("toolbar.strike"), children: /* @__PURE__ */ jsx82(StrikethroughIcon2, { className: "w-4 h-4" }) }),
27851
- /* @__PURE__ */ jsx82(ToolbarButton, { onClick: () => editor.chain().focus().toggleCode().run(), active: editor.isActive("code"), title: t("toolbar.code"), children: /* @__PURE__ */ jsx82(CodeIcon2, { className: "w-4 h-4" }) }),
27852
- /* @__PURE__ */ jsx82("div", { className: "w-px h-6 bg-border/50 mx-1" }),
27853
- /* @__PURE__ */ jsx82(
28973
+ /* @__PURE__ */ jsx86(ToolbarButton, { onClick: () => editor.chain().focus().toggleStrike().run(), active: editor.isActive("strike"), title: t("toolbar.strike"), children: /* @__PURE__ */ jsx86(StrikethroughIcon2, { className: "w-4 h-4" }) }),
28974
+ /* @__PURE__ */ jsx86(ToolbarButton, { onClick: () => editor.chain().focus().toggleCode().run(), active: editor.isActive("code"), title: t("toolbar.code"), children: /* @__PURE__ */ jsx86(CodeIcon2, { className: "w-4 h-4" }) }),
28975
+ /* @__PURE__ */ jsx86("div", { className: "w-px h-6 bg-border/50 mx-1" }),
28976
+ /* @__PURE__ */ jsx86(
27854
28977
  ToolbarButton,
27855
28978
  {
27856
28979
  onMouseDown: () => {
@@ -27861,22 +28984,38 @@ var BubbleMenuContent = ({
27861
28984
  },
27862
28985
  active: editor.isActive("link"),
27863
28986
  title: t("toolbar.link"),
27864
- children: /* @__PURE__ */ jsx82(LinkIcon2, { className: "w-4 h-4" })
28987
+ children: /* @__PURE__ */ jsx86(LinkIcon2, { className: "w-4 h-4" })
27865
28988
  }
27866
28989
  ),
27867
- /* @__PURE__ */ jsx82(ToolbarButton, { onClick: () => setActiveColorPalette("text"), title: t("colors.textColor"), children: /* @__PURE__ */ jsx82(TextColorIcon, { color: currentTextColor }) }),
27868
- /* @__PURE__ */ jsx82(ToolbarButton, { onClick: () => setActiveColorPalette("highlight"), active: editor.isActive("highlight"), title: t("colors.highlight"), children: /* @__PURE__ */ jsx82(HighlightColorIcon, { color: currentHighlightColor }) }),
27869
- isInTable2 && /* @__PURE__ */ jsxs68(Fragment28, { children: [
27870
- /* @__PURE__ */ jsx82(
28990
+ /* @__PURE__ */ jsx86(ToolbarButton, { onClick: () => setActiveColorPalette("text"), title: t("colors.textColor"), children: /* @__PURE__ */ jsx86(TextColorIcon, { color: currentTextColor }) }),
28991
+ /* @__PURE__ */ jsx86(ToolbarButton, { onClick: () => setActiveColorPalette("highlight"), active: editor.isActive("highlight"), title: t("colors.highlight"), children: /* @__PURE__ */ jsx86(HighlightColorIcon, { color: currentHighlightColor }) }),
28992
+ isInTable2 && /* @__PURE__ */ jsxs72(Fragment29, { children: [
28993
+ /* @__PURE__ */ jsx86(
27871
28994
  ToolbarButton,
27872
28995
  {
27873
28996
  onClick: () => setActiveColorPalette("cell-bg"),
27874
28997
  active: Boolean(currentCellBgColor),
27875
28998
  title: t("tableMenu.cellBackground") || "Cell background",
27876
- children: /* @__PURE__ */ jsx82(CellBgColorIcon, { color: currentCellBgColor })
28999
+ children: /* @__PURE__ */ jsx86(CellBgColorIcon, { color: currentCellBgColor })
29000
+ }
29001
+ ),
29002
+ /* @__PURE__ */ jsx86(
29003
+ ToolbarButton,
29004
+ {
29005
+ onClick: () => setActiveColorPalette("cell-border"),
29006
+ active: Boolean(
29007
+ editor.getAttributes("tableCell").borderColor || editor.getAttributes("tableHeader").borderColor || editor.getAttributes("tableCell").borderStyle || editor.getAttributes("tableHeader").borderStyle || editor.getAttributes("tableCell").borderWidth || editor.getAttributes("tableHeader").borderWidth
29008
+ ),
29009
+ title: t("tableMenu.cellBorder") || "Cell border",
29010
+ children: /* @__PURE__ */ jsx86(
29011
+ CellBorderIcon,
29012
+ {
29013
+ color: editor.getAttributes("tableCell").borderColor || editor.getAttributes("tableHeader").borderColor
29014
+ }
29015
+ )
27877
29016
  }
27878
29017
  ),
27879
- /* @__PURE__ */ jsx82(
29018
+ /* @__PURE__ */ jsx86(
27880
29019
  ToolbarButton,
27881
29020
  {
27882
29021
  onClick: () => {
@@ -27889,21 +29028,38 @@ var BubbleMenuContent = ({
27889
29028
  active: canSplitCell,
27890
29029
  disabled: !canMergeCells && !canSplitCell,
27891
29030
  title: canSplitCell ? t("tableMenu.splitCell") || "Split cell" : t("tableMenu.mergeCells") || "Merge cells",
27892
- children: /* @__PURE__ */ jsx82(TableCellsMerge, { className: "w-4 h-4" })
29031
+ children: /* @__PURE__ */ jsx86(TableCellsMerge, { className: "w-4 h-4" })
27893
29032
  }
27894
29033
  )
27895
29034
  ] }),
27896
- /* @__PURE__ */ jsx82(
29035
+ /* @__PURE__ */ jsx86(
27897
29036
  ToolbarButton,
27898
29037
  {
27899
29038
  onClick: () => setShowTypographyPanel(true),
27900
29039
  active: Boolean(currentFontSize || currentLineHeight || editor.isActive("subscript") || editor.isActive("superscript")),
27901
29040
  title: t("toolbar.textStyle"),
27902
- children: /* @__PURE__ */ jsx82(Type3, { className: "w-4 h-4" })
29041
+ children: /* @__PURE__ */ jsx86(Type3, { className: "w-4 h-4" })
27903
29042
  }
27904
29043
  )
27905
29044
  ] });
27906
29045
  };
29046
+ var LinkPreviewContent = ({ editor, onEdit }) => {
29047
+ const url = editor.getAttributes("link").href || "";
29048
+ const t = useSmartTranslations("UEditor");
29049
+ const handleOpen = () => {
29050
+ window.open(url, "_blank", "noopener,noreferrer");
29051
+ };
29052
+ const handleUnlink = () => {
29053
+ editor.chain().focus().unsetLink().run();
29054
+ };
29055
+ return /* @__PURE__ */ jsxs72("div", { className: "flex items-center gap-1 p-1 max-w-sm", children: [
29056
+ /* @__PURE__ */ jsx86("span", { className: "text-xs text-muted-foreground font-mono px-2 truncate max-w-[180px]", children: url }),
29057
+ /* @__PURE__ */ jsx86("div", { className: "w-px h-6 bg-border/50 mx-1" }),
29058
+ /* @__PURE__ */ jsx86(ToolbarButton, { onClick: handleOpen, title: t("linkPreview.open") || "Open link", children: /* @__PURE__ */ jsx86(ExternalLink3, { className: "w-4 h-4" }) }),
29059
+ /* @__PURE__ */ jsx86(ToolbarButton, { onClick: onEdit, title: t("linkPreview.edit") || "Edit link", children: /* @__PURE__ */ jsx86(Edit2, { className: "w-4 h-4" }) }),
29060
+ /* @__PURE__ */ jsx86(ToolbarButton, { onClick: handleUnlink, title: t("linkPreview.unlink") || "Remove link", className: "text-destructive hover:text-destructive", children: /* @__PURE__ */ jsx86(Unlink, { className: "w-4 h-4" }) })
29061
+ ] });
29062
+ };
27907
29063
  var CustomBubbleMenu = ({
27908
29064
  editor,
27909
29065
  fontSizes,
@@ -27911,16 +29067,16 @@ var CustomBubbleMenu = ({
27911
29067
  }) => {
27912
29068
  const SHOW_DELAY_MS = 180;
27913
29069
  const BUBBLE_MENU_OFFSET = 16;
27914
- const [isVisible, setIsVisible] = useState45(false);
27915
- const [position, setPosition] = useState45({ top: 0, left: 0 });
27916
- const menuRef = useRef32(null);
27917
- const keepOpenRef = useRef32(false);
27918
- const showTimeoutRef = useRef32(null);
29070
+ const [isVisible, setIsVisible] = useState48(false);
29071
+ const [position, setPosition] = useState48({ top: 0, left: 0 });
29072
+ const menuRef = useRef33(null);
29073
+ const keepOpenRef = useRef33(false);
29074
+ const showTimeoutRef = useRef33(null);
27919
29075
  const setKeepOpen = useCallback22((next) => {
27920
29076
  keepOpenRef.current = next;
27921
29077
  if (next) setIsVisible(true);
27922
29078
  }, []);
27923
- useEffect34(() => {
29079
+ useEffect36(() => {
27924
29080
  const clearShowTimeout = () => {
27925
29081
  if (showTimeoutRef.current) {
27926
29082
  clearTimeout(showTimeoutRef.current);
@@ -27930,7 +29086,8 @@ var CustomBubbleMenu = ({
27930
29086
  const updatePosition = () => {
27931
29087
  const { state, view } = editor;
27932
29088
  const { from, to, empty } = state.selection;
27933
- if (!keepOpenRef.current && (empty || !view.hasFocus())) {
29089
+ const isLinkActive = editor.isActive("link");
29090
+ if (!keepOpenRef.current && (empty && !isLinkActive || !view.hasFocus())) {
27934
29091
  clearShowTimeout();
27935
29092
  setIsVisible(false);
27936
29093
  return;
@@ -27969,7 +29126,7 @@ var CustomBubbleMenu = ({
27969
29126
  }, [editor]);
27970
29127
  if (!isVisible) return null;
27971
29128
  return createPortal8(
27972
- /* @__PURE__ */ jsx82(
29129
+ /* @__PURE__ */ jsx86(
27973
29130
  "div",
27974
29131
  {
27975
29132
  ref: menuRef,
@@ -27981,7 +29138,16 @@ var CustomBubbleMenu = ({
27981
29138
  transform: "translate(-50%, -100%)"
27982
29139
  },
27983
29140
  onMouseDown: (e) => e.preventDefault(),
27984
- children: /* @__PURE__ */ jsx82(BubbleMenuContent, { editor, onKeepOpenChange: setKeepOpen, fontSizes, lineHeights })
29141
+ children: editor.isActive("link") && !keepOpenRef.current ? /* @__PURE__ */ jsx86(LinkPreviewContent, { editor, onEdit: () => setKeepOpen(true) }) : /* @__PURE__ */ jsx86(
29142
+ BubbleMenuContent,
29143
+ {
29144
+ editor,
29145
+ onKeepOpenChange: setKeepOpen,
29146
+ fontSizes,
29147
+ lineHeights,
29148
+ initialShowLinkInput: keepOpenRef.current
29149
+ }
29150
+ )
27985
29151
  }
27986
29152
  ),
27987
29153
  document.body
@@ -27989,9 +29155,9 @@ var CustomBubbleMenu = ({
27989
29155
  };
27990
29156
  var CustomFloatingMenu = ({ editor }) => {
27991
29157
  const FLOATING_MENU_OFFSET = 16;
27992
- const [isVisible, setIsVisible] = useState45(false);
27993
- const [position, setPosition] = useState45({ top: 0, left: 0 });
27994
- useEffect34(() => {
29158
+ const [isVisible, setIsVisible] = useState48(false);
29159
+ const [position, setPosition] = useState48({ top: 0, left: 0 });
29160
+ useEffect36(() => {
27995
29161
  const updatePosition = () => {
27996
29162
  const { state, view } = editor;
27997
29163
  const { $from, empty } = state.selection;
@@ -28018,7 +29184,7 @@ var CustomFloatingMenu = ({ editor }) => {
28018
29184
  }, [editor]);
28019
29185
  if (!isVisible) return null;
28020
29186
  return createPortal8(
28021
- /* @__PURE__ */ jsx82(
29187
+ /* @__PURE__ */ jsx86(
28022
29188
  "div",
28023
29189
  {
28024
29190
  "data-popover": true,
@@ -28029,7 +29195,7 @@ var CustomFloatingMenu = ({ editor }) => {
28029
29195
  transform: "translate(-50%, -100%)"
28030
29196
  },
28031
29197
  onMouseDown: (e) => e.preventDefault(),
28032
- children: /* @__PURE__ */ jsx82(FloatingMenuContent, { editor })
29198
+ children: /* @__PURE__ */ jsx86(FloatingMenuContent, { editor })
28033
29199
  }
28034
29200
  ),
28035
29201
  document.body
@@ -28037,25 +29203,25 @@ var CustomFloatingMenu = ({ editor }) => {
28037
29203
  };
28038
29204
 
28039
29205
  // src/components/UEditor/CharacterCount.tsx
28040
- import { jsxs as jsxs69 } from "react/jsx-runtime";
29206
+ import { jsxs as jsxs73 } from "react/jsx-runtime";
28041
29207
  var CharacterCountDisplay = ({ editor, maxCharacters }) => {
28042
29208
  const t = useSmartTranslations("UEditor");
28043
29209
  const storage = editor.storage;
28044
29210
  const characterCount = storage.characterCount?.characters?.() ?? 0;
28045
29211
  const wordCount = storage.characterCount?.words?.() ?? 0;
28046
29212
  const percentage = maxCharacters ? Math.round(characterCount / maxCharacters * 100) : 0;
28047
- return /* @__PURE__ */ jsxs69("div", { className: "flex items-center gap-3 px-3 py-2 text-xs text-muted-foreground border-t bg-muted/20", children: [
28048
- /* @__PURE__ */ jsxs69("span", { children: [
29213
+ return /* @__PURE__ */ jsxs73("div", { className: "flex items-center gap-3 px-3 py-2 text-xs text-muted-foreground border-t bg-muted/20", children: [
29214
+ /* @__PURE__ */ jsxs73("span", { children: [
28049
29215
  wordCount,
28050
29216
  " ",
28051
29217
  t("words")
28052
29218
  ] }),
28053
- /* @__PURE__ */ jsxs69("span", { children: [
29219
+ /* @__PURE__ */ jsxs73("span", { children: [
28054
29220
  characterCount,
28055
29221
  " ",
28056
29222
  t("characters")
28057
29223
  ] }),
28058
- maxCharacters && /* @__PURE__ */ jsxs69("span", { className: cn(percentage > 90 && "text-destructive", percentage > 100 && "font-bold"), children: [
29224
+ maxCharacters && /* @__PURE__ */ jsxs73("span", { className: cn(percentage > 90 && "text-destructive", percentage > 100 && "font-bold"), children: [
28059
29225
  characterCount,
28060
29226
  "/",
28061
29227
  maxCharacters
@@ -28091,6 +29257,9 @@ function parseDataImageUrl(dataUrl) {
28091
29257
  }
28092
29258
  function decodeBase64ToBytes(base64Data) {
28093
29259
  const normalized = base64Data.replace(/\s+/g, "");
29260
+ if (typeof Buffer !== "undefined") {
29261
+ return new Uint8Array(Buffer.from(normalized, "base64"));
29262
+ }
28094
29263
  const binary = atob(normalized);
28095
29264
  const bytes = new Uint8Array(binary.length);
28096
29265
  for (let i = 0; i < binary.length; i += 1) {
@@ -28233,16 +29402,94 @@ var UEditorPrepareContentForSaveError = class extends Error {
28233
29402
  this.result = result;
28234
29403
  }
28235
29404
  };
29405
+ function isDataUrl(value) {
29406
+ return /^data:[^/]+\/[^;]+;base64,/i.test(value.trim());
29407
+ }
29408
+ function parseDataUrl(dataUrl) {
29409
+ const value = dataUrl.trim();
29410
+ if (!/^data:/i.test(value)) return null;
29411
+ const commaIndex = value.indexOf(",");
29412
+ if (commaIndex < 0) return null;
29413
+ const header = value.slice(5, commaIndex);
29414
+ const base64Data = value.slice(commaIndex + 1).trim();
29415
+ if (!/;base64/i.test(header)) return null;
29416
+ const mime = header.split(";")[0]?.trim().toLowerCase();
29417
+ if (!mime || !base64Data) return null;
29418
+ return { mime, base64Data };
29419
+ }
29420
+ function createFileFromDataUrl(dataUrl, name) {
29421
+ const parsed = parseDataUrl(dataUrl);
29422
+ if (!parsed) {
29423
+ throw new Error("Invalid data URL format.");
29424
+ }
29425
+ const bytes = decodeBase64ToBytes(parsed.base64Data);
29426
+ return new File([bytes], name || "attachment.bin", { type: parsed.mime });
29427
+ }
29428
+ function collectFileCardMatches(html) {
29429
+ const matches = [];
29430
+ const tagRegex = /<(div|a)\b[^>]*data-type="file-card"[^>]*>/gi;
29431
+ const hrefAttrRegex = /\bhref\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+))/i;
29432
+ const dataSrcRegex = /\bdata-src\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+))/i;
29433
+ let tagMatch = tagRegex.exec(html);
29434
+ while (tagMatch) {
29435
+ const tag = tagMatch[0];
29436
+ const start = tagMatch.index;
29437
+ const end = start + tag.length;
29438
+ const hrefMatch = hrefAttrRegex.exec(tag);
29439
+ let hrefAttr = null;
29440
+ if (hrefMatch) {
29441
+ const value = hrefMatch[1] ?? hrefMatch[2] ?? hrefMatch[3] ?? "";
29442
+ const quote = hrefMatch[1] !== void 0 ? '"' : hrefMatch[2] !== void 0 ? "'" : "";
29443
+ hrefAttr = {
29444
+ start: hrefMatch.index,
29445
+ end: hrefMatch.index + hrefMatch[0].length,
29446
+ value,
29447
+ quote
29448
+ };
29449
+ }
29450
+ const dataSrcMatch = dataSrcRegex.exec(tag);
29451
+ let dataSrcAttr = null;
29452
+ if (dataSrcMatch) {
29453
+ const value = dataSrcMatch[1] ?? dataSrcMatch[2] ?? dataSrcMatch[3] ?? "";
29454
+ const quote = dataSrcMatch[1] !== void 0 ? '"' : dataSrcMatch[2] !== void 0 ? "'" : "";
29455
+ dataSrcAttr = {
29456
+ start: dataSrcMatch.index,
29457
+ end: dataSrcMatch.index + dataSrcMatch[0].length,
29458
+ value,
29459
+ quote
29460
+ };
29461
+ }
29462
+ matches.push({ start, end, tag, hrefAttr, dataSrcAttr });
29463
+ tagMatch = tagRegex.exec(html);
29464
+ }
29465
+ return matches;
29466
+ }
29467
+ function replaceFileCardAttrs(tag, nextUrl) {
29468
+ let result = tag;
29469
+ const hrefRegex = /(\bhref\s*=\s*)(?:"[^"]*"|'[^']*'|[^\s"'=<>`]+)/i;
29470
+ const dataSrcRegex = /(\bdata-src\s*=\s*)(?:"[^"]*"|'[^']*'|[^\s"'=<>`]+)/i;
29471
+ if (hrefRegex.test(result)) {
29472
+ result = result.replace(hrefRegex, `$1"${nextUrl}"`);
29473
+ }
29474
+ if (dataSrcRegex.test(result)) {
29475
+ result = result.replace(dataSrcRegex, `$1"${nextUrl}"`);
29476
+ }
29477
+ return result;
29478
+ }
28236
29479
  async function prepareUEditorContentForSave({
28237
29480
  html,
28238
29481
  uploadImageForSave,
29482
+ uploadFileForSave,
28239
29483
  uploadConcurrency = 3
28240
29484
  }) {
28241
- if (!html || !html.includes("<img")) {
29485
+ const hasImages = html && html.includes("<img");
29486
+ const hasFileCards = html && html.includes('data-type="file-card"');
29487
+ if (!hasImages && !hasFileCards) {
28242
29488
  return createResult({ html, uploaded: [], inlineUploaded: [], errors: [] });
28243
29489
  }
28244
- const imgMatches = collectImgTagMatches(html);
28245
- if (imgMatches.length === 0) {
29490
+ const imgMatches = hasImages ? collectImgTagMatches(html) : [];
29491
+ const fileCardMatches = hasFileCards ? collectFileCardMatches(html) : [];
29492
+ if (imgMatches.length === 0 && fileCardMatches.length === 0) {
28246
29493
  return createResult({ html, uploaded: [], inlineUploaded: [], errors: [] });
28247
29494
  }
28248
29495
  const base64Candidates = [];
@@ -28257,69 +29504,137 @@ async function prepareUEditorContentForSave({
28257
29504
  src
28258
29505
  });
28259
29506
  }
28260
- if (base64Candidates.length === 0) {
28261
- return createResult({ html, uploaded: [], inlineUploaded: [], errors: [] });
28262
- }
28263
- if (!uploadImageForSave) {
28264
- return createResult({
28265
- html,
28266
- uploaded: [],
28267
- inlineUploaded: [],
28268
- errors: base64Candidates.map((item) => ({
28269
- index: item.index,
28270
- reason: "`uploadImageForSave` is required to transform base64 images before save."
28271
- }))
29507
+ const fileCandidates = [];
29508
+ for (const match of fileCardMatches) {
29509
+ const src = (match.dataSrcAttr?.value || match.hrefAttr?.value || "").trim();
29510
+ if (!src || !isDataUrl(src)) continue;
29511
+ const fileNameRegex = /\bdata-file-name\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+))/i;
29512
+ const fileNameMatch = fileNameRegex.exec(match.tag);
29513
+ const fileName = fileNameMatch ? fileNameMatch[1] ?? fileNameMatch[2] ?? fileNameMatch[3] ?? "attachment.bin" : "attachment.bin";
29514
+ fileCandidates.push({
29515
+ id: `${match.start}:${match.end}`,
29516
+ match,
29517
+ index: fileCandidates.length,
29518
+ src,
29519
+ fileName
28272
29520
  });
28273
29521
  }
29522
+ if (base64Candidates.length === 0 && fileCandidates.length === 0) {
29523
+ return createResult({ html, uploaded: [], inlineUploaded: [], errors: [] });
29524
+ }
28274
29525
  const uploaded = [];
28275
29526
  const inlineUploaded = [];
28276
29527
  const errors = [];
28277
29528
  const replacements = /* @__PURE__ */ new Map();
28278
- const uploadResults = await runWithConcurrency(
28279
- base64Candidates,
28280
- uploadConcurrency,
28281
- async (candidate) => {
28282
- try {
28283
- const file = createFileFromDataImageUrl(candidate.src, candidate.index);
28284
- const uploadResult = await uploadImageForSave(file);
28285
- const normalized = normalizeUploadResult(uploadResult);
28286
- return { candidate, file, ...normalized };
28287
- } catch (error) {
28288
- return { candidate, error: getErrorReason(error) };
29529
+ if (base64Candidates.length > 0) {
29530
+ if (!uploadImageForSave) {
29531
+ for (const item of base64Candidates) {
29532
+ errors.push({
29533
+ index: item.index,
29534
+ reason: "`uploadImageForSave` is required to transform base64 images before save."
29535
+ });
29536
+ }
29537
+ } else {
29538
+ const uploadResults = await runWithConcurrency(
29539
+ base64Candidates,
29540
+ uploadConcurrency,
29541
+ async (candidate) => {
29542
+ try {
29543
+ const file = createFileFromDataImageUrl(candidate.src, candidate.index);
29544
+ const uploadResult = await uploadImageForSave(file);
29545
+ const normalized = normalizeUploadResult(uploadResult);
29546
+ return { candidate, file, ...normalized };
29547
+ } catch (error) {
29548
+ return { candidate, error: getErrorReason(error) };
29549
+ }
29550
+ }
29551
+ );
29552
+ for (const item of uploadResults) {
29553
+ if ("error" in item) {
29554
+ errors.push({
29555
+ index: item.candidate.index,
29556
+ reason: item.error ?? "Unknown upload error."
29557
+ });
29558
+ continue;
29559
+ }
29560
+ replacements.set(item.candidate.id, item.url);
29561
+ uploaded.push({
29562
+ url: item.url,
29563
+ file: item.file,
29564
+ meta: item.meta
29565
+ });
29566
+ inlineUploaded.push({
29567
+ index: item.candidate.index,
29568
+ url: item.url,
29569
+ file: item.file,
29570
+ meta: item.meta
29571
+ });
28289
29572
  }
28290
29573
  }
28291
- );
28292
- for (const item of uploadResults) {
28293
- if ("error" in item) {
28294
- errors.push({
28295
- index: item.candidate.index,
28296
- reason: item.error ?? "Unknown upload error."
28297
- });
28298
- continue;
29574
+ }
29575
+ if (fileCandidates.length > 0) {
29576
+ const uploadFn = uploadFileForSave || uploadImageForSave;
29577
+ if (!uploadFn) {
29578
+ for (const item of fileCandidates) {
29579
+ errors.push({
29580
+ index: base64Candidates.length + item.index,
29581
+ reason: "`uploadFileForSave` or `uploadImageForSave` is required to transform base64 files before save."
29582
+ });
29583
+ }
29584
+ } else {
29585
+ const fileUploadResults = await runWithConcurrency(
29586
+ fileCandidates,
29587
+ uploadConcurrency,
29588
+ async (candidate) => {
29589
+ try {
29590
+ const file = createFileFromDataUrl(candidate.src, candidate.fileName);
29591
+ const uploadResult = await uploadFn(file);
29592
+ const normalized = normalizeUploadResult(uploadResult);
29593
+ return { candidate, file, ...normalized };
29594
+ } catch (error) {
29595
+ return { candidate, error: getErrorReason(error) };
29596
+ }
29597
+ }
29598
+ );
29599
+ for (const item of fileUploadResults) {
29600
+ if ("error" in item) {
29601
+ errors.push({
29602
+ index: base64Candidates.length + item.candidate.index,
29603
+ reason: item.error ?? "Unknown file upload error."
29604
+ });
29605
+ continue;
29606
+ }
29607
+ replacements.set(item.candidate.id, item.url);
29608
+ uploaded.push({
29609
+ url: item.url,
29610
+ file: item.file,
29611
+ meta: item.meta
29612
+ });
29613
+ }
28299
29614
  }
28300
- replacements.set(item.candidate.id, item.url);
28301
- uploaded.push({
28302
- url: item.url,
28303
- file: item.file,
28304
- meta: item.meta
28305
- });
28306
- inlineUploaded.push({
28307
- index: item.candidate.index,
28308
- url: item.url,
28309
- file: item.file,
28310
- meta: item.meta
28311
- });
28312
29615
  }
28313
- if (replacements.size === 0) {
28314
- return createResult({ html, uploaded, inlineUploaded, errors });
29616
+ const allMatches = [];
29617
+ for (const match of imgMatches) {
29618
+ allMatches.push({ type: "img", match });
29619
+ }
29620
+ for (const match of fileCardMatches) {
29621
+ allMatches.push({ type: "file", match });
28315
29622
  }
29623
+ allMatches.sort((a, b) => a.match.start - b.match.start);
28316
29624
  let transformed = "";
28317
29625
  let cursor = 0;
28318
- for (const match of imgMatches) {
29626
+ for (const item of allMatches) {
29627
+ const match = item.match;
28319
29628
  transformed += html.slice(cursor, match.start);
28320
29629
  const replacementKey = `${match.start}:${match.end}`;
28321
29630
  const replacementUrl = replacements.get(replacementKey);
28322
- transformed += replacementUrl ? replaceSrcInTag(match, replacementUrl) : match.tag;
29631
+ if (item.type === "img") {
29632
+ const imgMatch = match;
29633
+ transformed += replacementUrl ? replaceSrcInTag(imgMatch, replacementUrl) : imgMatch.tag;
29634
+ } else {
29635
+ const fileMatch = match;
29636
+ transformed += replacementUrl ? replaceFileCardAttrs(fileMatch.tag, replacementUrl) : fileMatch.tag;
29637
+ }
28323
29638
  cursor = match.end;
28324
29639
  }
28325
29640
  transformed += html.slice(cursor);
@@ -28327,7 +29642,7 @@ async function prepareUEditorContentForSave({
28327
29642
  }
28328
29643
 
28329
29644
  // src/components/UEditor/table-controls.tsx
28330
- import React75 from "react";
29645
+ import React78 from "react";
28331
29646
 
28332
29647
  // node_modules/prosemirror-model/dist/index.js
28333
29648
  function findDiffStart(a, b, pos) {
@@ -28384,7 +29699,7 @@ function findDiffEnd(a, b, posA, posB) {
28384
29699
  posB -= size;
28385
29700
  }
28386
29701
  }
28387
- var Fragment29 = class _Fragment {
29702
+ var Fragment30 = class _Fragment {
28388
29703
  /**
28389
29704
  @internal
28390
29705
  */
@@ -28676,7 +29991,7 @@ var Fragment29 = class _Fragment {
28676
29991
  throw new RangeError("Can not convert " + nodes + " to a Fragment" + (nodes.nodesBetween ? " (looks like multiple versions of prosemirror-model were loaded)" : ""));
28677
29992
  }
28678
29993
  };
28679
- Fragment29.empty = new Fragment29([], 0);
29994
+ Fragment30.empty = new Fragment30([], 0);
28680
29995
  var found = { index: 0, offset: 0 };
28681
29996
  function retIndex(index, offset) {
28682
29997
  found.index = index;
@@ -28901,7 +30216,7 @@ var Slice = class _Slice {
28901
30216
  let openStart = json.openStart || 0, openEnd = json.openEnd || 0;
28902
30217
  if (typeof openStart != "number" || typeof openEnd != "number")
28903
30218
  throw new RangeError("Invalid input for Slice.fromJSON");
28904
- return new _Slice(Fragment29.fromJSON(schema, json.content), openStart, openEnd);
30219
+ return new _Slice(Fragment30.fromJSON(schema, json.content), openStart, openEnd);
28905
30220
  }
28906
30221
  /**
28907
30222
  Create a slice from a fragment by taking the maximum possible
@@ -28916,7 +30231,7 @@ var Slice = class _Slice {
28916
30231
  return new _Slice(fragment, openStart, openEnd);
28917
30232
  }
28918
30233
  };
28919
- Slice.empty = new Slice(Fragment29.empty, 0, 0);
30234
+ Slice.empty = new Slice(Fragment30.empty, 0, 0);
28920
30235
  function removeRange(content, from, to) {
28921
30236
  let { index, offset } = content.findIndex(from), child = content.maybeChild(index);
28922
30237
  let { index: indexTo, offset: offsetTo } = content.findIndex(to);
@@ -29014,7 +30329,7 @@ function replaceThreeWay($from, $start, $end, $to, depth) {
29014
30329
  addNode(close(openEnd, replaceTwoWay($end, $to, depth + 1)), content);
29015
30330
  }
29016
30331
  addRange($to, null, depth, content);
29017
- return new Fragment29(content);
30332
+ return new Fragment30(content);
29018
30333
  }
29019
30334
  function replaceTwoWay($from, $to, depth) {
29020
30335
  let content = [];
@@ -29024,13 +30339,13 @@ function replaceTwoWay($from, $to, depth) {
29024
30339
  addNode(close(type, replaceTwoWay($from, $to, depth + 1)), content);
29025
30340
  }
29026
30341
  addRange($to, null, depth, content);
29027
- return new Fragment29(content);
30342
+ return new Fragment30(content);
29028
30343
  }
29029
30344
  function prepareSliceForReplace(slice, $along) {
29030
30345
  let extra = $along.depth - slice.openStart, parent = $along.node(extra);
29031
30346
  let node = parent.copy(slice.content);
29032
30347
  for (let i = extra - 1; i >= 0; i--)
29033
- node = $along.node(i).copy(Fragment29.from(node));
30348
+ node = $along.node(i).copy(Fragment30.from(node));
29034
30349
  return {
29035
30350
  start: node.resolveNoCache(slice.openStart + extra),
29036
30351
  end: node.resolveNoCache(node.content.size - slice.openEnd - extra)
@@ -29361,7 +30676,7 @@ var NodeRange = class {
29361
30676
  }
29362
30677
  };
29363
30678
  var emptyAttrs = /* @__PURE__ */ Object.create(null);
29364
- var Node2 = class _Node {
30679
+ var Node5 = class _Node {
29365
30680
  /**
29366
30681
  @internal
29367
30682
  */
@@ -29369,7 +30684,7 @@ var Node2 = class _Node {
29369
30684
  this.type = type;
29370
30685
  this.attrs = attrs;
29371
30686
  this.marks = marks;
29372
- this.content = content || Fragment29.empty;
30687
+ this.content = content || Fragment30.empty;
29373
30688
  }
29374
30689
  /**
29375
30690
  The array of this node's child nodes.
@@ -29674,7 +30989,7 @@ var Node2 = class _Node {
29674
30989
  can optionally pass `start` and `end` indices into the
29675
30990
  replacement fragment.
29676
30991
  */
29677
- canReplace(from, to, replacement = Fragment29.empty, start = 0, end = replacement.childCount) {
30992
+ canReplace(from, to, replacement = Fragment30.empty, start = 0, end = replacement.childCount) {
29678
30993
  let one = this.contentMatchAt(from).matchFragment(replacement, start, end);
29679
30994
  let two = one && one.matchFragment(this.content, to);
29680
30995
  if (!two || !two.validEnd)
@@ -29756,13 +31071,13 @@ var Node2 = class _Node {
29756
31071
  throw new RangeError("Invalid text node in JSON");
29757
31072
  return schema.text(json.text, marks);
29758
31073
  }
29759
- let content = Fragment29.fromJSON(schema, json.content);
31074
+ let content = Fragment30.fromJSON(schema, json.content);
29760
31075
  let node = schema.nodeType(json.type).create(json.attrs, content, marks);
29761
31076
  node.type.checkAttrs(node.attrs);
29762
31077
  return node;
29763
31078
  }
29764
31079
  };
29765
- Node2.prototype.text = void 0;
31080
+ Node5.prototype.text = void 0;
29766
31081
  function wrapMarks(marks, str) {
29767
31082
  for (let i = marks.length - 1; i >= 0; i--)
29768
31083
  str = marks[i].type.name + "(" + str + ")";
@@ -29852,7 +31167,7 @@ var ContentMatch = class _ContentMatch {
29852
31167
  function search(match, types) {
29853
31168
  let finished = match.matchFragment(after, startIndex);
29854
31169
  if (finished && (!toEnd || finished.validEnd))
29855
- return Fragment29.from(types.map((tp) => tp.createAndFill()));
31170
+ return Fragment30.from(types.map((tp) => tp.createAndFill()));
29856
31171
  for (let i = 0; i < match.next.length; i++) {
29857
31172
  let { type, next } = match.next[i];
29858
31173
  if (!(type.isText || type.hasRequiredAttrs()) && seen.indexOf(next) == -1) {
@@ -30420,7 +31735,7 @@ function mapFragment(fragment, f, parent) {
30420
31735
  child = f(child, parent, i);
30421
31736
  mapped.push(child);
30422
31737
  }
30423
- return Fragment29.fromArray(mapped);
31738
+ return Fragment30.fromArray(mapped);
30424
31739
  }
30425
31740
  var AddMarkStep = class _AddMarkStep extends Step {
30426
31741
  /**
@@ -30537,7 +31852,7 @@ var AddNodeMarkStep = class _AddNodeMarkStep extends Step {
30537
31852
  if (!node)
30538
31853
  return StepResult.fail("No node at mark step's position");
30539
31854
  let updated = node.type.create(node.attrs, null, this.mark.addToSet(node.marks));
30540
- return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment29.from(updated), 0, node.isLeaf ? 0 : 1));
31855
+ return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment30.from(updated), 0, node.isLeaf ? 0 : 1));
30541
31856
  }
30542
31857
  invert(doc) {
30543
31858
  let node = doc.nodeAt(this.pos);
@@ -30583,7 +31898,7 @@ var RemoveNodeMarkStep = class _RemoveNodeMarkStep extends Step {
30583
31898
  if (!node)
30584
31899
  return StepResult.fail("No node at mark step's position");
30585
31900
  let updated = node.type.create(node.attrs, null, this.mark.removeFromSet(node.marks));
30586
- return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment29.from(updated), 0, node.isLeaf ? 0 : 1));
31901
+ return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment30.from(updated), 0, node.isLeaf ? 0 : 1));
30587
31902
  }
30588
31903
  invert(doc) {
30589
31904
  let node = doc.nodeAt(this.pos);
@@ -30784,7 +32099,7 @@ var AttrStep = class _AttrStep extends Step {
30784
32099
  attrs[name] = node.attrs[name];
30785
32100
  attrs[this.attr] = this.value;
30786
32101
  let updated = node.type.create(attrs, null, node.marks);
30787
- return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment29.from(updated), 0, node.isLeaf ? 0 : 1));
32102
+ return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment30.from(updated), 0, node.isLeaf ? 0 : 1));
30788
32103
  }
30789
32104
  getMap() {
30790
32105
  return StepMap.empty;
@@ -31168,7 +32483,7 @@ var NodeSelection2 = class _NodeSelection extends Selection {
31168
32483
  return new _NodeSelection($pos);
31169
32484
  }
31170
32485
  content() {
31171
- return new Slice(Fragment29.from(this.node), 0, 0);
32486
+ return new Slice(Fragment30.from(this.node), 0, 0);
31172
32487
  }
31173
32488
  eq(other) {
31174
32489
  return other instanceof _NodeSelection && other.anchor == this.anchor;
@@ -31344,7 +32659,7 @@ function createKey(name) {
31344
32659
  keys[name] = 0;
31345
32660
  return name + "$";
31346
32661
  }
31347
- var PluginKey3 = class {
32662
+ var PluginKey4 = class {
31348
32663
  /**
31349
32664
  Create a plugin key.
31350
32665
  */
@@ -31776,7 +33091,7 @@ function tableNodeTypes(schema) {
31776
33091
  }
31777
33092
  return result;
31778
33093
  }
31779
- var tableEditingKey = new PluginKey3("selectingCells");
33094
+ var tableEditingKey = new PluginKey4("selectingCells");
31780
33095
  function cellAround($pos) {
31781
33096
  for (let d = $pos.depth - 1; d > 0; d--) if ($pos.node(d).type.spec.tableRole == "row") return $pos.node(0).resolve($pos.before(d + 1));
31782
33097
  return null;
@@ -31896,10 +33211,10 @@ var CellSelection = class CellSelection2 extends Selection {
31896
33211
  }
31897
33212
  rowContent.push(cell);
31898
33213
  }
31899
- rows.push(table.child(row).copy(Fragment29.from(rowContent)));
33214
+ rows.push(table.child(row).copy(Fragment30.from(rowContent)));
31900
33215
  }
31901
33216
  const fragment = this.isColSelection() && this.isRowSelection() ? table : rows;
31902
- return new Slice(Fragment29.from(fragment), 1, 1);
33217
+ return new Slice(Fragment30.from(fragment), 1, 1);
31903
33218
  }
31904
33219
  replace(tr, content = Slice.empty) {
31905
33220
  const mapFrom = tr.steps.length, ranges = this.ranges;
@@ -31911,7 +33226,7 @@ var CellSelection = class CellSelection2 extends Selection {
31911
33226
  if (sel) tr.setSelection(sel);
31912
33227
  }
31913
33228
  replaceWith(tr, node) {
31914
- this.replace(tr, new Slice(Fragment29.from(node), 0, 0));
33229
+ this.replace(tr, new Slice(Fragment30.from(node), 0, 0));
31915
33230
  }
31916
33231
  forEachCell(f) {
31917
33232
  const table = this.$anchorCell.node(-1);
@@ -32007,7 +33322,7 @@ var CellBookmark = class CellBookmark2 {
32007
33322
  else return Selection.near($headCell, 1);
32008
33323
  }
32009
33324
  };
32010
- var fixTablesKey = new PluginKey3("fix-tables");
33325
+ var fixTablesKey = new PluginKey4("fix-tables");
32011
33326
  function convertTableNodeToArrayOfRows(tableNode) {
32012
33327
  const map = TableMap2.get(tableNode);
32013
33328
  const rows = [];
@@ -32485,7 +33800,7 @@ function atEndOfCell(view, axis, dir) {
32485
33800
  }
32486
33801
  return null;
32487
33802
  }
32488
- var columnResizingPluginKey = new PluginKey3("tableColumnResizing");
33803
+ var columnResizingPluginKey = new PluginKey4("tableColumnResizing");
32489
33804
 
32490
33805
  // src/components/UEditor/table-controls.tsx
32491
33806
  import {
@@ -32496,7 +33811,7 @@ import {
32496
33811
  ArrowLeft as ArrowLeft2,
32497
33812
  ArrowRight as ArrowRight2,
32498
33813
  ArrowUp as ArrowUp2,
32499
- Copy as Copy2,
33814
+ Copy as Copy3,
32500
33815
  Table as TableIcon2,
32501
33816
  Trash2 as Trash24
32502
33817
  } from "lucide-react";
@@ -32556,7 +33871,7 @@ function buildTableHoverState({
32556
33871
  }
32557
33872
 
32558
33873
  // src/components/UEditor/table-drag-preview.tsx
32559
- import { Fragment as Fragment30, jsx as jsx83, jsxs as jsxs70 } from "react/jsx-runtime";
33874
+ import { Fragment as Fragment31, jsx as jsx87, jsxs as jsxs74 } from "react/jsx-runtime";
32560
33875
  function TableDragPreview({
32561
33876
  columnDragLabel,
32562
33877
  dragPreview,
@@ -32567,9 +33882,9 @@ function TableDragPreview({
32567
33882
  const expandPreviewWidth = dragPreview.kind === "add-column" ? layout.tableWidth + dragPreview.previewCols * layout.avgColumnWidth : layout.tableWidth;
32568
33883
  const expandPreviewHeight = dragPreview.kind === "add-row" ? layout.tableHeight + dragPreview.previewRows * layout.avgRowHeight : layout.tableHeight;
32569
33884
  const dragStatusText = dragPreview.kind === "row" ? `${rowDragLabel} ${dragPreview.originIndex + 1} -> ${dragPreview.targetIndex + 1}` : dragPreview.kind === "column" ? `${columnDragLabel} ${dragPreview.originIndex + 1} -> ${dragPreview.targetIndex + 1}` : dragPreview.kind === "add-row" ? `+${dragPreview.previewRows}R` : `+${dragPreview.previewCols}C`;
32570
- return /* @__PURE__ */ jsxs70(Fragment30, { children: [
32571
- dragPreview.kind === "row" && /* @__PURE__ */ jsxs70(Fragment30, { children: [
32572
- /* @__PURE__ */ jsx83(
33885
+ return /* @__PURE__ */ jsxs74(Fragment31, { children: [
33886
+ dragPreview.kind === "row" && /* @__PURE__ */ jsxs74(Fragment31, { children: [
33887
+ /* @__PURE__ */ jsx87(
32573
33888
  "div",
32574
33889
  {
32575
33890
  "aria-hidden": "true",
@@ -32582,7 +33897,7 @@ function TableDragPreview({
32582
33897
  }
32583
33898
  }
32584
33899
  ),
32585
- /* @__PURE__ */ jsx83(
33900
+ /* @__PURE__ */ jsx87(
32586
33901
  "div",
32587
33902
  {
32588
33903
  "aria-hidden": "true",
@@ -32596,8 +33911,8 @@ function TableDragPreview({
32596
33911
  }
32597
33912
  )
32598
33913
  ] }),
32599
- dragPreview.kind === "column" && /* @__PURE__ */ jsxs70(Fragment30, { children: [
32600
- /* @__PURE__ */ jsx83(
33914
+ dragPreview.kind === "column" && /* @__PURE__ */ jsxs74(Fragment31, { children: [
33915
+ /* @__PURE__ */ jsx87(
32601
33916
  "div",
32602
33917
  {
32603
33918
  "aria-hidden": "true",
@@ -32610,7 +33925,7 @@ function TableDragPreview({
32610
33925
  }
32611
33926
  }
32612
33927
  ),
32613
- /* @__PURE__ */ jsx83(
33928
+ /* @__PURE__ */ jsx87(
32614
33929
  "div",
32615
33930
  {
32616
33931
  "aria-hidden": "true",
@@ -32624,7 +33939,7 @@ function TableDragPreview({
32624
33939
  }
32625
33940
  )
32626
33941
  ] }),
32627
- (dragPreview.kind === "add-row" || dragPreview.kind === "add-column") && /* @__PURE__ */ jsx83(
33942
+ (dragPreview.kind === "add-row" || dragPreview.kind === "add-column") && /* @__PURE__ */ jsx87(
32628
33943
  "div",
32629
33944
  {
32630
33945
  "aria-hidden": "true",
@@ -32637,7 +33952,7 @@ function TableDragPreview({
32637
33952
  }
32638
33953
  }
32639
33954
  ),
32640
- /* @__PURE__ */ jsx83(
33955
+ /* @__PURE__ */ jsx87(
32641
33956
  "div",
32642
33957
  {
32643
33958
  role: "status",
@@ -32653,7 +33968,7 @@ function TableDragPreview({
32653
33968
  }
32654
33969
 
32655
33970
  // src/components/UEditor/table-add-rails.tsx
32656
- import { Fragment as Fragment31, jsx as jsx84, jsxs as jsxs71 } from "react/jsx-runtime";
33971
+ import { Fragment as Fragment32, jsx as jsx88, jsxs as jsxs75 } from "react/jsx-runtime";
32657
33972
  var ADD_COLUMN_RAIL_GAP = 4;
32658
33973
  var ADD_ROW_RAIL_GAP = 4;
32659
33974
  function TableAddRails({
@@ -32675,13 +33990,13 @@ function TableAddRails({
32675
33990
  const rowRailLeft = layout.tableLeft;
32676
33991
  const showColumnRail = controlsVisible || addColumnVisible;
32677
33992
  const showRowRail = controlsVisible || addRowVisible;
32678
- return /* @__PURE__ */ jsxs71(Fragment31, { children: [
32679
- /* @__PURE__ */ jsx84(
33993
+ return /* @__PURE__ */ jsxs75(Fragment32, { children: [
33994
+ /* @__PURE__ */ jsx88(
32680
33995
  Tooltip,
32681
33996
  {
32682
33997
  placement: "right",
32683
- content: /* @__PURE__ */ jsx84("span", { className: "text-xs font-medium", children: quickAddColumnLabel }),
32684
- children: /* @__PURE__ */ jsx84(
33998
+ content: /* @__PURE__ */ jsx88("span", { className: "text-xs font-medium", children: quickAddColumnLabel }),
33999
+ children: /* @__PURE__ */ jsx88(
32685
34000
  "button",
32686
34001
  {
32687
34002
  type: "button",
@@ -32708,17 +34023,17 @@ function TableAddRails({
32708
34023
  transform: showColumnRail ? "scale(1)" : "scale(0.92)",
32709
34024
  pointerEvents: showColumnRail ? "auto" : "none"
32710
34025
  },
32711
- children: /* @__PURE__ */ jsx84("span", { className: "text-sm font-medium leading-none", children: "+" })
34026
+ children: /* @__PURE__ */ jsx88("span", { className: "text-sm font-medium leading-none", children: "+" })
32712
34027
  }
32713
34028
  )
32714
34029
  }
32715
34030
  ),
32716
- /* @__PURE__ */ jsx84(
34031
+ /* @__PURE__ */ jsx88(
32717
34032
  Tooltip,
32718
34033
  {
32719
34034
  placement: "bottom",
32720
- content: /* @__PURE__ */ jsx84("span", { className: "text-xs font-medium", children: quickAddRowLabel }),
32721
- children: /* @__PURE__ */ jsx84(
34035
+ content: /* @__PURE__ */ jsx88("span", { className: "text-xs font-medium", children: quickAddRowLabel }),
34036
+ children: /* @__PURE__ */ jsx88(
32722
34037
  "button",
32723
34038
  {
32724
34039
  type: "button",
@@ -32745,7 +34060,7 @@ function TableAddRails({
32745
34060
  transform: showRowRail ? "scale(1)" : "scale(0.92)",
32746
34061
  pointerEvents: showRowRail ? "auto" : "none"
32747
34062
  },
32748
- children: /* @__PURE__ */ jsx84("span", { className: "text-sm font-medium leading-none", children: "+" })
34063
+ children: /* @__PURE__ */ jsx88("span", { className: "text-sm font-medium leading-none", children: "+" })
32749
34064
  }
32750
34065
  )
32751
34066
  }
@@ -32755,7 +34070,7 @@ function TableAddRails({
32755
34070
 
32756
34071
  // src/components/UEditor/table-control-menu.tsx
32757
34072
  import { MoreHorizontal as MoreHorizontal2 } from "lucide-react";
32758
- import { jsx as jsx85 } from "react/jsx-runtime";
34073
+ import { jsx as jsx89 } from "react/jsx-runtime";
32759
34074
  function TableControlMenu({
32760
34075
  controlsVisible,
32761
34076
  isOpen,
@@ -32767,7 +34082,7 @@ function TableControlMenu({
32767
34082
  top
32768
34083
  }) {
32769
34084
  const shown = controlsVisible || menuVisible || isOpen;
32770
- return /* @__PURE__ */ jsx85(
34085
+ return /* @__PURE__ */ jsx89(
32771
34086
  "div",
32772
34087
  {
32773
34088
  className: "absolute z-30",
@@ -32776,13 +34091,13 @@ function TableControlMenu({
32776
34091
  top,
32777
34092
  left
32778
34093
  },
32779
- children: /* @__PURE__ */ jsx85(
34094
+ children: /* @__PURE__ */ jsx89(
32780
34095
  Tooltip,
32781
34096
  {
32782
34097
  placement: "top",
32783
34098
  disabled: isOpen,
32784
- content: /* @__PURE__ */ jsx85("span", { className: "text-xs font-medium", children: label }),
32785
- children: /* @__PURE__ */ jsx85("span", { className: "inline-flex", children: /* @__PURE__ */ jsx85(
34099
+ content: /* @__PURE__ */ jsx89("span", { className: "text-xs font-medium", children: label }),
34100
+ children: /* @__PURE__ */ jsx89("span", { className: "inline-flex", children: /* @__PURE__ */ jsx89(
32786
34101
  DropdownMenu,
32787
34102
  {
32788
34103
  placement: "bottom-start",
@@ -32790,7 +34105,7 @@ function TableControlMenu({
32790
34105
  onOpenChange,
32791
34106
  contentClassName: "p-2",
32792
34107
  items,
32793
- trigger: /* @__PURE__ */ jsx85(
34108
+ trigger: /* @__PURE__ */ jsx89(
32794
34109
  "button",
32795
34110
  {
32796
34111
  type: "button",
@@ -32806,7 +34121,7 @@ function TableControlMenu({
32806
34121
  transform: shown ? "scale(1)" : "scale(0.82)",
32807
34122
  pointerEvents: shown ? "auto" : "none"
32808
34123
  },
32809
- children: /* @__PURE__ */ jsx85(MoreHorizontal2, { className: "h-4 w-4" })
34124
+ children: /* @__PURE__ */ jsx89(MoreHorizontal2, { className: "h-4 w-4" })
32810
34125
  }
32811
34126
  )
32812
34127
  }
@@ -32819,7 +34134,7 @@ function TableControlMenu({
32819
34134
 
32820
34135
  // src/components/UEditor/table-axis-handles.tsx
32821
34136
  import { GripHorizontal, GripVertical as GripVertical3 } from "lucide-react";
32822
- import { Fragment as Fragment32, jsx as jsx86 } from "react/jsx-runtime";
34137
+ import { Fragment as Fragment33, jsx as jsx90 } from "react/jsx-runtime";
32823
34138
  var IDLE_HANDLE_SCALE = "0.78";
32824
34139
  function TableRowHandles({
32825
34140
  activeRowIndex,
@@ -32833,12 +34148,12 @@ function TableRowHandles({
32833
34148
  rowHandleLeft,
32834
34149
  rowHandles
32835
34150
  }) {
32836
- return /* @__PURE__ */ jsx86(Fragment32, { children: rowHandles.map((rowHandle) => {
34151
+ return /* @__PURE__ */ jsx90(Fragment33, { children: rowHandles.map((rowHandle) => {
32837
34152
  const menuKey = `row:${rowHandle.index}`;
32838
34153
  const isActive = rowHandle.index === activeRowIndex;
32839
34154
  const visible = controlsVisible || hoverRowHandleIndex === rowHandle.index || openMenuKey === menuKey;
32840
34155
  const isShown = visible || isActive;
32841
- return /* @__PURE__ */ jsx86(
34156
+ return /* @__PURE__ */ jsx90(
32842
34157
  "div",
32843
34158
  {
32844
34159
  className: "absolute z-30",
@@ -32847,13 +34162,13 @@ function TableRowHandles({
32847
34162
  top: Math.max(8, rowHandle.center - 12),
32848
34163
  left: rowHandleLeft
32849
34164
  },
32850
- children: /* @__PURE__ */ jsx86(
34165
+ children: /* @__PURE__ */ jsx90(
32851
34166
  Tooltip,
32852
34167
  {
32853
34168
  placement: "right",
32854
34169
  disabled: openMenuKey === menuKey || !visible && isActive,
32855
- content: /* @__PURE__ */ jsx86("span", { className: "text-xs font-medium", children: `${rowDragLabel} ${rowHandle.index + 1}` }),
32856
- children: /* @__PURE__ */ jsx86("span", { className: "inline-flex", children: /* @__PURE__ */ jsx86(
34170
+ content: /* @__PURE__ */ jsx90("span", { className: "text-xs font-medium", children: `${rowDragLabel} ${rowHandle.index + 1}` }),
34171
+ children: /* @__PURE__ */ jsx90("span", { className: "inline-flex", children: /* @__PURE__ */ jsx90(
32857
34172
  DropdownMenu,
32858
34173
  {
32859
34174
  placement: "right",
@@ -32861,7 +34176,7 @@ function TableRowHandles({
32861
34176
  onOpenChange: (open) => onOpenMenuChange(menuKey, open),
32862
34177
  contentClassName: "p-2",
32863
34178
  items: getMenuItems(rowHandle),
32864
- trigger: /* @__PURE__ */ jsx86(
34179
+ trigger: /* @__PURE__ */ jsx90(
32865
34180
  "button",
32866
34181
  {
32867
34182
  type: "button",
@@ -32880,7 +34195,7 @@ function TableRowHandles({
32880
34195
  transform: isShown ? "scale(1)" : `scale(${IDLE_HANDLE_SCALE})`,
32881
34196
  pointerEvents: isShown ? "auto" : "none"
32882
34197
  },
32883
- children: visible ? /* @__PURE__ */ jsx86(GripVertical3, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx86("div", { className: "h-3 w-1 rounded-full bg-muted-foreground/50 hover:bg-muted-foreground" })
34198
+ children: visible ? /* @__PURE__ */ jsx90(GripVertical3, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx90("div", { className: "h-3 w-1 rounded-full bg-muted-foreground/50 hover:bg-muted-foreground" })
32884
34199
  }
32885
34200
  )
32886
34201
  }
@@ -32904,12 +34219,12 @@ function TableColumnHandles({
32904
34219
  onStartDrag,
32905
34220
  openMenuKey
32906
34221
  }) {
32907
- return /* @__PURE__ */ jsx86(Fragment32, { children: columnHandles.map((columnHandle) => {
34222
+ return /* @__PURE__ */ jsx90(Fragment33, { children: columnHandles.map((columnHandle) => {
32908
34223
  const menuKey = `column:${columnHandle.index}`;
32909
34224
  const isActive = columnHandle.index === activeColumnIndex;
32910
34225
  const visible = controlsVisible || hoverColumnHandleIndex === columnHandle.index || openMenuKey === menuKey;
32911
34226
  const isShown = visible || isActive;
32912
- return /* @__PURE__ */ jsx86(
34227
+ return /* @__PURE__ */ jsx90(
32913
34228
  "div",
32914
34229
  {
32915
34230
  className: "absolute z-30",
@@ -32918,13 +34233,13 @@ function TableColumnHandles({
32918
34233
  top: columnHandleTop,
32919
34234
  left: Math.max(8, columnHandle.center - 12)
32920
34235
  },
32921
- children: /* @__PURE__ */ jsx86(
34236
+ children: /* @__PURE__ */ jsx90(
32922
34237
  Tooltip,
32923
34238
  {
32924
34239
  placement: "top",
32925
34240
  disabled: openMenuKey === menuKey || !visible && isActive,
32926
- content: /* @__PURE__ */ jsx86("span", { className: "text-xs font-medium", children: `${columnDragLabel} ${columnHandle.index + 1}` }),
32927
- children: /* @__PURE__ */ jsx86("span", { className: "inline-flex", children: /* @__PURE__ */ jsx86(
34241
+ content: /* @__PURE__ */ jsx90("span", { className: "text-xs font-medium", children: `${columnDragLabel} ${columnHandle.index + 1}` }),
34242
+ children: /* @__PURE__ */ jsx90("span", { className: "inline-flex", children: /* @__PURE__ */ jsx90(
32928
34243
  DropdownMenu,
32929
34244
  {
32930
34245
  placement: "bottom-start",
@@ -32932,7 +34247,7 @@ function TableColumnHandles({
32932
34247
  onOpenChange: (open) => onOpenMenuChange(menuKey, open),
32933
34248
  contentClassName: "p-2",
32934
34249
  items: getMenuItems(columnHandle),
32935
- trigger: /* @__PURE__ */ jsx86(
34250
+ trigger: /* @__PURE__ */ jsx90(
32936
34251
  "button",
32937
34252
  {
32938
34253
  type: "button",
@@ -32951,7 +34266,7 @@ function TableColumnHandles({
32951
34266
  transform: isShown ? "scale(1)" : `scale(${IDLE_HANDLE_SCALE})`,
32952
34267
  pointerEvents: isShown ? "auto" : "none"
32953
34268
  },
32954
- children: visible ? /* @__PURE__ */ jsx86(GripHorizontal, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx86("div", { className: "h-1 w-3 rounded-full bg-muted-foreground/50 hover:bg-muted-foreground" })
34269
+ children: visible ? /* @__PURE__ */ jsx90(GripHorizontal, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx90("div", { className: "h-1 w-3 rounded-full bg-muted-foreground/50 hover:bg-muted-foreground" })
32955
34270
  }
32956
34271
  )
32957
34272
  }
@@ -33207,7 +34522,7 @@ function buildTableControlLayout(editor, surface, cell) {
33207
34522
  }
33208
34523
 
33209
34524
  // src/components/UEditor/table-controls.tsx
33210
- import { Fragment as Fragment33, jsx as jsx87, jsxs as jsxs72 } from "react/jsx-runtime";
34525
+ import { Fragment as Fragment34, jsx as jsx91, jsxs as jsxs76 } from "react/jsx-runtime";
33211
34526
  var TABLE_MENU_TOP_OFFSET = 10;
33212
34527
  function nearestIndex(centers, position) {
33213
34528
  let bestIndex = 0;
@@ -33233,17 +34548,17 @@ function getSelectedCell(editor) {
33233
34548
  }
33234
34549
  function TableControls({ editor, containerRef }) {
33235
34550
  const t = useSmartTranslations("UEditor");
33236
- const [layout, setLayout] = React75.useState(null);
33237
- const [dragPreview, setDragPreview] = React75.useState(null);
33238
- const [hoverState, setHoverState] = React75.useState(DEFAULT_TABLE_HOVER_STATE);
33239
- const [openMenuKey, setOpenMenuKey] = React75.useState(null);
33240
- const layoutRef = React75.useRef(null);
33241
- const dragStateRef = React75.useRef(null);
33242
- const syncFrameRef = React75.useRef(null);
33243
- React75.useEffect(() => {
34551
+ const [layout, setLayout] = React78.useState(null);
34552
+ const [dragPreview, setDragPreview] = React78.useState(null);
34553
+ const [hoverState, setHoverState] = React78.useState(DEFAULT_TABLE_HOVER_STATE);
34554
+ const [openMenuKey, setOpenMenuKey] = React78.useState(null);
34555
+ const layoutRef = React78.useRef(null);
34556
+ const dragStateRef = React78.useRef(null);
34557
+ const syncFrameRef = React78.useRef(null);
34558
+ React78.useEffect(() => {
33244
34559
  layoutRef.current = layout;
33245
34560
  }, [layout]);
33246
- const syncFromCell = React75.useCallback((cell) => {
34561
+ const syncFromCell = React78.useCallback((cell) => {
33247
34562
  const surface = containerRef.current;
33248
34563
  if (!surface || !cell) {
33249
34564
  setLayout(null);
@@ -33251,23 +34566,23 @@ function TableControls({ editor, containerRef }) {
33251
34566
  }
33252
34567
  setLayout(buildTableControlLayout(editor, surface, cell));
33253
34568
  }, [containerRef, editor]);
33254
- const syncFromSelection = React75.useCallback(() => {
34569
+ const syncFromSelection = React78.useCallback(() => {
33255
34570
  syncFromCell(getSelectedCell(editor));
33256
34571
  }, [editor, syncFromCell]);
33257
- const scheduleSyncFromSelection = React75.useCallback(() => {
34572
+ const scheduleSyncFromSelection = React78.useCallback(() => {
33258
34573
  if (syncFrameRef.current !== null) return;
33259
34574
  syncFrameRef.current = window.requestAnimationFrame(() => {
33260
34575
  syncFrameRef.current = null;
33261
34576
  syncFromSelection();
33262
34577
  });
33263
34578
  }, [syncFromSelection]);
33264
- React75.useEffect(() => () => {
34579
+ React78.useEffect(() => () => {
33265
34580
  if (syncFrameRef.current !== null) {
33266
34581
  window.cancelAnimationFrame(syncFrameRef.current);
33267
34582
  syncFrameRef.current = null;
33268
34583
  }
33269
34584
  }, []);
33270
- const refreshCurrentLayout = React75.useCallback(() => {
34585
+ const refreshCurrentLayout = React78.useCallback(() => {
33271
34586
  setLayout((prev) => {
33272
34587
  if (!prev) return prev;
33273
34588
  const surface = containerRef.current;
@@ -33277,12 +34592,12 @@ function TableControls({ editor, containerRef }) {
33277
34592
  return cell ? buildTableControlLayout(editor, surface, cell) : null;
33278
34593
  });
33279
34594
  }, [containerRef, editor]);
33280
- const clearDrag = React75.useCallback(() => {
34595
+ const clearDrag = React78.useCallback(() => {
33281
34596
  dragStateRef.current = null;
33282
34597
  setDragPreview(null);
33283
34598
  document.body.style.cursor = "";
33284
34599
  }, []);
33285
- const updateHoverState = React75.useCallback((event) => {
34600
+ const updateHoverState = React78.useCallback((event) => {
33286
34601
  const activeLayout = layoutRef.current;
33287
34602
  const surface = containerRef.current;
33288
34603
  if (!activeLayout || !surface || dragStateRef.current) {
@@ -33298,7 +34613,7 @@ function TableControls({ editor, containerRef }) {
33298
34613
  return areTableHoverStatesEqual(prev, nextState) ? prev : nextState;
33299
34614
  });
33300
34615
  }, [containerRef]);
33301
- React75.useEffect(() => {
34616
+ React78.useEffect(() => {
33302
34617
  const proseMirror = editor.view.dom;
33303
34618
  const surface = containerRef.current;
33304
34619
  if (!surface) return void 0;
@@ -33348,37 +34663,37 @@ function TableControls({ editor, containerRef }) {
33348
34663
  editor.off("update", refreshCurrentLayout);
33349
34664
  };
33350
34665
  }, [clearDrag, containerRef, editor, refreshCurrentLayout, syncFromCell, syncFromSelection, updateHoverState]);
33351
- const runAtCellPos = React75.useCallback((cellPos, command, options) => {
34666
+ const runAtCellPos = React78.useCallback((cellPos, command, options) => {
33352
34667
  const result = runTableCommandAtCellPos(editor, cellPos, command);
33353
34668
  if (options?.sync !== false) {
33354
34669
  scheduleSyncFromSelection();
33355
34670
  }
33356
34671
  return result;
33357
34672
  }, [editor, scheduleSyncFromSelection]);
33358
- const runAtActiveCell = React75.useCallback((command, options) => {
34673
+ const runAtActiveCell = React78.useCallback((command, options) => {
33359
34674
  return runAtCellPos(layoutRef.current?.cellPos ?? null, command, options);
33360
34675
  }, [runAtCellPos]);
33361
- const duplicateRowAt = React75.useCallback((rowIndex, cellPos) => {
34676
+ const duplicateRowAt = React78.useCallback((rowIndex, cellPos) => {
33362
34677
  const result = duplicateTableRowAt(editor, rowIndex, cellPos);
33363
34678
  scheduleSyncFromSelection();
33364
34679
  return result;
33365
34680
  }, [editor, scheduleSyncFromSelection]);
33366
- const clearRowAt = React75.useCallback((rowIndex, cellPos) => {
34681
+ const clearRowAt = React78.useCallback((rowIndex, cellPos) => {
33367
34682
  const result = clearTableRowAt(editor, rowIndex, cellPos);
33368
34683
  scheduleSyncFromSelection();
33369
34684
  return result;
33370
34685
  }, [editor, scheduleSyncFromSelection]);
33371
- const duplicateColumnAt = React75.useCallback((columnIndex, cellPos) => {
34686
+ const duplicateColumnAt = React78.useCallback((columnIndex, cellPos) => {
33372
34687
  const result = duplicateTableColumnAt(editor, columnIndex, cellPos);
33373
34688
  scheduleSyncFromSelection();
33374
34689
  return result;
33375
34690
  }, [editor, scheduleSyncFromSelection]);
33376
- const clearColumnAt = React75.useCallback((columnIndex, cellPos) => {
34691
+ const clearColumnAt = React78.useCallback((columnIndex, cellPos) => {
33377
34692
  const result = clearTableColumnAt(editor, columnIndex, cellPos);
33378
34693
  scheduleSyncFromSelection();
33379
34694
  return result;
33380
34695
  }, [editor, scheduleSyncFromSelection]);
33381
- const expandTableBy = React75.useCallback((rows, cols) => {
34696
+ const expandTableBy = React78.useCallback((rows, cols) => {
33382
34697
  const activeCellPos = layoutRef.current?.cellPos ?? editor.state.selection.from;
33383
34698
  const result = expandTableFromCell(editor, activeCellPos, rows, cols);
33384
34699
  scheduleSyncFromSelection();
@@ -33387,19 +34702,19 @@ function TableControls({ editor, containerRef }) {
33387
34702
  const canExpandTable = Boolean(layout);
33388
34703
  const controlsVisible = dragPreview !== null;
33389
34704
  const tableMenuOpen = openMenuKey === "table";
33390
- const startAddColumnDrag = React75.useCallback(() => {
34705
+ const startAddColumnDrag = React78.useCallback(() => {
33391
34706
  setOpenMenuKey(null);
33392
34707
  dragStateRef.current = { kind: "add-column", previewCols: 1 };
33393
34708
  setDragPreview({ kind: "add-column", previewCols: 1 });
33394
34709
  document.body.style.cursor = "ew-resize";
33395
34710
  }, []);
33396
- const startAddRowDrag = React75.useCallback(() => {
34711
+ const startAddRowDrag = React78.useCallback(() => {
33397
34712
  setOpenMenuKey(null);
33398
34713
  dragStateRef.current = { kind: "add-row", previewRows: 1 };
33399
34714
  setDragPreview({ kind: "add-row", previewRows: 1 });
33400
34715
  document.body.style.cursor = "ns-resize";
33401
34716
  }, []);
33402
- const startRowDrag = React75.useCallback((rowHandle) => {
34717
+ const startRowDrag = React78.useCallback((rowHandle) => {
33403
34718
  setOpenMenuKey(null);
33404
34719
  dragStateRef.current = {
33405
34720
  kind: "row",
@@ -33416,7 +34731,7 @@ function TableControls({ editor, containerRef }) {
33416
34731
  });
33417
34732
  document.body.style.cursor = "grabbing";
33418
34733
  }, []);
33419
- const startColumnDrag = React75.useCallback((columnHandle) => {
34734
+ const startColumnDrag = React78.useCallback((columnHandle) => {
33420
34735
  setOpenMenuKey(null);
33421
34736
  dragStateRef.current = {
33422
34737
  kind: "column",
@@ -33433,7 +34748,7 @@ function TableControls({ editor, containerRef }) {
33433
34748
  });
33434
34749
  document.body.style.cursor = "grabbing";
33435
34750
  }, []);
33436
- React75.useEffect(() => {
34751
+ React78.useEffect(() => {
33437
34752
  const handleMouseMove = (event) => {
33438
34753
  const dragState = dragStateRef.current;
33439
34754
  const activeLayout = layoutRef.current;
@@ -33522,7 +34837,7 @@ function TableControls({ editor, containerRef }) {
33522
34837
  window.removeEventListener("blur", clearDrag);
33523
34838
  };
33524
34839
  }, [clearDrag, containerRef, editor, expandTableBy, scheduleSyncFromSelection]);
33525
- const menuItems = React75.useMemo(() => {
34840
+ const menuItems = React78.useMemo(() => {
33526
34841
  if (!layout) return [];
33527
34842
  return [
33528
34843
  {
@@ -33590,7 +34905,7 @@ function TableControls({ editor, containerRef }) {
33590
34905
  }
33591
34906
  ];
33592
34907
  }, [layout, runAtActiveCell, t]);
33593
- const getRowHandleMenuItems = React75.useCallback((rowHandle) => [
34908
+ const getRowHandleMenuItems = React78.useCallback((rowHandle) => [
33594
34909
  {
33595
34910
  label: t("tableMenu.addRowBefore"),
33596
34911
  icon: ArrowUp2,
@@ -33603,7 +34918,7 @@ function TableControls({ editor, containerRef }) {
33603
34918
  },
33604
34919
  {
33605
34920
  label: t("tableMenu.duplicateRow"),
33606
- icon: Copy2,
34921
+ icon: Copy3,
33607
34922
  onClick: () => duplicateRowAt(rowHandle.index, rowHandle.cellPos)
33608
34923
  },
33609
34924
  {
@@ -33618,7 +34933,7 @@ function TableControls({ editor, containerRef }) {
33618
34933
  destructive: true
33619
34934
  }
33620
34935
  ], [clearRowAt, duplicateRowAt, runAtCellPos, t]);
33621
- const getColumnHandleMenuItems = React75.useCallback((columnHandle) => [
34936
+ const getColumnHandleMenuItems = React78.useCallback((columnHandle) => [
33622
34937
  {
33623
34938
  label: t("tableMenu.addColumnBefore"),
33624
34939
  icon: ArrowLeft2,
@@ -33631,7 +34946,7 @@ function TableControls({ editor, containerRef }) {
33631
34946
  },
33632
34947
  {
33633
34948
  label: t("tableMenu.duplicateColumn"),
33634
- icon: Copy2,
34949
+ icon: Copy3,
33635
34950
  onClick: () => duplicateColumnAt(columnHandle.index, columnHandle.cellPos)
33636
34951
  },
33637
34952
  {
@@ -33653,8 +34968,8 @@ function TableControls({ editor, containerRef }) {
33653
34968
  const menuLeft = Math.max(8, layout.tableLeft);
33654
34969
  const rowHandleLeft = layout.tableLeft - 12;
33655
34970
  const columnHandleTop = layout.tableTop - 12;
33656
- return /* @__PURE__ */ jsxs72(Fragment33, { children: [
33657
- /* @__PURE__ */ jsx87(
34971
+ return /* @__PURE__ */ jsxs76(Fragment34, { children: [
34972
+ /* @__PURE__ */ jsx91(
33658
34973
  TableRowHandles,
33659
34974
  {
33660
34975
  activeRowIndex: layout.activeRowIndex,
@@ -33671,7 +34986,7 @@ function TableControls({ editor, containerRef }) {
33671
34986
  rowHandles: layout.rowHandles
33672
34987
  }
33673
34988
  ),
33674
- /* @__PURE__ */ jsx87(
34989
+ /* @__PURE__ */ jsx91(
33675
34990
  TableColumnHandles,
33676
34991
  {
33677
34992
  activeColumnIndex: layout.activeColumnIndex,
@@ -33688,7 +35003,7 @@ function TableControls({ editor, containerRef }) {
33688
35003
  openMenuKey
33689
35004
  }
33690
35005
  ),
33691
- /* @__PURE__ */ jsx87(
35006
+ /* @__PURE__ */ jsx91(
33692
35007
  TableControlMenu,
33693
35008
  {
33694
35009
  controlsVisible,
@@ -33703,7 +35018,7 @@ function TableControls({ editor, containerRef }) {
33703
35018
  top: menuTop
33704
35019
  }
33705
35020
  ),
33706
- /* @__PURE__ */ jsx87(
35021
+ /* @__PURE__ */ jsx91(
33707
35022
  TableAddRails,
33708
35023
  {
33709
35024
  addColumnVisible: hoverState.addColumnVisible,
@@ -33717,7 +35032,7 @@ function TableControls({ editor, containerRef }) {
33717
35032
  quickAddRowLabel: t("tableMenu.quickAddRowAfter")
33718
35033
  }
33719
35034
  ),
33720
- /* @__PURE__ */ jsx87(
35035
+ /* @__PURE__ */ jsx91(
33721
35036
  TableDragPreview,
33722
35037
  {
33723
35038
  columnDragLabel: t("tableMenu.dragColumn"),
@@ -33876,10 +35191,10 @@ var UEDITOR_PROSEMIRROR_CLASS_NAME = cn(
33876
35191
  );
33877
35192
 
33878
35193
  // src/components/UEditor/use-table-interactions.ts
33879
- import React77, { useEffect as useEffect35, useRef as useRef34 } from "react";
35194
+ import React80, { useEffect as useEffect37, useRef as useRef35 } from "react";
33880
35195
 
33881
35196
  // src/components/UEditor/use-table-row-resize.ts
33882
- import React76, { useRef as useRef33 } from "react";
35197
+ import React79, { useRef as useRef34 } from "react";
33883
35198
  function useTableRowResize({
33884
35199
  editor,
33885
35200
  setHoveredTableCell,
@@ -33888,9 +35203,9 @@ function useTableRowResize({
33888
35203
  clearAllTableResizeHover,
33889
35204
  scheduleTableLayoutSync
33890
35205
  }) {
33891
- const commitFrameRef = useRef33(null);
33892
- const stateRef = useRef33(null);
33893
- const commitPreview = React76.useCallback(() => {
35206
+ const commitFrameRef = useRef34(null);
35207
+ const stateRef = useRef34(null);
35208
+ const commitPreview = React79.useCallback(() => {
33894
35209
  if (!editor) return;
33895
35210
  const state = stateRef.current;
33896
35211
  if (!state) return;
@@ -33925,22 +35240,22 @@ function useTableRowResize({
33925
35240
  showRowGuide(state.tableElement, state.rowElement, state.cellElement);
33926
35241
  scheduleTableLayoutSync();
33927
35242
  }, [editor, scheduleTableLayoutSync, showRowGuide]);
33928
- const scheduleCommit = React76.useCallback(() => {
35243
+ const scheduleCommit = React79.useCallback(() => {
33929
35244
  if (commitFrameRef.current !== null) return;
33930
35245
  commitFrameRef.current = window.requestAnimationFrame(() => {
33931
35246
  commitFrameRef.current = null;
33932
35247
  commitPreview();
33933
35248
  });
33934
35249
  }, [commitPreview]);
33935
- const syncActiveGuide = React76.useCallback(() => {
35250
+ const syncActiveGuide = React79.useCallback(() => {
33936
35251
  const state = stateRef.current;
33937
35252
  if (!state) return false;
33938
35253
  setHoveredTableCell(state.cellElement);
33939
35254
  showRowGuide(state.tableElement, state.rowElement, state.cellElement);
33940
35255
  return true;
33941
35256
  }, [setHoveredTableCell, showRowGuide]);
33942
- const isResizing = React76.useCallback(() => stateRef.current !== null, []);
33943
- const beginResize = React76.useCallback((event, table, row, cell) => {
35257
+ const isResizing = React79.useCallback(() => stateRef.current !== null, []);
35258
+ const beginResize = React79.useCallback((event, table, row, cell) => {
33944
35259
  if (!editor || !isRowResizeHotspot(cell, event.clientX, event.clientY)) {
33945
35260
  return false;
33946
35261
  }
@@ -33966,7 +35281,7 @@ function useTableRowResize({
33966
35281
  event.stopPropagation();
33967
35282
  return true;
33968
35283
  }, [editor, setHoveredTableCell, showRowGuide]);
33969
- const handlePointerMove = React76.useCallback((event) => {
35284
+ const handlePointerMove = React79.useCallback((event) => {
33970
35285
  const state = stateRef.current;
33971
35286
  if (!state) return;
33972
35287
  const nextHeight = Math.max(
@@ -33982,7 +35297,7 @@ function useTableRowResize({
33982
35297
  document.body.style.cursor = "row-resize";
33983
35298
  scheduleCommit();
33984
35299
  }, [scheduleCommit, showRowGuide]);
33985
- const handlePointerUp = React76.useCallback((event) => {
35300
+ const handlePointerUp = React79.useCallback((event) => {
33986
35301
  if (!editor) return;
33987
35302
  const state = stateRef.current;
33988
35303
  if (!state) return;
@@ -34012,7 +35327,7 @@ function useTableRowResize({
34012
35327
  clearAllTableResizeHover();
34013
35328
  scheduleTableLayoutSync();
34014
35329
  }, [clearAllTableResizeHover, clearHoveredTableCell, commitPreview, editor, scheduleTableLayoutSync]);
34015
- const cancelResize = React76.useCallback(() => {
35330
+ const cancelResize = React79.useCallback(() => {
34016
35331
  if (!stateRef.current) return;
34017
35332
  if (commitFrameRef.current !== null) {
34018
35333
  window.cancelAnimationFrame(commitFrameRef.current);
@@ -34024,7 +35339,7 @@ function useTableRowResize({
34024
35339
  clearAllTableResizeHover();
34025
35340
  scheduleTableLayoutSync();
34026
35341
  }, [clearAllTableResizeHover, clearHoveredTableCell, scheduleTableLayoutSync]);
34027
- const cleanup = React76.useCallback(() => {
35342
+ const cleanup = React79.useCallback(() => {
34028
35343
  if (commitFrameRef.current !== null) {
34029
35344
  window.cancelAnimationFrame(commitFrameRef.current);
34030
35345
  commitFrameRef.current = null;
@@ -34045,40 +35360,40 @@ function useTableRowResize({
34045
35360
 
34046
35361
  // src/components/UEditor/use-table-interactions.ts
34047
35362
  function useUEditorTableInteractions(editor, editable = true) {
34048
- const editorContentRef = useRef34(null);
34049
- const tableColumnGuideRef = useRef34(null);
34050
- const tableRowGuideRef = useRef34(null);
34051
- const activeTableCellHighlightRef = useRef34(null);
34052
- const hoveredTableCellRef = useRef34(null);
34053
- const activeTableCellRef = useRef34(null);
34054
- const suppressActiveCellHighlightRef = useRef34(false);
34055
- const tableLayoutSyncFrameRef = useRef34(null);
34056
- const setEditorResizeCursor = React77.useCallback((cursor) => {
35363
+ const editorContentRef = useRef35(null);
35364
+ const tableColumnGuideRef = useRef35(null);
35365
+ const tableRowGuideRef = useRef35(null);
35366
+ const activeTableCellHighlightRef = useRef35(null);
35367
+ const hoveredTableCellRef = useRef35(null);
35368
+ const activeTableCellRef = useRef35(null);
35369
+ const suppressActiveCellHighlightRef = useRef35(false);
35370
+ const tableLayoutSyncFrameRef = useRef35(null);
35371
+ const setEditorResizeCursor = React80.useCallback((cursor) => {
34057
35372
  const proseMirror = editorContentRef.current?.querySelector(".ProseMirror");
34058
35373
  if (proseMirror) {
34059
35374
  proseMirror.style.cursor = cursor;
34060
35375
  }
34061
35376
  }, []);
34062
- const hideColumnGuide = React77.useCallback(() => {
35377
+ const hideColumnGuide = React80.useCallback(() => {
34063
35378
  editorContentRef.current?.classList.remove("resize-cursor");
34064
35379
  const guide = tableColumnGuideRef.current;
34065
35380
  if (guide) {
34066
35381
  guide.style.opacity = "0";
34067
35382
  }
34068
35383
  }, []);
34069
- const hideRowGuide = React77.useCallback(() => {
35384
+ const hideRowGuide = React80.useCallback(() => {
34070
35385
  editorContentRef.current?.classList.remove("resize-row-cursor");
34071
35386
  const guide = tableRowGuideRef.current;
34072
35387
  if (guide) {
34073
35388
  guide.style.opacity = "0";
34074
35389
  }
34075
35390
  }, []);
34076
- const clearAllTableResizeHover = React77.useCallback(() => {
35391
+ const clearAllTableResizeHover = React80.useCallback(() => {
34077
35392
  setEditorResizeCursor("");
34078
35393
  hideColumnGuide();
34079
35394
  hideRowGuide();
34080
35395
  }, [hideColumnGuide, hideRowGuide, setEditorResizeCursor]);
34081
- const updateActiveCellHighlight = React77.useCallback((cell) => {
35396
+ const updateActiveCellHighlight = React80.useCallback((cell) => {
34082
35397
  const surface = editorContentRef.current;
34083
35398
  const highlight = activeTableCellHighlightRef.current;
34084
35399
  if (!highlight) return;
@@ -34093,7 +35408,7 @@ function useUEditorTableInteractions(editor, editable = true) {
34093
35408
  highlight.style.width = `${metrics.width}px`;
34094
35409
  highlight.style.height = `${metrics.height}px`;
34095
35410
  }, []);
34096
- const scheduleTableLayoutSync = React77.useCallback(() => {
35411
+ const scheduleTableLayoutSync = React80.useCallback(() => {
34097
35412
  if (tableLayoutSyncFrameRef.current !== null) return;
34098
35413
  tableLayoutSyncFrameRef.current = window.requestAnimationFrame(() => {
34099
35414
  tableLayoutSyncFrameRef.current = null;
@@ -34101,22 +35416,22 @@ function useUEditorTableInteractions(editor, editable = true) {
34101
35416
  editorContentRef.current?.dispatchEvent(new CustomEvent(UEDITOR_TABLE_LAYOUT_CHANGE_EVENT));
34102
35417
  });
34103
35418
  }, [updateActiveCellHighlight]);
34104
- const setActiveTableCell = React77.useCallback((cell) => {
35419
+ const setActiveTableCell = React80.useCallback((cell) => {
34105
35420
  if (activeTableCellRef.current === cell) return;
34106
35421
  activeTableCellRef.current = cell;
34107
35422
  updateActiveCellHighlight(activeTableCellRef.current);
34108
35423
  }, [updateActiveCellHighlight]);
34109
- const clearActiveTableCell = React77.useCallback(() => {
35424
+ const clearActiveTableCell = React80.useCallback(() => {
34110
35425
  activeTableCellRef.current = null;
34111
35426
  updateActiveCellHighlight(null);
34112
35427
  }, [updateActiveCellHighlight]);
34113
- const setHoveredTableCell = React77.useCallback((cell) => {
35428
+ const setHoveredTableCell = React80.useCallback((cell) => {
34114
35429
  hoveredTableCellRef.current = cell;
34115
35430
  }, []);
34116
- const clearHoveredTableCell = React77.useCallback(() => {
35431
+ const clearHoveredTableCell = React80.useCallback(() => {
34117
35432
  hoveredTableCellRef.current = null;
34118
35433
  }, []);
34119
- const showColumnGuide = React77.useCallback((table, row, cell) => {
35434
+ const showColumnGuide = React80.useCallback((table, row, cell) => {
34120
35435
  const surface = editorContentRef.current;
34121
35436
  const guide = tableColumnGuideRef.current;
34122
35437
  if (!surface || !guide) return;
@@ -34129,7 +35444,7 @@ function useUEditorTableInteractions(editor, editable = true) {
34129
35444
  surface.classList.add("resize-cursor");
34130
35445
  setEditorResizeCursor("col-resize");
34131
35446
  }, [setEditorResizeCursor]);
34132
- const showRowGuide = React77.useCallback((table, row, cell) => {
35447
+ const showRowGuide = React80.useCallback((table, row, cell) => {
34133
35448
  const surface = editorContentRef.current;
34134
35449
  const guide = tableRowGuideRef.current;
34135
35450
  if (!surface || !guide) return;
@@ -34158,11 +35473,11 @@ function useUEditorTableInteractions(editor, editable = true) {
34158
35473
  clearAllTableResizeHover,
34159
35474
  scheduleTableLayoutSync
34160
35475
  });
34161
- const syncActiveTableCellFromSelection = React77.useCallback(() => {
35476
+ const syncActiveTableCellFromSelection = React80.useCallback(() => {
34162
35477
  if (!editor) return;
34163
35478
  setActiveTableCell(getSelectionTableCell(editor.view));
34164
35479
  }, [editor, setActiveTableCell]);
34165
- useEffect35(() => {
35480
+ useEffect37(() => {
34166
35481
  if (!editor || !editable) return void 0;
34167
35482
  const proseMirror = editor.view.dom;
34168
35483
  const surface = editorContentRef.current;
@@ -34322,8 +35637,8 @@ function useUEditorTableInteractions(editor, editable = true) {
34322
35637
  }
34323
35638
 
34324
35639
  // src/components/UEditor/UEditor.tsx
34325
- import { jsx as jsx88, jsxs as jsxs73 } from "react/jsx-runtime";
34326
- var UEditor = React78.forwardRef(({
35640
+ import { jsx as jsx92, jsxs as jsxs77 } from "react/jsx-runtime";
35641
+ var UEditor = React81.forwardRef(({
34327
35642
  content = "",
34328
35643
  onChange,
34329
35644
  onHtmlChange,
@@ -34350,25 +35665,45 @@ var UEditor = React78.forwardRef(({
34350
35665
  fontFamilies,
34351
35666
  fontSizes,
34352
35667
  lineHeights,
34353
- letterSpacings
35668
+ letterSpacings,
35669
+ fetchMetadata,
35670
+ uploadFile,
35671
+ uploadFileForSave,
35672
+ collaborationOptions,
35673
+ extraExtensions
34354
35674
  }, ref) => {
34355
35675
  const t = useSmartTranslations("UEditor");
34356
35676
  const effectivePlaceholder = placeholder ?? t("placeholder");
34357
- const inFlightPrepareRef = useRef35(null);
34358
- const lastAppliedContentRef = useRef35(content ?? "");
35677
+ const inFlightPrepareRef = useRef36(null);
35678
+ const lastAppliedContentRef = useRef36(content ?? "");
35679
+ const resolvedUploadFile = useMemo24(() => {
35680
+ if (uploadFile) return uploadFile;
35681
+ if (uploadFileForSave) {
35682
+ return async (file) => {
35683
+ const res = await uploadFileForSave(file);
35684
+ return typeof res === "string" ? res : res.url;
35685
+ };
35686
+ }
35687
+ return uploadImage;
35688
+ }, [uploadFile, uploadFileForSave, uploadImage]);
34359
35689
  const extensions = useMemo24(
34360
- () => buildUEditorExtensions({
34361
- placeholder: effectivePlaceholder,
34362
- translate: t,
34363
- maxCharacters,
34364
- uploadImage,
34365
- imageInsertMode,
34366
- maxImageFileSize,
34367
- allowedImageMimeTypes,
34368
- fallbackToDataUrl,
34369
- editable
34370
- }),
34371
- [effectivePlaceholder, t, maxCharacters, uploadImage, imageInsertMode, maxImageFileSize, allowedImageMimeTypes, fallbackToDataUrl, editable]
35690
+ () => [
35691
+ ...buildUEditorExtensions({
35692
+ placeholder: effectivePlaceholder,
35693
+ translate: t,
35694
+ maxCharacters,
35695
+ uploadImage,
35696
+ uploadFile: resolvedUploadFile,
35697
+ imageInsertMode,
35698
+ maxImageFileSize,
35699
+ allowedImageMimeTypes,
35700
+ fallbackToDataUrl,
35701
+ editable,
35702
+ fetchMetadata
35703
+ }),
35704
+ ...extraExtensions ?? []
35705
+ ],
35706
+ [effectivePlaceholder, t, maxCharacters, uploadImage, resolvedUploadFile, imageInsertMode, maxImageFileSize, allowedImageMimeTypes, fallbackToDataUrl, editable, fetchMetadata, extraExtensions]
34372
35707
  );
34373
35708
  const editor = useEditor({
34374
35709
  immediatelyRender: false,
@@ -34392,6 +35727,7 @@ var UEditor = React78.forwardRef(({
34392
35727
  const anchor = target?.closest?.("a[href]");
34393
35728
  const href = anchor?.getAttribute("href") ?? "";
34394
35729
  if (!href) return false;
35730
+ if (editable) return false;
34395
35731
  if (!view.state.selection.empty) return false;
34396
35732
  event.preventDefault();
34397
35733
  event.stopPropagation();
@@ -34426,6 +35762,7 @@ var UEditor = React78.forwardRef(({
34426
35762
  inFlightPrepareRef.current = prepareUEditorContentForSave({
34427
35763
  html: htmlSnapshot,
34428
35764
  uploadImageForSave,
35765
+ uploadFileForSave,
34429
35766
  uploadConcurrency: uploadImageConcurrency
34430
35767
  }).finally(() => {
34431
35768
  inFlightPrepareRef.current = null;
@@ -34438,19 +35775,23 @@ var UEditor = React78.forwardRef(({
34438
35775
  return result;
34439
35776
  }
34440
35777
  }),
34441
- [content, editor, uploadImageForSave, uploadImageConcurrency]
35778
+ [content, editor, uploadImageForSave, uploadFileForSave, uploadImageConcurrency]
34442
35779
  );
34443
- useEffect36(() => {
35780
+ useEffect38(() => {
34444
35781
  if (!editor) return;
34445
35782
  const nextContent = content ?? "";
34446
35783
  if (lastAppliedContentRef.current === nextContent) return;
34447
35784
  lastAppliedContentRef.current = nextContent;
34448
35785
  if (editor.getHTML() !== nextContent) {
34449
- editor.commands.setContent(nextContent, { emitUpdate: false });
35786
+ Promise.resolve().then(() => {
35787
+ if (!editor.isDestroyed) {
35788
+ editor.commands.setContent(nextContent, { emitUpdate: false });
35789
+ }
35790
+ });
34450
35791
  }
34451
35792
  }, [content, editor]);
34452
35793
  if (!editor) {
34453
- return /* @__PURE__ */ jsx88(
35794
+ return /* @__PURE__ */ jsx92(
34454
35795
  "div",
34455
35796
  {
34456
35797
  className: cn("w-full rounded-lg border bg-background flex items-center justify-center text-muted-foreground", className),
@@ -34459,7 +35800,7 @@ var UEditor = React78.forwardRef(({
34459
35800
  }
34460
35801
  );
34461
35802
  }
34462
- return /* @__PURE__ */ jsxs73(
35803
+ return /* @__PURE__ */ jsxs77(
34463
35804
  "div",
34464
35805
  {
34465
35806
  className: cn(
@@ -34474,7 +35815,7 @@ var UEditor = React78.forwardRef(({
34474
35815
  className
34475
35816
  ),
34476
35817
  children: [
34477
- editable && showToolbar && /* @__PURE__ */ jsx88(
35818
+ editable && showToolbar && /* @__PURE__ */ jsx92(
34478
35819
  EditorToolbar,
34479
35820
  {
34480
35821
  editor,
@@ -34489,7 +35830,7 @@ var UEditor = React78.forwardRef(({
34489
35830
  letterSpacings
34490
35831
  }
34491
35832
  ),
34492
- editable && showBubbleMenu && /* @__PURE__ */ jsx88(
35833
+ editable && showBubbleMenu && /* @__PURE__ */ jsx92(
34493
35834
  CustomBubbleMenu,
34494
35835
  {
34495
35836
  editor,
@@ -34497,8 +35838,8 @@ var UEditor = React78.forwardRef(({
34497
35838
  lineHeights
34498
35839
  }
34499
35840
  ),
34500
- editable && showFloatingMenu && /* @__PURE__ */ jsx88(CustomFloatingMenu, { editor }),
34501
- /* @__PURE__ */ jsxs73(
35841
+ editable && showFloatingMenu && /* @__PURE__ */ jsx92(CustomFloatingMenu, { editor }),
35842
+ /* @__PURE__ */ jsxs77(
34502
35843
  "div",
34503
35844
  {
34504
35845
  ref: editorContentRef,
@@ -34508,7 +35849,7 @@ var UEditor = React78.forwardRef(({
34508
35849
  maxHeight
34509
35850
  },
34510
35851
  children: [
34511
- /* @__PURE__ */ jsx88(
35852
+ /* @__PURE__ */ jsx92(
34512
35853
  "span",
34513
35854
  {
34514
35855
  ref: tableColumnGuideRef,
@@ -34516,7 +35857,7 @@ var UEditor = React78.forwardRef(({
34516
35857
  className: "pointer-events-none absolute z-20 bg-primary opacity-0 transition-opacity duration-100"
34517
35858
  }
34518
35859
  ),
34519
- /* @__PURE__ */ jsx88(
35860
+ /* @__PURE__ */ jsx92(
34520
35861
  "span",
34521
35862
  {
34522
35863
  ref: tableRowGuideRef,
@@ -34524,7 +35865,7 @@ var UEditor = React78.forwardRef(({
34524
35865
  className: "pointer-events-none absolute z-20 bg-primary opacity-0 transition-opacity duration-100"
34525
35866
  }
34526
35867
  ),
34527
- /* @__PURE__ */ jsx88(
35868
+ /* @__PURE__ */ jsx92(
34528
35869
  "span",
34529
35870
  {
34530
35871
  ref: activeTableCellHighlightRef,
@@ -34533,8 +35874,8 @@ var UEditor = React78.forwardRef(({
34533
35874
  className: "pointer-events-none hidden absolute z-20 rounded-[2px] border-2 border-primary bg-primary/10 transition-[left,top,width,height] duration-100"
34534
35875
  }
34535
35876
  ),
34536
- editable && /* @__PURE__ */ jsx88(TableControls, { editor, containerRef: editorContentRef }),
34537
- /* @__PURE__ */ jsx88(
35877
+ editable && /* @__PURE__ */ jsx92(TableControls, { editor, containerRef: editorContentRef }),
35878
+ /* @__PURE__ */ jsx92(
34538
35879
  EditorContent,
34539
35880
  {
34540
35881
  editor,
@@ -34544,7 +35885,7 @@ var UEditor = React78.forwardRef(({
34544
35885
  ]
34545
35886
  }
34546
35887
  ),
34547
- showCharacterCount && /* @__PURE__ */ jsx88(CharacterCountDisplay, { editor, maxCharacters })
35888
+ showCharacterCount && /* @__PURE__ */ jsx92(CharacterCountDisplay, { editor, maxCharacters })
34548
35889
  ]
34549
35890
  }
34550
35891
  );