@thangph2146/lexical-editor 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +47 -0
  2. package/dist/editor-x/editor.cjs +732 -443
  3. package/dist/editor-x/editor.cjs.map +1 -1
  4. package/dist/editor-x/editor.css +1418 -1120
  5. package/dist/editor-x/editor.css.map +1 -1
  6. package/dist/editor-x/editor.d.cts +2 -1
  7. package/dist/editor-x/editor.d.ts +2 -1
  8. package/dist/editor-x/editor.js +736 -447
  9. package/dist/editor-x/editor.js.map +1 -1
  10. package/dist/index.cjs +772 -482
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.css +1418 -1120
  13. package/dist/index.css.map +1 -1
  14. package/dist/index.d.cts +1 -1
  15. package/dist/index.d.ts +1 -1
  16. package/dist/index.js +775 -485
  17. package/dist/index.js.map +1 -1
  18. package/package.json +86 -84
  19. package/src/components/lexical-editor.tsx +140 -123
  20. package/src/editor-x/editor.tsx +20 -5
  21. package/src/editor-x/plugins.tsx +385 -380
  22. package/src/nodes/list-with-color-node.tsx +160 -160
  23. package/src/plugins/autocomplete-plugin.tsx +2574 -2574
  24. package/src/plugins/context-menu-plugin.tsx +239 -9
  25. package/src/plugins/floating-text-format-plugin.tsx +84 -92
  26. package/src/plugins/images-plugin.tsx +4 -4
  27. package/src/plugins/list-color-plugin.tsx +178 -178
  28. package/src/plugins/tab-focus-plugin.tsx +66 -66
  29. package/src/plugins/table-column-resizer-plugin.tsx +329 -190
  30. package/src/plugins/toolbar/block-format/block-format-data.tsx +4 -0
  31. package/src/plugins/toolbar/block-format/format-bulleted-list.tsx +40 -40
  32. package/src/plugins/toolbar/block-format/format-list-with-marker.tsx +74 -74
  33. package/src/plugins/toolbar/block-format/format-numbered-list.tsx +40 -40
  34. package/src/plugins/toolbar/block-format-toolbar-plugin.tsx +118 -117
  35. package/src/plugins/toolbar/element-format-toolbar-plugin.tsx +37 -53
  36. package/src/plugins/toolbar/font-format-toolbar-plugin.tsx +8 -15
  37. package/src/plugins/toolbar/font-size-toolbar-plugin.tsx +2 -3
  38. package/src/plugins/toolbar/history-toolbar-plugin.tsx +2 -5
  39. package/src/plugins/toolbar/subsuper-toolbar-plugin.tsx +15 -23
  40. package/src/themes/_mixins.scss +158 -10
  41. package/src/themes/_variables.scss +168 -0
  42. package/src/themes/core/_code.scss +59 -0
  43. package/src/themes/core/_images.scss +80 -0
  44. package/src/themes/core/_lists.scss +214 -0
  45. package/src/themes/core/_misc.scss +46 -0
  46. package/src/themes/core/_reset.scss +119 -0
  47. package/src/themes/core/_tables.scss +145 -0
  48. package/src/themes/core/_text.scss +35 -0
  49. package/src/themes/core/_typography.scss +73 -0
  50. package/src/themes/editor-theme.scss +9 -623
  51. package/src/themes/editor-theme.ts +118 -118
  52. package/src/themes/plugins/_auto-embed.scss +11 -0
  53. package/src/themes/plugins/_color-picker.scss +103 -0
  54. package/src/themes/plugins/_draggable-block.scss +32 -0
  55. package/src/themes/plugins/_floating-link-editor.scss +47 -0
  56. package/src/themes/plugins/_floating-toolbars.scss +61 -0
  57. package/src/themes/plugins/_image-resizer.scss +38 -0
  58. package/src/themes/plugins/_image.scss +57 -0
  59. package/src/themes/plugins/_layout.scss +39 -0
  60. package/src/themes/plugins/_list-color.scss +23 -0
  61. package/src/themes/plugins/_mentions.scss +21 -0
  62. package/src/themes/plugins/_menus-and-pickers.scss +153 -0
  63. package/src/themes/plugins/_table.scss +20 -0
  64. package/src/themes/plugins/_toolbar.scss +36 -0
  65. package/src/themes/plugins/_tree-view.scss +11 -0
  66. package/src/themes/plugins.scss +20 -1165
  67. package/src/themes/ui-components/_animations.scss +31 -0
  68. package/src/themes/ui-components/_backgrounds.scss +27 -0
  69. package/src/themes/ui-components/_borders.scss +20 -0
  70. package/src/themes/ui-components/_button.scss +176 -0
  71. package/src/themes/ui-components/_checkbox.scss +14 -0
  72. package/src/themes/ui-components/_cursors.scss +31 -0
  73. package/src/themes/ui-components/_dialog.scss +86 -0
  74. package/src/themes/ui-components/_display-sizing.scss +100 -0
  75. package/src/themes/ui-components/_flex.scss +124 -0
  76. package/src/themes/ui-components/_form-layout.scss +15 -0
  77. package/src/themes/ui-components/_icons.scss +23 -0
  78. package/src/themes/ui-components/_input.scss +86 -0
  79. package/src/themes/ui-components/_label.scss +19 -0
  80. package/src/themes/ui-components/_loader.scss +9 -0
  81. package/src/themes/ui-components/_margins-paddings.scss +45 -0
  82. package/src/themes/ui-components/_popover.scss +16 -0
  83. package/src/themes/ui-components/_positioning.scss +73 -0
  84. package/src/themes/ui-components/_rounded.scss +19 -0
  85. package/src/themes/ui-components/_scroll-area.scss +11 -0
  86. package/src/themes/ui-components/_select.scss +110 -0
  87. package/src/themes/ui-components/_separator.scss +19 -0
  88. package/src/themes/ui-components/_shadow.scss +15 -0
  89. package/src/themes/ui-components/_tabs.scss +46 -0
  90. package/src/themes/ui-components/_text-utilities.scss +48 -0
  91. package/src/themes/ui-components/_toggle-toolbar.scss +128 -0
  92. package/src/themes/ui-components/_toggle.scss +80 -0
  93. package/src/themes/ui-components/_typography.scss +22 -0
  94. package/src/themes/ui-components.scss +27 -937
  95. package/src/transformers/markdown-list-transformer.ts +51 -51
  96. package/src/ui/button.tsx +11 -2
  97. package/src/ui/collapsible.tsx +1 -1
  98. package/src/ui/dialog.tsx +2 -2
  99. package/src/ui/flex.tsx +4 -4
  100. package/src/ui/popover.tsx +1 -1
  101. package/src/ui/tooltip.tsx +2 -2
@@ -2990,8 +2990,8 @@ var init_button = __esm({
2990
2990
  "src/ui/button.tsx"() {
2991
2991
  init_utils();
2992
2992
  Button = React20__namespace.forwardRef(
2993
- ({ className, variant = "default", size = "default", type = "button", ...props }, ref) => {
2994
- return /* @__PURE__ */ jsxRuntime.jsx(
2993
+ ({ className, variant = "default", size = "default", type = "button", isLoading, disabled, children, ...props }, ref) => {
2994
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2995
2995
  "button",
2996
2996
  {
2997
2997
  type,
@@ -2999,10 +2999,16 @@ var init_button = __esm({
2999
2999
  "editor-btn",
3000
3000
  variant !== "default" && `editor-btn--${variant}`,
3001
3001
  size !== "default" && `editor-btn--size-${size}`,
3002
+ isLoading && "editor-btn--loading",
3002
3003
  className
3003
3004
  ),
3005
+ disabled: isLoading || disabled,
3004
3006
  ref,
3005
- ...props
3007
+ ...props,
3008
+ children: [
3009
+ isLoading && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "editor-btn__loader editor-animate-spin", size: 16 }),
3010
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("editor-btn__content", isLoading && "editor-opacity-0"), children })
3011
+ ]
3006
3012
  }
3007
3013
  );
3008
3014
  }
@@ -4375,8 +4381,8 @@ function ImagePickerFolderTree({
4375
4381
  /* @__PURE__ */ jsxRuntime.jsx(TypographyP, { className: "editor-truncate", children: folder.name }),
4376
4382
  /* @__PURE__ */ jsxRuntime.jsx(TypographySpanSmallMuted, { className: "editor-ml-auto editor-shrink-0", children: `${folder.images.length} h\xECnh${folder.subfolders.length > 0 ? `, ${folder.subfolders.length} th\u01B0 m\u1EE5c` : ""}` })
4377
4383
  ] }),
4378
- /* @__PURE__ */ jsxRuntime.jsxs(CollapsibleContent, { className: "editor-ml-4 editor-mt-1", children: [
4379
- folder.images.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "editor-image-grid", children: folder.images.map((image) => /* @__PURE__ */ jsxRuntime.jsx(
4384
+ /* @__PURE__ */ jsxRuntime.jsxs(CollapsibleContent, { className: "editor-ml-4 editor-mt-1 editor-flex editor-flex-col editor-gap-1", children: [
4385
+ folder.images.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "editor-image-grid editor-gap-2", children: folder.images.map((image) => /* @__PURE__ */ jsxRuntime.jsx(
4380
4386
  "button",
4381
4387
  {
4382
4388
  type: "button",
@@ -4463,10 +4469,10 @@ function InsertImageUploadsDialogBody({
4463
4469
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "editor-form-grid", children: [
4464
4470
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "editor-form-item", children: [
4465
4471
  /* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Ch\u1ECDn h\xECnh \u1EA3nh t\u1EEB th\u01B0 vi\u1EC7n" }),
4466
- isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "editor-flex-center-justify-py-8", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "editor-loader" }) }) : !folderTree || folderTree.subfolders.length === 0 && folderTree.images.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "editor-empty-state", children: /* @__PURE__ */ jsxRuntime.jsx(TypographySpanSmallMuted, { children: "Ch\u01B0a c\xF3 h\xECnh \u1EA3nh n\xE0o \u0111\u01B0\u1EE3c upload" }) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "editor-scroll-area", children: [
4472
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "editor-flex-center-justify-py-8", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "editor-loader" }) }) : !folderTree || folderTree.subfolders.length === 0 && folderTree.images.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "editor-empty-state", children: /* @__PURE__ */ jsxRuntime.jsx(TypographySpanSmallMuted, { children: "Ch\u01B0a c\xF3 h\xECnh \u1EA3nh n\xE0o \u0111\u01B0\u1EE3c upload" }) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "editor-scroll-area editor-flex editor-flex-col editor-gap-1", children: [
4467
4473
  folderTree.images.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "editor-mb-3", children: [
4468
4474
  /* @__PURE__ */ jsxRuntime.jsx(TypographySpanSmallMuted, { className: "editor-mb-2 editor-px-1", children: "Root" }),
4469
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "editor-image-grid", children: folderTree.images.map((image) => /* @__PURE__ */ jsxRuntime.jsx(
4475
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "editor-image-grid editor-gap-2", children: folderTree.images.map((image) => /* @__PURE__ */ jsxRuntime.jsx(
4470
4476
  "button",
4471
4477
  {
4472
4478
  type: "button",
@@ -5057,7 +5063,7 @@ var init_image_placeholder = __esm({
5057
5063
  }
5058
5064
  });
5059
5065
  function ContentEditable({
5060
- placeholder: placeholder2,
5066
+ placeholder,
5061
5067
  className,
5062
5068
  placeholderClassName,
5063
5069
  placeholderDefaults = true
@@ -5071,8 +5077,8 @@ function ContentEditable({
5071
5077
  !isReadOnlyOrReview && "min-h-72 px-8 py-4",
5072
5078
  className
5073
5079
  ),
5074
- "aria-placeholder": placeholder2,
5075
- "aria-label": placeholder2 || "Editor n\u1ED9i dung",
5080
+ "aria-placeholder": placeholder,
5081
+ "aria-label": placeholder || "Editor n\u1ED9i dung",
5076
5082
  placeholder: /* @__PURE__ */ jsxRuntime.jsx(
5077
5083
  "div",
5078
5084
  {
@@ -5081,7 +5087,7 @@ function ContentEditable({
5081
5087
  "text-muted-foreground pointer-events-none select-none",
5082
5088
  placeholderDefaults && !isReadOnlyOrReview && "absolute top-0 left-0 overflow-hidden px-8 py-[18px] text-ellipsis"
5083
5089
  ),
5084
- children: placeholder2
5090
+ children: placeholder
5085
5091
  }
5086
5092
  )
5087
5093
  }
@@ -6507,10 +6513,10 @@ var init_flex = __esm({
6507
6513
  ref,
6508
6514
  className: cn(
6509
6515
  "editor-flex",
6510
- align && `editor-flex--items-${align}`,
6511
- justify && `editor-flex--justify-${justify}`,
6512
- direction && `editor-flex--flex-${direction}`,
6513
- wrap && `editor-flex--flex-${wrap}`,
6516
+ align && `editor-items-${align}`,
6517
+ justify && `editor-justify-${justify}`,
6518
+ direction && `editor-flex-${direction}`,
6519
+ wrap && `editor-flex-${wrap}`,
6514
6520
  className
6515
6521
  ),
6516
6522
  style: { ...gapStyle, ...style },
@@ -7215,10 +7221,10 @@ function SelectTrigger({ className, children, size = "default", ...props }) {
7215
7221
  }
7216
7222
  );
7217
7223
  }
7218
- function SelectValue({ placeholder: placeholder2 }) {
7224
+ function SelectValue({ placeholder }) {
7219
7225
  const context = React20__namespace.useContext(SelectContext);
7220
7226
  if (!context) throw new Error("SelectValue must be used within Select");
7221
- return /* @__PURE__ */ jsxRuntime.jsx("span", { children: context.value || placeholder2 });
7227
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { children: context.value || placeholder });
7222
7228
  }
7223
7229
  function SelectContent({ className, children, ...props }) {
7224
7230
  const context = React20__namespace.useContext(SelectContext);
@@ -10188,6 +10194,9 @@ var init_list_color_plugin = __esm({
10188
10194
  });
10189
10195
  function ContextMenuPlugin() {
10190
10196
  const [editor] = LexicalComposerContext.useLexicalComposerContext();
10197
+ const [contextTarget, setContextTarget] = React20.useState(null);
10198
+ const [showMarkerDialog, setShowMarkerDialog] = React20.useState(false);
10199
+ const [customMarker, setCustomMarker] = React20.useState("");
10191
10200
  const isInTable = (node) => utils.$findMatchingParent(node, table.$isTableCellNode) !== null;
10192
10201
  const isMergedCell = (node) => {
10193
10202
  const cell = utils.$findMatchingParent(node, table.$isTableCellNode);
@@ -10199,6 +10208,105 @@ function ContextMenuPlugin() {
10199
10208
  };
10200
10209
  const isInLayoutItem = (node) => utils.$findMatchingParent(node, $isLayoutItemNode) !== null;
10201
10210
  const isInList = (node) => utils.$findMatchingParent(node, list.$isListNode) !== null;
10211
+ const isInNumberList = (node) => {
10212
+ const listNode = utils.$findMatchingParent(node, list.$isListNode);
10213
+ return list.$isListNode(listNode) && listNode.getListType() === "number";
10214
+ };
10215
+ React20.useEffect(() => {
10216
+ const rootElement = editor.getRootElement();
10217
+ if (!rootElement) return;
10218
+ const onContextMenu = (event) => {
10219
+ const target = event.target;
10220
+ if (!(target instanceof HTMLElement)) return;
10221
+ setContextTarget(target);
10222
+ };
10223
+ rootElement.addEventListener("contextmenu", onContextMenu);
10224
+ return () => {
10225
+ rootElement.removeEventListener("contextmenu", onContextMenu);
10226
+ };
10227
+ }, [editor]);
10228
+ const getContextAnchorNode = React20.useCallback(() => {
10229
+ if (contextTarget) {
10230
+ const nearestNode = lexical.$getNearestNodeFromDOMNode(contextTarget);
10231
+ if (nearestNode) return nearestNode;
10232
+ }
10233
+ const selection = lexical.$getSelection();
10234
+ if (lexical.$isRangeSelection(selection)) {
10235
+ return selection.anchor.getNode();
10236
+ }
10237
+ return null;
10238
+ }, [contextTarget]);
10239
+ const updateNumberListMarkerType = React20.useCallback((markerType) => {
10240
+ editor.update(() => {
10241
+ const anchorNode = getContextAnchorNode();
10242
+ if (!anchorNode) return;
10243
+ const nearestListNode = utils.$findMatchingParent(
10244
+ anchorNode,
10245
+ (node) => list.$isListNode(node) && node.getListType() === "number"
10246
+ );
10247
+ if (!nearestListNode) return;
10248
+ let listNode = nearestListNode;
10249
+ let parent = listNode.getParent();
10250
+ while (parent) {
10251
+ if (list.$isListNode(parent) && parent.getListType() === "number") {
10252
+ listNode = parent;
10253
+ parent = parent.getParent();
10254
+ continue;
10255
+ }
10256
+ break;
10257
+ }
10258
+ if ($isListWithColorNode(listNode)) {
10259
+ listNode.setMarkerType(markerType);
10260
+ return;
10261
+ }
10262
+ const newList = createListWithColorNodeFromRegistry(
10263
+ editor,
10264
+ listNode.getListType(),
10265
+ listNode.getStart()
10266
+ );
10267
+ newList.setMarkerType(markerType);
10268
+ const children = listNode.getChildren();
10269
+ for (const child of children) newList.append(child);
10270
+ listNode.replace(newList);
10271
+ });
10272
+ }, [editor, getContextAnchorNode]);
10273
+ const syncMarkerToSameLevelLists = React20.useCallback((targetListNode, markerType) => {
10274
+ editor.update(() => {
10275
+ const parent = targetListNode.getParent();
10276
+ if (!parent) return;
10277
+ const siblings = parent.getChildren();
10278
+ for (const sibling of siblings) {
10279
+ if (list.$isListNode(sibling) && sibling.getListType() === "number" && sibling !== targetListNode) {
10280
+ if ($isListWithColorNode(sibling)) {
10281
+ sibling.setMarkerType(markerType);
10282
+ } else {
10283
+ const newList = $createListWithColorNode("number", sibling.getStart());
10284
+ newList.setMarkerType(markerType);
10285
+ const children = sibling.getChildren();
10286
+ for (const child of children) newList.append(child);
10287
+ sibling.replace(newList);
10288
+ }
10289
+ }
10290
+ }
10291
+ });
10292
+ }, [editor]);
10293
+ const handleCustomMarkerSubmit = () => {
10294
+ if (customMarker.trim()) {
10295
+ editor.update(() => {
10296
+ const anchorNode = getContextAnchorNode();
10297
+ if (!anchorNode) return;
10298
+ const nearestListNode = utils.$findMatchingParent(
10299
+ anchorNode,
10300
+ (node) => list.$isListNode(node) && node.getListType() === "number"
10301
+ );
10302
+ if (!nearestListNode) return;
10303
+ updateNumberListMarkerType(customMarker.trim());
10304
+ syncMarkerToSameLevelLists(nearestListNode, customMarker.trim());
10305
+ });
10306
+ setShowMarkerDialog(false);
10307
+ setCustomMarker("");
10308
+ }
10309
+ };
10202
10310
  const items = React20.useMemo(() => {
10203
10311
  return [
10204
10312
  new LexicalNodeContextMenuPlugin.NodeContextMenuOption(`G\u1ED9p \xF4`, {
@@ -10324,6 +10432,41 @@ function ContextMenuPlugin() {
10324
10432
  new LexicalNodeContextMenuPlugin.NodeContextMenuSeparator({
10325
10433
  $showOn: isInList
10326
10434
  }),
10435
+ new LexicalNodeContextMenuPlugin.NodeContextMenuOption(`\u0110\xE1nh s\u1ED1 1, 2, 3`, {
10436
+ $onSelect: () => {
10437
+ updateNumberListMarkerType(void 0);
10438
+ },
10439
+ $showOn: isInNumberList,
10440
+ disabled: false,
10441
+ icon: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListOrderedIcon, {}) })
10442
+ }),
10443
+ new LexicalNodeContextMenuPlugin.NodeContextMenuOption(`\u0110\xE1nh s\u1ED1 \u0111a c\u1EA5p 1.1 / 1.1.1`, {
10444
+ $onSelect: () => {
10445
+ updateNumberListMarkerType("multi-level");
10446
+ },
10447
+ $showOn: isInNumberList,
10448
+ disabled: false,
10449
+ icon: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListOrderedIcon, {}) })
10450
+ }),
10451
+ new LexicalNodeContextMenuPlugin.NodeContextMenuOption(`\u0110\xE1nh s\u1ED1 a, b, c`, {
10452
+ $onSelect: () => {
10453
+ updateNumberListMarkerType("alpha");
10454
+ },
10455
+ $showOn: isInNumberList,
10456
+ disabled: false,
10457
+ icon: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListOrderedIcon, {}) })
10458
+ }),
10459
+ new LexicalNodeContextMenuPlugin.NodeContextMenuOption(`T\xF9y ch\u1EC9nh marker...`, {
10460
+ $onSelect: () => {
10461
+ setShowMarkerDialog(true);
10462
+ },
10463
+ $showOn: isInNumberList,
10464
+ disabled: false,
10465
+ icon: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Hash, { className: "text-blue-600" }) })
10466
+ }),
10467
+ new LexicalNodeContextMenuPlugin.NodeContextMenuSeparator({
10468
+ $showOn: isInNumberList
10469
+ }),
10327
10470
  new LexicalNodeContextMenuPlugin.NodeContextMenuOption(`Remove Link`, {
10328
10471
  $onSelect: () => {
10329
10472
  editor.dispatchCommand(link.TOGGLE_LINK_COMMAND, null);
@@ -10419,23 +10562,101 @@ function ContextMenuPlugin() {
10419
10562
  icon: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, {}) })
10420
10563
  })
10421
10564
  ];
10422
- }, [editor]);
10423
- return /* @__PURE__ */ jsxRuntime.jsx(
10424
- LexicalNodeContextMenuPlugin.NodeContextMenuPlugin,
10425
- {
10426
- className: "editor-context-menu",
10427
- itemClassName: "editor-context-menu-item",
10428
- separatorClassName: "editor-context-menu-separator",
10429
- items
10430
- }
10431
- );
10565
+ }, [editor, updateNumberListMarkerType]);
10566
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10567
+ /* @__PURE__ */ jsxRuntime.jsx(
10568
+ LexicalNodeContextMenuPlugin.NodeContextMenuPlugin,
10569
+ {
10570
+ className: "editor-context-menu",
10571
+ itemClassName: "editor-context-menu-item",
10572
+ separatorClassName: "editor-context-menu-separator",
10573
+ items
10574
+ }
10575
+ ),
10576
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: showMarkerDialog, onOpenChange: setShowMarkerDialog, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { style: { maxWidth: "400px" }, children: [
10577
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
10578
+ /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "T\xF9y ch\u1EC9nh Marker" }),
10579
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "editor-text-sm editor-text-muted-foreground", children: "Nh\u1EADp ki\u1EC3u marker cho danh s\xE1ch c\u1EE7a b\u1EA1n" })
10580
+ ] }),
10581
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "editor-flex-col editor-py-4 editor-gap-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "editor-flex-col editor-gap-2", children: [
10582
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "marker-input", className: "editor-font-medium", children: "Ki\u1EC3u marker" }),
10583
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "editor-relative editor-flex editor-items-center", children: [
10584
+ /* @__PURE__ */ jsxRuntime.jsx(
10585
+ lucideReact.Hash,
10586
+ {
10587
+ className: "editor-absolute editor-text-muted-foreground",
10588
+ style: { left: "0.75rem" },
10589
+ size: 16
10590
+ }
10591
+ ),
10592
+ /* @__PURE__ */ jsxRuntime.jsx(
10593
+ Input,
10594
+ {
10595
+ id: "marker-input",
10596
+ value: customMarker,
10597
+ onChange: (e) => setCustomMarker(e.target.value),
10598
+ placeholder: "V\xED d\u1EE5: multi-level, alpha, 4.1, ...",
10599
+ style: { paddingLeft: "2.25rem" },
10600
+ onKeyDown: (e) => {
10601
+ if (e.key === "Enter") {
10602
+ handleCustomMarkerSubmit();
10603
+ }
10604
+ }
10605
+ }
10606
+ )
10607
+ ] }),
10608
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "editor-flex-col editor-gap-1 editor-text-sm editor-text-muted-foreground editor-mt-2", children: [
10609
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "editor-flex editor-items-center editor-gap-2", style: { margin: 0 }, children: [
10610
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "editor-font-medium", children: "multi-level" }),
10611
+ " - Hi\u1EC3n th\u1ECB d\u1EA1ng 4.1, 4.1.1"
10612
+ ] }),
10613
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "editor-flex editor-items-center editor-gap-2", style: { margin: 0 }, children: [
10614
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "editor-font-medium", children: "alpha" }),
10615
+ " - Hi\u1EC3n th\u1ECB d\u1EA1ng a, b, c"
10616
+ ] }),
10617
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "editor-flex editor-items-center editor-gap-2", style: { margin: 0 }, children: [
10618
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "editor-font-medium", children: "\u0110\u1EC3 tr\u1ED1ng" }),
10619
+ " - V\u1EC1 m\u1EB7c \u0111\u1ECBnh 1, 2, 3"
10620
+ ] })
10621
+ ] })
10622
+ ] }) }),
10623
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogFooter, { children: [
10624
+ /* @__PURE__ */ jsxRuntime.jsx(
10625
+ Button,
10626
+ {
10627
+ variant: "outline",
10628
+ onClick: () => setShowMarkerDialog(false),
10629
+ children: "H\u1EE7y"
10630
+ }
10631
+ ),
10632
+ /* @__PURE__ */ jsxRuntime.jsxs(
10633
+ Button,
10634
+ {
10635
+ onClick: handleCustomMarkerSubmit,
10636
+ disabled: !customMarker.trim(),
10637
+ className: "editor-gap-2",
10638
+ children: [
10639
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListIcon, { size: 16 }),
10640
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\xC1p d\u1EE5ng" })
10641
+ ]
10642
+ }
10643
+ )
10644
+ ] })
10645
+ ] }) })
10646
+ ] });
10432
10647
  }
10433
10648
  var init_context_menu_plugin = __esm({
10434
10649
  "src/plugins/context-menu-plugin.tsx"() {
10435
10650
  init_layout_item_node();
10651
+ init_nodes();
10652
+ init_list_with_color_node();
10436
10653
  init_layout_plugin();
10437
10654
  init_list_color_plugin();
10438
10655
  init_typography();
10656
+ init_dialog();
10657
+ init_input();
10658
+ init_button();
10659
+ init_label();
10439
10660
  }
10440
10661
  });
10441
10662
  function DragDropPastePlugin() {
@@ -28687,99 +28908,90 @@ function FloatingTextFormat({
28687
28908
  ref: popupCharStylesEditorRef,
28688
28909
  className: "editor-floating-text-format",
28689
28910
  children: editor.isEditable() && /* @__PURE__ */ jsxRuntime.jsxs(Flex, { align: "center", gap: 1, className: "editor-flex-nowrap", children: [
28690
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "editor-floating-group editor-flex editor-items-center", children: /* @__PURE__ */ jsxRuntime.jsxs(
28691
- ToggleGroup,
28692
- {
28693
- type: "multiple",
28694
- className: "editor-flex editor-items-center",
28695
- value: [
28696
- isBold ? "bold" : "",
28697
- isItalic ? "italic" : "",
28698
- isUnderline ? "underline" : "",
28699
- isStrikethrough ? "strikethrough" : "",
28700
- isCode ? "code" : "",
28701
- isLink ? "link" : ""
28702
- ].filter(Boolean),
28703
- children: [
28704
- /* @__PURE__ */ jsxRuntime.jsx(
28705
- ToggleGroupItem,
28706
- {
28707
- value: "bold",
28708
- "aria-label": "Toggle bold",
28709
- className: "editor-toolbar-item",
28710
- onClick: () => {
28711
- editor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "bold");
28712
- },
28713
- size: "sm",
28714
- children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BoldIcon, {}) })
28715
- }
28716
- ),
28717
- /* @__PURE__ */ jsxRuntime.jsx(
28718
- ToggleGroupItem,
28719
- {
28720
- value: "italic",
28721
- "aria-label": "Toggle italic",
28722
- className: "editor-toolbar-item",
28723
- onClick: () => {
28724
- editor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "italic");
28725
- },
28726
- size: "sm",
28727
- children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ItalicIcon, {}) })
28728
- }
28729
- ),
28730
- /* @__PURE__ */ jsxRuntime.jsx(
28731
- ToggleGroupItem,
28732
- {
28733
- value: "underline",
28734
- "aria-label": "Toggle underline",
28735
- className: "editor-toolbar-item",
28736
- onClick: () => {
28737
- editor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "underline");
28738
- },
28739
- size: "sm",
28740
- children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UnderlineIcon, {}) })
28741
- }
28742
- ),
28743
- /* @__PURE__ */ jsxRuntime.jsx(
28744
- ToggleGroupItem,
28745
- {
28746
- value: "strikethrough",
28747
- "aria-label": "Toggle strikethrough",
28748
- className: "editor-toolbar-item",
28749
- onClick: () => {
28750
- editor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "strikethrough");
28751
- },
28752
- size: "sm",
28753
- children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.StrikethroughIcon, {}) })
28754
- }
28755
- ),
28756
- /* @__PURE__ */ jsxRuntime.jsx(
28757
- ToggleGroupItem,
28758
- {
28759
- value: "code",
28760
- "aria-label": "Toggle code",
28761
- className: "editor-toolbar-item",
28762
- onClick: () => {
28763
- editor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "code");
28764
- },
28765
- size: "sm",
28766
- children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CodeIcon, {}) })
28767
- }
28768
- ),
28769
- /* @__PURE__ */ jsxRuntime.jsx(
28770
- ToggleGroupItem,
28771
- {
28772
- value: "link",
28773
- "aria-label": "Toggle link",
28774
- className: "editor-toolbar-item",
28775
- onClick: insertLink,
28776
- size: "sm",
28777
- children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LinkIcon, {}) })
28778
- }
28779
- )
28780
- ]
28781
- }
28782
- ) }),
28911
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "editor-floating-group editor-flex editor-items-center", children: [
28912
+ /* @__PURE__ */ jsxRuntime.jsx(
28913
+ Button,
28914
+ {
28915
+ variant: "ghost",
28916
+ size: "sm",
28917
+ className: "editor-toolbar-item",
28918
+ "data-state": isBold ? "on" : "off",
28919
+ onClick: () => {
28920
+ editor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "bold");
28921
+ },
28922
+ "aria-label": "Toggle bold",
28923
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BoldIcon, {}) })
28924
+ }
28925
+ ),
28926
+ /* @__PURE__ */ jsxRuntime.jsx(
28927
+ Button,
28928
+ {
28929
+ variant: "ghost",
28930
+ size: "sm",
28931
+ className: "editor-toolbar-item",
28932
+ "data-state": isItalic ? "on" : "off",
28933
+ onClick: () => {
28934
+ editor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "italic");
28935
+ },
28936
+ "aria-label": "Toggle italic",
28937
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ItalicIcon, {}) })
28938
+ }
28939
+ ),
28940
+ /* @__PURE__ */ jsxRuntime.jsx(
28941
+ Button,
28942
+ {
28943
+ variant: "ghost",
28944
+ size: "sm",
28945
+ className: "editor-toolbar-item",
28946
+ "data-state": isUnderline ? "on" : "off",
28947
+ onClick: () => {
28948
+ editor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "underline");
28949
+ },
28950
+ "aria-label": "Toggle underline",
28951
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UnderlineIcon, {}) })
28952
+ }
28953
+ ),
28954
+ /* @__PURE__ */ jsxRuntime.jsx(
28955
+ Button,
28956
+ {
28957
+ variant: "ghost",
28958
+ size: "sm",
28959
+ className: "editor-toolbar-item",
28960
+ "data-state": isStrikethrough ? "on" : "off",
28961
+ onClick: () => {
28962
+ editor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "strikethrough");
28963
+ },
28964
+ "aria-label": "Toggle strikethrough",
28965
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.StrikethroughIcon, {}) })
28966
+ }
28967
+ ),
28968
+ /* @__PURE__ */ jsxRuntime.jsx(
28969
+ Button,
28970
+ {
28971
+ variant: "ghost",
28972
+ size: "sm",
28973
+ className: "editor-toolbar-item",
28974
+ "data-state": isCode ? "on" : "off",
28975
+ onClick: () => {
28976
+ editor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "code");
28977
+ },
28978
+ "aria-label": "Toggle code",
28979
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CodeIcon, {}) })
28980
+ }
28981
+ ),
28982
+ /* @__PURE__ */ jsxRuntime.jsx(
28983
+ Button,
28984
+ {
28985
+ variant: "ghost",
28986
+ size: "sm",
28987
+ className: "editor-toolbar-item",
28988
+ "data-state": isLink ? "on" : "off",
28989
+ onClick: insertLink,
28990
+ "aria-label": "Toggle link",
28991
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LinkIcon, {}) })
28992
+ }
28993
+ )
28994
+ ] }),
28783
28995
  /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "editor-separator--vertical" }),
28784
28996
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "editor-floating-group--lg editor-flex editor-items-center", children: [
28785
28997
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -28976,8 +29188,8 @@ var init_floating_text_format_plugin = __esm({
28976
29188
  init_dialog();
28977
29189
  init_flex();
28978
29190
  init_separator();
28979
- init_toggle_group();
28980
29191
  init_typography();
29192
+ init_toggle_group();
28981
29193
  }
28982
29194
  });
28983
29195
  function KeywordsPlugin() {
@@ -30172,7 +30384,7 @@ function getResizeEdge(clientX, rect) {
30172
30384
  if (nearLeft && nearRight) return "right";
30173
30385
  return nearLeft ? "left" : "right";
30174
30386
  }
30175
- function getColumnIndexFromTableMap(tableNode, tableCellNode) {
30387
+ function $getColumnIndexFromTableMap(tableNode, tableCellNode) {
30176
30388
  if (!table.$isTableCellNode(tableCellNode)) return null;
30177
30389
  const [tableMap] = table.$computeTableMapSkipCellCheck(tableNode, null, null);
30178
30390
  for (let row = 0; row < tableMap.length; row++) {
@@ -30187,183 +30399,290 @@ function getColumnIndexFromTableMap(tableNode, tableCellNode) {
30187
30399
  }
30188
30400
  return null;
30189
30401
  }
30190
- function TableColumnResizerPlugin() {
30402
+ function TableColumnResizerPlugin({
30403
+ anchorElem = document.body
30404
+ }) {
30191
30405
  const [editor] = LexicalComposerContext.useLexicalComposerContext();
30192
30406
  const isEditable = useLexicalEditable.useLexicalEditable();
30193
30407
  const dragRef = React20.useRef(null);
30408
+ const [hoverState, setHoverState] = React20.useState(null);
30409
+ const resizerRef = React20.useRef(null);
30410
+ const onPointerDownImpl = React20.useCallback((event, cell, edge) => {
30411
+ if (event.button !== 0) return;
30412
+ event.preventDefault();
30413
+ const target = event.target;
30414
+ if (target) {
30415
+ target.setPointerCapture(event.pointerId);
30416
+ }
30417
+ let nextDragState = null;
30418
+ editor.update(() => {
30419
+ const tableCellNode = lexical.$getNearestNodeFromDOMNode(cell);
30420
+ if (!table.$isTableCellNode(tableCellNode)) return;
30421
+ const tableNode = table.$getTableNodeFromLexicalNodeOrThrow(tableCellNode);
30422
+ const tableElement = editor.getElementByKey(tableNode.getKey());
30423
+ if (!tableElement) return;
30424
+ const tableMap = table.$computeTableMapSkipCellCheck(tableNode, null, null)[0];
30425
+ const colCount = tableMap[0]?.length ?? 0;
30426
+ const columnIndexFromMap = $getColumnIndexFromTableMap(tableNode, tableCellNode);
30427
+ if (columnIndexFromMap === null) return;
30428
+ const colSpan = tableCellNode.getColSpan();
30429
+ const resizeColumnIndex = edge === "left" ? columnIndexFromMap - 1 : columnIndexFromMap + colSpan - 1;
30430
+ if (resizeColumnIndex < 0 || resizeColumnIndex >= colCount - 1) return;
30431
+ let currentWidths = tableNode.getColWidths();
30432
+ if (!currentWidths) {
30433
+ const columns = tableElement.querySelectorAll("col");
30434
+ const widths = [];
30435
+ if (columns.length === colCount) {
30436
+ columns.forEach((col) => {
30437
+ const styleWidth = col.style.width;
30438
+ if (styleWidth && styleWidth.endsWith("px")) {
30439
+ widths.push(parseFloat(styleWidth));
30440
+ } else {
30441
+ const rect = col.getBoundingClientRect();
30442
+ widths.push(rect.width || 0);
30443
+ }
30444
+ });
30445
+ }
30446
+ if (widths.length !== colCount) {
30447
+ const firstRow = tableElement.querySelector("tr");
30448
+ if (firstRow) {
30449
+ const cells = firstRow.querySelectorAll("th, td");
30450
+ if (cells.length === colCount) {
30451
+ cells.forEach((cell2) => {
30452
+ widths.push(cell2.getBoundingClientRect().width);
30453
+ });
30454
+ }
30455
+ }
30456
+ }
30457
+ if (widths.length !== colCount) {
30458
+ const tableRect = tableElement.getBoundingClientRect();
30459
+ const avgWidth = tableRect.width / (colCount || 1);
30460
+ for (let i = 0; i < colCount; i++) {
30461
+ widths.push(avgWidth);
30462
+ }
30463
+ }
30464
+ currentWidths = widths;
30465
+ }
30466
+ if (currentWidths[resizeColumnIndex] === void 0 || currentWidths[resizeColumnIndex + 1] === void 0) {
30467
+ return;
30468
+ }
30469
+ nextDragState = {
30470
+ columnIndex: resizeColumnIndex,
30471
+ initialColWidths: currentWidths,
30472
+ startX: event.clientX,
30473
+ startWidth: currentWidths[resizeColumnIndex],
30474
+ tableKey: tableNode.getKey()
30475
+ };
30476
+ });
30477
+ if (!nextDragState) return;
30478
+ dragRef.current = nextDragState;
30479
+ const rootElement = editor.getRootElement();
30480
+ if (rootElement) {
30481
+ rootElement.style.userSelect = "none";
30482
+ rootElement.style.cursor = "col-resize";
30483
+ }
30484
+ const onPointerMoveDocument = (event2) => {
30485
+ const drag = dragRef.current;
30486
+ if (!drag) return;
30487
+ event2.preventDefault();
30488
+ const deltaX = event2.clientX - drag.startX;
30489
+ const { tableKey, columnIndex, initialColWidths } = drag;
30490
+ editor.update(() => {
30491
+ const tableNode = lexical.$getNodeByKey(tableKey);
30492
+ if (!(tableNode instanceof table.TableNode)) return;
30493
+ const currentWidths = tableNode.getColWidths() || initialColWidths;
30494
+ const colCount = tableNode.getColumnCount();
30495
+ const nextColumnIndex = columnIndex + 1;
30496
+ if (nextColumnIndex >= colCount) return;
30497
+ const currentLeftWidth = initialColWidths[columnIndex];
30498
+ const currentRightWidth = initialColWidths[nextColumnIndex];
30499
+ if (currentLeftWidth === void 0 || currentRightWidth === void 0) return;
30500
+ const maxShrinkLeft = currentLeftWidth - MIN_COLUMN_WIDTH_PX;
30501
+ const maxGrowLeft = currentRightWidth - MIN_COLUMN_WIDTH_PX;
30502
+ const constrainedDelta = Math.min(Math.max(deltaX, -maxShrinkLeft), maxGrowLeft);
30503
+ const newLeftWidth = currentLeftWidth + constrainedDelta;
30504
+ const newRightWidth = currentRightWidth - constrainedDelta;
30505
+ const nextColWidths = Array.from({ length: colCount }, (_, i) => {
30506
+ if (i === columnIndex) return newLeftWidth;
30507
+ if (i === nextColumnIndex) return newRightWidth;
30508
+ return currentWidths[i] ?? initialColWidths[i] ?? 0;
30509
+ });
30510
+ if (typeof tableNode.setColWidths === "function") {
30511
+ tableNode.setColWidths(nextColWidths);
30512
+ } else {
30513
+ tableNode.__colWidths = nextColWidths;
30514
+ tableNode.__widths = nextColWidths;
30515
+ tableNode.markDirty();
30516
+ }
30517
+ });
30518
+ };
30519
+ const onPointerUpDocument = (event2) => {
30520
+ const drag = dragRef.current;
30521
+ if (!drag) return;
30522
+ const target2 = event2.target;
30523
+ if (target2 && target2.hasPointerCapture(event2.pointerId)) {
30524
+ target2.releasePointerCapture(event2.pointerId);
30525
+ }
30526
+ dragRef.current = null;
30527
+ const rootElement2 = editor.getRootElement();
30528
+ if (rootElement2) {
30529
+ rootElement2.style.userSelect = "";
30530
+ rootElement2.style.cursor = "";
30531
+ }
30532
+ document.removeEventListener("pointermove", onPointerMoveDocument);
30533
+ document.removeEventListener("pointerup", onPointerUpDocument);
30534
+ };
30535
+ document.addEventListener("pointermove", onPointerMoveDocument);
30536
+ document.addEventListener("pointerup", onPointerUpDocument);
30537
+ }, [editor]);
30538
+ const updateResizerPosition = React20.useCallback(() => {
30539
+ const state = hoverState;
30540
+ if (state === null || !resizerRef.current) return;
30541
+ const { cellKey, edge } = state;
30542
+ const cell = editor.getElementByKey(cellKey);
30543
+ if (!cell) return;
30544
+ const cellRect = cell.getBoundingClientRect();
30545
+ const anchorRect = anchorElem.getBoundingClientRect();
30546
+ const resizerElem = resizerRef.current;
30547
+ const tableElement = cell.closest("table");
30548
+ let top = cellRect.top - anchorRect.top;
30549
+ let height = cellRect.height;
30550
+ if (tableElement) {
30551
+ const tableRect = tableElement.getBoundingClientRect();
30552
+ top = tableRect.top - anchorRect.top;
30553
+ height = tableRect.height;
30554
+ }
30555
+ const left = (edge === "left" ? cellRect.left : cellRect.right) - anchorRect.left - 8;
30556
+ resizerElem.style.transform = `translate(${left}px, ${top}px)`;
30557
+ resizerElem.style.height = `${height}px`;
30558
+ resizerElem.style.opacity = "1";
30559
+ }, [editor, hoverState, anchorElem]);
30560
+ React20.useLayoutEffect(() => {
30561
+ updateResizerPosition();
30562
+ window.addEventListener("resize", updateResizerPosition);
30563
+ window.addEventListener("scroll", updateResizerPosition, true);
30564
+ const updateListener = editor.registerUpdateListener(() => {
30565
+ editor.read(() => {
30566
+ const state = hoverState;
30567
+ if (state !== null) {
30568
+ const cell = editor.getElementByKey(state.cellKey);
30569
+ if (!cell) {
30570
+ setHoverState(null);
30571
+ } else {
30572
+ updateResizerPosition();
30573
+ }
30574
+ }
30575
+ });
30576
+ });
30577
+ return () => {
30578
+ window.removeEventListener("resize", updateResizerPosition);
30579
+ window.removeEventListener("scroll", updateResizerPosition, true);
30580
+ updateListener();
30581
+ };
30582
+ }, [editor, hoverState, updateResizerPosition]);
30194
30583
  React20.useEffect(() => {
30195
30584
  if (!isEditable) return;
30196
30585
  const rootElement = editor.getRootElement();
30197
30586
  if (!rootElement) return;
30198
30587
  const setCursor = (cursor) => {
30199
- rootElement.style.cursor = cursor;
30588
+ if (rootElement) {
30589
+ rootElement.style.cursor = cursor;
30590
+ }
30200
30591
  };
30201
30592
  const clearCursor = () => {
30202
30593
  setCursor("");
30203
30594
  };
30204
30595
  const onPointerMove = (event) => {
30205
30596
  if (dragRef.current) return;
30206
- const cell = getCellTarget(event.target);
30207
- if (!cell) {
30208
- clearCursor();
30597
+ if (event.buttons !== 0) return;
30598
+ if (resizerRef.current && (event.target === resizerRef.current || resizerRef.current.contains(event.target))) {
30209
30599
  return;
30210
30600
  }
30211
- const edge = getResizeEdge(event.clientX, cell.getBoundingClientRect());
30212
- if (edge === "left") {
30213
- const table = cell.closest("table");
30214
- if (table) {
30215
- const tableRect = table.getBoundingClientRect();
30216
- const cellRect = cell.getBoundingClientRect();
30217
- if (Math.abs(cellRect.left - tableRect.left) < 5) {
30218
- clearCursor();
30219
- return;
30220
- }
30221
- }
30222
- }
30223
- setCursor(edge ? "col-resize" : "");
30224
- };
30225
- const onPointerDown = (event) => {
30226
- if (event.button !== 0) return;
30227
30601
  const cell = getCellTarget(event.target);
30228
- if (!cell) return;
30229
- const edge = getResizeEdge(event.clientX, cell.getBoundingClientRect());
30230
- if (!edge) return;
30231
- event.preventDefault();
30232
- let nextDragState = null;
30233
- editor.read(() => {
30234
- const tableCellNode = lexical.$getNearestNodeFromDOMNode(cell);
30235
- if (!table.$isTableCellNode(tableCellNode)) return;
30236
- const tableNode = table.$getTableNodeFromLexicalNodeOrThrow(tableCellNode);
30237
- const columnIndexFromMap = getColumnIndexFromTableMap(tableNode, tableCellNode);
30238
- if (columnIndexFromMap == null) return;
30239
- if (edge === "left" && columnIndexFromMap === 0) return;
30240
- const colSpan = tableCellNode.getColSpan();
30241
- const resizeColumnIndex = edge === "left" ? columnIndexFromMap - 1 : columnIndexFromMap + colSpan - 1;
30242
- let currentWidths = tableNode.getColWidths();
30243
- if (!currentWidths) {
30244
- const tableElement = editor.getElementByKey(tableNode.getKey());
30245
- if (tableElement instanceof HTMLTableElement) {
30246
- const [tableMap] = table.$computeTableMapSkipCellCheck(tableNode, null, null);
30247
- const colCount = tableNode.getColumnCount();
30248
- const widths = new Array(colCount).fill(void 0);
30249
- for (let r = 0; r < tableMap.length; r++) {
30250
- const row = tableMap[r];
30251
- if (!row) continue;
30252
- for (let c = 0; c < row.length; c++) {
30253
- if (widths[c] !== void 0) continue;
30254
- const tableMapCell = row[c];
30255
- if (!tableMapCell) continue;
30256
- const { cell: cell2 } = tableMapCell;
30257
- if (cell2.getColSpan() === 1) {
30258
- const cellElem = editor.getElementByKey(cell2.getKey());
30259
- if (cellElem) {
30260
- widths[c] = Math.round(cellElem.getBoundingClientRect().width);
30261
- }
30262
- }
30263
- }
30264
- if (widths.every((w) => w !== void 0)) break;
30265
- }
30266
- if (widths.some((w) => w === void 0)) {
30267
- if (tableElement.rows.length > 0) {
30268
- const row = tableElement.rows[0];
30269
- if (row && row.cells.length === colCount) {
30270
- const rowWidths = Array.from(row.cells).map((c) => Math.round(c.getBoundingClientRect().width));
30271
- for (let i = 0; i < colCount; i++) {
30272
- if (widths[i] === void 0) widths[i] = rowWidths[i];
30273
- }
30274
- }
30602
+ let nextHoverState = null;
30603
+ if (cell) {
30604
+ editor.read(() => {
30605
+ const cellNode = lexical.$getNearestNodeFromDOMNode(cell);
30606
+ if (table.$isTableCellNode(cellNode)) {
30607
+ const tableNode = table.$getTableNodeFromLexicalNodeOrThrow(cellNode);
30608
+ const cellKey = cellNode.getKey();
30609
+ const tableKey = tableNode.getKey();
30610
+ const edge = getResizeEdge(event.clientX, cell.getBoundingClientRect());
30611
+ if (edge) {
30612
+ const colCount = tableNode.getColumnCount();
30613
+ const colSpan = cellNode.getColSpan();
30614
+ const columnIndexFromMap = $getColumnIndexFromTableMap(tableNode, cellNode);
30615
+ if (columnIndexFromMap !== null && !(edge === "left" && columnIndexFromMap === 0 || edge === "right" && columnIndexFromMap + colSpan === colCount)) {
30616
+ nextHoverState = { cellKey, tableKey, edge };
30275
30617
  }
30276
30618
  }
30277
- if (widths.some((w) => w === void 0)) {
30278
- const tableWidth = tableElement.getBoundingClientRect().width;
30279
- const defaultWidth = tableWidth / colCount;
30280
- for (let i = 0; i < colCount; i++) {
30281
- if (widths[i] === void 0) widths[i] = defaultWidth;
30282
- }
30283
- }
30284
- currentWidths = widths;
30285
30619
  }
30620
+ });
30621
+ }
30622
+ if (!nextHoverState) {
30623
+ if (hoverState !== null) {
30624
+ clearCursor();
30625
+ setHoverState(null);
30286
30626
  }
30287
- if (!currentWidths) {
30288
- currentWidths = Array(tableNode.getColumnCount()).fill(MIN_COLUMN_WIDTH_PX);
30289
- }
30290
- const startWidth = currentWidths[resizeColumnIndex] ?? Math.max(Math.round(cell.getBoundingClientRect().width), MIN_COLUMN_WIDTH_PX);
30291
- nextDragState = {
30292
- tableKey: tableNode.getKey(),
30293
- columnIndex: resizeColumnIndex,
30294
- startX: event.clientX,
30295
- startWidth,
30296
- initialColWidths: [...currentWidths]
30297
- };
30298
- });
30299
- if (!nextDragState) return;
30300
- event.preventDefault();
30301
- event.stopPropagation();
30302
- dragRef.current = nextDragState;
30303
- setCursor("col-resize");
30304
- };
30305
- const onPointerMoveDocument = (event) => {
30306
- const drag = dragRef.current;
30307
- if (!drag) return;
30308
- const { initialColWidths, startX, columnIndex } = drag;
30309
- const deltaX = event.clientX - startX;
30310
- editor.update(() => {
30311
- const tableNode = lexical.$getNodeByKey(drag.tableKey);
30312
- if (!(tableNode instanceof table.TableNode)) return;
30313
- const colWidths = tableNode.getColWidths() ?? initialColWidths;
30314
- const nextColumnIndex = columnIndex + 1;
30315
- const hasNeighbor = nextColumnIndex < initialColWidths.length;
30316
- if (hasNeighbor) {
30317
- const currentLeftWidth = initialColWidths[columnIndex];
30318
- const currentRightWidth = initialColWidths[nextColumnIndex];
30319
- if (currentLeftWidth === void 0 || currentRightWidth === void 0) return;
30320
- const maxShrinkLeft = currentLeftWidth - MIN_COLUMN_WIDTH_PX;
30321
- const maxGrowLeft = currentRightWidth - MIN_COLUMN_WIDTH_PX;
30322
- const constrainedDelta = Math.min(Math.max(deltaX, -maxShrinkLeft), maxGrowLeft);
30323
- const newLeftWidth = currentLeftWidth + constrainedDelta;
30324
- const newRightWidth = currentRightWidth - constrainedDelta;
30325
- if (colWidths[columnIndex] === newLeftWidth && colWidths[nextColumnIndex] === newRightWidth)
30326
- return;
30327
- const nextColWidths = [...colWidths];
30328
- nextColWidths[columnIndex] = newLeftWidth;
30329
- nextColWidths[nextColumnIndex] = newRightWidth;
30330
- tableNode.setColWidths(nextColWidths);
30331
- } else {
30332
- const currentWidth = initialColWidths[columnIndex];
30333
- if (currentWidth === void 0) return;
30334
- const newWidth = Math.max(MIN_COLUMN_WIDTH_PX, Math.round(currentWidth + deltaX));
30335
- if (colWidths[columnIndex] === newWidth) return;
30336
- const nextColWidths = [...colWidths];
30337
- nextColWidths[columnIndex] = newWidth;
30338
- tableNode.setColWidths(nextColWidths);
30627
+ } else {
30628
+ setCursor("col-resize");
30629
+ if (!hoverState || hoverState.cellKey !== nextHoverState.cellKey || hoverState.edge !== nextHoverState.edge) {
30630
+ setHoverState(nextHoverState);
30339
30631
  }
30340
- });
30341
- };
30342
- const onPointerUpDocument = () => {
30343
- if (!dragRef.current) return;
30344
- dragRef.current = null;
30345
- clearCursor();
30632
+ }
30346
30633
  };
30347
- rootElement.addEventListener("pointermove", onPointerMove);
30348
- rootElement.addEventListener("pointerdown", onPointerDown);
30349
- document.addEventListener("pointermove", onPointerMoveDocument);
30350
- document.addEventListener("pointerup", onPointerUpDocument);
30634
+ anchorElem.addEventListener("pointermove", onPointerMove);
30351
30635
  return () => {
30352
- rootElement.removeEventListener("pointermove", onPointerMove);
30353
- rootElement.removeEventListener("pointerdown", onPointerDown);
30354
- document.removeEventListener("pointermove", onPointerMoveDocument);
30355
- document.removeEventListener("pointerup", onPointerUpDocument);
30636
+ anchorElem.removeEventListener("pointermove", onPointerMove);
30356
30637
  clearCursor();
30357
- dragRef.current = null;
30358
30638
  };
30359
- }, [editor, isEditable]);
30360
- return null;
30639
+ }, [editor, isEditable, hoverState, anchorElem]);
30640
+ const resizer = React20.useMemo(() => {
30641
+ const state = hoverState;
30642
+ if (state === null) return null;
30643
+ const { cellKey, edge } = state;
30644
+ return reactDom.createPortal(
30645
+ /* @__PURE__ */ jsxRuntime.jsx(
30646
+ "div",
30647
+ {
30648
+ ref: resizerRef,
30649
+ className: "editor-table-cell-resizer",
30650
+ style: {
30651
+ position: "absolute",
30652
+ top: 0,
30653
+ left: 0,
30654
+ width: "16px",
30655
+ opacity: 1,
30656
+ willChange: "transform",
30657
+ userSelect: "none"
30658
+ },
30659
+ onPointerDown: (event) => {
30660
+ event.stopPropagation();
30661
+ event.preventDefault();
30662
+ const cell = editor.getElementByKey(cellKey);
30663
+ if (cell instanceof HTMLTableCellElement) {
30664
+ onPointerDownImpl(event.nativeEvent, cell, edge);
30665
+ }
30666
+ },
30667
+ children: /* @__PURE__ */ jsxRuntime.jsx(
30668
+ "div",
30669
+ {
30670
+ className: "editor-table-cell-resize-ruler",
30671
+ style: { pointerEvents: "none" }
30672
+ }
30673
+ )
30674
+ }
30675
+ ),
30676
+ anchorElem
30677
+ );
30678
+ }, [hoverState, anchorElem, editor, onPointerDownImpl]);
30679
+ return resizer;
30361
30680
  }
30362
30681
  var EDGE_HITBOX_PX, MIN_COLUMN_WIDTH_PX;
30363
30682
  var init_table_column_resizer_plugin = __esm({
30364
30683
  "src/plugins/table-column-resizer-plugin.tsx"() {
30365
30684
  "use client";
30366
- EDGE_HITBOX_PX = 12;
30685
+ EDGE_HITBOX_PX = 8;
30367
30686
  MIN_COLUMN_WIDTH_PX = 15;
30368
30687
  }
30369
30688
  });
@@ -30467,6 +30786,10 @@ var init_block_format_data = __esm({
30467
30786
  label: "Alpha List (a, b, c)",
30468
30787
  icon: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CaseSensitiveIcon, {}) })
30469
30788
  },
30789
+ "number-multi-level": {
30790
+ label: "Multi-level List (1.1 / 1.1.1)",
30791
+ icon: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListOrderedIcon, {}) })
30792
+ },
30470
30793
  bullet: {
30471
30794
  label: "Bulleted List",
30472
30795
  icon: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListIcon, {}) })
@@ -30528,6 +30851,7 @@ function BlockFormatDropDown({
30528
30851
  else if (markerType === "+") type = "bullet-plus";
30529
30852
  } else if (type === "number") {
30530
30853
  if (markerType === "alpha") type = "number-alpha";
30854
+ else if (markerType === "multi-level") type = "number-multi-level";
30531
30855
  }
30532
30856
  }
30533
30857
  setBlockType(type);
@@ -31245,61 +31569,40 @@ function ElementFormatToolbarPlugin({
31245
31569
  }
31246
31570
  };
31247
31571
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
31248
- /* @__PURE__ */ jsxRuntime.jsx(
31249
- ToggleGroup,
31572
+ Object.entries(ELEMENT_FORMAT_OPTIONS).map(([value, option]) => /* @__PURE__ */ jsxRuntime.jsx(
31573
+ Button,
31250
31574
  {
31251
- type: "single",
31252
- value: elementFormat,
31253
- onValueChange: handleValueChange,
31575
+ variant: "outline",
31254
31576
  size: "sm",
31577
+ "aria-label": option.name,
31578
+ "data-state": elementFormat === value ? "on" : "off",
31579
+ onClick: () => handleValueChange(value),
31580
+ className: "editor-toolbar-item",
31581
+ children: option.icon
31582
+ },
31583
+ value
31584
+ )),
31585
+ separator && /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "editor-toolbar-separator" }),
31586
+ /* @__PURE__ */ jsxRuntime.jsx(
31587
+ Button,
31588
+ {
31255
31589
  variant: "outline",
31256
- children: Object.entries(ELEMENT_FORMAT_OPTIONS).map(([value, option]) => /* @__PURE__ */ jsxRuntime.jsx(
31257
- ToggleGroupItem,
31258
- {
31259
- value,
31260
- variant: "outline",
31261
- size: "sm",
31262
- "aria-label": option.name,
31263
- className: "editor-toolbar-item",
31264
- children: option.icon
31265
- },
31266
- value
31267
- ))
31590
+ size: "sm",
31591
+ "aria-label": "Outdent",
31592
+ onClick: () => handleValueChange("outdent"),
31593
+ className: "editor-toolbar-item",
31594
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.IndentDecreaseIcon, {}) })
31268
31595
  }
31269
31596
  ),
31270
- separator && /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "editor-toolbar-separator" }),
31271
- /* @__PURE__ */ jsxRuntime.jsxs(
31272
- ToggleGroup,
31597
+ /* @__PURE__ */ jsxRuntime.jsx(
31598
+ Button,
31273
31599
  {
31274
- type: "single",
31275
- value: elementFormat,
31276
- onValueChange: handleValueChange,
31277
- size: "sm",
31278
31600
  variant: "outline",
31279
- children: [
31280
- /* @__PURE__ */ jsxRuntime.jsx(
31281
- ToggleGroupItem,
31282
- {
31283
- value: "outdent",
31284
- "aria-label": "Outdent",
31285
- variant: "outline",
31286
- size: "sm",
31287
- className: "editor-toolbar-item",
31288
- children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.IndentDecreaseIcon, {}) })
31289
- }
31290
- ),
31291
- /* @__PURE__ */ jsxRuntime.jsx(
31292
- ToggleGroupItem,
31293
- {
31294
- value: "indent",
31295
- variant: "outline",
31296
- "aria-label": "Indent",
31297
- size: "sm",
31298
- className: "editor-toolbar-item",
31299
- children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.IndentIncreaseIcon, {}) })
31300
- }
31301
- )
31302
- ]
31601
+ size: "sm",
31602
+ "aria-label": "Indent",
31603
+ onClick: () => handleValueChange("indent"),
31604
+ className: "editor-toolbar-item",
31605
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.IndentIncreaseIcon, {}) })
31303
31606
  }
31304
31607
  )
31305
31608
  ] });
@@ -31312,8 +31615,8 @@ var init_element_format_toolbar_plugin = __esm({
31312
31615
  init_layout_item_node();
31313
31616
  init_use_update_toolbar();
31314
31617
  init_get_selected_node();
31618
+ init_button();
31315
31619
  init_separator();
31316
- init_toggle_group();
31317
31620
  init_typography();
31318
31621
  ELEMENT_FORMAT_OPTIONS = {
31319
31622
  left: {
@@ -31643,32 +31946,24 @@ function FontFormatToolbarPlugin() {
31643
31946
  }
31644
31947
  }, []);
31645
31948
  useUpdateToolbarHandler($updateToolbar);
31646
- return /* @__PURE__ */ jsxRuntime.jsx(
31647
- ToggleGroup,
31949
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: FORMATS.map(({ format, icon: Icon, label }) => /* @__PURE__ */ jsxRuntime.jsx(
31950
+ Button,
31648
31951
  {
31649
- type: "multiple",
31650
- value: activeFormats,
31651
- onValueChange: setActiveFormats,
31652
- variant: "default",
31952
+ variant: "ghost",
31653
31953
  size: "sm",
31654
- children: FORMATS.map(({ format, icon: Icon, label }) => /* @__PURE__ */ jsxRuntime.jsx(
31655
- ToggleGroupItem,
31656
- {
31657
- value: format,
31658
- "aria-label": label,
31659
- className: "editor-toolbar-item",
31660
- onClick: () => {
31661
- activeEditor.dispatchCommand(
31662
- lexical.FORMAT_TEXT_COMMAND,
31663
- format
31664
- );
31665
- },
31666
- children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "editor-icon-sm" })
31667
- },
31668
- format
31669
- ))
31670
- }
31671
- );
31954
+ "aria-label": label,
31955
+ "data-state": activeFormats.includes(format) ? "on" : "off",
31956
+ className: "editor-toolbar-item",
31957
+ onClick: () => {
31958
+ activeEditor.dispatchCommand(
31959
+ lexical.FORMAT_TEXT_COMMAND,
31960
+ format
31961
+ );
31962
+ },
31963
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "editor-icon-sm" })
31964
+ },
31965
+ format
31966
+ )) });
31672
31967
  }
31673
31968
  var FORMATS;
31674
31969
  var init_font_format_toolbar_plugin = __esm({
@@ -31676,7 +31971,7 @@ var init_font_format_toolbar_plugin = __esm({
31676
31971
  "use client";
31677
31972
  init_toolbar_context();
31678
31973
  init_use_update_toolbar();
31679
- init_toggle_group();
31974
+ init_button();
31680
31975
  FORMATS = [
31681
31976
  { format: "bold", icon: lucideReact.BoldIcon, label: "Bold" },
31682
31977
  { format: "italic", icon: lucideReact.ItalicIcon, label: "Italic" },
@@ -31685,14 +31980,6 @@ var init_font_format_toolbar_plugin = __esm({
31685
31980
  ];
31686
31981
  }
31687
31982
  });
31688
- function ButtonGroup({ className, children, ...props }) {
31689
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("editor-button-group", className), ...props, children });
31690
- }
31691
- var init_button_group = __esm({
31692
- "src/ui/button-group.tsx"() {
31693
- init_utils();
31694
- }
31695
- });
31696
31983
  function FontSizeToolbarPlugin() {
31697
31984
  const style = "font-size";
31698
31985
  const [fontSize, setFontSize] = React20.useState(DEFAULT_FONT_SIZE);
@@ -31782,7 +32069,7 @@ function FontSizeToolbarPlugin() {
31782
32069
  React20.useEffect(() => {
31783
32070
  return () => stopTimer();
31784
32071
  }, [stopTimer]);
31785
- return /* @__PURE__ */ jsxRuntime.jsxs(ButtonGroup, { children: [
32072
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
31786
32073
  /* @__PURE__ */ jsxRuntime.jsx(
31787
32074
  Button,
31788
32075
  {
@@ -31839,7 +32126,6 @@ var init_font_size_toolbar_plugin = __esm({
31839
32126
  init_toolbar_context();
31840
32127
  init_use_update_toolbar();
31841
32128
  init_button();
31842
- init_button_group();
31843
32129
  init_input();
31844
32130
  init_typography();
31845
32131
  DEFAULT_FONT_SIZE = 16;
@@ -31883,7 +32169,7 @@ function HistoryToolbarPlugin() {
31883
32169
  )
31884
32170
  );
31885
32171
  }, [$updateToolbar, activeEditor, editor]);
31886
- return /* @__PURE__ */ jsxRuntime.jsxs(ButtonGroup, { children: [
32172
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
31887
32173
  /* @__PURE__ */ jsxRuntime.jsx(
31888
32174
  Button,
31889
32175
  {
@@ -31894,7 +32180,6 @@ function HistoryToolbarPlugin() {
31894
32180
  title: utils.IS_APPLE ? "Undo (\u2318Z)" : "Undo (Ctrl+Z)",
31895
32181
  type: "button",
31896
32182
  "aria-label": "Undo",
31897
- size: "sm",
31898
32183
  variant: "ghost",
31899
32184
  className: "editor-toolbar-item",
31900
32185
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UndoIcon, { className: "editor-icon-sm" })
@@ -31910,7 +32195,6 @@ function HistoryToolbarPlugin() {
31910
32195
  title: utils.IS_APPLE ? "Redo (\u21E7\u2318Z)" : "Redo (Ctrl+Y)",
31911
32196
  type: "button",
31912
32197
  "aria-label": "Redo",
31913
- size: "sm",
31914
32198
  variant: "ghost",
31915
32199
  className: "editor-toolbar-item",
31916
32200
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RedoIcon, { className: "editor-icon-sm" })
@@ -31923,7 +32207,6 @@ var init_history_toolbar_plugin = __esm({
31923
32207
  "use client";
31924
32208
  init_toolbar_context();
31925
32209
  init_button();
31926
- init_button_group();
31927
32210
  }
31928
32211
  });
31929
32212
  var Toggle;
@@ -32033,50 +32316,43 @@ function SubSuperToolbarPlugin() {
32033
32316
  }
32034
32317
  };
32035
32318
  useUpdateToolbarHandler($updateToolbar);
32036
- return /* @__PURE__ */ jsxRuntime.jsxs(
32037
- ToggleGroup,
32038
- {
32039
- type: "single",
32040
- value: isSubscript ? "subscript" : isSuperscript ? "superscript" : "",
32041
- size: "default",
32042
- variant: "outline",
32043
- children: [
32044
- /* @__PURE__ */ jsxRuntime.jsx(
32045
- ToggleGroupItem,
32046
- {
32047
- value: "subscript",
32048
- size: "default",
32049
- "aria-label": "Toggle subscript",
32050
- onClick: () => {
32051
- activeEditor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "subscript");
32052
- },
32053
- variant: "outline",
32054
- children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SubscriptIcon, {}) })
32055
- }
32056
- ),
32057
- /* @__PURE__ */ jsxRuntime.jsx(
32058
- ToggleGroupItem,
32059
- {
32060
- value: "superscript",
32061
- size: "default",
32062
- "aria-label": "Toggle superscript",
32063
- onClick: () => {
32064
- activeEditor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "superscript");
32065
- },
32066
- variant: "outline",
32067
- children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SuperscriptIcon, {}) })
32068
- }
32069
- )
32070
- ]
32071
- }
32072
- );
32319
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
32320
+ /* @__PURE__ */ jsxRuntime.jsx(
32321
+ Button,
32322
+ {
32323
+ variant: "outline",
32324
+ size: "icon",
32325
+ "aria-label": "Toggle subscript",
32326
+ "data-state": isSubscript ? "on" : "off",
32327
+ onClick: () => {
32328
+ activeEditor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "subscript");
32329
+ },
32330
+ className: "editor-toolbar-item",
32331
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SubscriptIcon, {}) })
32332
+ }
32333
+ ),
32334
+ /* @__PURE__ */ jsxRuntime.jsx(
32335
+ Button,
32336
+ {
32337
+ variant: "outline",
32338
+ size: "icon",
32339
+ "aria-label": "Toggle superscript",
32340
+ "data-state": isSuperscript ? "on" : "off",
32341
+ onClick: () => {
32342
+ activeEditor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "superscript");
32343
+ },
32344
+ className: "editor-toolbar-item",
32345
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SuperscriptIcon, {}) })
32346
+ }
32347
+ )
32348
+ ] });
32073
32349
  }
32074
32350
  var init_subsuper_toolbar_plugin = __esm({
32075
32351
  "src/plugins/toolbar/subsuper-toolbar-plugin.tsx"() {
32076
32352
  "use client";
32077
32353
  init_toolbar_context();
32078
32354
  init_use_update_toolbar();
32079
- init_toggle_group();
32355
+ init_button();
32080
32356
  init_typography();
32081
32357
  }
32082
32358
  });
@@ -32589,7 +32865,8 @@ __export(plugins_exports, {
32589
32865
  Plugins: () => Plugins
32590
32866
  });
32591
32867
  function Plugins({
32592
- readOnly = false
32868
+ readOnly = false,
32869
+ placeholder = ""
32593
32870
  }) {
32594
32871
  const [floatingAnchorElem, setFloatingAnchorElem] = React20.useState(null);
32595
32872
  const [isLinkEditMode, setIsLinkEditMode] = React20.useState(false);
@@ -32606,47 +32883,50 @@ function Plugins({
32606
32883
  children: ({ blockType }) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
32607
32884
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "editor-toolbar-group", children: /* @__PURE__ */ jsxRuntime.jsx(HistoryToolbarPlugin, {}) }),
32608
32885
  /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "editor-toolbar-separator" }),
32609
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "editor-toolbar-group", children: /* @__PURE__ */ jsxRuntime.jsxs(BlockInsertPlugin, { children: [
32610
- /* @__PURE__ */ jsxRuntime.jsx(InsertHorizontalRule, {}),
32611
- /* @__PURE__ */ jsxRuntime.jsx(InsertImage, {}),
32612
- /* @__PURE__ */ jsxRuntime.jsx(InsertTable, {}),
32613
- /* @__PURE__ */ jsxRuntime.jsx(InsertColumnsLayout, {}),
32614
- /* @__PURE__ */ jsxRuntime.jsx(InsertEmbeds, {})
32615
- ] }) }),
32616
- /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "editor-toolbar-separator" }),
32617
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "editor-toolbar-group", children: /* @__PURE__ */ jsxRuntime.jsxs(BlockFormatDropDown, { children: [
32618
- /* @__PURE__ */ jsxRuntime.jsx(FormatParagraph, {}),
32619
- /* @__PURE__ */ jsxRuntime.jsx(FormatHeading, { levels: ["h1", "h2", "h3"] }),
32620
- /* @__PURE__ */ jsxRuntime.jsx(FormatNumberedList, {}),
32621
- /* @__PURE__ */ jsxRuntime.jsx(
32622
- FormatListWithMarker,
32623
- {
32624
- blockFormatValue: "number-alpha",
32625
- listType: "number",
32626
- markerType: "alpha"
32627
- }
32628
- ),
32629
- /* @__PURE__ */ jsxRuntime.jsx(FormatBulletedList, {}),
32630
- /* @__PURE__ */ jsxRuntime.jsx(
32631
- FormatListWithMarker,
32632
- {
32633
- blockFormatValue: "bullet-dash",
32634
- listType: "bullet",
32635
- markerType: "-"
32636
- }
32637
- ),
32638
- /* @__PURE__ */ jsxRuntime.jsx(
32639
- FormatListWithMarker,
32640
- {
32641
- blockFormatValue: "bullet-plus",
32642
- listType: "bullet",
32643
- markerType: "+"
32644
- }
32645
- ),
32646
- /* @__PURE__ */ jsxRuntime.jsx(FormatCheckList, {}),
32647
- /* @__PURE__ */ jsxRuntime.jsx(FormatCodeBlock, {}),
32648
- /* @__PURE__ */ jsxRuntime.jsx(FormatQuote, {})
32649
- ] }) }),
32886
+ blockType !== "code" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
32887
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "editor-toolbar-group", children: /* @__PURE__ */ jsxRuntime.jsxs(BlockInsertPlugin, { children: [
32888
+ /* @__PURE__ */ jsxRuntime.jsx(InsertHorizontalRule, {}),
32889
+ /* @__PURE__ */ jsxRuntime.jsx(InsertImage, {}),
32890
+ /* @__PURE__ */ jsxRuntime.jsx(InsertTable, {}),
32891
+ /* @__PURE__ */ jsxRuntime.jsx(InsertColumnsLayout, {}),
32892
+ /* @__PURE__ */ jsxRuntime.jsx(InsertEmbeds, {})
32893
+ ] }) }),
32894
+ /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "editor-toolbar-separator" }),
32895
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "editor-toolbar-group", children: /* @__PURE__ */ jsxRuntime.jsxs(BlockFormatDropDown, { children: [
32896
+ /* @__PURE__ */ jsxRuntime.jsx(FormatParagraph, {}),
32897
+ /* @__PURE__ */ jsxRuntime.jsx(FormatHeading, { levels: ["h1", "h2", "h3"] }),
32898
+ /* @__PURE__ */ jsxRuntime.jsx(FormatNumberedList, {}),
32899
+ /* @__PURE__ */ jsxRuntime.jsx(
32900
+ FormatListWithMarker,
32901
+ {
32902
+ blockFormatValue: "number-alpha",
32903
+ listType: "number",
32904
+ markerType: "alpha"
32905
+ }
32906
+ ),
32907
+ /* @__PURE__ */ jsxRuntime.jsx(FormatBulletedList, {}),
32908
+ /* @__PURE__ */ jsxRuntime.jsx(
32909
+ FormatListWithMarker,
32910
+ {
32911
+ blockFormatValue: "bullet-dash",
32912
+ listType: "bullet",
32913
+ markerType: "-"
32914
+ }
32915
+ ),
32916
+ /* @__PURE__ */ jsxRuntime.jsx(
32917
+ FormatListWithMarker,
32918
+ {
32919
+ blockFormatValue: "bullet-plus",
32920
+ listType: "bullet",
32921
+ markerType: "+"
32922
+ }
32923
+ ),
32924
+ /* @__PURE__ */ jsxRuntime.jsx(FormatCheckList, {}),
32925
+ /* @__PURE__ */ jsxRuntime.jsx(FormatCodeBlock, {}),
32926
+ /* @__PURE__ */ jsxRuntime.jsx(FormatQuote, {})
32927
+ ] }) }),
32928
+ /* @__PURE__ */ jsxRuntime.jsx(Separator, { orientation: "vertical", className: "editor-toolbar-separator" })
32929
+ ] }),
32650
32930
  blockType === "code" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "editor-toolbar-group", children: /* @__PURE__ */ jsxRuntime.jsx(CodeLanguageToolbarPlugin, {}) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
32651
32931
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "editor-toolbar-group", children: [
32652
32932
  /* @__PURE__ */ jsxRuntime.jsx(FontFamilyToolbarPlugin, {}),
@@ -32697,7 +32977,7 @@ function Plugins({
32697
32977
  /* @__PURE__ */ jsxRuntime.jsx(LexicalHorizontalRulePlugin.HorizontalRulePlugin, {}),
32698
32978
  /* @__PURE__ */ jsxRuntime.jsx(LexicalTablePlugin.TablePlugin, { hasHorizontalScroll: true }),
32699
32979
  /* @__PURE__ */ jsxRuntime.jsx(InsertTableCommandPlugin, {}),
32700
- /* @__PURE__ */ jsxRuntime.jsx(TableColumnResizerPlugin, {}),
32980
+ /* @__PURE__ */ jsxRuntime.jsx(TableColumnResizerPlugin, { anchorElem: floatingAnchorElem ?? document.body }),
32701
32981
  /* @__PURE__ */ jsxRuntime.jsx(LexicalListPlugin.ListPlugin, {}),
32702
32982
  /* @__PURE__ */ jsxRuntime.jsx(LexicalTabIndentationPlugin.TabIndentationPlugin, {}),
32703
32983
  /* @__PURE__ */ jsxRuntime.jsx(LexicalHistoryPlugin.HistoryPlugin, {})
@@ -32826,7 +33106,6 @@ function Plugins({
32826
33106
  ] }) })
32827
33107
  ] });
32828
33108
  }
32829
- var placeholder;
32830
33109
  var init_plugins = __esm({
32831
33110
  "src/editor-x/plugins.tsx"() {
32832
33111
  "use client";
@@ -32915,7 +33194,6 @@ var init_plugins = __esm({
32915
33194
  init_markdown_tweet_transformer();
32916
33195
  init_markdown_list_transformer();
32917
33196
  init_separator();
32918
- placeholder = "Press / for commands...";
32919
33197
  }
32920
33198
  });
32921
33199
 
@@ -33059,7 +33337,8 @@ function Editor({
33059
33337
  editorSerializedState,
33060
33338
  onChange,
33061
33339
  onSerializedChange,
33062
- readOnly = false
33340
+ readOnly = false,
33341
+ placeholder = ""
33063
33342
  }) {
33064
33343
  const { ref: editorRef, width: editorWidth } = useElementSize();
33065
33344
  const editorMaxWidth = editorWidth || void 0;
@@ -33070,7 +33349,18 @@ function Editor({
33070
33349
  Promise.resolve().then(() => (init_plugins(), plugins_exports)).then((m) => ({ Plugins: m.Plugins }))
33071
33350
  ]).then(([nodes2, { Plugins: Plugins3 }]) => setConfig({ nodes: nodes2, Plugins: Plugins3 }));
33072
33351
  }, []);
33073
- if (!config) {
33352
+ const editorConfig = React20.useMemo(() => {
33353
+ if (!config || !config.nodes) return null;
33354
+ const validNodes = config.nodes.filter((node) => {
33355
+ if (node === void 0) {
33356
+ console.error("[Editor] Found undefined node in config.nodes");
33357
+ return false;
33358
+ }
33359
+ return true;
33360
+ });
33361
+ return createEditorConfig(validNodes);
33362
+ }, [config]);
33363
+ if (!config || !editorConfig) {
33074
33364
  return /* @__PURE__ */ jsxRuntime.jsx(
33075
33365
  "div",
33076
33366
  {
@@ -33082,7 +33372,6 @@ function Editor({
33082
33372
  }
33083
33373
  );
33084
33374
  }
33085
- const editorConfig = createEditorConfig(config.nodes);
33086
33375
  const { Plugins: Plugins2 } = config;
33087
33376
  return /* @__PURE__ */ jsxRuntime.jsx(
33088
33377
  "div",
@@ -33103,7 +33392,7 @@ function Editor({
33103
33392
  ...editorSerializedState ? { editorState: JSON.stringify(editorSerializedState) } : {}
33104
33393
  },
33105
33394
  children: /* @__PURE__ */ jsxRuntime.jsxs(TooltipProvider, { children: [
33106
- /* @__PURE__ */ jsxRuntime.jsx(Plugins2, { readOnly }),
33395
+ /* @__PURE__ */ jsxRuntime.jsx(Plugins2, { readOnly, placeholder }),
33107
33396
  !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
33108
33397
  LexicalOnChangePlugin.OnChangePlugin,
33109
33398
  {