@haklex/rich-editor 0.0.80 → 0.0.82

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 (35) hide show
  1. package/dist/AlertQuoteEditNode-BDoonB4u.js +267 -0
  2. package/dist/KaTeXRenderer-BsyRH5_t.js +214 -0
  3. package/dist/LinkCardRenderer-OEMBDUhD.js +45 -0
  4. package/dist/MermaidPlugin-Df2Cm2yX.js +67 -0
  5. package/dist/PresentDialogContext-DQw6MrNh.js +59 -0
  6. package/dist/RubyRenderer-BpDb_amz.js +14 -0
  7. package/dist/SubmitShortcutPlugin-6IvsbZD-.js +1463 -0
  8. package/dist/commands-entry.mjs +14 -23
  9. package/dist/config-tfg1FWhG.js +1149 -0
  10. package/dist/context/NestedContentRendererContext.d.ts +2 -1
  11. package/dist/context/NestedContentRendererContext.d.ts.map +1 -1
  12. package/dist/favicon-DIWusrrw.js +41 -0
  13. package/dist/index.mjs +259 -284
  14. package/dist/node-registry-CeVi2y9f.js +666 -0
  15. package/dist/nodes-entry.mjs +7 -47
  16. package/dist/plugins-entry.mjs +10 -27
  17. package/dist/renderers-entry.mjs +40 -57
  18. package/dist/rich-editor.css +2 -1
  19. package/dist/shared.css-wgGgtK_e.js +23 -0
  20. package/dist/static-entry.mjs +16 -45
  21. package/dist/styles-entry.mjs +3 -12
  22. package/dist/theme-DHOUKKSr.js +1034 -0
  23. package/package.json +4 -4
  24. package/dist/AlertQuoteEditNode-CHdvQnOr.js +0 -293
  25. package/dist/KaTeXRenderer-C8jv_5xr.js +0 -214
  26. package/dist/LinkCardRenderer-QmkOlyXb.js +0 -36
  27. package/dist/MermaidPlugin-DjLUVZvB.js +0 -97
  28. package/dist/PresentDialogContext-BpSB8tXC.js +0 -52
  29. package/dist/RubyRenderer-DbeobSoH.js +0 -13
  30. package/dist/SubmitShortcutPlugin-BFBAwTb1.js +0 -1627
  31. package/dist/config-DcR_yktp.js +0 -1236
  32. package/dist/favicon-BQgbXF_a.js +0 -43
  33. package/dist/node-registry-B2U2_LrI.js +0 -766
  34. package/dist/shared.css-DNuMYx6Q.js +0 -21
  35. package/dist/theme-CYsyGmCL.js +0 -1040
@@ -0,0 +1,666 @@
1
+ import { A as _defineProperty, S as ImageNode, T as FootnoteNode, g as KaTeXInlineNode, i as TagNode, p as MentionNode, s as SpoilerNode, t as editorTheme, u as MermaidNode, y as KaTeXBlockNode } from "./theme-DHOUKKSr.js";
2
+ import { l as RendererWrapper, s as useFootnoteDefinitions } from "./KaTeXRenderer-BsyRH5_t.js";
3
+ import { D as BannerNode, O as normalizeBannerType, b as CodeBlockNode, f as $isGridContainerNode, g as FootnoteSectionNode, i as VideoNode, k as BannerRenderer, n as builtinNodes, p as GridContainerNode, s as RubyNode, u as LinkCardNode, v as DetailsNode, w as $isBannerNode, x as CodeBlockRenderer, y as $isCodeBlockNode } from "./config-tfg1FWhG.js";
4
+ import { n as AlertQuoteEditNode, r as NESTED_EDITOR_NODES } from "./AlertQuoteEditNode-BDoonB4u.js";
5
+ import { LinkPlugin } from "@lexical/react/LexicalLinkPlugin";
6
+ import { ListPlugin } from "@lexical/react/LexicalListPlugin";
7
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
8
+ import { createElement, useCallback, useEffect, useState } from "react";
9
+ import { $createNodeSelection, $createParagraphNode, $getNodeByKey, $getRoot, $getSelection, $insertNodes, $isDecoratorNode, $isElementNode, $isNodeSelection, $nodesOfType, $setSelection, createEditor } from "lexical";
10
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
+ import { Flag, LayoutGrid, Minus, Plus } from "lucide-react";
12
+ import { ContentEditable } from "@lexical/react/LexicalContentEditable";
13
+ import { LexicalErrorBoundary } from "@lexical/react/LexicalErrorBoundary";
14
+ import { LexicalNestedComposer } from "@lexical/react/LexicalNestedComposer";
15
+ import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
16
+ import { useLexicalNodeSelection } from "@lexical/react/useLexicalNodeSelection";
17
+ //#region src/utils/codeBlockSelectionIntent.ts
18
+ var codeBlockCursorIntentMap = /* @__PURE__ */ new Map();
19
+ function setCodeBlockCursorIntent(nodeKey, placement) {
20
+ codeBlockCursorIntentMap.set(nodeKey, placement);
21
+ }
22
+ function consumeCodeBlockCursorIntent(nodeKey) {
23
+ const placement = codeBlockCursorIntentMap.get(nodeKey);
24
+ if (!placement) return null;
25
+ codeBlockCursorIntentMap.delete(nodeKey);
26
+ return placement;
27
+ }
28
+ //#endregion
29
+ //#region src/components/decorators/BannerEditDecorator.tsx
30
+ function BannerEditDecorator({ nodeKey, bannerType, contentEditor }) {
31
+ const [editor] = useLexicalComposerContext();
32
+ const editable = editor.isEditable();
33
+ const handleTypeChange = useCallback((newType) => {
34
+ editor.update(() => {
35
+ const node = $getNodeByKey(nodeKey);
36
+ if ($isBannerNode(node)) node.setBannerType(newType);
37
+ });
38
+ }, [editor, nodeKey]);
39
+ return /* @__PURE__ */ jsxs("div", {
40
+ className: "rich-banner-inner",
41
+ children: [/* @__PURE__ */ jsx(RendererWrapper, {
42
+ defaultRenderer: BannerRenderer,
43
+ rendererKey: "Banner",
44
+ props: {
45
+ type: bannerType,
46
+ editable,
47
+ onTypeChange: editable ? handleTypeChange : void 0
48
+ }
49
+ }), /* @__PURE__ */ jsx("div", {
50
+ className: "rich-banner-content",
51
+ children: /* @__PURE__ */ jsxs(LexicalNestedComposer, {
52
+ initialEditor: contentEditor,
53
+ children: [
54
+ /* @__PURE__ */ jsx(RichTextPlugin, {
55
+ ErrorBoundary: LexicalErrorBoundary,
56
+ contentEditable: /* @__PURE__ */ jsx(ContentEditable, {
57
+ "aria-placeholder": "",
58
+ className: "rich-banner-content-editable",
59
+ placeholder: /* @__PURE__ */ jsx("span", { style: { display: "none" } }),
60
+ style: { outline: "none" }
61
+ })
62
+ }),
63
+ /* @__PURE__ */ jsx(ListPlugin, {}),
64
+ /* @__PURE__ */ jsx(LinkPlugin, {})
65
+ ]
66
+ })
67
+ })]
68
+ });
69
+ }
70
+ //#endregion
71
+ //#region src/nodes/BannerEditNode.ts
72
+ function createContentEditor() {
73
+ return createEditor({
74
+ namespace: "BannerContent",
75
+ nodes: NESTED_EDITOR_NODES,
76
+ theme: editorTheme,
77
+ onError: (error) => {
78
+ console.error("[BannerContent]", error);
79
+ }
80
+ });
81
+ }
82
+ var BannerEditNode = class BannerEditNode extends BannerNode {
83
+ static clone(node) {
84
+ const cloned = new BannerEditNode(node.__bannerType, node.__contentState, node.__key);
85
+ cloned.__contentEditor = node.__contentEditor;
86
+ return cloned;
87
+ }
88
+ constructor(bannerType, contentState, key) {
89
+ super(bannerType, contentState, key);
90
+ _defineProperty(this, "__contentEditor", void 0);
91
+ this.__contentEditor = createContentEditor();
92
+ if (contentState) {
93
+ const editorState = this.__contentEditor.parseEditorState(contentState);
94
+ this.__contentEditor.setEditorState(editorState);
95
+ }
96
+ }
97
+ getContentEditor() {
98
+ return this.__contentEditor;
99
+ }
100
+ static importJSON(serializedNode) {
101
+ const legacy = serializedNode;
102
+ const bannerType = normalizeBannerType(serializedNode.bannerType);
103
+ if (serializedNode.content) return new BannerEditNode(bannerType, serializedNode.content);
104
+ if (legacy.children) return new BannerEditNode(bannerType, { root: {
105
+ children: legacy.children,
106
+ direction: null,
107
+ format: "",
108
+ indent: 0,
109
+ type: "root",
110
+ version: 1
111
+ } });
112
+ return new BannerEditNode(bannerType);
113
+ }
114
+ exportJSON() {
115
+ return {
116
+ ...super.exportJSON(),
117
+ type: "banner",
118
+ bannerType: this.__bannerType,
119
+ content: this.__contentEditor.getEditorState().toJSON(),
120
+ version: 1
121
+ };
122
+ }
123
+ decorate(_editor, _config) {
124
+ return createElement(BannerEditDecorator, {
125
+ nodeKey: this.__key,
126
+ bannerType: this.__bannerType,
127
+ contentEditor: this.__contentEditor
128
+ });
129
+ }
130
+ };
131
+ _defineProperty(BannerEditNode, "commandItems", [{
132
+ title: "Banner",
133
+ icon: createElement(Flag, { size: 20 }),
134
+ description: "Highlighted banner block",
135
+ keywords: [
136
+ "banner",
137
+ "notice",
138
+ "announcement"
139
+ ],
140
+ section: "ADVANCED",
141
+ placement: ["slash", "toolbar"],
142
+ group: "insert",
143
+ onSelect: (editor) => {
144
+ editor.update(() => {
145
+ $insertNodes([$createBannerEditNode("note")]);
146
+ });
147
+ }
148
+ }]);
149
+ function $createBannerEditNode(bannerType, contentState) {
150
+ return new BannerEditNode(bannerType, contentState);
151
+ }
152
+ //#endregion
153
+ //#region src/components/decorators/CodeBlockEditDecorator.tsx
154
+ function CodeBlockEditDecorator({ nodeKey, code, language }) {
155
+ const [editor] = useLexicalComposerContext();
156
+ const [isSelected] = useLexicalNodeSelection(nodeKey);
157
+ const [shouldFocusEditor, setShouldFocusEditor] = useState(false);
158
+ const [cursorPlacement, setCursorPlacement] = useState("start");
159
+ const editable = editor.isEditable();
160
+ useEffect(() => {
161
+ if (!editable || !isSelected) {
162
+ setShouldFocusEditor(false);
163
+ return;
164
+ }
165
+ let nextShouldFocus = false;
166
+ let nextCursorPlacement = "start";
167
+ editor.getEditorState().read(() => {
168
+ const selection = $getSelection();
169
+ const selectedNodes = $isNodeSelection(selection) ? selection.getNodes() : null;
170
+ nextShouldFocus = selectedNodes !== null && selectedNodes.length === 1 && selectedNodes[0]?.getKey() === nodeKey;
171
+ if (nextShouldFocus) nextCursorPlacement = consumeCodeBlockCursorIntent(nodeKey) ?? "start";
172
+ });
173
+ setShouldFocusEditor(nextShouldFocus);
174
+ if (nextShouldFocus) setCursorPlacement(nextCursorPlacement);
175
+ }, [
176
+ editable,
177
+ editor,
178
+ isSelected,
179
+ nodeKey
180
+ ]);
181
+ const handleCodeChange = useCallback((newCode) => {
182
+ editor.update(() => {
183
+ const node = $getNodeByKey(nodeKey);
184
+ if ($isCodeBlockNode(node)) node.setCode(newCode);
185
+ });
186
+ }, [editor, nodeKey]);
187
+ const handleLanguageChange = useCallback((newLanguage) => {
188
+ editor.update(() => {
189
+ const node = $getNodeByKey(nodeKey);
190
+ if ($isCodeBlockNode(node)) node.setLanguage(newLanguage);
191
+ });
192
+ }, [editor, nodeKey]);
193
+ const handleDelete = useCallback(() => {
194
+ editor.getRootElement()?.focus({ preventScroll: true });
195
+ editor.update(() => {
196
+ const node = $getNodeByKey(nodeKey);
197
+ if (!node) return;
198
+ const prev = node.getPreviousSibling();
199
+ const next = node.getNextSibling();
200
+ const parent = node.getParent();
201
+ node.remove();
202
+ if (prev) {
203
+ if ($isElementNode(prev)) prev.selectEnd();
204
+ else {
205
+ if ($isDecoratorNode(prev) && prev.getType() === "code-block") setCodeBlockCursorIntent(prev.getKey(), "end");
206
+ const selection = $createNodeSelection();
207
+ selection.add(prev.getKey());
208
+ $setSelection(selection);
209
+ }
210
+ return;
211
+ }
212
+ if (next) {
213
+ if ($isElementNode(next)) next.selectStart();
214
+ else {
215
+ if ($isDecoratorNode(next) && next.getType() === "code-block") setCodeBlockCursorIntent(next.getKey(), "start");
216
+ const selection = $createNodeSelection();
217
+ selection.add(next.getKey());
218
+ $setSelection(selection);
219
+ }
220
+ return;
221
+ }
222
+ if (parent) {
223
+ const p = $createParagraphNode();
224
+ parent.append(p);
225
+ p.selectStart();
226
+ }
227
+ });
228
+ }, [editor, nodeKey]);
229
+ const handleExitBlock = useCallback((direction) => {
230
+ editor.getRootElement()?.focus({ preventScroll: true });
231
+ editor.update(() => {
232
+ const node = $getNodeByKey(nodeKey);
233
+ if (!node) return;
234
+ if (direction === "before") {
235
+ const prev = node.getPreviousSibling();
236
+ if (!prev) return;
237
+ if ($isElementNode(prev)) prev.selectEnd();
238
+ else {
239
+ if ($isDecoratorNode(prev) && prev.getType() === "code-block") setCodeBlockCursorIntent(prev.getKey(), "end");
240
+ const selection = $createNodeSelection();
241
+ selection.add(prev.getKey());
242
+ $setSelection(selection);
243
+ }
244
+ return;
245
+ }
246
+ let next = node.getNextSibling();
247
+ if (!next) {
248
+ const p = $createParagraphNode();
249
+ node.insertAfter(p);
250
+ next = p;
251
+ }
252
+ if ($isElementNode(next)) next.selectStart();
253
+ else {
254
+ if ($isDecoratorNode(next) && next.getType() === "code-block") setCodeBlockCursorIntent(next.getKey(), "start");
255
+ const selection = $createNodeSelection();
256
+ selection.add(next.getKey());
257
+ $setSelection(selection);
258
+ }
259
+ });
260
+ }, [editor, nodeKey]);
261
+ return /* @__PURE__ */ jsx(RendererWrapper, {
262
+ defaultRenderer: CodeBlockRenderer,
263
+ rendererKey: "CodeBlock",
264
+ props: {
265
+ code,
266
+ language,
267
+ editable,
268
+ onCodeChange: editable ? handleCodeChange : void 0,
269
+ onLanguageChange: editable ? handleLanguageChange : void 0,
270
+ onDelete: editable ? handleDelete : void 0,
271
+ onExitBlock: editable ? handleExitBlock : void 0,
272
+ selected: editable ? shouldFocusEditor : false,
273
+ cursorPlacement: editable ? cursorPlacement : "start"
274
+ }
275
+ });
276
+ }
277
+ //#endregion
278
+ //#region src/nodes/CodeBlockEditNode.ts
279
+ var _CodeBlockEditNode;
280
+ var CodeBlockEditNode = class CodeBlockEditNode extends CodeBlockNode {
281
+ static clone(node) {
282
+ return new CodeBlockEditNode(node.__code, node.__language, node.__key);
283
+ }
284
+ static importJSON(serializedNode) {
285
+ return new CodeBlockEditNode(serializedNode.code, serializedNode.language);
286
+ }
287
+ decorate(_editor, _config) {
288
+ return createElement(CodeBlockEditDecorator, {
289
+ nodeKey: this.__key,
290
+ code: this.__code,
291
+ language: this.__language
292
+ });
293
+ }
294
+ };
295
+ _CodeBlockEditNode = CodeBlockEditNode;
296
+ _defineProperty(CodeBlockEditNode, "commandItems", CodeBlockNode.commandItems.map((item) => ({
297
+ ...item,
298
+ onSelect: (editor) => {
299
+ editor.update(() => {
300
+ $insertNodes([new _CodeBlockEditNode("", "text")]);
301
+ });
302
+ }
303
+ })));
304
+ function $createCodeBlockEditNode(code, language) {
305
+ return new CodeBlockEditNode(code, language);
306
+ }
307
+ //#endregion
308
+ //#region src/components/renderers/FootnoteSectionEditRenderer.tsx
309
+ function FootnoteSectionEditRenderer({ definitions }) {
310
+ const [editor] = useLexicalComposerContext();
311
+ const { displayNumberMap } = useFootnoteDefinitions();
312
+ const sortedEntries = Object.entries(definitions).sort(([a], [b]) => (displayNumberMap[a] ?? 0) - (displayNumberMap[b] ?? 0));
313
+ const handleContentChange = useCallback((identifier, newContent) => {
314
+ editor.update(() => {
315
+ const sectionNodes = $nodesOfType(FootnoteSectionNode);
316
+ if (sectionNodes.length > 0) sectionNodes[0].setDefinition(identifier, newContent);
317
+ });
318
+ }, [editor]);
319
+ const handleRemove = useCallback((identifier) => {
320
+ editor.update(() => {
321
+ const sectionNodes = $nodesOfType(FootnoteSectionNode);
322
+ if (sectionNodes.length > 0) sectionNodes[0].removeDefinition(identifier);
323
+ });
324
+ }, [editor]);
325
+ if (sortedEntries.length === 0) return null;
326
+ return /* @__PURE__ */ jsxs("div", {
327
+ className: "rich-footnote-section-content rich-footnote-section-edit",
328
+ role: "doc-endnotes",
329
+ children: [/* @__PURE__ */ jsx("hr", { className: "rich-footnote-section-divider" }), /* @__PURE__ */ jsx("ol", {
330
+ className: "rich-footnote-section-list",
331
+ children: sortedEntries.map(([identifier, content]) => {
332
+ const displayNum = displayNumberMap[identifier] ?? identifier;
333
+ return /* @__PURE__ */ jsxs("li", {
334
+ className: "rich-footnote-section-item rich-footnote-section-item-edit",
335
+ id: `footnote-${identifier}`,
336
+ children: [
337
+ /* @__PURE__ */ jsxs("span", {
338
+ className: "rich-footnote-section-item-num",
339
+ children: [displayNum, "."]
340
+ }),
341
+ /* @__PURE__ */ jsx("input", {
342
+ className: "rich-footnote-section-item-input",
343
+ placeholder: `Footnote content for [^${identifier}]`,
344
+ type: "text",
345
+ value: content,
346
+ onChange: (e) => handleContentChange(identifier, e.target.value)
347
+ }),
348
+ /* @__PURE__ */ jsx("button", {
349
+ "aria-label": `Remove footnote ${identifier}`,
350
+ className: "rich-footnote-section-item-remove",
351
+ type: "button",
352
+ onClick: () => handleRemove(identifier),
353
+ children: "×"
354
+ })
355
+ ]
356
+ }, identifier);
357
+ })
358
+ })]
359
+ });
360
+ }
361
+ //#endregion
362
+ //#region src/nodes/FootnoteSectionEditNode.ts
363
+ var FootnoteSectionEditNode = class FootnoteSectionEditNode extends FootnoteSectionNode {
364
+ static getType() {
365
+ return "footnote-section";
366
+ }
367
+ static clone(node) {
368
+ return new FootnoteSectionEditNode({ ...node.__definitions }, node.__key);
369
+ }
370
+ static importJSON(serializedNode) {
371
+ return new FootnoteSectionEditNode(serializedNode.definitions);
372
+ }
373
+ decorate(_editor, _config) {
374
+ return createElement(FootnoteSectionEditRenderer, {
375
+ definitions: this.__definitions,
376
+ nodeKey: this.__key
377
+ });
378
+ }
379
+ };
380
+ //#endregion
381
+ //#region src/components/decorators/GridEditDecorator.tsx
382
+ var COL_OPTIONS = [
383
+ 1,
384
+ 2,
385
+ 3,
386
+ 4
387
+ ];
388
+ function GridEditDecorator({ nodeKey, cols: initialCols, gap, cellEditors }) {
389
+ const [editor] = useLexicalComposerContext();
390
+ const [currentCols, setCurrentCols] = useState(initialCols);
391
+ useEffect(() => {
392
+ return editor.registerUpdateListener(({ editorState }) => {
393
+ editorState.read(() => {
394
+ const node = $getNodeByKey(nodeKey);
395
+ if ($isGridContainerNode(node)) setCurrentCols(node.getCols());
396
+ });
397
+ });
398
+ }, [editor, nodeKey]);
399
+ const handleSetCols = useCallback((cols) => {
400
+ editor.update(() => {
401
+ const node = $getNodeByKey(nodeKey);
402
+ if ($isGridContainerNode(node)) node.setCols(cols);
403
+ });
404
+ }, [editor, nodeKey]);
405
+ const handleAddRow = useCallback(() => {
406
+ editor.update(() => {
407
+ const node = $getNodeByKey(nodeKey);
408
+ if ($isGridContainerNode(node)) node.addCells(node.getCols());
409
+ });
410
+ }, [editor, nodeKey]);
411
+ const handleRemoveRow = useCallback(() => {
412
+ editor.update(() => {
413
+ const node = $getNodeByKey(nodeKey);
414
+ if (!$isGridEditNode(node)) return;
415
+ const cols = node.getCols();
416
+ const editors = node.getCellEditors();
417
+ if (editors.length <= cols) return;
418
+ if (!editors.slice(-cols).every((cellEditor) => cellEditor.getEditorState().read(() => $getRoot().getTextContentSize() === 0))) return;
419
+ node.removeCells(cols);
420
+ });
421
+ }, [editor, nodeKey]);
422
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
423
+ className: "rich-grid-toolbar",
424
+ onMouseDown: (e) => e.preventDefault(),
425
+ children: [
426
+ /* @__PURE__ */ jsx("span", {
427
+ className: "rich-grid-toolbar-icon",
428
+ children: /* @__PURE__ */ jsx(LayoutGrid, { size: 14 })
429
+ }),
430
+ COL_OPTIONS.map((n) => /* @__PURE__ */ jsx("button", {
431
+ "aria-label": `${n} columns`,
432
+ className: `rich-grid-col-btn${n === currentCols ? " rich-grid-col-btn-active" : ""}`,
433
+ type: "button",
434
+ onClick: () => handleSetCols(n),
435
+ children: n
436
+ }, n)),
437
+ /* @__PURE__ */ jsx("div", { className: "rich-grid-toolbar-divider" }),
438
+ /* @__PURE__ */ jsx("button", {
439
+ "aria-label": "Add row",
440
+ className: "rich-grid-action-btn",
441
+ type: "button",
442
+ onClick: handleAddRow,
443
+ children: /* @__PURE__ */ jsx(Plus, { size: 14 })
444
+ }),
445
+ /* @__PURE__ */ jsx("button", {
446
+ "aria-label": "Remove row",
447
+ className: "rich-grid-action-btn",
448
+ type: "button",
449
+ onClick: handleRemoveRow,
450
+ children: /* @__PURE__ */ jsx(Minus, { size: 14 })
451
+ })
452
+ ]
453
+ }), /* @__PURE__ */ jsx("div", {
454
+ className: "rich-grid-inner",
455
+ style: {
456
+ gridTemplateColumns: `repeat(${currentCols}, 1fr)`,
457
+ gap
458
+ },
459
+ children: cellEditors.map((cellEditor, i) => /* @__PURE__ */ jsx("div", {
460
+ className: "rich-grid-cell",
461
+ children: /* @__PURE__ */ jsxs(LexicalNestedComposer, {
462
+ initialEditor: cellEditor,
463
+ children: [
464
+ /* @__PURE__ */ jsx(RichTextPlugin, {
465
+ ErrorBoundary: LexicalErrorBoundary,
466
+ contentEditable: /* @__PURE__ */ jsx(ContentEditable, {
467
+ "aria-placeholder": "",
468
+ className: "rich-grid-cell-editable",
469
+ placeholder: /* @__PURE__ */ jsx("span", { style: { display: "none" } })
470
+ })
471
+ }),
472
+ /* @__PURE__ */ jsx(ListPlugin, {}),
473
+ /* @__PURE__ */ jsx(LinkPlugin, {})
474
+ ]
475
+ })
476
+ }, i))
477
+ })] });
478
+ }
479
+ //#endregion
480
+ //#region src/nodes/GridEditNode.ts
481
+ function createCellEditor() {
482
+ return createEditor({
483
+ namespace: "GridCell",
484
+ nodes: NESTED_EDITOR_NODES,
485
+ theme: editorTheme,
486
+ onError: (error) => {
487
+ console.error("[GridCell]", error);
488
+ }
489
+ });
490
+ }
491
+ var GridEditNode = class GridEditNode extends GridContainerNode {
492
+ static clone(node) {
493
+ const cloned = new GridEditNode(node.__cols, node.__gap, node.__cellStates, node.__key);
494
+ cloned.__cellEditors = [...node.__cellEditors];
495
+ return cloned;
496
+ }
497
+ constructor(cols = 2, gap, cellStates, key) {
498
+ super(cols, gap, cellStates, key);
499
+ _defineProperty(this, "__cellEditors", void 0);
500
+ this.__cellEditors = this.__cellStates.map((state) => {
501
+ const editor = createCellEditor();
502
+ const editorState = editor.parseEditorState(state);
503
+ editor.setEditorState(editorState);
504
+ return editor;
505
+ });
506
+ }
507
+ getCellEditors() {
508
+ return this.getLatest().__cellEditors;
509
+ }
510
+ setCols(cols) {
511
+ const writable = this.getWritable();
512
+ const prev = writable.__cellEditors.length;
513
+ writable.__cols = cols;
514
+ if (cols > prev) for (let i = prev; i < cols; i++) {
515
+ const editor = createCellEditor();
516
+ writable.__cellEditors.push(editor);
517
+ writable.__cellStates.push({ root: {
518
+ children: [{
519
+ type: "paragraph",
520
+ children: [],
521
+ direction: null,
522
+ format: "",
523
+ indent: 0,
524
+ textFormat: 0,
525
+ textStyle: "",
526
+ version: 1
527
+ }],
528
+ direction: null,
529
+ format: "",
530
+ indent: 0,
531
+ type: "root",
532
+ version: 1
533
+ } });
534
+ }
535
+ }
536
+ addCells(count) {
537
+ const writable = this.getWritable();
538
+ for (let i = 0; i < count; i++) {
539
+ const editor = createCellEditor();
540
+ writable.__cellEditors.push(editor);
541
+ writable.__cellStates.push({ root: {
542
+ children: [{
543
+ type: "paragraph",
544
+ children: [],
545
+ direction: null,
546
+ format: "",
547
+ indent: 0,
548
+ textFormat: 0,
549
+ textStyle: "",
550
+ version: 1
551
+ }],
552
+ direction: null,
553
+ format: "",
554
+ indent: 0,
555
+ type: "root",
556
+ version: 1
557
+ } });
558
+ }
559
+ }
560
+ removeCells(count) {
561
+ const writable = this.getWritable();
562
+ const editors = writable.__cellEditors;
563
+ const states = writable.__cellStates;
564
+ const toRemove = Math.min(count, editors.length);
565
+ for (let i = 0; i < toRemove; i++) {
566
+ const editor = editors.at(-1);
567
+ if (!editor) break;
568
+ if (!editor.getEditorState().read(() => {
569
+ return $getRoot().getTextContentSize() === 0;
570
+ })) break;
571
+ editors.pop();
572
+ states.pop();
573
+ }
574
+ }
575
+ static importJSON(serializedNode) {
576
+ const legacy = serializedNode;
577
+ const cols = legacy.cols || 2;
578
+ const rawGap = legacy.gap;
579
+ const gap = typeof rawGap === "number" ? `${rawGap}px` : rawGap;
580
+ if (legacy.cells && legacy.cells.length > 0) return new GridEditNode(cols, gap, legacy.cells);
581
+ if (legacy.children) return new GridEditNode(cols, gap, legacy.children.map((child) => {
582
+ return { root: {
583
+ children: [child],
584
+ direction: null,
585
+ format: "",
586
+ indent: 0,
587
+ type: "root",
588
+ version: 1
589
+ } };
590
+ }));
591
+ return new GridEditNode(cols, gap);
592
+ }
593
+ exportJSON() {
594
+ return {
595
+ ...super.exportJSON(),
596
+ type: "grid-container",
597
+ cols: this.__cols,
598
+ gap: this.__gap,
599
+ cells: this.__cellEditors.map((editor) => editor.getEditorState().toJSON()),
600
+ version: 1
601
+ };
602
+ }
603
+ decorate(_editor, _config) {
604
+ return createElement(GridEditDecorator, {
605
+ nodeKey: this.__key,
606
+ cols: this.__cols,
607
+ gap: this.__gap,
608
+ cellEditors: this.__cellEditors
609
+ });
610
+ }
611
+ };
612
+ _defineProperty(GridEditNode, "slashMenuItems", [{
613
+ title: "Grid",
614
+ icon: createElement(LayoutGrid, { size: 20 }),
615
+ description: "Grid layout container",
616
+ keywords: [
617
+ "grid",
618
+ "columns",
619
+ "layout"
620
+ ],
621
+ section: "LAYOUT",
622
+ onSelect: (editor) => {
623
+ editor.update(() => {
624
+ $insertNodes([$createGridEditNode(2)]);
625
+ });
626
+ }
627
+ }]);
628
+ function $createGridEditNode(cols = 2, gap) {
629
+ return new GridEditNode(cols, gap);
630
+ }
631
+ function $isGridEditNode(node) {
632
+ return node instanceof GridEditNode;
633
+ }
634
+ //#endregion
635
+ //#region src/config-edit.ts
636
+ var customEditNodes = [
637
+ SpoilerNode,
638
+ MentionNode,
639
+ KaTeXInlineNode,
640
+ KaTeXBlockNode,
641
+ ImageNode,
642
+ AlertQuoteEditNode,
643
+ CodeBlockEditNode,
644
+ FootnoteNode,
645
+ FootnoteSectionEditNode,
646
+ VideoNode,
647
+ LinkCardNode,
648
+ DetailsNode,
649
+ GridEditNode,
650
+ BannerEditNode,
651
+ MermaidNode,
652
+ RubyNode,
653
+ TagNode
654
+ ];
655
+ var allEditNodes = [...builtinNodes, ...customEditNodes];
656
+ //#endregion
657
+ //#region src/node-registry.ts
658
+ var _resolvedEditNodes = null;
659
+ function setResolvedEditNodes(nodes) {
660
+ _resolvedEditNodes = nodes;
661
+ }
662
+ function getResolvedEditNodes() {
663
+ return _resolvedEditNodes ?? allEditNodes;
664
+ }
665
+ //#endregion
666
+ export { FootnoteSectionEditNode as a, setCodeBlockCursorIntent as c, customEditNodes as i, setResolvedEditNodes as n, $createCodeBlockEditNode as o, allEditNodes as r, $createBannerEditNode as s, getResolvedEditNodes as t };