@haklex/rich-editor 0.0.30 → 0.0.32

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 (59) hide show
  1. package/dist/{RichEditor-D1twFNL-.js → RichEditor-CXvIPtDS.js} +423 -73
  2. package/dist/components/decorators/GridEditDecorator.d.ts.map +1 -1
  3. package/dist/components/renderers/AlertStaticDecorator.d.ts +9 -0
  4. package/dist/components/renderers/AlertStaticDecorator.d.ts.map +1 -0
  5. package/dist/components/renderers/BannerStaticDecorator.d.ts +9 -0
  6. package/dist/components/renderers/BannerStaticDecorator.d.ts.map +1 -0
  7. package/dist/components/renderers/FootnoteStaticRenderer.d.ts +5 -0
  8. package/dist/components/renderers/FootnoteStaticRenderer.d.ts.map +1 -0
  9. package/dist/components/renderers/GridStaticDecorator.d.ts +9 -0
  10. package/dist/components/renderers/GridStaticDecorator.d.ts.map +1 -0
  11. package/dist/context/NestedContentRendererContext.d.ts +6 -0
  12. package/dist/context/NestedContentRendererContext.d.ts.map +1 -0
  13. package/dist/editor.mjs +2 -2
  14. package/dist/index.d.ts +7 -2
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.mjs +95 -52
  17. package/dist/nodes/AlertQuoteEditNode.d.ts +9 -2
  18. package/dist/nodes/AlertQuoteEditNode.d.ts.map +1 -1
  19. package/dist/nodes/AlertQuoteNode.d.ts +5 -6
  20. package/dist/nodes/AlertQuoteNode.d.ts.map +1 -1
  21. package/dist/nodes/BannerEditNode.d.ts +9 -2
  22. package/dist/nodes/BannerEditNode.d.ts.map +1 -1
  23. package/dist/nodes/BannerNode.d.ts +5 -6
  24. package/dist/nodes/BannerNode.d.ts.map +1 -1
  25. package/dist/nodes/GridContainerNode.d.ts +3 -5
  26. package/dist/nodes/GridContainerNode.d.ts.map +1 -1
  27. package/dist/nodes/GridEditNode.d.ts +12 -1
  28. package/dist/nodes/GridEditNode.d.ts.map +1 -1
  29. package/dist/plugins/AlertPlugin.d.ts.map +1 -1
  30. package/dist/plugins/FootnotePlugin.d.ts.map +1 -1
  31. package/dist/rich-editor.css +1 -1
  32. package/dist/static-entry.d.ts +22 -0
  33. package/dist/static-entry.d.ts.map +1 -0
  34. package/dist/static-entry.mjs +39 -0
  35. package/dist/styles/shared.css.d.ts.map +1 -1
  36. package/dist/styles/theme.d.ts.map +1 -1
  37. package/dist/styles-entry.d.ts +7 -0
  38. package/dist/styles-entry.d.ts.map +1 -0
  39. package/dist/styles-entry.mjs +26 -0
  40. package/dist/{utils-BuZqZkYK.js → theme-C_ic3l9g.js} +665 -804
  41. package/dist/transformers/alert.d.ts.map +1 -1
  42. package/dist/transformers/container.d.ts.map +1 -1
  43. package/dist/transformers/grid-container.d.ts.map +1 -1
  44. package/dist/transformers/index.d.ts +1 -0
  45. package/dist/transformers/index.d.ts.map +1 -1
  46. package/dist/transformers/superscript-subscript.d.ts +2 -0
  47. package/dist/transformers/superscript-subscript.d.ts.map +1 -0
  48. package/dist/types.d.ts +0 -10
  49. package/dist/types.d.ts.map +1 -1
  50. package/dist/utils/extractTextContent.d.ts +3 -0
  51. package/dist/utils/extractTextContent.d.ts.map +1 -0
  52. package/dist/utils-C9cpKf8S.js +28 -0
  53. package/package.json +11 -7
  54. package/dist/RichRenderer-hHQ4JQs0.js +0 -113
  55. package/dist/components/RichRenderer.d.ts +0 -3
  56. package/dist/components/RichRenderer.d.ts.map +0 -1
  57. package/dist/renderer.d.ts +0 -3
  58. package/dist/renderer.d.ts.map +0 -1
  59. package/dist/renderer.mjs +0 -4
@@ -1,3 +1,6 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
1
4
  import { jsxs, Fragment, jsx } from "react/jsx-runtime";
2
5
  import { PortalThemeProvider } from "@haklex/rich-style-token";
3
6
  import { CheckListPlugin } from "@lexical/react/LexicalCheckListPlugin";
@@ -9,18 +12,23 @@ import { ListPlugin } from "@lexical/react/LexicalListPlugin";
9
12
  import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
10
13
  import { TabIndentationPlugin } from "@lexical/react/LexicalTabIndentationPlugin";
11
14
  import { TablePlugin } from "@lexical/react/LexicalTablePlugin";
12
- import { W as $isAlertQuoteNode, X as RendererWrapper, Y as AlertRenderer, Z as AlertQuoteNode, _ as $isBannerNode, a0 as BannerRenderer, a1 as BannerNode, a2 as normalizeBannerType, a3 as $isCodeBlockNode, a4 as CodeBlockRenderer, a5 as CodeBlockNode, Q as useFootnoteDefinitions, s as FootnoteSectionNode, k as $isGridContainerNode, G as GridContainerNode, e as editorTheme, N as NESTED_EDITOR_NODES, b as builtinNodes, a6 as SpoilerNode, a7 as MentionNode, t as KaTeXInlineNode, K as KaTeXBlockNode, a8 as ImageNode, a9 as FootnoteNode, aa as VideoNode, L as LinkCardNode, ab as DetailsNode, M as MermaidNode, ac as $createAlertQuoteNode, ad as $createImageNode, ae as $createKaTeXInlineNode, af as $createKaTeXBlockNode, ag as $createBannerNode, ah as $createDetailsNode, ai as $createFootnoteNode, j as $isFootnoteSectionNode, $ as $createFootnoteSectionNode, aj as $createMentionNode, ak as $createSpoilerNode, i as $createMermaidNode, d as clsx, C as ColorSchemeProvider, R as RendererConfigProvider, F as FootnotePlugin, g as getVariantClass } from "./utils-BuZqZkYK.js";
15
+ import { Q as $isAlertQuoteNode, d as RendererWrapper, S as AlertRenderer, T as SpoilerNode, U as MentionNode, V as FootnoteNode, H as KaTeXInlineNode, W as AlertQuoteNode, f as editorTheme, X as $isBannerNode, Y as BannerRenderer, Z as BannerNode, _ as normalizeBannerType, a0 as $isCodeBlockNode, a1 as CodeBlockRenderer, a2 as CodeBlockNode, i as useFootnoteDefinitions, D as FootnoteSectionNode, s as $isGridContainerNode, G as GridContainerNode, b as builtinNodes, K as KaTeXBlockNode, a3 as ImageNode, a4 as VideoNode, L as LinkCardNode, a5 as DetailsNode, M as MermaidNode, F as FootnoteDefinitionsProvider, a6 as $createImageNode, a7 as $createKaTeXInlineNode, a8 as $createKaTeXBlockNode, a9 as $createDetailsNode, aa as $createFootnoteNode, r as $isFootnoteSectionNode, $ as $createFootnoteSectionNode, ab as $createMentionNode, g as extractTextContent, ac as $createSpoilerNode, q as $createMermaidNode, C as ColorSchemeProvider, R as RendererConfigProvider } from "./theme-C_ic3l9g.js";
16
+ import { $getNodeByKey, $insertNodes, createEditor, $nodesOfType, $getRoot, createCommand, COMMAND_PRIORITY_EDITOR, $parseSerializedNode, $getSelection, $isRangeSelection, $createParagraphNode, $createTextNode, KEY_ENTER_COMMAND, COMMAND_PRIORITY_HIGH } from "lexical";
17
+ import { Info, Lightbulb, TriangleAlert, Flag, LayoutGrid, Plus, Minus } from "lucide-react";
13
18
  import { useCallback, createElement, useState, useEffect, useRef } from "react";
14
19
  import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
15
20
  import { ContentEditable as ContentEditable$1 } from "@lexical/react/LexicalContentEditable";
16
21
  import { LexicalNestedComposer } from "@lexical/react/LexicalNestedComposer";
17
- import { $getNodeByKey, $nodesOfType, $getRoot, createEditor, createCommand, $insertNodes, COMMAND_PRIORITY_EDITOR, $getSelection, $isRangeSelection, $createParagraphNode, $createTextNode, KEY_ENTER_COMMAND, COMMAND_PRIORITY_HIGH } from "lexical";
18
- import { LayoutGrid, Plus, Minus } from "lucide-react";
19
- import { createLinkMatcherWithRegExp, registerAutoLink } from "@lexical/link";
20
- import { INSERT_HORIZONTAL_RULE_COMMAND, $createHorizontalRuleNode } from "@lexical/extension";
22
+ import { CodeNode } from "@lexical/code";
23
+ import { HorizontalRuleNode, INSERT_HORIZONTAL_RULE_COMMAND, $createHorizontalRuleNode } from "@lexical/extension";
24
+ import { LinkNode, AutoLinkNode, createLinkMatcherWithRegExp, registerAutoLink } from "@lexical/link";
25
+ import { ListNode, ListItemNode } from "@lexical/list";
26
+ import { HeadingNode, QuoteNode } from "@lexical/rich-text";
27
+ import { TableNode, TableCellNode, TableRowNode } from "@lexical/table";
21
28
  import { MarkdownShortcutPlugin } from "@lexical/react/LexicalMarkdownShortcutPlugin";
22
29
  import { CHECK_LIST, TRANSFORMERS } from "@lexical/markdown";
23
- import { GIT_ALERT_TRANSFORMER as GIT_ALERT_TRANSFORMER$1, CONTAINER_TRANSFORMER as CONTAINER_TRANSFORMER$1, FOOTNOTE_TRANSFORMER as FOOTNOTE_TRANSFORMER$1, FOOTNOTE_SECTION_TRANSFORMER as FOOTNOTE_SECTION_TRANSFORMER$1, KATEX_INLINE_TRANSFORMER as KATEX_INLINE_TRANSFORMER$1, KATEX_BLOCK_TRANSFORMER as KATEX_BLOCK_TRANSFORMER$1, MENTION_TRANSFORMER as MENTION_TRANSFORMER$1, SPOILER_TRANSFORMER as SPOILER_TRANSFORMER$1, INSERT_TRANSFORMER, IMAGE_BLOCK_TRANSFORMER, VIDEO_BLOCK_TRANSFORMER, CODE_BLOCK_NODE_TRANSFORMER, LINK_CARD_BLOCK_TRANSFORMER, MERMAID_BLOCK_TRANSFORMER, HORIZONTAL_RULE_BLOCK_TRANSFORMER, TABLE_BLOCK_TRANSFORMER } from "@haklex/rich-headless/transformers";
30
+ import { GIT_ALERT_TRANSFORMER as GIT_ALERT_TRANSFORMER$1, CONTAINER_TRANSFORMER as CONTAINER_TRANSFORMER$1, FOOTNOTE_TRANSFORMER as FOOTNOTE_TRANSFORMER$1, FOOTNOTE_SECTION_TRANSFORMER as FOOTNOTE_SECTION_TRANSFORMER$1, KATEX_INLINE_TRANSFORMER as KATEX_INLINE_TRANSFORMER$1, KATEX_BLOCK_TRANSFORMER as KATEX_BLOCK_TRANSFORMER$1, MENTION_TRANSFORMER as MENTION_TRANSFORMER$1, SPOILER_TRANSFORMER as SPOILER_TRANSFORMER$1, INSERT_TRANSFORMER, SUPERSCRIPT_TRANSFORMER, SUBSCRIPT_TRANSFORMER, IMAGE_BLOCK_TRANSFORMER, VIDEO_BLOCK_TRANSFORMER, CODE_BLOCK_NODE_TRANSFORMER, LINK_CARD_BLOCK_TRANSFORMER, MERMAID_BLOCK_TRANSFORMER, HORIZONTAL_RULE_BLOCK_TRANSFORMER, TABLE_BLOCK_TRANSFORMER } from "@haklex/rich-headless/transformers";
31
+ import { f as clsx, g as getVariantClass } from "./utils-C9cpKf8S.js";
24
32
  function AlertEditDecorator({
25
33
  nodeKey,
26
34
  alertType,
@@ -73,24 +81,71 @@ function AlertEditDecorator({
73
81
  ] }) })
74
82
  ] });
75
83
  }
76
- class AlertQuoteEditNode extends AlertQuoteNode {
84
+ const NESTED_EDITOR_NODES = [
85
+ HeadingNode,
86
+ QuoteNode,
87
+ ListNode,
88
+ ListItemNode,
89
+ LinkNode,
90
+ AutoLinkNode,
91
+ HorizontalRuleNode,
92
+ CodeNode,
93
+ TableNode,
94
+ TableCellNode,
95
+ TableRowNode,
96
+ SpoilerNode,
97
+ MentionNode,
98
+ FootnoteNode,
99
+ KaTeXInlineNode
100
+ ];
101
+ function createContentEditor$1() {
102
+ return createEditor({
103
+ namespace: "AlertContent",
104
+ nodes: NESTED_EDITOR_NODES,
105
+ theme: editorTheme,
106
+ onError: (error) => {
107
+ console.error("[AlertContent]", error);
108
+ }
109
+ });
110
+ }
111
+ const _AlertQuoteEditNode = class _AlertQuoteEditNode extends AlertQuoteNode {
112
+ constructor(alertType, contentState, key) {
113
+ super(alertType, contentState, key);
114
+ __publicField(this, "__contentEditor");
115
+ this.__contentEditor = createContentEditor$1();
116
+ if (contentState) {
117
+ const editorState = this.__contentEditor.parseEditorState(contentState);
118
+ this.__contentEditor.setEditorState(editorState);
119
+ }
120
+ }
77
121
  static clone(node) {
78
- return new AlertQuoteEditNode(
122
+ const cloned = new _AlertQuoteEditNode(
79
123
  node.__alertType,
80
- node.__contentEditor,
124
+ node.__contentState,
81
125
  node.__key
82
126
  );
127
+ cloned.__contentEditor = node.__contentEditor;
128
+ return cloned;
129
+ }
130
+ getContentEditor() {
131
+ return this.__contentEditor;
83
132
  }
84
133
  static importJSON(serializedNode) {
85
- const node = new AlertQuoteEditNode(serializedNode.alertType);
86
- if (serializedNode.content) {
87
- const editorState = node.__contentEditor.parseEditorState(
88
- serializedNode.content
89
- );
90
- node.__contentEditor.setEditorState(editorState);
91
- }
134
+ const node = new _AlertQuoteEditNode(
135
+ serializedNode.alertType,
136
+ serializedNode.content
137
+ );
92
138
  return node;
93
139
  }
140
+ exportJSON() {
141
+ return {
142
+ ...super.exportJSON(),
143
+ type: "alert-quote",
144
+ alertType: this.__alertType,
145
+ content: this.__contentEditor.getEditorState().toJSON(),
146
+ version: 1
147
+ };
148
+ }
94
149
  decorate(_editor, _config) {
95
150
  return createElement(AlertEditDecorator, {
96
151
  nodeKey: this.__key,
@@ -98,6 +153,48 @@ class AlertQuoteEditNode extends AlertQuoteNode {
98
153
  contentEditor: this.__contentEditor
99
154
  });
100
155
  }
156
+ };
157
+ __publicField(_AlertQuoteEditNode, "slashMenuItems", [
158
+ {
159
+ title: "Callout",
160
+ icon: createElement(Info, { size: 20 }),
161
+ description: "Info callout block",
162
+ keywords: ["alert", "note", "info", "callout"],
163
+ section: "ADVANCED",
164
+ onSelect: (editor) => {
165
+ editor.update(() => {
166
+ $insertNodes([$createAlertQuoteEditNode("note")]);
167
+ });
168
+ }
169
+ },
170
+ {
171
+ title: "Tip",
172
+ icon: createElement(Lightbulb, { size: 20 }),
173
+ description: "Highlight a useful tip",
174
+ keywords: ["alert", "tip", "hint"],
175
+ section: "ADVANCED",
176
+ onSelect: (editor) => {
177
+ editor.update(() => {
178
+ $insertNodes([$createAlertQuoteEditNode("tip")]);
179
+ });
180
+ }
181
+ },
182
+ {
183
+ title: "Warning",
184
+ icon: createElement(TriangleAlert, { size: 20 }),
185
+ description: "Warn about something",
186
+ keywords: ["alert", "warning", "caution"],
187
+ section: "ADVANCED",
188
+ onSelect: (editor) => {
189
+ editor.update(() => {
190
+ $insertNodes([$createAlertQuoteEditNode("warning")]);
191
+ });
192
+ }
193
+ }
194
+ ]);
195
+ let AlertQuoteEditNode = _AlertQuoteEditNode;
196
+ function $createAlertQuoteEditNode(alertType, contentState) {
197
+ return new AlertQuoteEditNode(alertType, contentState);
101
198
  }
102
199
  function BannerEditDecorator({
103
200
  nodeKey,
@@ -151,24 +248,45 @@ function BannerEditDecorator({
151
248
  ] }) })
152
249
  ] });
153
250
  }
154
- class BannerEditNode extends BannerNode {
251
+ function createContentEditor() {
252
+ return createEditor({
253
+ namespace: "BannerContent",
254
+ nodes: NESTED_EDITOR_NODES,
255
+ theme: editorTheme,
256
+ onError: (error) => {
257
+ console.error("[BannerContent]", error);
258
+ }
259
+ });
260
+ }
261
+ const _BannerEditNode = class _BannerEditNode extends BannerNode {
262
+ constructor(bannerType, contentState, key) {
263
+ super(bannerType, contentState, key);
264
+ __publicField(this, "__contentEditor");
265
+ this.__contentEditor = createContentEditor();
266
+ if (contentState) {
267
+ const editorState = this.__contentEditor.parseEditorState(contentState);
268
+ this.__contentEditor.setEditorState(editorState);
269
+ }
270
+ }
155
271
  static clone(node) {
156
- return new BannerEditNode(
272
+ const cloned = new _BannerEditNode(
157
273
  node.__bannerType,
158
- node.__contentEditor,
274
+ node.__contentState,
159
275
  node.__key
160
276
  );
277
+ cloned.__contentEditor = node.__contentEditor;
278
+ return cloned;
279
+ }
280
+ getContentEditor() {
281
+ return this.__contentEditor;
161
282
  }
162
283
  static importJSON(serializedNode) {
163
284
  const legacy = serializedNode;
164
285
  const bannerType = normalizeBannerType(serializedNode.bannerType);
165
- const node = new BannerEditNode(bannerType);
166
286
  if (serializedNode.content) {
167
- const editorState = node.__contentEditor.parseEditorState(
168
- serializedNode.content
169
- );
170
- node.__contentEditor.setEditorState(editorState);
171
- } else if (legacy.children) {
287
+ return new _BannerEditNode(bannerType, serializedNode.content);
288
+ }
289
+ if (legacy.children) {
172
290
  const content = {
173
291
  root: {
174
292
  children: legacy.children,
@@ -179,10 +297,18 @@ class BannerEditNode extends BannerNode {
179
297
  version: 1
180
298
  }
181
299
  };
182
- const editorState = node.__contentEditor.parseEditorState(content);
183
- node.__contentEditor.setEditorState(editorState);
300
+ return new _BannerEditNode(bannerType, content);
184
301
  }
185
- return node;
302
+ return new _BannerEditNode(bannerType);
303
+ }
304
+ exportJSON() {
305
+ return {
306
+ ...super.exportJSON(),
307
+ type: "banner",
308
+ bannerType: this.__bannerType,
309
+ content: this.__contentEditor.getEditorState().toJSON(),
310
+ version: 1
311
+ };
186
312
  }
187
313
  decorate(_editor, _config) {
188
314
  return createElement(BannerEditDecorator, {
@@ -191,6 +317,24 @@ class BannerEditNode extends BannerNode {
191
317
  contentEditor: this.__contentEditor
192
318
  });
193
319
  }
320
+ };
321
+ __publicField(_BannerEditNode, "slashMenuItems", [
322
+ {
323
+ title: "Banner",
324
+ icon: createElement(Flag, { size: 20 }),
325
+ description: "Highlighted banner block",
326
+ keywords: ["banner", "notice", "announcement"],
327
+ section: "ADVANCED",
328
+ onSelect: (editor) => {
329
+ editor.update(() => {
330
+ $insertNodes([$createBannerEditNode("note")]);
331
+ });
332
+ }
333
+ }
334
+ ]);
335
+ let BannerEditNode = _BannerEditNode;
336
+ function $createBannerEditNode(bannerType, contentState) {
337
+ return new BannerEditNode(bannerType, contentState);
194
338
  }
195
339
  function CodeBlockEditDecorator({
196
340
  nodeKey,
@@ -376,7 +520,7 @@ function GridEditDecorator({
376
520
  const handleRemoveRow = useCallback(() => {
377
521
  editor.update(() => {
378
522
  const node = $getNodeByKey(nodeKey);
379
- if (!$isGridContainerNode(node)) return;
523
+ if (!$isGridEditNode(node)) return;
380
524
  const cols = node.getCols();
381
525
  const editors = node.getCellEditors();
382
526
  if (editors.length <= cols) return;
@@ -471,36 +615,52 @@ function createCellEditor() {
471
615
  }
472
616
  });
473
617
  }
474
- class GridEditNode extends GridContainerNode {
618
+ const _GridEditNode = class _GridEditNode extends GridContainerNode {
619
+ constructor(cols = 2, gap, cellStates, key) {
620
+ super(cols, gap, cellStates, key);
621
+ __publicField(this, "__cellEditors");
622
+ this.__cellEditors = this.__cellStates.map((state) => {
623
+ const editor = createCellEditor();
624
+ const editorState = editor.parseEditorState(state);
625
+ editor.setEditorState(editorState);
626
+ return editor;
627
+ });
628
+ }
475
629
  static clone(node) {
476
- return new GridEditNode(
630
+ const cloned = new _GridEditNode(
477
631
  node.__cols,
478
632
  node.__gap,
479
- [...node.__cellEditors],
633
+ node.__cellStates,
480
634
  node.__key
481
635
  );
636
+ cloned.__cellEditors = [...node.__cellEditors];
637
+ return cloned;
482
638
  }
483
- static importJSON(serializedNode) {
484
- const legacy = serializedNode;
485
- const cols = legacy.cols || 2;
486
- const rawGap = legacy.gap;
487
- const gap = typeof rawGap === "number" ? `${rawGap}px` : rawGap;
488
- const node = new GridEditNode(cols, gap);
489
- if (legacy.cells && legacy.cells.length > 0) {
490
- const editors = legacy.cells.map((cellState) => {
491
- const editor = createCellEditor();
492
- const editorState = editor.parseEditorState(cellState);
493
- editor.setEditorState(editorState);
494
- return editor;
495
- });
496
- node.__cellEditors = editors;
497
- } else if (legacy.children) {
498
- const { children } = legacy;
499
- const editors = children.map((child) => {
639
+ getCellEditors() {
640
+ return this.getLatest().__cellEditors;
641
+ }
642
+ setCols(cols) {
643
+ const writable = this.getWritable();
644
+ const prev = writable.__cellEditors.length;
645
+ writable.__cols = cols;
646
+ if (cols > prev) {
647
+ for (let i = prev; i < cols; i++) {
500
648
  const editor = createCellEditor();
501
- const content = {
649
+ writable.__cellEditors.push(editor);
650
+ const emptyState = {
502
651
  root: {
503
- children: [child],
652
+ children: [
653
+ {
654
+ type: "paragraph",
655
+ children: [],
656
+ direction: null,
657
+ format: "",
658
+ indent: 0,
659
+ textFormat: 0,
660
+ textStyle: "",
661
+ version: 1
662
+ }
663
+ ],
504
664
  direction: null,
505
665
  format: "",
506
666
  indent: 0,
@@ -508,13 +668,93 @@ class GridEditNode extends GridContainerNode {
508
668
  version: 1
509
669
  }
510
670
  };
511
- const editorState = editor.parseEditorState(content);
512
- editor.setEditorState(editorState);
513
- return editor;
671
+ writable.__cellStates.push(emptyState);
672
+ }
673
+ }
674
+ }
675
+ addCells(count) {
676
+ const writable = this.getWritable();
677
+ for (let i = 0; i < count; i++) {
678
+ const editor = createCellEditor();
679
+ writable.__cellEditors.push(editor);
680
+ const emptyState = {
681
+ root: {
682
+ children: [
683
+ {
684
+ type: "paragraph",
685
+ children: [],
686
+ direction: null,
687
+ format: "",
688
+ indent: 0,
689
+ textFormat: 0,
690
+ textStyle: "",
691
+ version: 1
692
+ }
693
+ ],
694
+ direction: null,
695
+ format: "",
696
+ indent: 0,
697
+ type: "root",
698
+ version: 1
699
+ }
700
+ };
701
+ writable.__cellStates.push(emptyState);
702
+ }
703
+ }
704
+ removeCells(count) {
705
+ const writable = this.getWritable();
706
+ const editors = writable.__cellEditors;
707
+ const states = writable.__cellStates;
708
+ const toRemove = Math.min(count, editors.length);
709
+ for (let i = 0; i < toRemove; i++) {
710
+ const editor = editors.at(-1);
711
+ if (!editor) break;
712
+ const isEmpty = editor.getEditorState().read(() => {
713
+ return $getRoot().getTextContentSize() === 0;
514
714
  });
515
- node.__cellEditors = editors;
715
+ if (!isEmpty) break;
716
+ editors.pop();
717
+ states.pop();
516
718
  }
517
- return node;
719
+ }
720
+ static importJSON(serializedNode) {
721
+ const legacy = serializedNode;
722
+ const cols = legacy.cols || 2;
723
+ const rawGap = legacy.gap;
724
+ const gap = typeof rawGap === "number" ? `${rawGap}px` : rawGap;
725
+ if (legacy.cells && legacy.cells.length > 0) {
726
+ return new _GridEditNode(cols, gap, legacy.cells);
727
+ }
728
+ if (legacy.children) {
729
+ const cellStates = legacy.children.map(
730
+ (child) => {
731
+ return {
732
+ root: {
733
+ children: [child],
734
+ direction: null,
735
+ format: "",
736
+ indent: 0,
737
+ type: "root",
738
+ version: 1
739
+ }
740
+ };
741
+ }
742
+ );
743
+ return new _GridEditNode(cols, gap, cellStates);
744
+ }
745
+ return new _GridEditNode(cols, gap);
746
+ }
747
+ exportJSON() {
748
+ return {
749
+ ...super.exportJSON(),
750
+ type: "grid-container",
751
+ cols: this.__cols,
752
+ gap: this.__gap,
753
+ cells: this.__cellEditors.map(
754
+ (editor) => editor.getEditorState().toJSON()
755
+ ),
756
+ version: 1
757
+ };
518
758
  }
519
759
  decorate(_editor, _config) {
520
760
  return createElement(GridEditDecorator, {
@@ -524,6 +764,27 @@ class GridEditNode extends GridContainerNode {
524
764
  cellEditors: this.__cellEditors
525
765
  });
526
766
  }
767
+ };
768
+ __publicField(_GridEditNode, "slashMenuItems", [
769
+ {
770
+ title: "Grid",
771
+ icon: createElement(LayoutGrid, { size: 20 }),
772
+ description: "Grid layout container",
773
+ keywords: ["grid", "columns", "layout"],
774
+ section: "LAYOUT",
775
+ onSelect: (editor) => {
776
+ editor.update(() => {
777
+ $insertNodes([$createGridEditNode(2)]);
778
+ });
779
+ }
780
+ }
781
+ ]);
782
+ let GridEditNode = _GridEditNode;
783
+ function $createGridEditNode(cols = 2, gap) {
784
+ return new GridEditNode(cols, gap);
785
+ }
786
+ function $isGridEditNode(node) {
787
+ return node instanceof GridEditNode;
527
788
  }
528
789
  const customEditNodes = [
529
790
  SpoilerNode,
@@ -560,7 +821,7 @@ function AlertPlugin() {
560
821
  return editor.registerCommand(
561
822
  INSERT_ALERT_COMMAND,
562
823
  (alertType) => {
563
- $insertNodes([$createAlertQuoteNode(alertType)]);
824
+ $insertNodes([$createAlertQuoteEditNode(alertType)]);
564
825
  return true;
565
826
  },
566
827
  COMMAND_PRIORITY_EDITOR
@@ -608,6 +869,99 @@ function EditorRefPlugin({ onEditorReady }) {
608
869
  }, [editor]);
609
870
  return null;
610
871
  }
872
+ function FootnotePlugin({ children }) {
873
+ const [editor] = useLexicalComposerContext();
874
+ const [definitions, setDefinitions] = useState({});
875
+ const [displayNumberMap, setDisplayNumberMap] = useState({});
876
+ const pendingUpdateRef = useRef(false);
877
+ useEffect(() => {
878
+ return editor.registerUpdateListener(({ editorState }) => {
879
+ editorState.read(() => {
880
+ const footnoteNodes = $nodesOfType(FootnoteNode);
881
+ const seen = /* @__PURE__ */ new Set();
882
+ const numberMap = {};
883
+ let counter = 1;
884
+ for (const node of footnoteNodes) {
885
+ const id = node.getIdentifier();
886
+ if (!seen.has(id)) {
887
+ seen.add(id);
888
+ numberMap[id] = counter++;
889
+ }
890
+ }
891
+ setDisplayNumberMap(numberMap);
892
+ const sectionNodes = $nodesOfType(FootnoteSectionNode);
893
+ if (sectionNodes.length > 0) {
894
+ setDefinitions(sectionNodes[0].getDefinitions());
895
+ } else {
896
+ setDefinitions({});
897
+ }
898
+ if (!editor.isEditable() || pendingUpdateRef.current) return;
899
+ if (footnoteNodes.length === 0 && sectionNodes.length > 0) {
900
+ pendingUpdateRef.current = true;
901
+ queueMicrotask(() => {
902
+ editor.update(() => {
903
+ const sections = $nodesOfType(FootnoteSectionNode);
904
+ for (const s of sections) s.remove();
905
+ });
906
+ pendingUpdateRef.current = false;
907
+ });
908
+ return;
909
+ }
910
+ if (footnoteNodes.length > 0 && sectionNodes.length === 0) {
911
+ const seenSnapshot = [...seen];
912
+ pendingUpdateRef.current = true;
913
+ queueMicrotask(() => {
914
+ editor.update(() => {
915
+ const root = $getRoot();
916
+ const defs = {};
917
+ for (const id of seenSnapshot) {
918
+ defs[id] = "";
919
+ }
920
+ const section = $parseSerializedNode({
921
+ type: "footnote-section",
922
+ definitions: defs,
923
+ version: 1
924
+ });
925
+ root.append(section);
926
+ });
927
+ pendingUpdateRef.current = false;
928
+ });
929
+ } else if (sectionNodes.length > 0) {
930
+ const existingDefs = sectionNodes[0].getDefinitions();
931
+ const missingIds = [...seen].filter((id) => !(id in existingDefs));
932
+ const orphanIds = Object.keys(existingDefs).filter(
933
+ (id) => !seen.has(id)
934
+ );
935
+ if (missingIds.length > 0 || orphanIds.length > 0) {
936
+ pendingUpdateRef.current = true;
937
+ queueMicrotask(() => {
938
+ editor.update(() => {
939
+ const freshSections = $nodesOfType(FootnoteSectionNode);
940
+ if (freshSections.length > 0) {
941
+ for (const id of missingIds) {
942
+ freshSections[0].setDefinition(id, "");
943
+ }
944
+ for (const id of orphanIds) {
945
+ freshSections[0].removeDefinition(id);
946
+ }
947
+ }
948
+ });
949
+ pendingUpdateRef.current = false;
950
+ });
951
+ }
952
+ }
953
+ });
954
+ });
955
+ }, [editor]);
956
+ return /* @__PURE__ */ jsx(
957
+ FootnoteDefinitionsProvider,
958
+ {
959
+ definitions,
960
+ displayNumberMap,
961
+ children
962
+ }
963
+ );
964
+ }
611
965
  function HorizontalRulePlugin() {
612
966
  const [editor] = useLexicalComposerContext();
613
967
  useEffect(() => {
@@ -695,7 +1049,6 @@ const GIT_ALERT_TRANSFORMER = {
695
1049
  replace: (parentNode, children, match) => {
696
1050
  const typeKey = match[1];
697
1051
  const alertType = ALERT_TYPE_MAP[typeKey] || "note";
698
- const alertNode = $createAlertQuoteNode(alertType);
699
1052
  const serializedChildren = children.map((child) => child.exportJSON());
700
1053
  const content = {
701
1054
  root: {
@@ -718,8 +1071,7 @@ const GIT_ALERT_TRANSFORMER = {
718
1071
  version: 1
719
1072
  }
720
1073
  };
721
- const editorState = alertNode.getContentEditor().parseEditorState(content);
722
- alertNode.getContentEditor().setEditorState(editorState);
1074
+ const alertNode = $createAlertQuoteEditNode(alertType, content);
723
1075
  parentNode.replace(alertNode);
724
1076
  }
725
1077
  };
@@ -744,7 +1096,6 @@ const CONTAINER_TRANSFORMER = {
744
1096
  const params = match[2];
745
1097
  if (type in BANNER_TYPE_MAP) {
746
1098
  const bannerType = BANNER_TYPE_MAP[type];
747
- const banner = $createBannerNode(bannerType);
748
1099
  const serializedChildren = children.map(
749
1100
  (child) => child.exportJSON()
750
1101
  );
@@ -769,8 +1120,7 @@ const CONTAINER_TRANSFORMER = {
769
1120
  version: 1
770
1121
  }
771
1122
  };
772
- const editorState = banner.getContentEditor().parseEditorState(content);
773
- banner.getContentEditor().setEditorState(editorState);
1123
+ const banner = $createBannerEditNode(bannerType, content);
774
1124
  parentNode.replace(banner);
775
1125
  return;
776
1126
  }
@@ -854,11 +1204,7 @@ const GRID_CONTAINER_BLOCK_TRANSFORMER = {
854
1204
  dependencies: [],
855
1205
  export: (node) => {
856
1206
  if (!$isGridContainerNode(node)) return null;
857
- const cells = node.getCellEditors().map(
858
- (editor) => editor.getEditorState().read(() => {
859
- return $getRoot().getTextContent();
860
- })
861
- );
1207
+ const cells = node.getCellStates().map((state) => extractTextContent(state));
862
1208
  const body = cells.map((content) => `::: cell
863
1209
  ${content}
864
1210
  :::`).join("\n");
@@ -886,6 +1232,8 @@ const ALL_TRANSFORMERS = [
886
1232
  MENTION_TRANSFORMER,
887
1233
  FOOTNOTE_TRANSFORMER,
888
1234
  INSERT_TRANSFORMER,
1235
+ SUPERSCRIPT_TRANSFORMER,
1236
+ SUBSCRIPT_TRANSFORMER,
889
1237
  KATEX_INLINE_TRANSFORMER,
890
1238
  // Block transformers (order matters - more specific first)
891
1239
  FOOTNOTE_SECTION_TRANSFORMER,
@@ -1090,15 +1438,17 @@ function RichEditor({
1090
1438
  }
1091
1439
  export {
1092
1440
  ALL_TRANSFORMERS as A,
1093
- FootnoteSectionEditNode as F,
1441
+ FootnotePlugin as F,
1094
1442
  INSERT_ALERT_COMMAND as I,
1443
+ NESTED_EDITOR_NODES as N,
1095
1444
  RichEditor as R,
1096
1445
  allEditNodes as a,
1097
- INSERT_IMAGE_COMMAND as b,
1446
+ FootnoteSectionEditNode as b,
1098
1447
  customEditNodes as c,
1099
- INSERT_KATEX_BLOCK_COMMAND as d,
1100
- INSERT_KATEX_INLINE_COMMAND as e,
1101
- INSERT_MERMAID_COMMAND as f,
1448
+ INSERT_IMAGE_COMMAND as d,
1449
+ INSERT_KATEX_BLOCK_COMMAND as e,
1450
+ INSERT_KATEX_INLINE_COMMAND as f,
1102
1451
  getResolvedEditNodes as g,
1452
+ INSERT_MERMAID_COMMAND as h,
1103
1453
  setResolvedEditNodes as s
1104
1454
  };
@@ -1 +1 @@
1
- {"version":3,"file":"GridEditDecorator.d.ts","sourceRoot":"","sources":["../../../src/components/decorators/GridEditDecorator.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAO5C,UAAU,sBAAsB;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,EAAE,aAAa,EAAE,CAAA;CAC7B;AAID,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,IAAI,EAAE,WAAW,EACjB,GAAG,EACH,WAAW,GACZ,EAAE,sBAAsB,+BAyHxB"}
1
+ {"version":3,"file":"GridEditDecorator.d.ts","sourceRoot":"","sources":["../../../src/components/decorators/GridEditDecorator.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAQ5C,UAAU,sBAAsB;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,EAAE,aAAa,EAAE,CAAA;CAC7B;AAID,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,IAAI,EAAE,WAAW,EACjB,GAAG,EACH,WAAW,GACZ,EAAE,sBAAsB,+BAyHxB"}
@@ -0,0 +1,9 @@
1
+ import { SerializedEditorState } from 'lexical';
2
+ import { AlertType } from '../../nodes/AlertQuoteNode';
3
+ interface AlertStaticDecoratorProps {
4
+ alertType: AlertType;
5
+ contentState: SerializedEditorState;
6
+ }
7
+ export declare function AlertStaticDecorator({ alertType, contentState, }: AlertStaticDecoratorProps): import("react").JSX.Element;
8
+ export {};
9
+ //# sourceMappingURL=AlertStaticDecorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AlertStaticDecorator.d.ts","sourceRoot":"","sources":["../../../src/components/renderers/AlertStaticDecorator.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAGpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAI3D,UAAU,yBAAyB;IACjC,SAAS,EAAE,SAAS,CAAA;IACpB,YAAY,EAAE,qBAAqB,CAAA;CACpC;AAED,wBAAgB,oBAAoB,CAAC,EACnC,SAAS,EACT,YAAY,GACb,EAAE,yBAAyB,+BAa3B"}