@underverse-ui/underverse 1.0.50 → 1.0.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "package": "@underverse-ui/underverse",
3
- "version": "1.0.50",
3
+ "version": "1.0.52",
4
4
  "sourceEntry": "src/index.ts",
5
5
  "totalExports": 239,
6
6
  "exports": [
package/dist/index.cjs CHANGED
@@ -937,6 +937,11 @@ var en_default = {
937
937
  cancelBtn: "Cancel",
938
938
  addFromUrl: "Add from URL"
939
939
  },
940
+ emojiPicker: {
941
+ searchPlaceholder: "Search emoji",
942
+ noResults: "No emoji found",
943
+ tryDifferentSearch: "Try a different keyword"
944
+ },
940
945
  tableMenu: {
941
946
  insert3x3: "Insert 3\xD73 Table",
942
947
  addColumnBefore: "Add Column Before",
@@ -1156,6 +1161,11 @@ var vi_default = {
1156
1161
  cancelBtn: "H\u1EE7y",
1157
1162
  addFromUrl: "Th\xEAm t\u1EEB URL"
1158
1163
  },
1164
+ emojiPicker: {
1165
+ searchPlaceholder: "T\xECm ki\u1EBFm bi\u1EC3u t\u01B0\u1EE3ng c\u1EA3m x\xFAc",
1166
+ noResults: "Kh\xF4ng t\xECm th\u1EA5y emoji",
1167
+ tryDifferentSearch: "Th\u1EED t\u1EEB kh\xF3a kh\xE1c"
1168
+ },
1159
1169
  tableMenu: {
1160
1170
  insert3x3: "Ch\xE8n b\u1EA3ng 3\xD73",
1161
1171
  addColumnBefore: "Th\xEAm c\u1ED9t tr\u01B0\u1EDBc",
@@ -1374,6 +1384,11 @@ var ko_default = {
1374
1384
  cancelBtn: "\uCDE8\uC18C",
1375
1385
  addFromUrl: "URL\uC5D0\uC11C \uCD94\uAC00"
1376
1386
  },
1387
+ emojiPicker: {
1388
+ searchPlaceholder: "\uC774\uBAA8\uC9C0 \uAC80\uC0C9",
1389
+ noResults: "\uC774\uBAA8\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
1390
+ tryDifferentSearch: "\uB2E4\uB978 \uAC80\uC0C9\uC5B4\uB97C \uC2DC\uB3C4\uD574 \uBCF4\uC138\uC694"
1391
+ },
1377
1392
  tableMenu: {
1378
1393
  insert3x3: "3x3 \uD45C \uC0BD\uC785",
1379
1394
  addColumnBefore: "\uC55E\uC5D0 \uC5F4 \uCD94\uAC00",
@@ -1592,6 +1607,11 @@ var ja_default = {
1592
1607
  cancelBtn: "\u30AD\u30E3\u30F3\u30BB\u30EB",
1593
1608
  addFromUrl: "URL\u304B\u3089\u8FFD\u52A0"
1594
1609
  },
1610
+ emojiPicker: {
1611
+ searchPlaceholder: "\u7D75\u6587\u5B57\u3092\u691C\u7D22",
1612
+ noResults: "\u7D75\u6587\u5B57\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093",
1613
+ tryDifferentSearch: "\u5225\u306E\u30AD\u30FC\u30EF\u30FC\u30C9\u3067\u304A\u8A66\u3057\u304F\u3060\u3055\u3044"
1614
+ },
1595
1615
  tableMenu: {
1596
1616
  insert3x3: "3x3 \u8868\u3092\u633F\u5165",
1597
1617
  addColumnBefore: "\u524D\u306B\u5217\u3092\u8FFD\u52A0",
@@ -1613,6 +1633,26 @@ var defaultTranslations = {
1613
1633
  ko: ko_default,
1614
1634
  ja: ja_default
1615
1635
  };
1636
+ function resolveObjectPath(input, path) {
1637
+ const parts = path.split(".");
1638
+ let current = input;
1639
+ for (const part of parts) {
1640
+ if (current && typeof current === "object" && part in current) {
1641
+ current = current[part];
1642
+ } else {
1643
+ return null;
1644
+ }
1645
+ }
1646
+ return current;
1647
+ }
1648
+ function resolveTranslationValue(translations, namespace, key) {
1649
+ const namespaceValue = resolveObjectPath(translations, namespace);
1650
+ const value = resolveObjectPath(namespaceValue, key);
1651
+ return typeof value === "string" ? value : null;
1652
+ }
1653
+ function getUnderverseDefaultTranslation(locale, namespace, key) {
1654
+ return resolveTranslationValue(defaultTranslations[locale] ?? defaultTranslations.en, namespace, key) ?? resolveTranslationValue(defaultTranslations.en, namespace, key) ?? key;
1655
+ }
1616
1656
  var TranslationContext = React4.createContext(null);
1617
1657
  var TranslationProvider = ({ children, locale = "en", translations }) => {
1618
1658
  const t = React4.useCallback(
@@ -1622,20 +1662,7 @@ var TranslationProvider = ({ children, locale = "en", translations }) => {
1622
1662
  ...defaultTranslations[locale],
1623
1663
  ...translations?.[locale]
1624
1664
  };
1625
- const parts = namespace.split(".");
1626
- let current = mergedTranslations;
1627
- for (const part of parts) {
1628
- if (current && typeof current === "object" && part in current) {
1629
- current = current[part];
1630
- } else {
1631
- return key;
1632
- }
1633
- }
1634
- if (current && typeof current === "object" && key in current) {
1635
- const value = current[key];
1636
- return typeof value === "string" ? value : key;
1637
- }
1638
- return key;
1665
+ return resolveTranslationValue(mergedTranslations, namespace, key) ?? key;
1639
1666
  };
1640
1667
  },
1641
1668
  [locale, translations]
@@ -1646,20 +1673,7 @@ var useUnderverseTranslations = (namespace) => {
1646
1673
  const context = React4.useContext(TranslationContext);
1647
1674
  if (!context) {
1648
1675
  return (key) => {
1649
- const parts = namespace.split(".");
1650
- let current = defaultTranslations.en;
1651
- for (const part of parts) {
1652
- if (current && typeof current === "object" && part in current) {
1653
- current = current[part];
1654
- } else {
1655
- return key;
1656
- }
1657
- }
1658
- if (current && typeof current === "object" && key in current) {
1659
- const value = current[key];
1660
- return typeof value === "string" ? value : key;
1661
- }
1662
- return key;
1676
+ return getUnderverseDefaultTranslation("en", namespace, key);
1663
1677
  };
1664
1678
  }
1665
1679
  return context.t(namespace);
@@ -1685,17 +1699,53 @@ var ForceInternalContext = React5.createContext(false);
1685
1699
  var ForceInternalTranslationsProvider = ({ children }) => {
1686
1700
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ForceInternalContext.Provider, { value: true, children });
1687
1701
  };
1702
+ function normalizeLocale(locale, fallback) {
1703
+ const normalized = locale?.toLowerCase().split("-")[0];
1704
+ if (normalized === "en" || normalized === "vi" || normalized === "ko" || normalized === "ja") {
1705
+ return normalized;
1706
+ }
1707
+ return fallback;
1708
+ }
1709
+ function isUnresolvedTranslation(value, namespace, key) {
1710
+ return value === key || value === `${namespace}.${key}`;
1711
+ }
1688
1712
  function useSmartTranslations(namespace) {
1689
1713
  const forceInternal = React5.useContext(ForceInternalContext);
1690
1714
  const internalT = useUnderverseTranslations(namespace);
1715
+ const internalLocale = useUnderverseLocale();
1691
1716
  if (forceInternal || !nextIntlHooks?.useTranslations) {
1692
1717
  return internalT;
1693
1718
  }
1719
+ let resolvedLocale = internalLocale;
1720
+ try {
1721
+ resolvedLocale = normalizeLocale(nextIntlHooks.useLocale?.(), internalLocale);
1722
+ } catch {
1723
+ resolvedLocale = internalLocale;
1724
+ }
1694
1725
  try {
1695
1726
  const nextIntlT = nextIntlHooks.useTranslations(namespace);
1696
- return nextIntlT;
1727
+ return (key) => {
1728
+ try {
1729
+ const translated = nextIntlT(key);
1730
+ if (!isUnresolvedTranslation(translated, namespace, key)) {
1731
+ return translated;
1732
+ }
1733
+ } catch {
1734
+ }
1735
+ const internalValue = internalT(key);
1736
+ if (internalValue !== key) {
1737
+ return internalValue;
1738
+ }
1739
+ return getUnderverseDefaultTranslation(resolvedLocale, namespace, key);
1740
+ };
1697
1741
  } catch {
1698
- return internalT;
1742
+ return (key) => {
1743
+ const internalValue = internalT(key);
1744
+ if (internalValue !== key) {
1745
+ return internalValue;
1746
+ }
1747
+ return getUnderverseDefaultTranslation(resolvedLocale, namespace, key);
1748
+ };
1699
1749
  }
1700
1750
  }
1701
1751
  function useSmartLocale() {
@@ -22400,6 +22450,23 @@ var defaultTranslations2 = {
22400
22450
  }
22401
22451
  }
22402
22452
  };
22453
+ function resolveObjectPath2(input, path) {
22454
+ const parts = path.split(".");
22455
+ let current = input;
22456
+ for (const part of parts) {
22457
+ if (current && typeof current === "object" && part in current) {
22458
+ current = current[part];
22459
+ } else {
22460
+ return null;
22461
+ }
22462
+ }
22463
+ return current;
22464
+ }
22465
+ function resolveTranslationValue2(translations, namespace, key) {
22466
+ const namespaceValue = resolveObjectPath2(translations, namespace);
22467
+ const value = resolveObjectPath2(namespaceValue, key);
22468
+ return typeof value === "string" ? value : null;
22469
+ }
22403
22470
  var TranslationContext2 = React70.createContext(null);
22404
22471
  var UnderverseProvider = ({ children, locale = "en", translations }) => {
22405
22472
  const t = React70.useCallback(
@@ -22409,20 +22476,7 @@ var UnderverseProvider = ({ children, locale = "en", translations }) => {
22409
22476
  ...defaultTranslations2[locale],
22410
22477
  ...translations
22411
22478
  };
22412
- const parts = namespace.split(".");
22413
- let current = mergedTranslations;
22414
- for (const part of parts) {
22415
- if (current && typeof current === "object" && part in current) {
22416
- current = current[part];
22417
- } else {
22418
- return key;
22419
- }
22420
- }
22421
- if (current && typeof current === "object" && key in current) {
22422
- const value = current[key];
22423
- return typeof value === "string" ? value : key;
22424
- }
22425
- return key;
22479
+ return resolveTranslationValue2(mergedTranslations, namespace, key) ?? key;
22426
22480
  };
22427
22481
  },
22428
22482
  [locale, translations]
@@ -22451,20 +22505,8 @@ function interpolate(template, params) {
22451
22505
  function getInternalTranslation(namespace, locale) {
22452
22506
  return (key, params) => {
22453
22507
  const localeTranslations = defaultTranslations2[locale] || defaultTranslations2.en;
22454
- const parts = namespace.split(".");
22455
- let current = localeTranslations;
22456
- for (const part of parts) {
22457
- if (current && typeof current === "object" && part in current) {
22458
- current = current[part];
22459
- } else {
22460
- return interpolate(key, params);
22461
- }
22462
- }
22463
- if (current && typeof current === "object" && key in current) {
22464
- const value = current[key];
22465
- return typeof value === "string" ? interpolate(value, params) : interpolate(key, params);
22466
- }
22467
- return interpolate(key, params);
22508
+ const value = resolveTranslationValue2(localeTranslations, namespace, key);
22509
+ return typeof value === "string" ? interpolate(value, params) : interpolate(key, params);
22468
22510
  };
22469
22511
  }
22470
22512
  function useTranslations(namespace) {
@@ -22525,7 +22567,6 @@ var import_extension_blockquote = __toESM(require("@tiptap/extension-blockquote"
22525
22567
  var import_extension_code = __toESM(require("@tiptap/extension-code"), 1);
22526
22568
  var import_extension_code_block_lowlight = __toESM(require("@tiptap/extension-code-block-lowlight"), 1);
22527
22569
  var import_extension_history = __toESM(require("@tiptap/extension-history"), 1);
22528
- var import_extension_placeholder = __toESM(require("@tiptap/extension-placeholder"), 1);
22529
22570
  var import_extension_link = __toESM(require("@tiptap/extension-link"), 1);
22530
22571
  var import_extension_text_style = require("@tiptap/extension-text-style");
22531
22572
  var import_extension_color = __toESM(require("@tiptap/extension-color"), 1);
@@ -22550,6 +22591,32 @@ var import_react47 = require("react");
22550
22591
  var import_lucide_react39 = require("lucide-react");
22551
22592
  var import_tippy = __toESM(require("tippy.js"), 1);
22552
22593
  var import_jsx_runtime79 = require("react/jsx-runtime");
22594
+ var DEFAULT_MESSAGES = {
22595
+ noResults: "No results",
22596
+ basicBlocks: "Basic Blocks",
22597
+ text: "Text",
22598
+ textDesc: "Start writing with plain text",
22599
+ heading1: "Heading 1",
22600
+ heading1Desc: "Large section heading",
22601
+ heading2: "Heading 2",
22602
+ heading2Desc: "Medium section heading",
22603
+ heading3: "Heading 3",
22604
+ heading3Desc: "Small section heading",
22605
+ bulletList: "Bullet List",
22606
+ bulletListDesc: "Create a simple bullet list",
22607
+ orderedList: "Numbered List",
22608
+ orderedListDesc: "Create a list with numbering",
22609
+ todoList: "Todo List",
22610
+ todoListDesc: "Track tasks with a todo list",
22611
+ quote: "Quote",
22612
+ quoteDesc: "Capture a quote",
22613
+ codeBlock: "Code Block",
22614
+ codeBlockDesc: "Display code with syntax highlighting",
22615
+ divider: "Divider",
22616
+ dividerDesc: "Visually divide blocks",
22617
+ table: "Table",
22618
+ tableDesc: "Insert a table"
22619
+ };
22553
22620
  var CommandList = (0, import_react47.forwardRef)((props, ref) => {
22554
22621
  const [selectedIndex, setSelectedIndex] = (0, import_react47.useState)(0);
22555
22622
  const listRef = (0, import_react47.useRef)(null);
@@ -22581,10 +22648,10 @@ var CommandList = (0, import_react47.forwardRef)((props, ref) => {
22581
22648
  }
22582
22649
  }));
22583
22650
  if (props.items.length === 0) {
22584
- return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "w-72 p-4 text-center text-sm text-muted-foreground", children: "No results" });
22651
+ return /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "w-72 p-4 text-center text-sm text-muted-foreground", children: props.messages.noResults });
22585
22652
  }
22586
22653
  return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { ref: listRef, className: "w-72 max-h-80 overflow-y-auto bg-card border border-border rounded-2xl shadow-lg", children: [
22587
- /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "px-3 py-2 border-b", children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Basic Blocks" }) }),
22654
+ /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "px-3 py-2 border-b", children: /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: props.messages.basicBlocks }) }),
22588
22655
  /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("div", { className: "p-1", children: props.items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)(
22589
22656
  "button",
22590
22657
  {
@@ -22617,92 +22684,92 @@ var CommandList = (0, import_react47.forwardRef)((props, ref) => {
22617
22684
  ] });
22618
22685
  });
22619
22686
  CommandList.displayName = "CommandList";
22620
- var getSuggestionItems = ({ query }) => {
22687
+ var getSuggestionItems = ({ query, messages }) => {
22621
22688
  return [
22622
22689
  {
22623
22690
  icon: import_lucide_react39.Type,
22624
- title: "Text",
22625
- description: "Start writing with plain text",
22691
+ title: messages.text,
22692
+ description: messages.textDesc,
22626
22693
  command: ({ editor, range }) => {
22627
22694
  editor.chain().focus().deleteRange(range).setParagraph().run();
22628
22695
  }
22629
22696
  },
22630
22697
  {
22631
22698
  icon: import_lucide_react39.Heading1,
22632
- title: "Heading 1",
22633
- description: "Large section heading",
22699
+ title: messages.heading1,
22700
+ description: messages.heading1Desc,
22634
22701
  command: ({ editor, range }) => {
22635
22702
  editor.chain().focus().deleteRange(range).setNode("heading", { level: 1 }).run();
22636
22703
  }
22637
22704
  },
22638
22705
  {
22639
22706
  icon: import_lucide_react39.Heading2,
22640
- title: "Heading 2",
22641
- description: "Medium section heading",
22707
+ title: messages.heading2,
22708
+ description: messages.heading2Desc,
22642
22709
  command: ({ editor, range }) => {
22643
22710
  editor.chain().focus().deleteRange(range).setNode("heading", { level: 2 }).run();
22644
22711
  }
22645
22712
  },
22646
22713
  {
22647
22714
  icon: import_lucide_react39.Heading3,
22648
- title: "Heading 3",
22649
- description: "Small section heading",
22715
+ title: messages.heading3,
22716
+ description: messages.heading3Desc,
22650
22717
  command: ({ editor, range }) => {
22651
22718
  editor.chain().focus().deleteRange(range).setNode("heading", { level: 3 }).run();
22652
22719
  }
22653
22720
  },
22654
22721
  {
22655
22722
  icon: import_lucide_react39.List,
22656
- title: "Bullet List",
22657
- description: "Create a simple bullet list",
22723
+ title: messages.bulletList,
22724
+ description: messages.bulletListDesc,
22658
22725
  command: ({ editor, range }) => {
22659
22726
  editor.chain().focus().deleteRange(range).toggleBulletList().run();
22660
22727
  }
22661
22728
  },
22662
22729
  {
22663
22730
  icon: import_lucide_react39.ListOrdered,
22664
- title: "Numbered List",
22665
- description: "Create a list with numbering",
22731
+ title: messages.orderedList,
22732
+ description: messages.orderedListDesc,
22666
22733
  command: ({ editor, range }) => {
22667
22734
  editor.chain().focus().deleteRange(range).toggleOrderedList().run();
22668
22735
  }
22669
22736
  },
22670
22737
  {
22671
22738
  icon: import_lucide_react39.ListTodo,
22672
- title: "Todo List",
22673
- description: "Track tasks with a todo list",
22739
+ title: messages.todoList,
22740
+ description: messages.todoListDesc,
22674
22741
  command: ({ editor, range }) => {
22675
22742
  editor.chain().focus().deleteRange(range).toggleTaskList().run();
22676
22743
  }
22677
22744
  },
22678
22745
  {
22679
22746
  icon: import_lucide_react39.Quote,
22680
- title: "Quote",
22681
- description: "Capture a quote",
22747
+ title: messages.quote,
22748
+ description: messages.quoteDesc,
22682
22749
  command: ({ editor, range }) => {
22683
22750
  editor.chain().focus().deleteRange(range).toggleBlockquote().run();
22684
22751
  }
22685
22752
  },
22686
22753
  {
22687
22754
  icon: import_lucide_react39.FileCode,
22688
- title: "Code Block",
22689
- description: "Display code with syntax highlighting",
22755
+ title: messages.codeBlock,
22756
+ description: messages.codeBlockDesc,
22690
22757
  command: ({ editor, range }) => {
22691
22758
  editor.chain().focus().deleteRange(range).toggleCodeBlock().run();
22692
22759
  }
22693
22760
  },
22694
22761
  {
22695
22762
  icon: import_lucide_react39.Minus,
22696
- title: "Divider",
22697
- description: "Visually divide blocks",
22763
+ title: messages.divider,
22764
+ description: messages.dividerDesc,
22698
22765
  command: ({ editor, range }) => {
22699
22766
  editor.chain().focus().deleteRange(range).setHorizontalRule().run();
22700
22767
  }
22701
22768
  },
22702
22769
  {
22703
22770
  icon: import_lucide_react39.Table,
22704
- title: "Table",
22705
- description: "Insert a table",
22771
+ title: messages.table,
22772
+ description: messages.tableDesc,
22706
22773
  command: ({ editor, range }) => {
22707
22774
  editor.chain().focus().deleteRange(range).insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run();
22708
22775
  }
@@ -22711,7 +22778,13 @@ var getSuggestionItems = ({ query }) => {
22711
22778
  };
22712
22779
  var SlashCommand = import_core.Extension.create({
22713
22780
  name: "slashCommand",
22781
+ addOptions() {
22782
+ return {
22783
+ messages: DEFAULT_MESSAGES
22784
+ };
22785
+ },
22714
22786
  addProseMirrorPlugins() {
22787
+ const messages = this.options.messages;
22715
22788
  return [
22716
22789
  (0, import_suggestion.default)({
22717
22790
  editor: this.editor,
@@ -22719,14 +22792,17 @@ var SlashCommand = import_core.Extension.create({
22719
22792
  command: ({ editor, range, props }) => {
22720
22793
  props.command({ editor, range });
22721
22794
  },
22722
- items: getSuggestionItems,
22795
+ items: ({ query, editor }) => getSuggestionItems({ query, editor, messages }),
22723
22796
  render: () => {
22724
22797
  let component;
22725
22798
  let popup;
22726
22799
  return {
22727
22800
  onStart: (props) => {
22728
22801
  component = new import_react46.ReactRenderer(CommandList, {
22729
- props,
22802
+ props: {
22803
+ ...props,
22804
+ messages
22805
+ },
22730
22806
  editor: props.editor
22731
22807
  });
22732
22808
  if (!props.clientRect) {
@@ -22743,7 +22819,10 @@ var SlashCommand = import_core.Extension.create({
22743
22819
  });
22744
22820
  },
22745
22821
  onUpdate(props) {
22746
- component?.updateProps(props);
22822
+ component?.updateProps({
22823
+ ...props,
22824
+ messages
22825
+ });
22747
22826
  if (!props.clientRect) {
22748
22827
  return;
22749
22828
  }
@@ -23776,10 +23855,83 @@ var EmojiSuggestion = import_core3.Extension.create({
23776
23855
  }
23777
23856
  });
23778
23857
 
23858
+ // src/components/UEditor/placeholder.ts
23859
+ var import_core4 = require("@tiptap/core");
23860
+ var import_state3 = require("@tiptap/pm/state");
23861
+ var import_view = require("@tiptap/pm/view");
23862
+ var UEditorPlaceholder = import_core4.Extension.create({
23863
+ name: "placeholder",
23864
+ addOptions() {
23865
+ return {
23866
+ emptyEditorClass: "is-editor-empty",
23867
+ emptyNodeClass: "is-empty",
23868
+ dataAttribute: "placeholder",
23869
+ placeholder: "Write something...",
23870
+ showOnlyWhenEditable: true,
23871
+ showOnlyCurrent: true,
23872
+ includeChildren: false,
23873
+ shouldShow: () => true
23874
+ };
23875
+ },
23876
+ addProseMirrorPlugins() {
23877
+ const dataAttribute = `data-${this.options.dataAttribute}`;
23878
+ return [
23879
+ new import_state3.Plugin({
23880
+ key: new import_state3.PluginKey("placeholder"),
23881
+ props: {
23882
+ decorations: ({ doc, selection }) => {
23883
+ const active = this.editor.isEditable || !this.options.showOnlyWhenEditable;
23884
+ const { anchor } = selection;
23885
+ const decorations = [];
23886
+ let hasTable = false;
23887
+ if (!active) {
23888
+ return null;
23889
+ }
23890
+ const isEmptyDoc = this.editor.isEmpty;
23891
+ doc.descendants((node) => {
23892
+ if (node.type.name === "table") {
23893
+ hasTable = true;
23894
+ return false;
23895
+ }
23896
+ return void 0;
23897
+ });
23898
+ doc.descendants((node, pos) => {
23899
+ const hasAnchor = anchor >= pos && anchor <= pos + node.nodeSize;
23900
+ const isEmpty = !node.isLeaf && (0, import_core4.isNodeEmpty)(node);
23901
+ if (!((hasAnchor || !this.options.showOnlyCurrent) && isEmpty)) {
23902
+ return this.options.includeChildren;
23903
+ }
23904
+ if (!this.options.shouldShow({ editor: this.editor, node, pos, hasAnchor, isEmptyDoc, hasTable })) {
23905
+ return this.options.includeChildren;
23906
+ }
23907
+ const placeholderValue = typeof this.options.placeholder === "function" ? this.options.placeholder({ editor: this.editor, node, pos, hasAnchor }) : this.options.placeholder;
23908
+ if (!placeholderValue) {
23909
+ return this.options.includeChildren;
23910
+ }
23911
+ const classes = [this.options.emptyNodeClass];
23912
+ if (isEmptyDoc) {
23913
+ classes.push(this.options.emptyEditorClass);
23914
+ }
23915
+ decorations.push(
23916
+ import_view.Decoration.node(pos, pos + node.nodeSize, {
23917
+ class: classes.join(" "),
23918
+ [dataAttribute]: placeholderValue
23919
+ })
23920
+ );
23921
+ return this.options.includeChildren;
23922
+ });
23923
+ return import_view.DecorationSet.create(doc, decorations);
23924
+ }
23925
+ }
23926
+ })
23927
+ ];
23928
+ }
23929
+ });
23930
+
23779
23931
  // src/components/UEditor/resizable-image.tsx
23780
23932
  var import_react50 = require("react");
23781
23933
  var import_extension_image = __toESM(require("@tiptap/extension-image"), 1);
23782
- var import_core4 = require("@tiptap/core");
23934
+ var import_core5 = require("@tiptap/core");
23783
23935
  var import_react51 = require("@tiptap/react");
23784
23936
  var import_jsx_runtime81 = require("react/jsx-runtime");
23785
23937
  var MIN_IMAGE_SIZE_PX = 40;
@@ -23978,7 +24130,7 @@ var ResizableImage = import_extension_image.default.extend({
23978
24130
  };
23979
24131
  },
23980
24132
  renderHTML({ HTMLAttributes }) {
23981
- return ["img", (0, import_core4.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes)];
24133
+ return ["img", (0, import_core5.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes)];
23982
24134
  },
23983
24135
  addNodeView() {
23984
24136
  return (0, import_react51.ReactNodeViewRenderer)(ResizableImageNodeView);
@@ -23995,6 +24147,7 @@ var resizable_image_default = ResizableImage;
23995
24147
  var lowlight = (0, import_lowlight.createLowlight)(import_lowlight.common);
23996
24148
  function buildUEditorExtensions({
23997
24149
  placeholder,
24150
+ translate,
23998
24151
  maxCharacters,
23999
24152
  uploadImage,
24000
24153
  imageInsertMode = "base64",
@@ -24087,12 +24240,49 @@ function buildUEditorExtensions({
24087
24240
  }),
24088
24241
  import_extension_typography.default,
24089
24242
  import_extension_history.default,
24090
- import_extension_placeholder.default.configure({
24243
+ UEditorPlaceholder.configure({
24091
24244
  placeholder,
24092
24245
  emptyEditorClass: "is-editor-empty",
24093
- emptyNodeClass: "is-empty"
24246
+ emptyNodeClass: "is-empty",
24247
+ shouldShow: ({ node, hasTable }) => {
24248
+ const nodeName = node.type.name;
24249
+ if (nodeName === "table" || nodeName === "tableCell" || nodeName === "tableHeader") {
24250
+ return false;
24251
+ }
24252
+ if (hasTable) {
24253
+ return false;
24254
+ }
24255
+ return true;
24256
+ }
24257
+ }),
24258
+ SlashCommand.configure({
24259
+ messages: {
24260
+ noResults: translate("slashCommand.noResults"),
24261
+ basicBlocks: translate("slashCommand.basicBlocks"),
24262
+ text: translate("slashCommand.text"),
24263
+ textDesc: translate("slashCommand.textDesc"),
24264
+ heading1: translate("slashCommand.heading1"),
24265
+ heading1Desc: translate("slashCommand.heading1Desc"),
24266
+ heading2: translate("slashCommand.heading2"),
24267
+ heading2Desc: translate("slashCommand.heading2Desc"),
24268
+ heading3: translate("slashCommand.heading3"),
24269
+ heading3Desc: translate("slashCommand.heading3Desc"),
24270
+ bulletList: translate("slashCommand.bulletList"),
24271
+ bulletListDesc: translate("slashCommand.bulletListDesc"),
24272
+ orderedList: translate("slashCommand.orderedList"),
24273
+ orderedListDesc: translate("slashCommand.orderedListDesc"),
24274
+ todoList: translate("slashCommand.todoList"),
24275
+ todoListDesc: translate("slashCommand.todoListDesc"),
24276
+ quote: translate("slashCommand.quote"),
24277
+ quoteDesc: translate("slashCommand.quoteDesc"),
24278
+ codeBlock: translate("slashCommand.codeBlock"),
24279
+ codeBlockDesc: translate("slashCommand.codeBlockDesc"),
24280
+ divider: translate("slashCommand.divider"),
24281
+ dividerDesc: translate("slashCommand.dividerDesc"),
24282
+ table: translate("slashCommand.table"),
24283
+ tableDesc: translate("slashCommand.tableDesc")
24284
+ }
24094
24285
  }),
24095
- SlashCommand,
24096
24286
  EmojiSuggestion
24097
24287
  ];
24098
24288
  }
@@ -24279,6 +24469,7 @@ var CATEGORY_ICONS = {
24279
24469
  "flags": import_lucide_react43.Flag
24280
24470
  };
24281
24471
  var EmojiPicker = ({ onSelect, onClose }) => {
24472
+ const t = useSmartTranslations("UEditor");
24282
24473
  const [search, setSearch] = (0, import_react54.useState)("");
24283
24474
  const [activeCategory, setActiveCategory] = (0, import_react54.useState)(EMOJI_LIST[0]?.id || "");
24284
24475
  const scrollContainerRef = (0, import_react54.useRef)(null);
@@ -24348,7 +24539,7 @@ var EmojiPicker = ({ onSelect, onClose }) => {
24348
24539
  "input",
24349
24540
  {
24350
24541
  type: "text",
24351
- placeholder: "T\xECm ki\u1EBFm bi\u1EC3u t\u01B0\u1EE3ng c\u1EA3m x\xFAc",
24542
+ placeholder: t("emojiPicker.searchPlaceholder"),
24352
24543
  value: search,
24353
24544
  onChange: (e) => setSearch(e.target.value),
24354
24545
  className: cn(
@@ -24394,8 +24585,8 @@ var EmojiPicker = ({ onSelect, onClose }) => {
24394
24585
  )) })
24395
24586
  ] }, category.id)) : /* @__PURE__ */ (0, import_jsx_runtime84.jsxs)("div", { className: "flex flex-col items-center justify-center h-full text-center", children: [
24396
24587
  /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "text-4xl mb-2", children: "\u{1F50D}" }),
24397
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "text-sm font-medium text-muted-foreground", children: "Kh\xF4ng t\xECm th\u1EA5y emoji" }),
24398
- /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "text-xs text-muted-foreground mt-1", children: "Th\u1EED t\u1EEB kh\xF3a kh\xE1c" })
24588
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "text-sm font-medium text-muted-foreground", children: t("emojiPicker.noResults") }),
24589
+ /* @__PURE__ */ (0, import_jsx_runtime84.jsx)("div", { className: "text-xs text-muted-foreground mt-1", children: t("emojiPicker.tryDifferentSearch") })
24399
24590
  ] })
24400
24591
  ) : (
24401
24592
  // All Categories - Messenger Style
@@ -25665,8 +25856,8 @@ var UEditor = import_react57.default.forwardRef(({
25665
25856
  const effectivePlaceholder = placeholder ?? t("placeholder");
25666
25857
  const inFlightPrepareRef = (0, import_react57.useRef)(null);
25667
25858
  const extensions = (0, import_react57.useMemo)(
25668
- () => buildUEditorExtensions({ placeholder: effectivePlaceholder, maxCharacters, uploadImage, imageInsertMode, editable }),
25669
- [effectivePlaceholder, maxCharacters, uploadImage, imageInsertMode, editable]
25859
+ () => buildUEditorExtensions({ placeholder: effectivePlaceholder, translate: t, maxCharacters, uploadImage, imageInsertMode, editable }),
25860
+ [effectivePlaceholder, t, maxCharacters, uploadImage, imageInsertMode, editable]
25670
25861
  );
25671
25862
  const editor = (0, import_react58.useEditor)({
25672
25863
  immediatelyRender: false,