@thangph2146/lexical-editor 0.0.3 → 0.0.5

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 (100) hide show
  1. package/dist/editor-x/editor.cjs +724 -435
  2. package/dist/editor-x/editor.cjs.map +1 -1
  3. package/dist/editor-x/editor.css +1391 -1091
  4. package/dist/editor-x/editor.css.map +1 -1
  5. package/dist/editor-x/editor.js +728 -439
  6. package/dist/editor-x/editor.js.map +1 -1
  7. package/dist/index.cjs +760 -472
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.css +1391 -1091
  10. package/dist/index.css.map +1 -1
  11. package/dist/index.js +763 -475
  12. package/dist/index.js.map +1 -1
  13. package/package.json +1 -1
  14. package/src/components/lexical-editor.tsx +138 -123
  15. package/src/editor-ui/content-editable.tsx +3 -3
  16. package/src/editor-x/editor.tsx +16 -3
  17. package/src/editor-x/plugins.tsx +385 -380
  18. package/src/nodes/list-with-color-node.tsx +160 -160
  19. package/src/plugins/autocomplete-plugin.tsx +2574 -2574
  20. package/src/plugins/context-menu-plugin.tsx +239 -9
  21. package/src/plugins/floating-text-format-plugin.tsx +84 -92
  22. package/src/plugins/images-plugin.tsx +4 -4
  23. package/src/plugins/list-color-plugin.tsx +178 -178
  24. package/src/plugins/tab-focus-plugin.tsx +66 -66
  25. package/src/plugins/table-column-resizer-plugin.tsx +329 -190
  26. package/src/plugins/toolbar/block-format/block-format-data.tsx +4 -0
  27. package/src/plugins/toolbar/block-format/format-bulleted-list.tsx +40 -40
  28. package/src/plugins/toolbar/block-format/format-list-with-marker.tsx +74 -74
  29. package/src/plugins/toolbar/block-format/format-numbered-list.tsx +40 -40
  30. package/src/plugins/toolbar/block-format-toolbar-plugin.tsx +118 -117
  31. package/src/plugins/toolbar/element-format-toolbar-plugin.tsx +37 -53
  32. package/src/plugins/toolbar/font-format-toolbar-plugin.tsx +8 -15
  33. package/src/plugins/toolbar/font-size-toolbar-plugin.tsx +2 -3
  34. package/src/plugins/toolbar/history-toolbar-plugin.tsx +2 -5
  35. package/src/plugins/toolbar/subsuper-toolbar-plugin.tsx +15 -23
  36. package/src/themes/_mixins.scss +158 -10
  37. package/src/themes/_variables.scss +168 -0
  38. package/src/themes/core/_code.scss +59 -0
  39. package/src/themes/core/_images.scss +80 -0
  40. package/src/themes/core/_lists.scss +214 -0
  41. package/src/themes/core/_misc.scss +46 -0
  42. package/src/themes/core/_reset.scss +119 -0
  43. package/src/themes/core/_tables.scss +145 -0
  44. package/src/themes/core/_text.scss +35 -0
  45. package/src/themes/core/_typography.scss +73 -0
  46. package/src/themes/editor-theme copy.scss +763 -0
  47. package/src/themes/editor-theme.scss +9 -621
  48. package/src/themes/editor-theme.ts +118 -118
  49. package/src/themes/plugins/_auto-embed.scss +11 -0
  50. package/src/themes/plugins/_color-picker.scss +103 -0
  51. package/src/themes/plugins/_draggable-block.scss +32 -0
  52. package/src/themes/plugins/_floating-link-editor.scss +47 -0
  53. package/src/themes/plugins/_floating-toolbars.scss +61 -0
  54. package/src/themes/plugins/_image-resizer.scss +38 -0
  55. package/src/themes/plugins/_image.scss +57 -0
  56. package/src/themes/plugins/_layout.scss +39 -0
  57. package/src/themes/plugins/_list-color.scss +23 -0
  58. package/src/themes/plugins/_mentions.scss +21 -0
  59. package/src/themes/plugins/_menus-and-pickers.scss +153 -0
  60. package/src/themes/plugins/_table.scss +20 -0
  61. package/src/themes/plugins/_toolbar.scss +36 -0
  62. package/src/themes/plugins/_tree-view.scss +11 -0
  63. package/src/themes/plugins copy.scss +656 -0
  64. package/src/themes/plugins.scss +20 -1165
  65. package/src/themes/ui-components/_animations.scss +31 -0
  66. package/src/themes/ui-components/_backgrounds.scss +27 -0
  67. package/src/themes/ui-components/_borders.scss +20 -0
  68. package/src/themes/ui-components/_button.scss +176 -0
  69. package/src/themes/ui-components/_checkbox.scss +14 -0
  70. package/src/themes/ui-components/_cursors.scss +31 -0
  71. package/src/themes/ui-components/_dialog.scss +86 -0
  72. package/src/themes/ui-components/_display-sizing.scss +100 -0
  73. package/src/themes/ui-components/_flex.scss +124 -0
  74. package/src/themes/ui-components/_form-layout.scss +15 -0
  75. package/src/themes/ui-components/_icons.scss +23 -0
  76. package/src/themes/ui-components/_input.scss +86 -0
  77. package/src/themes/ui-components/_label.scss +19 -0
  78. package/src/themes/ui-components/_loader.scss +9 -0
  79. package/src/themes/ui-components/_margins-paddings.scss +45 -0
  80. package/src/themes/ui-components/_popover.scss +16 -0
  81. package/src/themes/ui-components/_positioning.scss +73 -0
  82. package/src/themes/ui-components/_rounded.scss +19 -0
  83. package/src/themes/ui-components/_scroll-area.scss +11 -0
  84. package/src/themes/ui-components/_select.scss +110 -0
  85. package/src/themes/ui-components/_separator.scss +19 -0
  86. package/src/themes/ui-components/_shadow.scss +15 -0
  87. package/src/themes/ui-components/_tabs.scss +46 -0
  88. package/src/themes/ui-components/_text-utilities.scss +48 -0
  89. package/src/themes/ui-components/_toggle-toolbar.scss +128 -0
  90. package/src/themes/ui-components/_toggle.scss +80 -0
  91. package/src/themes/ui-components/_typography.scss +22 -0
  92. package/src/themes/ui-components copy.scss +1335 -0
  93. package/src/themes/ui-components.scss +27 -937
  94. package/src/transformers/markdown-list-transformer.ts +51 -51
  95. package/src/ui/button.tsx +11 -2
  96. package/src/ui/collapsible.tsx +1 -1
  97. package/src/ui/dialog.tsx +2 -2
  98. package/src/ui/flex.tsx +4 -4
  99. package/src/ui/popover.tsx +1 -1
  100. package/src/ui/tooltip.tsx +2 -2
@@ -1,13 +1,13 @@
1
1
  import * as React20 from 'react';
2
- import { createContext, useRef, useState, useEffect, useCallback, Suspense, useContext, useMemo, useLayoutEffect } from 'react';
2
+ import { createContext, useRef, useState, useEffect, useCallback, Suspense, useMemo, useContext, useLayoutEffect } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
5
5
  import { $patchStyleText, $setBlocksType, $getSelectionStyleValueForProperty, $isAtNodeEnd } from '@lexical/selection';
6
6
  import { mergeRegister, IS_APPLE, $findMatchingParent, $getNearestNodeOfType, $getNearestBlockElementAncestorOrThrow, $wrapNodeInElement, $insertNodeToNearestRoot, mediaFileReader, isMimeType, addClassNamesToElement, calculateZoomLevel } from '@lexical/utils';
7
- import { $getNodeByKey, FORMAT_ELEMENT_COMMAND, $isNodeSelection, $getRoot, $getSelection, $setSelection, $isRangeSelection, SELECTION_CHANGE_COMMAND, COMMAND_PRIORITY_LOW, CLICK_COMMAND, DRAGSTART_COMMAND, KEY_DELETE_COMMAND, KEY_BACKSPACE_COMMAND, KEY_ENTER_COMMAND, KEY_ESCAPE_COMMAND, COMMAND_PRIORITY_CRITICAL, CAN_UNDO_COMMAND, CAN_REDO_COMMAND, UNDO_COMMAND, REDO_COMMAND, $isRootOrShadowRoot, FORMAT_TEXT_COMMAND, KEY_MODIFIER_COMMAND, COMMAND_PRIORITY_NORMAL, $isTextNode, $createParagraphNode, $isElementNode, COMMAND_PRIORITY_EDITOR, $insertNodes, COMMAND_PRIORITY_HIGH, DRAGOVER_COMMAND, DROP_COMMAND, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ARROW_LEFT_COMMAND, FOCUS_COMMAND, KEY_TAB_COMMAND, CUT_COMMAND, COPY_COMMAND, PASTE_COMMAND, $isDecoratorNode, $createTextNode, INDENT_CONTENT_COMMAND, CLEAR_HISTORY_COMMAND, CLEAR_EDITOR_COMMAND, ParagraphNode, TextNode, OUTDENT_CONTENT_COMMAND, $getNearestNodeFromDOMNode, $applyNodeReplacement, $createRangeSelection, $isParagraphNode, DecoratorNode, createEditor, RootNode, ElementNode, createCommand, HISTORY_MERGE_TAG, $isLineBreakNode, isHTMLElement, $addUpdateTag } from 'lexical';
7
+ import { $getNodeByKey, FORMAT_ELEMENT_COMMAND, $isNodeSelection, $getRoot, $getSelection, $setSelection, $isRangeSelection, SELECTION_CHANGE_COMMAND, COMMAND_PRIORITY_LOW, CLICK_COMMAND, DRAGSTART_COMMAND, KEY_DELETE_COMMAND, KEY_BACKSPACE_COMMAND, KEY_ENTER_COMMAND, KEY_ESCAPE_COMMAND, COMMAND_PRIORITY_CRITICAL, CAN_UNDO_COMMAND, CAN_REDO_COMMAND, UNDO_COMMAND, REDO_COMMAND, $isRootOrShadowRoot, FORMAT_TEXT_COMMAND, KEY_MODIFIER_COMMAND, COMMAND_PRIORITY_NORMAL, $isTextNode, $createParagraphNode, $isElementNode, COMMAND_PRIORITY_EDITOR, $getNearestNodeFromDOMNode, $insertNodes, COMMAND_PRIORITY_HIGH, DRAGOVER_COMMAND, DROP_COMMAND, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_RIGHT_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ARROW_LEFT_COMMAND, FOCUS_COMMAND, KEY_TAB_COMMAND, CUT_COMMAND, COPY_COMMAND, PASTE_COMMAND, $isDecoratorNode, $createTextNode, INDENT_CONTENT_COMMAND, CLEAR_HISTORY_COMMAND, CLEAR_EDITOR_COMMAND, ParagraphNode, TextNode, OUTDENT_CONTENT_COMMAND, $applyNodeReplacement, $createRangeSelection, $isParagraphNode, DecoratorNode, createEditor, RootNode, ElementNode, createCommand, HISTORY_MERGE_TAG, $isLineBreakNode, isHTMLElement, $addUpdateTag } from 'lexical';
8
8
  import { BlockWithAlignableContents } from '@lexical/react/LexicalBlockWithAlignableContents';
9
9
  import { $isDecoratorBlockNode, DecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode';
10
- import { UndoIcon, RedoIcon, PlusIcon, ScissorsIcon, ImageIcon, TableIcon, Columns3Icon, TypeIcon, Minus, Plus, SubscriptIcon, SuperscriptIcon, LinkIcon, EraserIcon, BaselineIcon, PaintBucketIcon, IndentDecreaseIcon, IndentIncreaseIcon, CircleUserRoundIcon, GripVerticalIcon, TextIcon, ListTodoIcon, ListOrderedIcon, ListIcon, QuoteIcon, CodeIcon, MinusIcon, Combine, SplitSquareVertical, Columns3, Rows3, LayoutGrid, Palette, Link2Off, Scissors, Copy, Clipboard, ClipboardType, Trash2, SendIcon, UploadIcon, DownloadIcon, FileTextIcon, LockIcon, UnlockIcon, Trash2Icon, NotebookPenIcon, Loader2, PipetteIcon, Heading3Icon, Heading2Icon, Heading1Icon, AlignJustifyIcon, AlignRightIcon, AlignCenterIcon, AlignLeftIcon, YoutubeIcon, TwitterIcon, BoldIcon, ItalicIcon, UnderlineIcon, StrikethroughIcon, ChevronRight, Folder, CircleCheckIcon, CopyIcon, X, Check, Pencil, Trash, MicIcon, ListPlusIcon, ListMinusIcon, CaseSensitiveIcon, AlignLeft, AlignCenter, AlignRight, Minimize2, Maximize2, ImageMinus, ImagePlus } from 'lucide-react';
10
+ import { UndoIcon, RedoIcon, PlusIcon, ScissorsIcon, ImageIcon, TableIcon, Columns3Icon, TypeIcon, Minus, Plus, SubscriptIcon, SuperscriptIcon, LinkIcon, EraserIcon, BaselineIcon, PaintBucketIcon, IndentDecreaseIcon, IndentIncreaseIcon, CircleUserRoundIcon, GripVerticalIcon, TextIcon, ListTodoIcon, ListOrderedIcon, ListIcon, QuoteIcon, CodeIcon, MinusIcon, Combine, SplitSquareVertical, Columns3, Rows3, LayoutGrid, Palette, Hash, Link2Off, Scissors, Copy, Clipboard, ClipboardType, Trash2, SendIcon, UploadIcon, DownloadIcon, FileTextIcon, LockIcon, UnlockIcon, Trash2Icon, NotebookPenIcon, Loader2, PipetteIcon, Heading3Icon, Heading2Icon, Heading1Icon, AlignJustifyIcon, AlignRightIcon, AlignCenterIcon, AlignLeftIcon, YoutubeIcon, TwitterIcon, BoldIcon, ItalicIcon, UnderlineIcon, StrikethroughIcon, ChevronRight, Folder, CircleCheckIcon, CopyIcon, X, Check, Pencil, Trash, MicIcon, ListPlusIcon, ListMinusIcon, CaseSensitiveIcon, AlignLeft, AlignCenter, AlignRight, Minimize2, Maximize2, ImageMinus, ImagePlus } from 'lucide-react';
11
11
  import { useLexicalEditable } from '@lexical/react/useLexicalEditable';
12
12
  import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection';
13
13
  import { createPortal } from 'react-dom';
@@ -25,7 +25,7 @@ import { TOGGLE_LINK_COMMAND, $isLinkNode, LinkNode, AutoLinkNode, $createLinkNo
25
25
  import { OverflowNode } from '@lexical/overflow';
26
26
  import { INSERT_HORIZONTAL_RULE_COMMAND, HorizontalRuleNode, $createHorizontalRuleNode, $isHorizontalRuleNode } from '@lexical/react/LexicalHorizontalRuleNode';
27
27
  import { $isHeadingNode, $isQuoteNode, $createHeadingNode, $createQuoteNode, DRAG_DROP_PASTE, HeadingNode, QuoteNode } from '@lexical/rich-text';
28
- import { $isTableSelection, TableNode, INSERT_TABLE_COMMAND, $isTableCellNode, $mergeCells, $unmergeCell, $insertTableColumnAtSelection, $insertTableRowAtSelection, TableCellNode, TableRowNode, $createTableNodeWithDimensions, $getTableNodeFromLexicalNodeOrThrow, $computeTableMapSkipCellCheck, $isTableNode, $isTableRowNode, TableCellHeaderStates, $createTableNode, $createTableRowNode, $createTableCellNode } from '@lexical/table';
28
+ import { $isTableSelection, TableNode, $isTableCellNode, $getTableNodeFromLexicalNodeOrThrow, $computeTableMapSkipCellCheck, INSERT_TABLE_COMMAND, $mergeCells, $unmergeCell, $insertTableColumnAtSelection, $insertTableRowAtSelection, TableCellNode, TableRowNode, $createTableNodeWithDimensions, $isTableNode, $isTableRowNode, TableCellHeaderStates, $createTableNode, $createTableRowNode, $createTableCellNode } from '@lexical/table';
29
29
  import { $rootTextContent } from '@lexical/text';
30
30
  import { editorStateFromSerializedDocument, serializedDocumentFromEditorState, importFile, exportFile } from '@lexical/file';
31
31
  import { CHECK_LIST, MULTILINE_ELEMENT_TRANSFORMERS, TEXT_FORMAT_TRANSFORMERS, TEXT_MATCH_TRANSFORMERS, ELEMENT_TRANSFORMERS, $convertFromMarkdownString, $convertToMarkdownString } from '@lexical/markdown';
@@ -2964,8 +2964,8 @@ var init_button = __esm({
2964
2964
  "src/ui/button.tsx"() {
2965
2965
  init_utils();
2966
2966
  Button = React20.forwardRef(
2967
- ({ className, variant = "default", size = "default", type = "button", ...props }, ref) => {
2968
- return /* @__PURE__ */ jsx(
2967
+ ({ className, variant = "default", size = "default", type = "button", isLoading, disabled, children, ...props }, ref) => {
2968
+ return /* @__PURE__ */ jsxs(
2969
2969
  "button",
2970
2970
  {
2971
2971
  type,
@@ -2973,10 +2973,16 @@ var init_button = __esm({
2973
2973
  "editor-btn",
2974
2974
  variant !== "default" && `editor-btn--${variant}`,
2975
2975
  size !== "default" && `editor-btn--size-${size}`,
2976
+ isLoading && "editor-btn--loading",
2976
2977
  className
2977
2978
  ),
2979
+ disabled: isLoading || disabled,
2978
2980
  ref,
2979
- ...props
2981
+ ...props,
2982
+ children: [
2983
+ isLoading && /* @__PURE__ */ jsx(Loader2, { className: "editor-btn__loader editor-animate-spin", size: 16 }),
2984
+ /* @__PURE__ */ jsx("span", { className: cn("editor-btn__content", isLoading && "editor-opacity-0"), children })
2985
+ ]
2980
2986
  }
2981
2987
  );
2982
2988
  }
@@ -4349,8 +4355,8 @@ function ImagePickerFolderTree({
4349
4355
  /* @__PURE__ */ jsx(TypographyP, { className: "editor-truncate", children: folder.name }),
4350
4356
  /* @__PURE__ */ 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` : ""}` })
4351
4357
  ] }),
4352
- /* @__PURE__ */ jsxs(CollapsibleContent, { className: "editor-ml-4 editor-mt-1", children: [
4353
- folder.images.length > 0 && /* @__PURE__ */ jsx("div", { className: "editor-image-grid", children: folder.images.map((image) => /* @__PURE__ */ jsx(
4358
+ /* @__PURE__ */ jsxs(CollapsibleContent, { className: "editor-ml-4 editor-mt-1 editor-flex editor-flex-col editor-gap-1", children: [
4359
+ folder.images.length > 0 && /* @__PURE__ */ jsx("div", { className: "editor-image-grid editor-gap-2", children: folder.images.map((image) => /* @__PURE__ */ jsx(
4354
4360
  "button",
4355
4361
  {
4356
4362
  type: "button",
@@ -4437,10 +4443,10 @@ function InsertImageUploadsDialogBody({
4437
4443
  return /* @__PURE__ */ jsxs("div", { className: "editor-form-grid", children: [
4438
4444
  /* @__PURE__ */ jsxs("div", { className: "editor-form-item", children: [
4439
4445
  /* @__PURE__ */ jsx(Label, { children: "Ch\u1ECDn h\xECnh \u1EA3nh t\u1EEB th\u01B0 vi\u1EC7n" }),
4440
- isLoading ? /* @__PURE__ */ jsx("div", { className: "editor-flex-center-justify-py-8", children: /* @__PURE__ */ jsx(Loader2, { className: "editor-loader" }) }) : !folderTree || folderTree.subfolders.length === 0 && folderTree.images.length === 0 ? /* @__PURE__ */ jsx("div", { className: "editor-empty-state", children: /* @__PURE__ */ jsx(TypographySpanSmallMuted, { children: "Ch\u01B0a c\xF3 h\xECnh \u1EA3nh n\xE0o \u0111\u01B0\u1EE3c upload" }) }) : /* @__PURE__ */ jsxs("div", { className: "editor-scroll-area", children: [
4446
+ isLoading ? /* @__PURE__ */ jsx("div", { className: "editor-flex-center-justify-py-8", children: /* @__PURE__ */ jsx(Loader2, { className: "editor-loader" }) }) : !folderTree || folderTree.subfolders.length === 0 && folderTree.images.length === 0 ? /* @__PURE__ */ jsx("div", { className: "editor-empty-state", children: /* @__PURE__ */ jsx(TypographySpanSmallMuted, { children: "Ch\u01B0a c\xF3 h\xECnh \u1EA3nh n\xE0o \u0111\u01B0\u1EE3c upload" }) }) : /* @__PURE__ */ jsxs("div", { className: "editor-scroll-area editor-flex editor-flex-col editor-gap-1", children: [
4441
4447
  folderTree.images.length > 0 && /* @__PURE__ */ jsxs("div", { className: "editor-mb-3", children: [
4442
4448
  /* @__PURE__ */ jsx(TypographySpanSmallMuted, { className: "editor-mb-2 editor-px-1", children: "Root" }),
4443
- /* @__PURE__ */ jsx("div", { className: "editor-image-grid", children: folderTree.images.map((image) => /* @__PURE__ */ jsx(
4449
+ /* @__PURE__ */ jsx("div", { className: "editor-image-grid editor-gap-2", children: folderTree.images.map((image) => /* @__PURE__ */ jsx(
4444
4450
  "button",
4445
4451
  {
4446
4452
  type: "button",
@@ -5036,13 +5042,13 @@ function ContentEditable({
5036
5042
  placeholderClassName,
5037
5043
  placeholderDefaults = true
5038
5044
  }) {
5039
- const isReadOnly = className?.includes("--readonly");
5045
+ const isReadOnlyOrReview = className?.includes("--readonly") || className?.includes("--review");
5040
5046
  return /* @__PURE__ */ jsx(
5041
5047
  ContentEditable$1,
5042
5048
  {
5043
5049
  className: cn(
5044
5050
  "ContentEditable__root relative block focus:outline-none",
5045
- !isReadOnly && "min-h-72 px-8 py-4",
5051
+ !isReadOnlyOrReview && "min-h-72 px-8 py-4",
5046
5052
  className
5047
5053
  ),
5048
5054
  "aria-placeholder": placeholder2,
@@ -5053,7 +5059,7 @@ function ContentEditable({
5053
5059
  className: cn(
5054
5060
  placeholderClassName,
5055
5061
  "text-muted-foreground pointer-events-none select-none",
5056
- placeholderDefaults && !isReadOnly && "absolute top-0 left-0 overflow-hidden px-8 py-[18px] text-ellipsis"
5062
+ placeholderDefaults && !isReadOnlyOrReview && "absolute top-0 left-0 overflow-hidden px-8 py-[18px] text-ellipsis"
5057
5063
  ),
5058
5064
  children: placeholder2
5059
5065
  }
@@ -6481,10 +6487,10 @@ var init_flex = __esm({
6481
6487
  ref,
6482
6488
  className: cn(
6483
6489
  "editor-flex",
6484
- align && `editor-flex--items-${align}`,
6485
- justify && `editor-flex--justify-${justify}`,
6486
- direction && `editor-flex--flex-${direction}`,
6487
- wrap && `editor-flex--flex-${wrap}`,
6490
+ align && `editor-items-${align}`,
6491
+ justify && `editor-justify-${justify}`,
6492
+ direction && `editor-flex-${direction}`,
6493
+ wrap && `editor-flex-${wrap}`,
6488
6494
  className
6489
6495
  ),
6490
6496
  style: { ...gapStyle, ...style },
@@ -10162,6 +10168,9 @@ var init_list_color_plugin = __esm({
10162
10168
  });
10163
10169
  function ContextMenuPlugin() {
10164
10170
  const [editor] = useLexicalComposerContext();
10171
+ const [contextTarget, setContextTarget] = useState(null);
10172
+ const [showMarkerDialog, setShowMarkerDialog] = useState(false);
10173
+ const [customMarker, setCustomMarker] = useState("");
10165
10174
  const isInTable = (node) => $findMatchingParent(node, $isTableCellNode) !== null;
10166
10175
  const isMergedCell = (node) => {
10167
10176
  const cell = $findMatchingParent(node, $isTableCellNode);
@@ -10173,6 +10182,105 @@ function ContextMenuPlugin() {
10173
10182
  };
10174
10183
  const isInLayoutItem = (node) => $findMatchingParent(node, $isLayoutItemNode) !== null;
10175
10184
  const isInList = (node) => $findMatchingParent(node, $isListNode) !== null;
10185
+ const isInNumberList = (node) => {
10186
+ const listNode = $findMatchingParent(node, $isListNode);
10187
+ return $isListNode(listNode) && listNode.getListType() === "number";
10188
+ };
10189
+ useEffect(() => {
10190
+ const rootElement = editor.getRootElement();
10191
+ if (!rootElement) return;
10192
+ const onContextMenu = (event) => {
10193
+ const target = event.target;
10194
+ if (!(target instanceof HTMLElement)) return;
10195
+ setContextTarget(target);
10196
+ };
10197
+ rootElement.addEventListener("contextmenu", onContextMenu);
10198
+ return () => {
10199
+ rootElement.removeEventListener("contextmenu", onContextMenu);
10200
+ };
10201
+ }, [editor]);
10202
+ const getContextAnchorNode = useCallback(() => {
10203
+ if (contextTarget) {
10204
+ const nearestNode = $getNearestNodeFromDOMNode(contextTarget);
10205
+ if (nearestNode) return nearestNode;
10206
+ }
10207
+ const selection = $getSelection();
10208
+ if ($isRangeSelection(selection)) {
10209
+ return selection.anchor.getNode();
10210
+ }
10211
+ return null;
10212
+ }, [contextTarget]);
10213
+ const updateNumberListMarkerType = useCallback((markerType) => {
10214
+ editor.update(() => {
10215
+ const anchorNode = getContextAnchorNode();
10216
+ if (!anchorNode) return;
10217
+ const nearestListNode = $findMatchingParent(
10218
+ anchorNode,
10219
+ (node) => $isListNode(node) && node.getListType() === "number"
10220
+ );
10221
+ if (!nearestListNode) return;
10222
+ let listNode = nearestListNode;
10223
+ let parent = listNode.getParent();
10224
+ while (parent) {
10225
+ if ($isListNode(parent) && parent.getListType() === "number") {
10226
+ listNode = parent;
10227
+ parent = parent.getParent();
10228
+ continue;
10229
+ }
10230
+ break;
10231
+ }
10232
+ if ($isListWithColorNode(listNode)) {
10233
+ listNode.setMarkerType(markerType);
10234
+ return;
10235
+ }
10236
+ const newList = createListWithColorNodeFromRegistry(
10237
+ editor,
10238
+ listNode.getListType(),
10239
+ listNode.getStart()
10240
+ );
10241
+ newList.setMarkerType(markerType);
10242
+ const children = listNode.getChildren();
10243
+ for (const child of children) newList.append(child);
10244
+ listNode.replace(newList);
10245
+ });
10246
+ }, [editor, getContextAnchorNode]);
10247
+ const syncMarkerToSameLevelLists = useCallback((targetListNode, markerType) => {
10248
+ editor.update(() => {
10249
+ const parent = targetListNode.getParent();
10250
+ if (!parent) return;
10251
+ const siblings = parent.getChildren();
10252
+ for (const sibling of siblings) {
10253
+ if ($isListNode(sibling) && sibling.getListType() === "number" && sibling !== targetListNode) {
10254
+ if ($isListWithColorNode(sibling)) {
10255
+ sibling.setMarkerType(markerType);
10256
+ } else {
10257
+ const newList = $createListWithColorNode("number", sibling.getStart());
10258
+ newList.setMarkerType(markerType);
10259
+ const children = sibling.getChildren();
10260
+ for (const child of children) newList.append(child);
10261
+ sibling.replace(newList);
10262
+ }
10263
+ }
10264
+ }
10265
+ });
10266
+ }, [editor]);
10267
+ const handleCustomMarkerSubmit = () => {
10268
+ if (customMarker.trim()) {
10269
+ editor.update(() => {
10270
+ const anchorNode = getContextAnchorNode();
10271
+ if (!anchorNode) return;
10272
+ const nearestListNode = $findMatchingParent(
10273
+ anchorNode,
10274
+ (node) => $isListNode(node) && node.getListType() === "number"
10275
+ );
10276
+ if (!nearestListNode) return;
10277
+ updateNumberListMarkerType(customMarker.trim());
10278
+ syncMarkerToSameLevelLists(nearestListNode, customMarker.trim());
10279
+ });
10280
+ setShowMarkerDialog(false);
10281
+ setCustomMarker("");
10282
+ }
10283
+ };
10176
10284
  const items = useMemo(() => {
10177
10285
  return [
10178
10286
  new NodeContextMenuOption(`G\u1ED9p \xF4`, {
@@ -10298,6 +10406,41 @@ function ContextMenuPlugin() {
10298
10406
  new NodeContextMenuSeparator({
10299
10407
  $showOn: isInList
10300
10408
  }),
10409
+ new NodeContextMenuOption(`\u0110\xE1nh s\u1ED1 1, 2, 3`, {
10410
+ $onSelect: () => {
10411
+ updateNumberListMarkerType(void 0);
10412
+ },
10413
+ $showOn: isInNumberList,
10414
+ disabled: false,
10415
+ icon: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(ListOrderedIcon, {}) })
10416
+ }),
10417
+ new NodeContextMenuOption(`\u0110\xE1nh s\u1ED1 \u0111a c\u1EA5p 1.1 / 1.1.1`, {
10418
+ $onSelect: () => {
10419
+ updateNumberListMarkerType("multi-level");
10420
+ },
10421
+ $showOn: isInNumberList,
10422
+ disabled: false,
10423
+ icon: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(ListOrderedIcon, {}) })
10424
+ }),
10425
+ new NodeContextMenuOption(`\u0110\xE1nh s\u1ED1 a, b, c`, {
10426
+ $onSelect: () => {
10427
+ updateNumberListMarkerType("alpha");
10428
+ },
10429
+ $showOn: isInNumberList,
10430
+ disabled: false,
10431
+ icon: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(ListOrderedIcon, {}) })
10432
+ }),
10433
+ new NodeContextMenuOption(`T\xF9y ch\u1EC9nh marker...`, {
10434
+ $onSelect: () => {
10435
+ setShowMarkerDialog(true);
10436
+ },
10437
+ $showOn: isInNumberList,
10438
+ disabled: false,
10439
+ icon: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(Hash, { className: "text-blue-600" }) })
10440
+ }),
10441
+ new NodeContextMenuSeparator({
10442
+ $showOn: isInNumberList
10443
+ }),
10301
10444
  new NodeContextMenuOption(`Remove Link`, {
10302
10445
  $onSelect: () => {
10303
10446
  editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);
@@ -10393,23 +10536,101 @@ function ContextMenuPlugin() {
10393
10536
  icon: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(Trash2, {}) })
10394
10537
  })
10395
10538
  ];
10396
- }, [editor]);
10397
- return /* @__PURE__ */ jsx(
10398
- NodeContextMenuPlugin,
10399
- {
10400
- className: "editor-context-menu",
10401
- itemClassName: "editor-context-menu-item",
10402
- separatorClassName: "editor-context-menu-separator",
10403
- items
10404
- }
10405
- );
10539
+ }, [editor, updateNumberListMarkerType]);
10540
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
10541
+ /* @__PURE__ */ jsx(
10542
+ NodeContextMenuPlugin,
10543
+ {
10544
+ className: "editor-context-menu",
10545
+ itemClassName: "editor-context-menu-item",
10546
+ separatorClassName: "editor-context-menu-separator",
10547
+ items
10548
+ }
10549
+ ),
10550
+ /* @__PURE__ */ jsx(Dialog, { open: showMarkerDialog, onOpenChange: setShowMarkerDialog, children: /* @__PURE__ */ jsxs(DialogContent, { style: { maxWidth: "400px" }, children: [
10551
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
10552
+ /* @__PURE__ */ jsx(DialogTitle, { children: "T\xF9y ch\u1EC9nh Marker" }),
10553
+ /* @__PURE__ */ jsx("p", { className: "editor-text-sm editor-text-muted-foreground", children: "Nh\u1EADp ki\u1EC3u marker cho danh s\xE1ch c\u1EE7a b\u1EA1n" })
10554
+ ] }),
10555
+ /* @__PURE__ */ jsx("div", { className: "editor-flex-col editor-py-4 editor-gap-4", children: /* @__PURE__ */ jsxs("div", { className: "editor-flex-col editor-gap-2", children: [
10556
+ /* @__PURE__ */ jsx(Label, { htmlFor: "marker-input", className: "editor-font-medium", children: "Ki\u1EC3u marker" }),
10557
+ /* @__PURE__ */ jsxs("div", { className: "editor-relative editor-flex editor-items-center", children: [
10558
+ /* @__PURE__ */ jsx(
10559
+ Hash,
10560
+ {
10561
+ className: "editor-absolute editor-text-muted-foreground",
10562
+ style: { left: "0.75rem" },
10563
+ size: 16
10564
+ }
10565
+ ),
10566
+ /* @__PURE__ */ jsx(
10567
+ Input,
10568
+ {
10569
+ id: "marker-input",
10570
+ value: customMarker,
10571
+ onChange: (e) => setCustomMarker(e.target.value),
10572
+ placeholder: "V\xED d\u1EE5: multi-level, alpha, 4.1, ...",
10573
+ style: { paddingLeft: "2.25rem" },
10574
+ onKeyDown: (e) => {
10575
+ if (e.key === "Enter") {
10576
+ handleCustomMarkerSubmit();
10577
+ }
10578
+ }
10579
+ }
10580
+ )
10581
+ ] }),
10582
+ /* @__PURE__ */ jsxs("div", { className: "editor-flex-col editor-gap-1 editor-text-sm editor-text-muted-foreground editor-mt-2", children: [
10583
+ /* @__PURE__ */ jsxs("p", { className: "editor-flex editor-items-center editor-gap-2", style: { margin: 0 }, children: [
10584
+ /* @__PURE__ */ jsx("span", { className: "editor-font-medium", children: "multi-level" }),
10585
+ " - Hi\u1EC3n th\u1ECB d\u1EA1ng 4.1, 4.1.1"
10586
+ ] }),
10587
+ /* @__PURE__ */ jsxs("p", { className: "editor-flex editor-items-center editor-gap-2", style: { margin: 0 }, children: [
10588
+ /* @__PURE__ */ jsx("span", { className: "editor-font-medium", children: "alpha" }),
10589
+ " - Hi\u1EC3n th\u1ECB d\u1EA1ng a, b, c"
10590
+ ] }),
10591
+ /* @__PURE__ */ jsxs("p", { className: "editor-flex editor-items-center editor-gap-2", style: { margin: 0 }, children: [
10592
+ /* @__PURE__ */ jsx("span", { className: "editor-font-medium", children: "\u0110\u1EC3 tr\u1ED1ng" }),
10593
+ " - V\u1EC1 m\u1EB7c \u0111\u1ECBnh 1, 2, 3"
10594
+ ] })
10595
+ ] })
10596
+ ] }) }),
10597
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [
10598
+ /* @__PURE__ */ jsx(
10599
+ Button,
10600
+ {
10601
+ variant: "outline",
10602
+ onClick: () => setShowMarkerDialog(false),
10603
+ children: "H\u1EE7y"
10604
+ }
10605
+ ),
10606
+ /* @__PURE__ */ jsxs(
10607
+ Button,
10608
+ {
10609
+ onClick: handleCustomMarkerSubmit,
10610
+ disabled: !customMarker.trim(),
10611
+ className: "editor-gap-2",
10612
+ children: [
10613
+ /* @__PURE__ */ jsx(ListIcon, { size: 16 }),
10614
+ /* @__PURE__ */ jsx("span", { children: "\xC1p d\u1EE5ng" })
10615
+ ]
10616
+ }
10617
+ )
10618
+ ] })
10619
+ ] }) })
10620
+ ] });
10406
10621
  }
10407
10622
  var init_context_menu_plugin = __esm({
10408
10623
  "src/plugins/context-menu-plugin.tsx"() {
10409
10624
  init_layout_item_node();
10625
+ init_nodes();
10626
+ init_list_with_color_node();
10410
10627
  init_layout_plugin();
10411
10628
  init_list_color_plugin();
10412
10629
  init_typography();
10630
+ init_dialog();
10631
+ init_input();
10632
+ init_button();
10633
+ init_label();
10413
10634
  }
10414
10635
  });
10415
10636
  function DragDropPastePlugin() {
@@ -28661,99 +28882,90 @@ function FloatingTextFormat({
28661
28882
  ref: popupCharStylesEditorRef,
28662
28883
  className: "editor-floating-text-format",
28663
28884
  children: editor.isEditable() && /* @__PURE__ */ jsxs(Flex, { align: "center", gap: 1, className: "editor-flex-nowrap", children: [
28664
- /* @__PURE__ */ jsx("div", { className: "editor-floating-group editor-flex editor-items-center", children: /* @__PURE__ */ jsxs(
28665
- ToggleGroup,
28666
- {
28667
- type: "multiple",
28668
- className: "editor-flex editor-items-center",
28669
- value: [
28670
- isBold ? "bold" : "",
28671
- isItalic ? "italic" : "",
28672
- isUnderline ? "underline" : "",
28673
- isStrikethrough ? "strikethrough" : "",
28674
- isCode ? "code" : "",
28675
- isLink ? "link" : ""
28676
- ].filter(Boolean),
28677
- children: [
28678
- /* @__PURE__ */ jsx(
28679
- ToggleGroupItem,
28680
- {
28681
- value: "bold",
28682
- "aria-label": "Toggle bold",
28683
- className: "editor-toolbar-item",
28684
- onClick: () => {
28685
- editor.dispatchCommand(FORMAT_TEXT_COMMAND, "bold");
28686
- },
28687
- size: "sm",
28688
- children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(BoldIcon, {}) })
28689
- }
28690
- ),
28691
- /* @__PURE__ */ jsx(
28692
- ToggleGroupItem,
28693
- {
28694
- value: "italic",
28695
- "aria-label": "Toggle italic",
28696
- className: "editor-toolbar-item",
28697
- onClick: () => {
28698
- editor.dispatchCommand(FORMAT_TEXT_COMMAND, "italic");
28699
- },
28700
- size: "sm",
28701
- children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(ItalicIcon, {}) })
28702
- }
28703
- ),
28704
- /* @__PURE__ */ jsx(
28705
- ToggleGroupItem,
28706
- {
28707
- value: "underline",
28708
- "aria-label": "Toggle underline",
28709
- className: "editor-toolbar-item",
28710
- onClick: () => {
28711
- editor.dispatchCommand(FORMAT_TEXT_COMMAND, "underline");
28712
- },
28713
- size: "sm",
28714
- children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(UnderlineIcon, {}) })
28715
- }
28716
- ),
28717
- /* @__PURE__ */ jsx(
28718
- ToggleGroupItem,
28719
- {
28720
- value: "strikethrough",
28721
- "aria-label": "Toggle strikethrough",
28722
- className: "editor-toolbar-item",
28723
- onClick: () => {
28724
- editor.dispatchCommand(FORMAT_TEXT_COMMAND, "strikethrough");
28725
- },
28726
- size: "sm",
28727
- children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(StrikethroughIcon, {}) })
28728
- }
28729
- ),
28730
- /* @__PURE__ */ jsx(
28731
- ToggleGroupItem,
28732
- {
28733
- value: "code",
28734
- "aria-label": "Toggle code",
28735
- className: "editor-toolbar-item",
28736
- onClick: () => {
28737
- editor.dispatchCommand(FORMAT_TEXT_COMMAND, "code");
28738
- },
28739
- size: "sm",
28740
- children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(CodeIcon, {}) })
28741
- }
28742
- ),
28743
- /* @__PURE__ */ jsx(
28744
- ToggleGroupItem,
28745
- {
28746
- value: "link",
28747
- "aria-label": "Toggle link",
28748
- className: "editor-toolbar-item",
28749
- onClick: insertLink,
28750
- size: "sm",
28751
- children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(LinkIcon, {}) })
28752
- }
28753
- )
28754
- ]
28755
- }
28756
- ) }),
28885
+ /* @__PURE__ */ jsxs("div", { className: "editor-floating-group editor-flex editor-items-center", children: [
28886
+ /* @__PURE__ */ jsx(
28887
+ Button,
28888
+ {
28889
+ variant: "ghost",
28890
+ size: "sm",
28891
+ className: "editor-toolbar-item",
28892
+ "data-state": isBold ? "on" : "off",
28893
+ onClick: () => {
28894
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, "bold");
28895
+ },
28896
+ "aria-label": "Toggle bold",
28897
+ children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(BoldIcon, {}) })
28898
+ }
28899
+ ),
28900
+ /* @__PURE__ */ jsx(
28901
+ Button,
28902
+ {
28903
+ variant: "ghost",
28904
+ size: "sm",
28905
+ className: "editor-toolbar-item",
28906
+ "data-state": isItalic ? "on" : "off",
28907
+ onClick: () => {
28908
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, "italic");
28909
+ },
28910
+ "aria-label": "Toggle italic",
28911
+ children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(ItalicIcon, {}) })
28912
+ }
28913
+ ),
28914
+ /* @__PURE__ */ jsx(
28915
+ Button,
28916
+ {
28917
+ variant: "ghost",
28918
+ size: "sm",
28919
+ className: "editor-toolbar-item",
28920
+ "data-state": isUnderline ? "on" : "off",
28921
+ onClick: () => {
28922
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, "underline");
28923
+ },
28924
+ "aria-label": "Toggle underline",
28925
+ children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(UnderlineIcon, {}) })
28926
+ }
28927
+ ),
28928
+ /* @__PURE__ */ jsx(
28929
+ Button,
28930
+ {
28931
+ variant: "ghost",
28932
+ size: "sm",
28933
+ className: "editor-toolbar-item",
28934
+ "data-state": isStrikethrough ? "on" : "off",
28935
+ onClick: () => {
28936
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, "strikethrough");
28937
+ },
28938
+ "aria-label": "Toggle strikethrough",
28939
+ children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(StrikethroughIcon, {}) })
28940
+ }
28941
+ ),
28942
+ /* @__PURE__ */ jsx(
28943
+ Button,
28944
+ {
28945
+ variant: "ghost",
28946
+ size: "sm",
28947
+ className: "editor-toolbar-item",
28948
+ "data-state": isCode ? "on" : "off",
28949
+ onClick: () => {
28950
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, "code");
28951
+ },
28952
+ "aria-label": "Toggle code",
28953
+ children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(CodeIcon, {}) })
28954
+ }
28955
+ ),
28956
+ /* @__PURE__ */ jsx(
28957
+ Button,
28958
+ {
28959
+ variant: "ghost",
28960
+ size: "sm",
28961
+ className: "editor-toolbar-item",
28962
+ "data-state": isLink ? "on" : "off",
28963
+ onClick: insertLink,
28964
+ "aria-label": "Toggle link",
28965
+ children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(LinkIcon, {}) })
28966
+ }
28967
+ )
28968
+ ] }),
28757
28969
  /* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "editor-separator--vertical" }),
28758
28970
  /* @__PURE__ */ jsxs("div", { className: "editor-floating-group--lg editor-flex editor-items-center", children: [
28759
28971
  /* @__PURE__ */ jsx(
@@ -28950,8 +29162,8 @@ var init_floating_text_format_plugin = __esm({
28950
29162
  init_dialog();
28951
29163
  init_flex();
28952
29164
  init_separator();
28953
- init_toggle_group();
28954
29165
  init_typography();
29166
+ init_toggle_group();
28955
29167
  }
28956
29168
  });
28957
29169
  function KeywordsPlugin() {
@@ -30146,7 +30358,7 @@ function getResizeEdge(clientX, rect) {
30146
30358
  if (nearLeft && nearRight) return "right";
30147
30359
  return nearLeft ? "left" : "right";
30148
30360
  }
30149
- function getColumnIndexFromTableMap(tableNode, tableCellNode) {
30361
+ function $getColumnIndexFromTableMap(tableNode, tableCellNode) {
30150
30362
  if (!$isTableCellNode(tableCellNode)) return null;
30151
30363
  const [tableMap] = $computeTableMapSkipCellCheck(tableNode, null, null);
30152
30364
  for (let row = 0; row < tableMap.length; row++) {
@@ -30161,183 +30373,290 @@ function getColumnIndexFromTableMap(tableNode, tableCellNode) {
30161
30373
  }
30162
30374
  return null;
30163
30375
  }
30164
- function TableColumnResizerPlugin() {
30376
+ function TableColumnResizerPlugin({
30377
+ anchorElem = document.body
30378
+ }) {
30165
30379
  const [editor] = useLexicalComposerContext();
30166
30380
  const isEditable = useLexicalEditable();
30167
30381
  const dragRef = useRef(null);
30382
+ const [hoverState, setHoverState] = useState(null);
30383
+ const resizerRef = useRef(null);
30384
+ const onPointerDownImpl = useCallback((event, cell, edge) => {
30385
+ if (event.button !== 0) return;
30386
+ event.preventDefault();
30387
+ const target = event.target;
30388
+ if (target) {
30389
+ target.setPointerCapture(event.pointerId);
30390
+ }
30391
+ let nextDragState = null;
30392
+ editor.update(() => {
30393
+ const tableCellNode = $getNearestNodeFromDOMNode(cell);
30394
+ if (!$isTableCellNode(tableCellNode)) return;
30395
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
30396
+ const tableElement = editor.getElementByKey(tableNode.getKey());
30397
+ if (!tableElement) return;
30398
+ const tableMap = $computeTableMapSkipCellCheck(tableNode, null, null)[0];
30399
+ const colCount = tableMap[0]?.length ?? 0;
30400
+ const columnIndexFromMap = $getColumnIndexFromTableMap(tableNode, tableCellNode);
30401
+ if (columnIndexFromMap === null) return;
30402
+ const colSpan = tableCellNode.getColSpan();
30403
+ const resizeColumnIndex = edge === "left" ? columnIndexFromMap - 1 : columnIndexFromMap + colSpan - 1;
30404
+ if (resizeColumnIndex < 0 || resizeColumnIndex >= colCount - 1) return;
30405
+ let currentWidths = tableNode.getColWidths();
30406
+ if (!currentWidths) {
30407
+ const columns = tableElement.querySelectorAll("col");
30408
+ const widths = [];
30409
+ if (columns.length === colCount) {
30410
+ columns.forEach((col) => {
30411
+ const styleWidth = col.style.width;
30412
+ if (styleWidth && styleWidth.endsWith("px")) {
30413
+ widths.push(parseFloat(styleWidth));
30414
+ } else {
30415
+ const rect = col.getBoundingClientRect();
30416
+ widths.push(rect.width || 0);
30417
+ }
30418
+ });
30419
+ }
30420
+ if (widths.length !== colCount) {
30421
+ const firstRow = tableElement.querySelector("tr");
30422
+ if (firstRow) {
30423
+ const cells = firstRow.querySelectorAll("th, td");
30424
+ if (cells.length === colCount) {
30425
+ cells.forEach((cell2) => {
30426
+ widths.push(cell2.getBoundingClientRect().width);
30427
+ });
30428
+ }
30429
+ }
30430
+ }
30431
+ if (widths.length !== colCount) {
30432
+ const tableRect = tableElement.getBoundingClientRect();
30433
+ const avgWidth = tableRect.width / (colCount || 1);
30434
+ for (let i = 0; i < colCount; i++) {
30435
+ widths.push(avgWidth);
30436
+ }
30437
+ }
30438
+ currentWidths = widths;
30439
+ }
30440
+ if (currentWidths[resizeColumnIndex] === void 0 || currentWidths[resizeColumnIndex + 1] === void 0) {
30441
+ return;
30442
+ }
30443
+ nextDragState = {
30444
+ columnIndex: resizeColumnIndex,
30445
+ initialColWidths: currentWidths,
30446
+ startX: event.clientX,
30447
+ startWidth: currentWidths[resizeColumnIndex],
30448
+ tableKey: tableNode.getKey()
30449
+ };
30450
+ });
30451
+ if (!nextDragState) return;
30452
+ dragRef.current = nextDragState;
30453
+ const rootElement = editor.getRootElement();
30454
+ if (rootElement) {
30455
+ rootElement.style.userSelect = "none";
30456
+ rootElement.style.cursor = "col-resize";
30457
+ }
30458
+ const onPointerMoveDocument = (event2) => {
30459
+ const drag = dragRef.current;
30460
+ if (!drag) return;
30461
+ event2.preventDefault();
30462
+ const deltaX = event2.clientX - drag.startX;
30463
+ const { tableKey, columnIndex, initialColWidths } = drag;
30464
+ editor.update(() => {
30465
+ const tableNode = $getNodeByKey(tableKey);
30466
+ if (!(tableNode instanceof TableNode)) return;
30467
+ const currentWidths = tableNode.getColWidths() || initialColWidths;
30468
+ const colCount = tableNode.getColumnCount();
30469
+ const nextColumnIndex = columnIndex + 1;
30470
+ if (nextColumnIndex >= colCount) return;
30471
+ const currentLeftWidth = initialColWidths[columnIndex];
30472
+ const currentRightWidth = initialColWidths[nextColumnIndex];
30473
+ if (currentLeftWidth === void 0 || currentRightWidth === void 0) return;
30474
+ const maxShrinkLeft = currentLeftWidth - MIN_COLUMN_WIDTH_PX;
30475
+ const maxGrowLeft = currentRightWidth - MIN_COLUMN_WIDTH_PX;
30476
+ const constrainedDelta = Math.min(Math.max(deltaX, -maxShrinkLeft), maxGrowLeft);
30477
+ const newLeftWidth = currentLeftWidth + constrainedDelta;
30478
+ const newRightWidth = currentRightWidth - constrainedDelta;
30479
+ const nextColWidths = Array.from({ length: colCount }, (_, i) => {
30480
+ if (i === columnIndex) return newLeftWidth;
30481
+ if (i === nextColumnIndex) return newRightWidth;
30482
+ return currentWidths[i] ?? initialColWidths[i] ?? 0;
30483
+ });
30484
+ if (typeof tableNode.setColWidths === "function") {
30485
+ tableNode.setColWidths(nextColWidths);
30486
+ } else {
30487
+ tableNode.__colWidths = nextColWidths;
30488
+ tableNode.__widths = nextColWidths;
30489
+ tableNode.markDirty();
30490
+ }
30491
+ });
30492
+ };
30493
+ const onPointerUpDocument = (event2) => {
30494
+ const drag = dragRef.current;
30495
+ if (!drag) return;
30496
+ const target2 = event2.target;
30497
+ if (target2 && target2.hasPointerCapture(event2.pointerId)) {
30498
+ target2.releasePointerCapture(event2.pointerId);
30499
+ }
30500
+ dragRef.current = null;
30501
+ const rootElement2 = editor.getRootElement();
30502
+ if (rootElement2) {
30503
+ rootElement2.style.userSelect = "";
30504
+ rootElement2.style.cursor = "";
30505
+ }
30506
+ document.removeEventListener("pointermove", onPointerMoveDocument);
30507
+ document.removeEventListener("pointerup", onPointerUpDocument);
30508
+ };
30509
+ document.addEventListener("pointermove", onPointerMoveDocument);
30510
+ document.addEventListener("pointerup", onPointerUpDocument);
30511
+ }, [editor]);
30512
+ const updateResizerPosition = useCallback(() => {
30513
+ const state = hoverState;
30514
+ if (state === null || !resizerRef.current) return;
30515
+ const { cellKey, edge } = state;
30516
+ const cell = editor.getElementByKey(cellKey);
30517
+ if (!cell) return;
30518
+ const cellRect = cell.getBoundingClientRect();
30519
+ const anchorRect = anchorElem.getBoundingClientRect();
30520
+ const resizerElem = resizerRef.current;
30521
+ const tableElement = cell.closest("table");
30522
+ let top = cellRect.top - anchorRect.top;
30523
+ let height = cellRect.height;
30524
+ if (tableElement) {
30525
+ const tableRect = tableElement.getBoundingClientRect();
30526
+ top = tableRect.top - anchorRect.top;
30527
+ height = tableRect.height;
30528
+ }
30529
+ const left = (edge === "left" ? cellRect.left : cellRect.right) - anchorRect.left - 8;
30530
+ resizerElem.style.transform = `translate(${left}px, ${top}px)`;
30531
+ resizerElem.style.height = `${height}px`;
30532
+ resizerElem.style.opacity = "1";
30533
+ }, [editor, hoverState, anchorElem]);
30534
+ useLayoutEffect(() => {
30535
+ updateResizerPosition();
30536
+ window.addEventListener("resize", updateResizerPosition);
30537
+ window.addEventListener("scroll", updateResizerPosition, true);
30538
+ const updateListener = editor.registerUpdateListener(() => {
30539
+ editor.read(() => {
30540
+ const state = hoverState;
30541
+ if (state !== null) {
30542
+ const cell = editor.getElementByKey(state.cellKey);
30543
+ if (!cell) {
30544
+ setHoverState(null);
30545
+ } else {
30546
+ updateResizerPosition();
30547
+ }
30548
+ }
30549
+ });
30550
+ });
30551
+ return () => {
30552
+ window.removeEventListener("resize", updateResizerPosition);
30553
+ window.removeEventListener("scroll", updateResizerPosition, true);
30554
+ updateListener();
30555
+ };
30556
+ }, [editor, hoverState, updateResizerPosition]);
30168
30557
  useEffect(() => {
30169
30558
  if (!isEditable) return;
30170
30559
  const rootElement = editor.getRootElement();
30171
30560
  if (!rootElement) return;
30172
30561
  const setCursor = (cursor) => {
30173
- rootElement.style.cursor = cursor;
30562
+ if (rootElement) {
30563
+ rootElement.style.cursor = cursor;
30564
+ }
30174
30565
  };
30175
30566
  const clearCursor = () => {
30176
30567
  setCursor("");
30177
30568
  };
30178
30569
  const onPointerMove = (event) => {
30179
30570
  if (dragRef.current) return;
30180
- const cell = getCellTarget(event.target);
30181
- if (!cell) {
30182
- clearCursor();
30571
+ if (event.buttons !== 0) return;
30572
+ if (resizerRef.current && (event.target === resizerRef.current || resizerRef.current.contains(event.target))) {
30183
30573
  return;
30184
30574
  }
30185
- const edge = getResizeEdge(event.clientX, cell.getBoundingClientRect());
30186
- if (edge === "left") {
30187
- const table = cell.closest("table");
30188
- if (table) {
30189
- const tableRect = table.getBoundingClientRect();
30190
- const cellRect = cell.getBoundingClientRect();
30191
- if (Math.abs(cellRect.left - tableRect.left) < 5) {
30192
- clearCursor();
30193
- return;
30194
- }
30195
- }
30196
- }
30197
- setCursor(edge ? "col-resize" : "");
30198
- };
30199
- const onPointerDown = (event) => {
30200
- if (event.button !== 0) return;
30201
30575
  const cell = getCellTarget(event.target);
30202
- if (!cell) return;
30203
- const edge = getResizeEdge(event.clientX, cell.getBoundingClientRect());
30204
- if (!edge) return;
30205
- event.preventDefault();
30206
- let nextDragState = null;
30207
- editor.read(() => {
30208
- const tableCellNode = $getNearestNodeFromDOMNode(cell);
30209
- if (!$isTableCellNode(tableCellNode)) return;
30210
- const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
30211
- const columnIndexFromMap = getColumnIndexFromTableMap(tableNode, tableCellNode);
30212
- if (columnIndexFromMap == null) return;
30213
- if (edge === "left" && columnIndexFromMap === 0) return;
30214
- const colSpan = tableCellNode.getColSpan();
30215
- const resizeColumnIndex = edge === "left" ? columnIndexFromMap - 1 : columnIndexFromMap + colSpan - 1;
30216
- let currentWidths = tableNode.getColWidths();
30217
- if (!currentWidths) {
30218
- const tableElement = editor.getElementByKey(tableNode.getKey());
30219
- if (tableElement instanceof HTMLTableElement) {
30220
- const [tableMap] = $computeTableMapSkipCellCheck(tableNode, null, null);
30221
- const colCount = tableNode.getColumnCount();
30222
- const widths = new Array(colCount).fill(void 0);
30223
- for (let r = 0; r < tableMap.length; r++) {
30224
- const row = tableMap[r];
30225
- if (!row) continue;
30226
- for (let c = 0; c < row.length; c++) {
30227
- if (widths[c] !== void 0) continue;
30228
- const tableMapCell = row[c];
30229
- if (!tableMapCell) continue;
30230
- const { cell: cell2 } = tableMapCell;
30231
- if (cell2.getColSpan() === 1) {
30232
- const cellElem = editor.getElementByKey(cell2.getKey());
30233
- if (cellElem) {
30234
- widths[c] = Math.round(cellElem.getBoundingClientRect().width);
30235
- }
30236
- }
30237
- }
30238
- if (widths.every((w) => w !== void 0)) break;
30239
- }
30240
- if (widths.some((w) => w === void 0)) {
30241
- if (tableElement.rows.length > 0) {
30242
- const row = tableElement.rows[0];
30243
- if (row && row.cells.length === colCount) {
30244
- const rowWidths = Array.from(row.cells).map((c) => Math.round(c.getBoundingClientRect().width));
30245
- for (let i = 0; i < colCount; i++) {
30246
- if (widths[i] === void 0) widths[i] = rowWidths[i];
30247
- }
30248
- }
30576
+ let nextHoverState = null;
30577
+ if (cell) {
30578
+ editor.read(() => {
30579
+ const cellNode = $getNearestNodeFromDOMNode(cell);
30580
+ if ($isTableCellNode(cellNode)) {
30581
+ const tableNode = $getTableNodeFromLexicalNodeOrThrow(cellNode);
30582
+ const cellKey = cellNode.getKey();
30583
+ const tableKey = tableNode.getKey();
30584
+ const edge = getResizeEdge(event.clientX, cell.getBoundingClientRect());
30585
+ if (edge) {
30586
+ const colCount = tableNode.getColumnCount();
30587
+ const colSpan = cellNode.getColSpan();
30588
+ const columnIndexFromMap = $getColumnIndexFromTableMap(tableNode, cellNode);
30589
+ if (columnIndexFromMap !== null && !(edge === "left" && columnIndexFromMap === 0 || edge === "right" && columnIndexFromMap + colSpan === colCount)) {
30590
+ nextHoverState = { cellKey, tableKey, edge };
30249
30591
  }
30250
30592
  }
30251
- if (widths.some((w) => w === void 0)) {
30252
- const tableWidth = tableElement.getBoundingClientRect().width;
30253
- const defaultWidth = tableWidth / colCount;
30254
- for (let i = 0; i < colCount; i++) {
30255
- if (widths[i] === void 0) widths[i] = defaultWidth;
30256
- }
30257
- }
30258
- currentWidths = widths;
30259
30593
  }
30594
+ });
30595
+ }
30596
+ if (!nextHoverState) {
30597
+ if (hoverState !== null) {
30598
+ clearCursor();
30599
+ setHoverState(null);
30260
30600
  }
30261
- if (!currentWidths) {
30262
- currentWidths = Array(tableNode.getColumnCount()).fill(MIN_COLUMN_WIDTH_PX);
30263
- }
30264
- const startWidth = currentWidths[resizeColumnIndex] ?? Math.max(Math.round(cell.getBoundingClientRect().width), MIN_COLUMN_WIDTH_PX);
30265
- nextDragState = {
30266
- tableKey: tableNode.getKey(),
30267
- columnIndex: resizeColumnIndex,
30268
- startX: event.clientX,
30269
- startWidth,
30270
- initialColWidths: [...currentWidths]
30271
- };
30272
- });
30273
- if (!nextDragState) return;
30274
- event.preventDefault();
30275
- event.stopPropagation();
30276
- dragRef.current = nextDragState;
30277
- setCursor("col-resize");
30278
- };
30279
- const onPointerMoveDocument = (event) => {
30280
- const drag = dragRef.current;
30281
- if (!drag) return;
30282
- const { initialColWidths, startX, columnIndex } = drag;
30283
- const deltaX = event.clientX - startX;
30284
- editor.update(() => {
30285
- const tableNode = $getNodeByKey(drag.tableKey);
30286
- if (!(tableNode instanceof TableNode)) return;
30287
- const colWidths = tableNode.getColWidths() ?? initialColWidths;
30288
- const nextColumnIndex = columnIndex + 1;
30289
- const hasNeighbor = nextColumnIndex < initialColWidths.length;
30290
- if (hasNeighbor) {
30291
- const currentLeftWidth = initialColWidths[columnIndex];
30292
- const currentRightWidth = initialColWidths[nextColumnIndex];
30293
- if (currentLeftWidth === void 0 || currentRightWidth === void 0) return;
30294
- const maxShrinkLeft = currentLeftWidth - MIN_COLUMN_WIDTH_PX;
30295
- const maxGrowLeft = currentRightWidth - MIN_COLUMN_WIDTH_PX;
30296
- const constrainedDelta = Math.min(Math.max(deltaX, -maxShrinkLeft), maxGrowLeft);
30297
- const newLeftWidth = currentLeftWidth + constrainedDelta;
30298
- const newRightWidth = currentRightWidth - constrainedDelta;
30299
- if (colWidths[columnIndex] === newLeftWidth && colWidths[nextColumnIndex] === newRightWidth)
30300
- return;
30301
- const nextColWidths = [...colWidths];
30302
- nextColWidths[columnIndex] = newLeftWidth;
30303
- nextColWidths[nextColumnIndex] = newRightWidth;
30304
- tableNode.setColWidths(nextColWidths);
30305
- } else {
30306
- const currentWidth = initialColWidths[columnIndex];
30307
- if (currentWidth === void 0) return;
30308
- const newWidth = Math.max(MIN_COLUMN_WIDTH_PX, Math.round(currentWidth + deltaX));
30309
- if (colWidths[columnIndex] === newWidth) return;
30310
- const nextColWidths = [...colWidths];
30311
- nextColWidths[columnIndex] = newWidth;
30312
- tableNode.setColWidths(nextColWidths);
30601
+ } else {
30602
+ setCursor("col-resize");
30603
+ if (!hoverState || hoverState.cellKey !== nextHoverState.cellKey || hoverState.edge !== nextHoverState.edge) {
30604
+ setHoverState(nextHoverState);
30313
30605
  }
30314
- });
30315
- };
30316
- const onPointerUpDocument = () => {
30317
- if (!dragRef.current) return;
30318
- dragRef.current = null;
30319
- clearCursor();
30606
+ }
30320
30607
  };
30321
- rootElement.addEventListener("pointermove", onPointerMove);
30322
- rootElement.addEventListener("pointerdown", onPointerDown);
30323
- document.addEventListener("pointermove", onPointerMoveDocument);
30324
- document.addEventListener("pointerup", onPointerUpDocument);
30608
+ anchorElem.addEventListener("pointermove", onPointerMove);
30325
30609
  return () => {
30326
- rootElement.removeEventListener("pointermove", onPointerMove);
30327
- rootElement.removeEventListener("pointerdown", onPointerDown);
30328
- document.removeEventListener("pointermove", onPointerMoveDocument);
30329
- document.removeEventListener("pointerup", onPointerUpDocument);
30610
+ anchorElem.removeEventListener("pointermove", onPointerMove);
30330
30611
  clearCursor();
30331
- dragRef.current = null;
30332
30612
  };
30333
- }, [editor, isEditable]);
30334
- return null;
30613
+ }, [editor, isEditable, hoverState, anchorElem]);
30614
+ const resizer = useMemo(() => {
30615
+ const state = hoverState;
30616
+ if (state === null) return null;
30617
+ const { cellKey, edge } = state;
30618
+ return createPortal(
30619
+ /* @__PURE__ */ jsx(
30620
+ "div",
30621
+ {
30622
+ ref: resizerRef,
30623
+ className: "editor-table-cell-resizer",
30624
+ style: {
30625
+ position: "absolute",
30626
+ top: 0,
30627
+ left: 0,
30628
+ width: "16px",
30629
+ opacity: 1,
30630
+ willChange: "transform",
30631
+ userSelect: "none"
30632
+ },
30633
+ onPointerDown: (event) => {
30634
+ event.stopPropagation();
30635
+ event.preventDefault();
30636
+ const cell = editor.getElementByKey(cellKey);
30637
+ if (cell instanceof HTMLTableCellElement) {
30638
+ onPointerDownImpl(event.nativeEvent, cell, edge);
30639
+ }
30640
+ },
30641
+ children: /* @__PURE__ */ jsx(
30642
+ "div",
30643
+ {
30644
+ className: "editor-table-cell-resize-ruler",
30645
+ style: { pointerEvents: "none" }
30646
+ }
30647
+ )
30648
+ }
30649
+ ),
30650
+ anchorElem
30651
+ );
30652
+ }, [hoverState, anchorElem, editor, onPointerDownImpl]);
30653
+ return resizer;
30335
30654
  }
30336
30655
  var EDGE_HITBOX_PX, MIN_COLUMN_WIDTH_PX;
30337
30656
  var init_table_column_resizer_plugin = __esm({
30338
30657
  "src/plugins/table-column-resizer-plugin.tsx"() {
30339
30658
  "use client";
30340
- EDGE_HITBOX_PX = 12;
30659
+ EDGE_HITBOX_PX = 8;
30341
30660
  MIN_COLUMN_WIDTH_PX = 15;
30342
30661
  }
30343
30662
  });
@@ -30441,6 +30760,10 @@ var init_block_format_data = __esm({
30441
30760
  label: "Alpha List (a, b, c)",
30442
30761
  icon: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(CaseSensitiveIcon, {}) })
30443
30762
  },
30763
+ "number-multi-level": {
30764
+ label: "Multi-level List (1.1 / 1.1.1)",
30765
+ icon: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(ListOrderedIcon, {}) })
30766
+ },
30444
30767
  bullet: {
30445
30768
  label: "Bulleted List",
30446
30769
  icon: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(ListIcon, {}) })
@@ -30502,6 +30825,7 @@ function BlockFormatDropDown({
30502
30825
  else if (markerType === "+") type = "bullet-plus";
30503
30826
  } else if (type === "number") {
30504
30827
  if (markerType === "alpha") type = "number-alpha";
30828
+ else if (markerType === "multi-level") type = "number-multi-level";
30505
30829
  }
30506
30830
  }
30507
30831
  setBlockType(type);
@@ -31219,61 +31543,40 @@ function ElementFormatToolbarPlugin({
31219
31543
  }
31220
31544
  };
31221
31545
  return /* @__PURE__ */ jsxs(Fragment, { children: [
31222
- /* @__PURE__ */ jsx(
31223
- ToggleGroup,
31546
+ Object.entries(ELEMENT_FORMAT_OPTIONS).map(([value, option]) => /* @__PURE__ */ jsx(
31547
+ Button,
31224
31548
  {
31225
- type: "single",
31226
- value: elementFormat,
31227
- onValueChange: handleValueChange,
31549
+ variant: "outline",
31228
31550
  size: "sm",
31551
+ "aria-label": option.name,
31552
+ "data-state": elementFormat === value ? "on" : "off",
31553
+ onClick: () => handleValueChange(value),
31554
+ className: "editor-toolbar-item",
31555
+ children: option.icon
31556
+ },
31557
+ value
31558
+ )),
31559
+ separator && /* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "editor-toolbar-separator" }),
31560
+ /* @__PURE__ */ jsx(
31561
+ Button,
31562
+ {
31229
31563
  variant: "outline",
31230
- children: Object.entries(ELEMENT_FORMAT_OPTIONS).map(([value, option]) => /* @__PURE__ */ jsx(
31231
- ToggleGroupItem,
31232
- {
31233
- value,
31234
- variant: "outline",
31235
- size: "sm",
31236
- "aria-label": option.name,
31237
- className: "editor-toolbar-item",
31238
- children: option.icon
31239
- },
31240
- value
31241
- ))
31564
+ size: "sm",
31565
+ "aria-label": "Outdent",
31566
+ onClick: () => handleValueChange("outdent"),
31567
+ className: "editor-toolbar-item",
31568
+ children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(IndentDecreaseIcon, {}) })
31242
31569
  }
31243
31570
  ),
31244
- separator && /* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "editor-toolbar-separator" }),
31245
- /* @__PURE__ */ jsxs(
31246
- ToggleGroup,
31571
+ /* @__PURE__ */ jsx(
31572
+ Button,
31247
31573
  {
31248
- type: "single",
31249
- value: elementFormat,
31250
- onValueChange: handleValueChange,
31251
- size: "sm",
31252
31574
  variant: "outline",
31253
- children: [
31254
- /* @__PURE__ */ jsx(
31255
- ToggleGroupItem,
31256
- {
31257
- value: "outdent",
31258
- "aria-label": "Outdent",
31259
- variant: "outline",
31260
- size: "sm",
31261
- className: "editor-toolbar-item",
31262
- children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(IndentDecreaseIcon, {}) })
31263
- }
31264
- ),
31265
- /* @__PURE__ */ jsx(
31266
- ToggleGroupItem,
31267
- {
31268
- value: "indent",
31269
- variant: "outline",
31270
- "aria-label": "Indent",
31271
- size: "sm",
31272
- className: "editor-toolbar-item",
31273
- children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(IndentIncreaseIcon, {}) })
31274
- }
31275
- )
31276
- ]
31575
+ size: "sm",
31576
+ "aria-label": "Indent",
31577
+ onClick: () => handleValueChange("indent"),
31578
+ className: "editor-toolbar-item",
31579
+ children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(IndentIncreaseIcon, {}) })
31277
31580
  }
31278
31581
  )
31279
31582
  ] });
@@ -31286,8 +31589,8 @@ var init_element_format_toolbar_plugin = __esm({
31286
31589
  init_layout_item_node();
31287
31590
  init_use_update_toolbar();
31288
31591
  init_get_selected_node();
31592
+ init_button();
31289
31593
  init_separator();
31290
- init_toggle_group();
31291
31594
  init_typography();
31292
31595
  ELEMENT_FORMAT_OPTIONS = {
31293
31596
  left: {
@@ -31617,32 +31920,24 @@ function FontFormatToolbarPlugin() {
31617
31920
  }
31618
31921
  }, []);
31619
31922
  useUpdateToolbarHandler($updateToolbar);
31620
- return /* @__PURE__ */ jsx(
31621
- ToggleGroup,
31923
+ return /* @__PURE__ */ jsx(Fragment, { children: FORMATS.map(({ format, icon: Icon, label }) => /* @__PURE__ */ jsx(
31924
+ Button,
31622
31925
  {
31623
- type: "multiple",
31624
- value: activeFormats,
31625
- onValueChange: setActiveFormats,
31626
- variant: "default",
31926
+ variant: "ghost",
31627
31927
  size: "sm",
31628
- children: FORMATS.map(({ format, icon: Icon, label }) => /* @__PURE__ */ jsx(
31629
- ToggleGroupItem,
31630
- {
31631
- value: format,
31632
- "aria-label": label,
31633
- className: "editor-toolbar-item",
31634
- onClick: () => {
31635
- activeEditor.dispatchCommand(
31636
- FORMAT_TEXT_COMMAND,
31637
- format
31638
- );
31639
- },
31640
- children: /* @__PURE__ */ jsx(Icon, { className: "editor-icon-sm" })
31641
- },
31642
- format
31643
- ))
31644
- }
31645
- );
31928
+ "aria-label": label,
31929
+ "data-state": activeFormats.includes(format) ? "on" : "off",
31930
+ className: "editor-toolbar-item",
31931
+ onClick: () => {
31932
+ activeEditor.dispatchCommand(
31933
+ FORMAT_TEXT_COMMAND,
31934
+ format
31935
+ );
31936
+ },
31937
+ children: /* @__PURE__ */ jsx(Icon, { className: "editor-icon-sm" })
31938
+ },
31939
+ format
31940
+ )) });
31646
31941
  }
31647
31942
  var FORMATS;
31648
31943
  var init_font_format_toolbar_plugin = __esm({
@@ -31650,7 +31945,7 @@ var init_font_format_toolbar_plugin = __esm({
31650
31945
  "use client";
31651
31946
  init_toolbar_context();
31652
31947
  init_use_update_toolbar();
31653
- init_toggle_group();
31948
+ init_button();
31654
31949
  FORMATS = [
31655
31950
  { format: "bold", icon: BoldIcon, label: "Bold" },
31656
31951
  { format: "italic", icon: ItalicIcon, label: "Italic" },
@@ -31659,14 +31954,6 @@ var init_font_format_toolbar_plugin = __esm({
31659
31954
  ];
31660
31955
  }
31661
31956
  });
31662
- function ButtonGroup({ className, children, ...props }) {
31663
- return /* @__PURE__ */ jsx("div", { className: cn("editor-button-group", className), ...props, children });
31664
- }
31665
- var init_button_group = __esm({
31666
- "src/ui/button-group.tsx"() {
31667
- init_utils();
31668
- }
31669
- });
31670
31957
  function FontSizeToolbarPlugin() {
31671
31958
  const style = "font-size";
31672
31959
  const [fontSize, setFontSize] = useState(DEFAULT_FONT_SIZE);
@@ -31756,7 +32043,7 @@ function FontSizeToolbarPlugin() {
31756
32043
  useEffect(() => {
31757
32044
  return () => stopTimer();
31758
32045
  }, [stopTimer]);
31759
- return /* @__PURE__ */ jsxs(ButtonGroup, { children: [
32046
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
31760
32047
  /* @__PURE__ */ jsx(
31761
32048
  Button,
31762
32049
  {
@@ -31813,7 +32100,6 @@ var init_font_size_toolbar_plugin = __esm({
31813
32100
  init_toolbar_context();
31814
32101
  init_use_update_toolbar();
31815
32102
  init_button();
31816
- init_button_group();
31817
32103
  init_input();
31818
32104
  init_typography();
31819
32105
  DEFAULT_FONT_SIZE = 16;
@@ -31857,7 +32143,7 @@ function HistoryToolbarPlugin() {
31857
32143
  )
31858
32144
  );
31859
32145
  }, [$updateToolbar, activeEditor, editor]);
31860
- return /* @__PURE__ */ jsxs(ButtonGroup, { children: [
32146
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
31861
32147
  /* @__PURE__ */ jsx(
31862
32148
  Button,
31863
32149
  {
@@ -31868,7 +32154,6 @@ function HistoryToolbarPlugin() {
31868
32154
  title: IS_APPLE ? "Undo (\u2318Z)" : "Undo (Ctrl+Z)",
31869
32155
  type: "button",
31870
32156
  "aria-label": "Undo",
31871
- size: "sm",
31872
32157
  variant: "ghost",
31873
32158
  className: "editor-toolbar-item",
31874
32159
  children: /* @__PURE__ */ jsx(UndoIcon, { className: "editor-icon-sm" })
@@ -31884,7 +32169,6 @@ function HistoryToolbarPlugin() {
31884
32169
  title: IS_APPLE ? "Redo (\u21E7\u2318Z)" : "Redo (Ctrl+Y)",
31885
32170
  type: "button",
31886
32171
  "aria-label": "Redo",
31887
- size: "sm",
31888
32172
  variant: "ghost",
31889
32173
  className: "editor-toolbar-item",
31890
32174
  children: /* @__PURE__ */ jsx(RedoIcon, { className: "editor-icon-sm" })
@@ -31897,7 +32181,6 @@ var init_history_toolbar_plugin = __esm({
31897
32181
  "use client";
31898
32182
  init_toolbar_context();
31899
32183
  init_button();
31900
- init_button_group();
31901
32184
  }
31902
32185
  });
31903
32186
  var Toggle;
@@ -32007,50 +32290,43 @@ function SubSuperToolbarPlugin() {
32007
32290
  }
32008
32291
  };
32009
32292
  useUpdateToolbarHandler($updateToolbar);
32010
- return /* @__PURE__ */ jsxs(
32011
- ToggleGroup,
32012
- {
32013
- type: "single",
32014
- value: isSubscript ? "subscript" : isSuperscript ? "superscript" : "",
32015
- size: "default",
32016
- variant: "outline",
32017
- children: [
32018
- /* @__PURE__ */ jsx(
32019
- ToggleGroupItem,
32020
- {
32021
- value: "subscript",
32022
- size: "default",
32023
- "aria-label": "Toggle subscript",
32024
- onClick: () => {
32025
- activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, "subscript");
32026
- },
32027
- variant: "outline",
32028
- children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(SubscriptIcon, {}) })
32029
- }
32030
- ),
32031
- /* @__PURE__ */ jsx(
32032
- ToggleGroupItem,
32033
- {
32034
- value: "superscript",
32035
- size: "default",
32036
- "aria-label": "Toggle superscript",
32037
- onClick: () => {
32038
- activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, "superscript");
32039
- },
32040
- variant: "outline",
32041
- children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(SuperscriptIcon, {}) })
32042
- }
32043
- )
32044
- ]
32045
- }
32046
- );
32293
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
32294
+ /* @__PURE__ */ jsx(
32295
+ Button,
32296
+ {
32297
+ variant: "outline",
32298
+ size: "icon",
32299
+ "aria-label": "Toggle subscript",
32300
+ "data-state": isSubscript ? "on" : "off",
32301
+ onClick: () => {
32302
+ activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, "subscript");
32303
+ },
32304
+ className: "editor-toolbar-item",
32305
+ children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(SubscriptIcon, {}) })
32306
+ }
32307
+ ),
32308
+ /* @__PURE__ */ jsx(
32309
+ Button,
32310
+ {
32311
+ variant: "outline",
32312
+ size: "icon",
32313
+ "aria-label": "Toggle superscript",
32314
+ "data-state": isSuperscript ? "on" : "off",
32315
+ onClick: () => {
32316
+ activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, "superscript");
32317
+ },
32318
+ className: "editor-toolbar-item",
32319
+ children: /* @__PURE__ */ jsx(IconSize, { size: "sm", children: /* @__PURE__ */ jsx(SuperscriptIcon, {}) })
32320
+ }
32321
+ )
32322
+ ] });
32047
32323
  }
32048
32324
  var init_subsuper_toolbar_plugin = __esm({
32049
32325
  "src/plugins/toolbar/subsuper-toolbar-plugin.tsx"() {
32050
32326
  "use client";
32051
32327
  init_toolbar_context();
32052
32328
  init_use_update_toolbar();
32053
- init_toggle_group();
32329
+ init_button();
32054
32330
  init_typography();
32055
32331
  }
32056
32332
  });
@@ -32580,47 +32856,50 @@ function Plugins({
32580
32856
  children: ({ blockType }) => /* @__PURE__ */ jsxs(Fragment, { children: [
32581
32857
  /* @__PURE__ */ jsx("div", { className: "editor-toolbar-group", children: /* @__PURE__ */ jsx(HistoryToolbarPlugin, {}) }),
32582
32858
  /* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "editor-toolbar-separator" }),
32583
- /* @__PURE__ */ jsx("div", { className: "editor-toolbar-group", children: /* @__PURE__ */ jsxs(BlockInsertPlugin, { children: [
32584
- /* @__PURE__ */ jsx(InsertHorizontalRule, {}),
32585
- /* @__PURE__ */ jsx(InsertImage, {}),
32586
- /* @__PURE__ */ jsx(InsertTable, {}),
32587
- /* @__PURE__ */ jsx(InsertColumnsLayout, {}),
32588
- /* @__PURE__ */ jsx(InsertEmbeds, {})
32589
- ] }) }),
32590
- /* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "editor-toolbar-separator" }),
32591
- /* @__PURE__ */ jsx("div", { className: "editor-toolbar-group", children: /* @__PURE__ */ jsxs(BlockFormatDropDown, { children: [
32592
- /* @__PURE__ */ jsx(FormatParagraph, {}),
32593
- /* @__PURE__ */ jsx(FormatHeading, { levels: ["h1", "h2", "h3"] }),
32594
- /* @__PURE__ */ jsx(FormatNumberedList, {}),
32595
- /* @__PURE__ */ jsx(
32596
- FormatListWithMarker,
32597
- {
32598
- blockFormatValue: "number-alpha",
32599
- listType: "number",
32600
- markerType: "alpha"
32601
- }
32602
- ),
32603
- /* @__PURE__ */ jsx(FormatBulletedList, {}),
32604
- /* @__PURE__ */ jsx(
32605
- FormatListWithMarker,
32606
- {
32607
- blockFormatValue: "bullet-dash",
32608
- listType: "bullet",
32609
- markerType: "-"
32610
- }
32611
- ),
32612
- /* @__PURE__ */ jsx(
32613
- FormatListWithMarker,
32614
- {
32615
- blockFormatValue: "bullet-plus",
32616
- listType: "bullet",
32617
- markerType: "+"
32618
- }
32619
- ),
32620
- /* @__PURE__ */ jsx(FormatCheckList, {}),
32621
- /* @__PURE__ */ jsx(FormatCodeBlock, {}),
32622
- /* @__PURE__ */ jsx(FormatQuote, {})
32623
- ] }) }),
32859
+ blockType !== "code" && /* @__PURE__ */ jsxs(Fragment, { children: [
32860
+ /* @__PURE__ */ jsx("div", { className: "editor-toolbar-group", children: /* @__PURE__ */ jsxs(BlockInsertPlugin, { children: [
32861
+ /* @__PURE__ */ jsx(InsertHorizontalRule, {}),
32862
+ /* @__PURE__ */ jsx(InsertImage, {}),
32863
+ /* @__PURE__ */ jsx(InsertTable, {}),
32864
+ /* @__PURE__ */ jsx(InsertColumnsLayout, {}),
32865
+ /* @__PURE__ */ jsx(InsertEmbeds, {})
32866
+ ] }) }),
32867
+ /* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "editor-toolbar-separator" }),
32868
+ /* @__PURE__ */ jsx("div", { className: "editor-toolbar-group", children: /* @__PURE__ */ jsxs(BlockFormatDropDown, { children: [
32869
+ /* @__PURE__ */ jsx(FormatParagraph, {}),
32870
+ /* @__PURE__ */ jsx(FormatHeading, { levels: ["h1", "h2", "h3"] }),
32871
+ /* @__PURE__ */ jsx(FormatNumberedList, {}),
32872
+ /* @__PURE__ */ jsx(
32873
+ FormatListWithMarker,
32874
+ {
32875
+ blockFormatValue: "number-alpha",
32876
+ listType: "number",
32877
+ markerType: "alpha"
32878
+ }
32879
+ ),
32880
+ /* @__PURE__ */ jsx(FormatBulletedList, {}),
32881
+ /* @__PURE__ */ jsx(
32882
+ FormatListWithMarker,
32883
+ {
32884
+ blockFormatValue: "bullet-dash",
32885
+ listType: "bullet",
32886
+ markerType: "-"
32887
+ }
32888
+ ),
32889
+ /* @__PURE__ */ jsx(
32890
+ FormatListWithMarker,
32891
+ {
32892
+ blockFormatValue: "bullet-plus",
32893
+ listType: "bullet",
32894
+ markerType: "+"
32895
+ }
32896
+ ),
32897
+ /* @__PURE__ */ jsx(FormatCheckList, {}),
32898
+ /* @__PURE__ */ jsx(FormatCodeBlock, {}),
32899
+ /* @__PURE__ */ jsx(FormatQuote, {})
32900
+ ] }) }),
32901
+ /* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "editor-toolbar-separator" })
32902
+ ] }),
32624
32903
  blockType === "code" ? /* @__PURE__ */ jsx("div", { className: "editor-toolbar-group", children: /* @__PURE__ */ jsx(CodeLanguageToolbarPlugin, {}) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
32625
32904
  /* @__PURE__ */ jsxs("div", { className: "editor-toolbar-group", children: [
32626
32905
  /* @__PURE__ */ jsx(FontFamilyToolbarPlugin, {}),
@@ -32671,7 +32950,7 @@ function Plugins({
32671
32950
  /* @__PURE__ */ jsx(HorizontalRulePlugin, {}),
32672
32951
  /* @__PURE__ */ jsx(TablePlugin, { hasHorizontalScroll: true }),
32673
32952
  /* @__PURE__ */ jsx(InsertTableCommandPlugin, {}),
32674
- /* @__PURE__ */ jsx(TableColumnResizerPlugin, {}),
32953
+ /* @__PURE__ */ jsx(TableColumnResizerPlugin, { anchorElem: floatingAnchorElem ?? document.body }),
32675
32954
  /* @__PURE__ */ jsx(ListPlugin, {}),
32676
32955
  /* @__PURE__ */ jsx(TabIndentationPlugin, {}),
32677
32956
  /* @__PURE__ */ jsx(HistoryPlugin, {})
@@ -33044,7 +33323,18 @@ function Editor({
33044
33323
  Promise.resolve().then(() => (init_plugins(), plugins_exports)).then((m) => ({ Plugins: m.Plugins }))
33045
33324
  ]).then(([nodes2, { Plugins: Plugins3 }]) => setConfig({ nodes: nodes2, Plugins: Plugins3 }));
33046
33325
  }, []);
33047
- if (!config) {
33326
+ const editorConfig = useMemo(() => {
33327
+ if (!config || !config.nodes) return null;
33328
+ const validNodes = config.nodes.filter((node) => {
33329
+ if (node === void 0) {
33330
+ console.error("[Editor] Found undefined node in config.nodes");
33331
+ return false;
33332
+ }
33333
+ return true;
33334
+ });
33335
+ return createEditorConfig(validNodes);
33336
+ }, [config]);
33337
+ if (!config || !editorConfig) {
33048
33338
  return /* @__PURE__ */ jsx(
33049
33339
  "div",
33050
33340
  {
@@ -33056,7 +33346,6 @@ function Editor({
33056
33346
  }
33057
33347
  );
33058
33348
  }
33059
- const editorConfig = createEditorConfig(config.nodes);
33060
33349
  const { Plugins: Plugins2 } = config;
33061
33350
  return /* @__PURE__ */ jsx(
33062
33351
  "div",