@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.
package/dist/index.js CHANGED
@@ -748,6 +748,11 @@ var en_default = {
748
748
  cancelBtn: "Cancel",
749
749
  addFromUrl: "Add from URL"
750
750
  },
751
+ emojiPicker: {
752
+ searchPlaceholder: "Search emoji",
753
+ noResults: "No emoji found",
754
+ tryDifferentSearch: "Try a different keyword"
755
+ },
751
756
  tableMenu: {
752
757
  insert3x3: "Insert 3\xD73 Table",
753
758
  addColumnBefore: "Add Column Before",
@@ -967,6 +972,11 @@ var vi_default = {
967
972
  cancelBtn: "H\u1EE7y",
968
973
  addFromUrl: "Th\xEAm t\u1EEB URL"
969
974
  },
975
+ emojiPicker: {
976
+ searchPlaceholder: "T\xECm ki\u1EBFm bi\u1EC3u t\u01B0\u1EE3ng c\u1EA3m x\xFAc",
977
+ noResults: "Kh\xF4ng t\xECm th\u1EA5y emoji",
978
+ tryDifferentSearch: "Th\u1EED t\u1EEB kh\xF3a kh\xE1c"
979
+ },
970
980
  tableMenu: {
971
981
  insert3x3: "Ch\xE8n b\u1EA3ng 3\xD73",
972
982
  addColumnBefore: "Th\xEAm c\u1ED9t tr\u01B0\u1EDBc",
@@ -1185,6 +1195,11 @@ var ko_default = {
1185
1195
  cancelBtn: "\uCDE8\uC18C",
1186
1196
  addFromUrl: "URL\uC5D0\uC11C \uCD94\uAC00"
1187
1197
  },
1198
+ emojiPicker: {
1199
+ searchPlaceholder: "\uC774\uBAA8\uC9C0 \uAC80\uC0C9",
1200
+ noResults: "\uC774\uBAA8\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
1201
+ tryDifferentSearch: "\uB2E4\uB978 \uAC80\uC0C9\uC5B4\uB97C \uC2DC\uB3C4\uD574 \uBCF4\uC138\uC694"
1202
+ },
1188
1203
  tableMenu: {
1189
1204
  insert3x3: "3x3 \uD45C \uC0BD\uC785",
1190
1205
  addColumnBefore: "\uC55E\uC5D0 \uC5F4 \uCD94\uAC00",
@@ -1403,6 +1418,11 @@ var ja_default = {
1403
1418
  cancelBtn: "\u30AD\u30E3\u30F3\u30BB\u30EB",
1404
1419
  addFromUrl: "URL\u304B\u3089\u8FFD\u52A0"
1405
1420
  },
1421
+ emojiPicker: {
1422
+ searchPlaceholder: "\u7D75\u6587\u5B57\u3092\u691C\u7D22",
1423
+ noResults: "\u7D75\u6587\u5B57\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093",
1424
+ tryDifferentSearch: "\u5225\u306E\u30AD\u30FC\u30EF\u30FC\u30C9\u3067\u304A\u8A66\u3057\u304F\u3060\u3055\u3044"
1425
+ },
1406
1426
  tableMenu: {
1407
1427
  insert3x3: "3x3 \u8868\u3092\u633F\u5165",
1408
1428
  addColumnBefore: "\u524D\u306B\u5217\u3092\u8FFD\u52A0",
@@ -1424,6 +1444,26 @@ var defaultTranslations = {
1424
1444
  ko: ko_default,
1425
1445
  ja: ja_default
1426
1446
  };
1447
+ function resolveObjectPath(input, path) {
1448
+ const parts = path.split(".");
1449
+ let current = input;
1450
+ for (const part of parts) {
1451
+ if (current && typeof current === "object" && part in current) {
1452
+ current = current[part];
1453
+ } else {
1454
+ return null;
1455
+ }
1456
+ }
1457
+ return current;
1458
+ }
1459
+ function resolveTranslationValue(translations, namespace, key) {
1460
+ const namespaceValue = resolveObjectPath(translations, namespace);
1461
+ const value = resolveObjectPath(namespaceValue, key);
1462
+ return typeof value === "string" ? value : null;
1463
+ }
1464
+ function getUnderverseDefaultTranslation(locale, namespace, key) {
1465
+ return resolveTranslationValue(defaultTranslations[locale] ?? defaultTranslations.en, namespace, key) ?? resolveTranslationValue(defaultTranslations.en, namespace, key) ?? key;
1466
+ }
1427
1467
  var TranslationContext = React4.createContext(null);
1428
1468
  var TranslationProvider = ({ children, locale = "en", translations }) => {
1429
1469
  const t = React4.useCallback(
@@ -1433,20 +1473,7 @@ var TranslationProvider = ({ children, locale = "en", translations }) => {
1433
1473
  ...defaultTranslations[locale],
1434
1474
  ...translations?.[locale]
1435
1475
  };
1436
- const parts = namespace.split(".");
1437
- let current = mergedTranslations;
1438
- for (const part of parts) {
1439
- if (current && typeof current === "object" && part in current) {
1440
- current = current[part];
1441
- } else {
1442
- return key;
1443
- }
1444
- }
1445
- if (current && typeof current === "object" && key in current) {
1446
- const value = current[key];
1447
- return typeof value === "string" ? value : key;
1448
- }
1449
- return key;
1476
+ return resolveTranslationValue(mergedTranslations, namespace, key) ?? key;
1450
1477
  };
1451
1478
  },
1452
1479
  [locale, translations]
@@ -1457,20 +1484,7 @@ var useUnderverseTranslations = (namespace) => {
1457
1484
  const context = React4.useContext(TranslationContext);
1458
1485
  if (!context) {
1459
1486
  return (key) => {
1460
- const parts = namespace.split(".");
1461
- let current = defaultTranslations.en;
1462
- for (const part of parts) {
1463
- if (current && typeof current === "object" && part in current) {
1464
- current = current[part];
1465
- } else {
1466
- return key;
1467
- }
1468
- }
1469
- if (current && typeof current === "object" && key in current) {
1470
- const value = current[key];
1471
- return typeof value === "string" ? value : key;
1472
- }
1473
- return key;
1487
+ return getUnderverseDefaultTranslation("en", namespace, key);
1474
1488
  };
1475
1489
  }
1476
1490
  return context.t(namespace);
@@ -1496,17 +1510,53 @@ var ForceInternalContext = React5.createContext(false);
1496
1510
  var ForceInternalTranslationsProvider = ({ children }) => {
1497
1511
  return /* @__PURE__ */ jsx6(ForceInternalContext.Provider, { value: true, children });
1498
1512
  };
1513
+ function normalizeLocale(locale, fallback) {
1514
+ const normalized = locale?.toLowerCase().split("-")[0];
1515
+ if (normalized === "en" || normalized === "vi" || normalized === "ko" || normalized === "ja") {
1516
+ return normalized;
1517
+ }
1518
+ return fallback;
1519
+ }
1520
+ function isUnresolvedTranslation(value, namespace, key) {
1521
+ return value === key || value === `${namespace}.${key}`;
1522
+ }
1499
1523
  function useSmartTranslations(namespace) {
1500
1524
  const forceInternal = React5.useContext(ForceInternalContext);
1501
1525
  const internalT = useUnderverseTranslations(namespace);
1526
+ const internalLocale = useUnderverseLocale();
1502
1527
  if (forceInternal || !nextIntlHooks?.useTranslations) {
1503
1528
  return internalT;
1504
1529
  }
1530
+ let resolvedLocale = internalLocale;
1531
+ try {
1532
+ resolvedLocale = normalizeLocale(nextIntlHooks.useLocale?.(), internalLocale);
1533
+ } catch {
1534
+ resolvedLocale = internalLocale;
1535
+ }
1505
1536
  try {
1506
1537
  const nextIntlT = nextIntlHooks.useTranslations(namespace);
1507
- return nextIntlT;
1538
+ return (key) => {
1539
+ try {
1540
+ const translated = nextIntlT(key);
1541
+ if (!isUnresolvedTranslation(translated, namespace, key)) {
1542
+ return translated;
1543
+ }
1544
+ } catch {
1545
+ }
1546
+ const internalValue = internalT(key);
1547
+ if (internalValue !== key) {
1548
+ return internalValue;
1549
+ }
1550
+ return getUnderverseDefaultTranslation(resolvedLocale, namespace, key);
1551
+ };
1508
1552
  } catch {
1509
- return internalT;
1553
+ return (key) => {
1554
+ const internalValue = internalT(key);
1555
+ if (internalValue !== key) {
1556
+ return internalValue;
1557
+ }
1558
+ return getUnderverseDefaultTranslation(resolvedLocale, namespace, key);
1559
+ };
1510
1560
  }
1511
1561
  }
1512
1562
  function useSmartLocale() {
@@ -22227,6 +22277,23 @@ var defaultTranslations2 = {
22227
22277
  }
22228
22278
  }
22229
22279
  };
22280
+ function resolveObjectPath2(input, path) {
22281
+ const parts = path.split(".");
22282
+ let current = input;
22283
+ for (const part of parts) {
22284
+ if (current && typeof current === "object" && part in current) {
22285
+ current = current[part];
22286
+ } else {
22287
+ return null;
22288
+ }
22289
+ }
22290
+ return current;
22291
+ }
22292
+ function resolveTranslationValue2(translations, namespace, key) {
22293
+ const namespaceValue = resolveObjectPath2(translations, namespace);
22294
+ const value = resolveObjectPath2(namespaceValue, key);
22295
+ return typeof value === "string" ? value : null;
22296
+ }
22230
22297
  var TranslationContext2 = React70.createContext(null);
22231
22298
  var UnderverseProvider = ({ children, locale = "en", translations }) => {
22232
22299
  const t = React70.useCallback(
@@ -22236,20 +22303,7 @@ var UnderverseProvider = ({ children, locale = "en", translations }) => {
22236
22303
  ...defaultTranslations2[locale],
22237
22304
  ...translations
22238
22305
  };
22239
- const parts = namespace.split(".");
22240
- let current = mergedTranslations;
22241
- for (const part of parts) {
22242
- if (current && typeof current === "object" && part in current) {
22243
- current = current[part];
22244
- } else {
22245
- return key;
22246
- }
22247
- }
22248
- if (current && typeof current === "object" && key in current) {
22249
- const value = current[key];
22250
- return typeof value === "string" ? value : key;
22251
- }
22252
- return key;
22306
+ return resolveTranslationValue2(mergedTranslations, namespace, key) ?? key;
22253
22307
  };
22254
22308
  },
22255
22309
  [locale, translations]
@@ -22278,20 +22332,8 @@ function interpolate(template, params) {
22278
22332
  function getInternalTranslation(namespace, locale) {
22279
22333
  return (key, params) => {
22280
22334
  const localeTranslations = defaultTranslations2[locale] || defaultTranslations2.en;
22281
- const parts = namespace.split(".");
22282
- let current = localeTranslations;
22283
- for (const part of parts) {
22284
- if (current && typeof current === "object" && part in current) {
22285
- current = current[part];
22286
- } else {
22287
- return interpolate(key, params);
22288
- }
22289
- }
22290
- if (current && typeof current === "object" && key in current) {
22291
- const value = current[key];
22292
- return typeof value === "string" ? interpolate(value, params) : interpolate(key, params);
22293
- }
22294
- return interpolate(key, params);
22335
+ const value = resolveTranslationValue2(localeTranslations, namespace, key);
22336
+ return typeof value === "string" ? interpolate(value, params) : interpolate(key, params);
22295
22337
  };
22296
22338
  }
22297
22339
  function useTranslations(namespace) {
@@ -22352,7 +22394,6 @@ import Blockquote from "@tiptap/extension-blockquote";
22352
22394
  import Code from "@tiptap/extension-code";
22353
22395
  import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
22354
22396
  import History2 from "@tiptap/extension-history";
22355
- import Placeholder from "@tiptap/extension-placeholder";
22356
22397
  import Link from "@tiptap/extension-link";
22357
22398
  import { TextStyle } from "@tiptap/extension-text-style";
22358
22399
  import Color from "@tiptap/extension-color";
@@ -22389,6 +22430,32 @@ import {
22389
22430
  } from "lucide-react";
22390
22431
  import tippy from "tippy.js";
22391
22432
  import { jsx as jsx79, jsxs as jsxs69 } from "react/jsx-runtime";
22433
+ var DEFAULT_MESSAGES = {
22434
+ noResults: "No results",
22435
+ basicBlocks: "Basic Blocks",
22436
+ text: "Text",
22437
+ textDesc: "Start writing with plain text",
22438
+ heading1: "Heading 1",
22439
+ heading1Desc: "Large section heading",
22440
+ heading2: "Heading 2",
22441
+ heading2Desc: "Medium section heading",
22442
+ heading3: "Heading 3",
22443
+ heading3Desc: "Small section heading",
22444
+ bulletList: "Bullet List",
22445
+ bulletListDesc: "Create a simple bullet list",
22446
+ orderedList: "Numbered List",
22447
+ orderedListDesc: "Create a list with numbering",
22448
+ todoList: "Todo List",
22449
+ todoListDesc: "Track tasks with a todo list",
22450
+ quote: "Quote",
22451
+ quoteDesc: "Capture a quote",
22452
+ codeBlock: "Code Block",
22453
+ codeBlockDesc: "Display code with syntax highlighting",
22454
+ divider: "Divider",
22455
+ dividerDesc: "Visually divide blocks",
22456
+ table: "Table",
22457
+ tableDesc: "Insert a table"
22458
+ };
22392
22459
  var CommandList = forwardRef13((props, ref) => {
22393
22460
  const [selectedIndex, setSelectedIndex] = useState47(0);
22394
22461
  const listRef = useRef30(null);
@@ -22420,10 +22487,10 @@ var CommandList = forwardRef13((props, ref) => {
22420
22487
  }
22421
22488
  }));
22422
22489
  if (props.items.length === 0) {
22423
- return /* @__PURE__ */ jsx79("div", { className: "w-72 p-4 text-center text-sm text-muted-foreground", children: "No results" });
22490
+ return /* @__PURE__ */ jsx79("div", { className: "w-72 p-4 text-center text-sm text-muted-foreground", children: props.messages.noResults });
22424
22491
  }
22425
22492
  return /* @__PURE__ */ jsxs69("div", { ref: listRef, className: "w-72 max-h-80 overflow-y-auto bg-card border border-border rounded-2xl shadow-lg", children: [
22426
- /* @__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: "Basic Blocks" }) }),
22493
+ /* @__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 }) }),
22427
22494
  /* @__PURE__ */ jsx79("div", { className: "p-1", children: props.items.map((item, index) => /* @__PURE__ */ jsxs69(
22428
22495
  "button",
22429
22496
  {
@@ -22456,92 +22523,92 @@ var CommandList = forwardRef13((props, ref) => {
22456
22523
  ] });
22457
22524
  });
22458
22525
  CommandList.displayName = "CommandList";
22459
- var getSuggestionItems = ({ query }) => {
22526
+ var getSuggestionItems = ({ query, messages }) => {
22460
22527
  return [
22461
22528
  {
22462
22529
  icon: Type,
22463
- title: "Text",
22464
- description: "Start writing with plain text",
22530
+ title: messages.text,
22531
+ description: messages.textDesc,
22465
22532
  command: ({ editor, range }) => {
22466
22533
  editor.chain().focus().deleteRange(range).setParagraph().run();
22467
22534
  }
22468
22535
  },
22469
22536
  {
22470
22537
  icon: Heading1,
22471
- title: "Heading 1",
22472
- description: "Large section heading",
22538
+ title: messages.heading1,
22539
+ description: messages.heading1Desc,
22473
22540
  command: ({ editor, range }) => {
22474
22541
  editor.chain().focus().deleteRange(range).setNode("heading", { level: 1 }).run();
22475
22542
  }
22476
22543
  },
22477
22544
  {
22478
22545
  icon: Heading2,
22479
- title: "Heading 2",
22480
- description: "Medium section heading",
22546
+ title: messages.heading2,
22547
+ description: messages.heading2Desc,
22481
22548
  command: ({ editor, range }) => {
22482
22549
  editor.chain().focus().deleteRange(range).setNode("heading", { level: 2 }).run();
22483
22550
  }
22484
22551
  },
22485
22552
  {
22486
22553
  icon: Heading3,
22487
- title: "Heading 3",
22488
- description: "Small section heading",
22554
+ title: messages.heading3,
22555
+ description: messages.heading3Desc,
22489
22556
  command: ({ editor, range }) => {
22490
22557
  editor.chain().focus().deleteRange(range).setNode("heading", { level: 3 }).run();
22491
22558
  }
22492
22559
  },
22493
22560
  {
22494
22561
  icon: List3,
22495
- title: "Bullet List",
22496
- description: "Create a simple bullet list",
22562
+ title: messages.bulletList,
22563
+ description: messages.bulletListDesc,
22497
22564
  command: ({ editor, range }) => {
22498
22565
  editor.chain().focus().deleteRange(range).toggleBulletList().run();
22499
22566
  }
22500
22567
  },
22501
22568
  {
22502
22569
  icon: ListOrdered,
22503
- title: "Numbered List",
22504
- description: "Create a list with numbering",
22570
+ title: messages.orderedList,
22571
+ description: messages.orderedListDesc,
22505
22572
  command: ({ editor, range }) => {
22506
22573
  editor.chain().focus().deleteRange(range).toggleOrderedList().run();
22507
22574
  }
22508
22575
  },
22509
22576
  {
22510
22577
  icon: ListTodo,
22511
- title: "Todo List",
22512
- description: "Track tasks with a todo list",
22578
+ title: messages.todoList,
22579
+ description: messages.todoListDesc,
22513
22580
  command: ({ editor, range }) => {
22514
22581
  editor.chain().focus().deleteRange(range).toggleTaskList().run();
22515
22582
  }
22516
22583
  },
22517
22584
  {
22518
22585
  icon: Quote,
22519
- title: "Quote",
22520
- description: "Capture a quote",
22586
+ title: messages.quote,
22587
+ description: messages.quoteDesc,
22521
22588
  command: ({ editor, range }) => {
22522
22589
  editor.chain().focus().deleteRange(range).toggleBlockquote().run();
22523
22590
  }
22524
22591
  },
22525
22592
  {
22526
22593
  icon: FileCode2,
22527
- title: "Code Block",
22528
- description: "Display code with syntax highlighting",
22594
+ title: messages.codeBlock,
22595
+ description: messages.codeBlockDesc,
22529
22596
  command: ({ editor, range }) => {
22530
22597
  editor.chain().focus().deleteRange(range).toggleCodeBlock().run();
22531
22598
  }
22532
22599
  },
22533
22600
  {
22534
22601
  icon: Minus,
22535
- title: "Divider",
22536
- description: "Visually divide blocks",
22602
+ title: messages.divider,
22603
+ description: messages.dividerDesc,
22537
22604
  command: ({ editor, range }) => {
22538
22605
  editor.chain().focus().deleteRange(range).setHorizontalRule().run();
22539
22606
  }
22540
22607
  },
22541
22608
  {
22542
22609
  icon: Table2,
22543
- title: "Table",
22544
- description: "Insert a table",
22610
+ title: messages.table,
22611
+ description: messages.tableDesc,
22545
22612
  command: ({ editor, range }) => {
22546
22613
  editor.chain().focus().deleteRange(range).insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run();
22547
22614
  }
@@ -22550,7 +22617,13 @@ var getSuggestionItems = ({ query }) => {
22550
22617
  };
22551
22618
  var SlashCommand = Extension.create({
22552
22619
  name: "slashCommand",
22620
+ addOptions() {
22621
+ return {
22622
+ messages: DEFAULT_MESSAGES
22623
+ };
22624
+ },
22553
22625
  addProseMirrorPlugins() {
22626
+ const messages = this.options.messages;
22554
22627
  return [
22555
22628
  Suggestion({
22556
22629
  editor: this.editor,
@@ -22558,14 +22631,17 @@ var SlashCommand = Extension.create({
22558
22631
  command: ({ editor, range, props }) => {
22559
22632
  props.command({ editor, range });
22560
22633
  },
22561
- items: getSuggestionItems,
22634
+ items: ({ query, editor }) => getSuggestionItems({ query, editor, messages }),
22562
22635
  render: () => {
22563
22636
  let component;
22564
22637
  let popup;
22565
22638
  return {
22566
22639
  onStart: (props) => {
22567
22640
  component = new ReactRenderer(CommandList, {
22568
- props,
22641
+ props: {
22642
+ ...props,
22643
+ messages
22644
+ },
22569
22645
  editor: props.editor
22570
22646
  });
22571
22647
  if (!props.clientRect) {
@@ -22582,7 +22658,10 @@ var SlashCommand = Extension.create({
22582
22658
  });
22583
22659
  },
22584
22660
  onUpdate(props) {
22585
- component?.updateProps(props);
22661
+ component?.updateProps({
22662
+ ...props,
22663
+ messages
22664
+ });
22586
22665
  if (!props.clientRect) {
22587
22666
  return;
22588
22667
  }
@@ -23615,6 +23694,79 @@ var EmojiSuggestion = Extension3.create({
23615
23694
  }
23616
23695
  });
23617
23696
 
23697
+ // src/components/UEditor/placeholder.ts
23698
+ import { Extension as Extension4, isNodeEmpty } from "@tiptap/core";
23699
+ import { Plugin as Plugin2, PluginKey as PluginKey2 } from "@tiptap/pm/state";
23700
+ import { Decoration, DecorationSet } from "@tiptap/pm/view";
23701
+ var UEditorPlaceholder = Extension4.create({
23702
+ name: "placeholder",
23703
+ addOptions() {
23704
+ return {
23705
+ emptyEditorClass: "is-editor-empty",
23706
+ emptyNodeClass: "is-empty",
23707
+ dataAttribute: "placeholder",
23708
+ placeholder: "Write something...",
23709
+ showOnlyWhenEditable: true,
23710
+ showOnlyCurrent: true,
23711
+ includeChildren: false,
23712
+ shouldShow: () => true
23713
+ };
23714
+ },
23715
+ addProseMirrorPlugins() {
23716
+ const dataAttribute = `data-${this.options.dataAttribute}`;
23717
+ return [
23718
+ new Plugin2({
23719
+ key: new PluginKey2("placeholder"),
23720
+ props: {
23721
+ decorations: ({ doc, selection }) => {
23722
+ const active = this.editor.isEditable || !this.options.showOnlyWhenEditable;
23723
+ const { anchor } = selection;
23724
+ const decorations = [];
23725
+ let hasTable = false;
23726
+ if (!active) {
23727
+ return null;
23728
+ }
23729
+ const isEmptyDoc = this.editor.isEmpty;
23730
+ doc.descendants((node) => {
23731
+ if (node.type.name === "table") {
23732
+ hasTable = true;
23733
+ return false;
23734
+ }
23735
+ return void 0;
23736
+ });
23737
+ doc.descendants((node, pos) => {
23738
+ const hasAnchor = anchor >= pos && anchor <= pos + node.nodeSize;
23739
+ const isEmpty = !node.isLeaf && isNodeEmpty(node);
23740
+ if (!((hasAnchor || !this.options.showOnlyCurrent) && isEmpty)) {
23741
+ return this.options.includeChildren;
23742
+ }
23743
+ if (!this.options.shouldShow({ editor: this.editor, node, pos, hasAnchor, isEmptyDoc, hasTable })) {
23744
+ return this.options.includeChildren;
23745
+ }
23746
+ const placeholderValue = typeof this.options.placeholder === "function" ? this.options.placeholder({ editor: this.editor, node, pos, hasAnchor }) : this.options.placeholder;
23747
+ if (!placeholderValue) {
23748
+ return this.options.includeChildren;
23749
+ }
23750
+ const classes = [this.options.emptyNodeClass];
23751
+ if (isEmptyDoc) {
23752
+ classes.push(this.options.emptyEditorClass);
23753
+ }
23754
+ decorations.push(
23755
+ Decoration.node(pos, pos + node.nodeSize, {
23756
+ class: classes.join(" "),
23757
+ [dataAttribute]: placeholderValue
23758
+ })
23759
+ );
23760
+ return this.options.includeChildren;
23761
+ });
23762
+ return DecorationSet.create(doc, decorations);
23763
+ }
23764
+ }
23765
+ })
23766
+ ];
23767
+ }
23768
+ });
23769
+
23618
23770
  // src/components/UEditor/resizable-image.tsx
23619
23771
  import { useEffect as useEffect33, useRef as useRef31, useState as useState49 } from "react";
23620
23772
  import Image3 from "@tiptap/extension-image";
@@ -23834,6 +23986,7 @@ var resizable_image_default = ResizableImage;
23834
23986
  var lowlight = createLowlight(common);
23835
23987
  function buildUEditorExtensions({
23836
23988
  placeholder,
23989
+ translate,
23837
23990
  maxCharacters,
23838
23991
  uploadImage,
23839
23992
  imageInsertMode = "base64",
@@ -23926,12 +24079,49 @@ function buildUEditorExtensions({
23926
24079
  }),
23927
24080
  Typography,
23928
24081
  History2,
23929
- Placeholder.configure({
24082
+ UEditorPlaceholder.configure({
23930
24083
  placeholder,
23931
24084
  emptyEditorClass: "is-editor-empty",
23932
- emptyNodeClass: "is-empty"
24085
+ emptyNodeClass: "is-empty",
24086
+ shouldShow: ({ node, hasTable }) => {
24087
+ const nodeName = node.type.name;
24088
+ if (nodeName === "table" || nodeName === "tableCell" || nodeName === "tableHeader") {
24089
+ return false;
24090
+ }
24091
+ if (hasTable) {
24092
+ return false;
24093
+ }
24094
+ return true;
24095
+ }
24096
+ }),
24097
+ SlashCommand.configure({
24098
+ messages: {
24099
+ noResults: translate("slashCommand.noResults"),
24100
+ basicBlocks: translate("slashCommand.basicBlocks"),
24101
+ text: translate("slashCommand.text"),
24102
+ textDesc: translate("slashCommand.textDesc"),
24103
+ heading1: translate("slashCommand.heading1"),
24104
+ heading1Desc: translate("slashCommand.heading1Desc"),
24105
+ heading2: translate("slashCommand.heading2"),
24106
+ heading2Desc: translate("slashCommand.heading2Desc"),
24107
+ heading3: translate("slashCommand.heading3"),
24108
+ heading3Desc: translate("slashCommand.heading3Desc"),
24109
+ bulletList: translate("slashCommand.bulletList"),
24110
+ bulletListDesc: translate("slashCommand.bulletListDesc"),
24111
+ orderedList: translate("slashCommand.orderedList"),
24112
+ orderedListDesc: translate("slashCommand.orderedListDesc"),
24113
+ todoList: translate("slashCommand.todoList"),
24114
+ todoListDesc: translate("slashCommand.todoListDesc"),
24115
+ quote: translate("slashCommand.quote"),
24116
+ quoteDesc: translate("slashCommand.quoteDesc"),
24117
+ codeBlock: translate("slashCommand.codeBlock"),
24118
+ codeBlockDesc: translate("slashCommand.codeBlockDesc"),
24119
+ divider: translate("slashCommand.divider"),
24120
+ dividerDesc: translate("slashCommand.dividerDesc"),
24121
+ table: translate("slashCommand.table"),
24122
+ tableDesc: translate("slashCommand.tableDesc")
24123
+ }
23933
24124
  }),
23934
- SlashCommand,
23935
24125
  EmojiSuggestion
23936
24126
  ];
23937
24127
  }
@@ -24152,6 +24342,7 @@ var CATEGORY_ICONS = {
24152
24342
  "flags": Flag
24153
24343
  };
24154
24344
  var EmojiPicker = ({ onSelect, onClose }) => {
24345
+ const t = useSmartTranslations("UEditor");
24155
24346
  const [search, setSearch] = useState51("");
24156
24347
  const [activeCategory, setActiveCategory] = useState51(EMOJI_LIST[0]?.id || "");
24157
24348
  const scrollContainerRef = useRef33(null);
@@ -24221,7 +24412,7 @@ var EmojiPicker = ({ onSelect, onClose }) => {
24221
24412
  "input",
24222
24413
  {
24223
24414
  type: "text",
24224
- placeholder: "T\xECm ki\u1EBFm bi\u1EC3u t\u01B0\u1EE3ng c\u1EA3m x\xFAc",
24415
+ placeholder: t("emojiPicker.searchPlaceholder"),
24225
24416
  value: search,
24226
24417
  onChange: (e) => setSearch(e.target.value),
24227
24418
  className: cn(
@@ -24267,8 +24458,8 @@ var EmojiPicker = ({ onSelect, onClose }) => {
24267
24458
  )) })
24268
24459
  ] }, category.id)) : /* @__PURE__ */ jsxs74("div", { className: "flex flex-col items-center justify-center h-full text-center", children: [
24269
24460
  /* @__PURE__ */ jsx84("div", { className: "text-4xl mb-2", children: "\u{1F50D}" }),
24270
- /* @__PURE__ */ jsx84("div", { className: "text-sm font-medium text-muted-foreground", children: "Kh\xF4ng t\xECm th\u1EA5y emoji" }),
24271
- /* @__PURE__ */ jsx84("div", { className: "text-xs text-muted-foreground mt-1", children: "Th\u1EED t\u1EEB kh\xF3a kh\xE1c" })
24461
+ /* @__PURE__ */ jsx84("div", { className: "text-sm font-medium text-muted-foreground", children: t("emojiPicker.noResults") }),
24462
+ /* @__PURE__ */ jsx84("div", { className: "text-xs text-muted-foreground mt-1", children: t("emojiPicker.tryDifferentSearch") })
24272
24463
  ] })
24273
24464
  ) : (
24274
24465
  // All Categories - Messenger Style
@@ -25560,8 +25751,8 @@ var UEditor = React79.forwardRef(({
25560
25751
  const effectivePlaceholder = placeholder ?? t("placeholder");
25561
25752
  const inFlightPrepareRef = useRef36(null);
25562
25753
  const extensions = useMemo29(
25563
- () => buildUEditorExtensions({ placeholder: effectivePlaceholder, maxCharacters, uploadImage, imageInsertMode, editable }),
25564
- [effectivePlaceholder, maxCharacters, uploadImage, imageInsertMode, editable]
25754
+ () => buildUEditorExtensions({ placeholder: effectivePlaceholder, translate: t, maxCharacters, uploadImage, imageInsertMode, editable }),
25755
+ [effectivePlaceholder, t, maxCharacters, uploadImage, imageInsertMode, editable]
25565
25756
  );
25566
25757
  const editor = useEditor({
25567
25758
  immediatelyRender: false,