@haklex/rich-ext-nested-doc 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,267 +1,273 @@
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);
4
- import { t as truncateEditorState, h as hasRenderableEditorState, d as dialogPopup, e as editOverlayRoot, r as rendererContent, p as previewSurface, N as NestedDocRenderer, a as previewEmpty, b as editOverlay, $ as $isNestedDocNode, c as dialogShell, f as dialogHeader, g as dialogHeaderLeft, i as dialogTitle, j as dialogHeaderRight, k as dialogHeaderCloseBtn, l as editorArea, m as dialogFooter, n as NestedDocNode } from "./transformer-CeHuyTaK.js";
5
- import { o, q, s } from "./transformer-CeHuyTaK.js";
6
- import { useColorScheme, editorTheme } from "@haklex/rich-editor";
1
+ import { C as rendererContent, S as previewSurface, _ as dialogTitle, a as _defineProperty, b as editorArea, c as truncateEditorState, d as dialogHeader, f as dialogHeaderCloseBtn, g as dialogShell, h as dialogPopup, i as NestedDocNode, l as NestedDocRenderer, m as dialogHeaderRight, n as $createNestedDocNode, o as NestedDocStaticDecorator, p as dialogHeaderLeft, r as $isNestedDocNode, s as hasRenderableEditorState, t as NESTED_DOC_BLOCK_TRANSFORMER, u as dialogFooter, v as editOverlay, x as previewEmpty, y as editOverlayRoot } from "./transformer-DtRgDFYm.js";
2
+ import { editorTheme, useColorScheme } from "@haklex/rich-editor";
7
3
  import { getResolvedEditNodes } from "@haklex/rich-editor/nodes";
8
- import { $getNodeByKey, $insertNodes, createEditor, createCommand, COMMAND_PRIORITY_EDITOR } from "lexical";
9
- import { Pencil, FileText, X } from "lucide-react";
10
- import { createContext, use, useMemo, useCallback, useRef, useState, createElement, useEffect } from "react";
11
- import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { $getNodeByKey, $insertNodes, COMMAND_PRIORITY_EDITOR, createCommand, createEditor } from "lexical";
5
+ import { FileText, Pencil, X } from "lucide-react";
6
+ import { createContext, createElement, use, useCallback, useEffect, useMemo, useRef, useState } from "react";
12
7
  import { ActionBar, ActionButton } from "@haklex/rich-editor-ui";
13
- import { usePortalTheme, PortalContainerProvider } from "@haklex/rich-style-token";
8
+ import { PortalContainerProvider, usePortalTheme } from "@haklex/rich-style-token";
14
9
  import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
15
- const NestedDocDialogEditorContext = createContext(null);
16
- const NestedDocDialogEditorProvider = NestedDocDialogEditorContext.Provider;
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ //#region src/NestedDocDialogEditorContext.tsx
12
+ var NestedDocDialogEditorContext = createContext(null);
13
+ var NestedDocDialogEditorProvider = NestedDocDialogEditorContext.Provider;
17
14
  function useNestedDocDialogEditor() {
18
- return use(NestedDocDialogEditorContext);
15
+ return use(NestedDocDialogEditorContext);
19
16
  }
20
- const PREVIEW_NODE_LIMIT = 6;
21
- const EMPTY_EDITOR_STATE = {
22
- root: {
23
- children: [
24
- {
25
- children: [],
26
- direction: "ltr",
27
- format: "",
28
- indent: 0,
29
- type: "paragraph",
30
- version: 1,
31
- textFormat: 0,
32
- textStyle: ""
33
- }
34
- ],
35
- direction: "ltr",
36
- format: "",
37
- indent: 0,
38
- type: "root",
39
- version: 1
40
- }
41
- };
42
- function NestedDocEditDecorator({
43
- nodeKey,
44
- contentEditor,
45
- contentState
46
- }) {
47
- const [editor] = useLexicalComposerContext();
48
- const colorScheme = useColorScheme();
49
- const { className: portalClassName } = usePortalTheme();
50
- const DialogEditor = useNestedDocDialogEditor();
51
- const previewState = useMemo(
52
- () => truncateEditorState(contentState, PREVIEW_NODE_LIMIT),
53
- [contentState]
54
- );
55
- const hasPreview = hasRenderableEditorState(previewState);
56
- const handleOpenDialog = useCallback(async () => {
57
- if (!DialogEditor) return;
58
- const { presentDialog } = await import("@haklex/rich-editor-ui");
59
- presentDialog({
60
- content: ({ dismiss }) => /* @__PURE__ */ jsx(
61
- NestedDocDialogContent,
62
- {
63
- DialogEditor,
64
- contentEditor,
65
- initialState: contentEditor.getEditorState().toJSON(),
66
- nodeKey,
67
- parentEditor: editor,
68
- onDismiss: dismiss
69
- }
70
- ),
71
- className: dialogPopup,
72
- portalClassName,
73
- theme: colorScheme,
74
- showCloseButton: false,
75
- clickOutsideToDismiss: false
76
- });
77
- }, [DialogEditor, colorScheme, contentEditor, editor, nodeKey, portalClassName]);
78
- return /* @__PURE__ */ jsxs(
79
- "div",
80
- {
81
- "aria-label": "Open nested document editor",
82
- className: editOverlayRoot,
83
- role: "button",
84
- tabIndex: 0,
85
- onClick: handleOpenDialog,
86
- onKeyDown: (event) => {
87
- if (event.key === "Enter" || event.key === " ") {
88
- event.preventDefault();
89
- handleOpenDialog();
90
- }
91
- },
92
- children: [
93
- /* @__PURE__ */ jsx("div", { className: `${rendererContent} rich-nested-doc-content`, children: hasPreview ? /* @__PURE__ */ jsx("div", { className: previewSurface, children: /* @__PURE__ */ jsx(NestedDocRenderer, { value: previewState }) }) : /* @__PURE__ */ jsx("p", { className: previewEmpty, children: "Empty nested document. Click to edit." }) }),
94
- /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: editOverlay, children: /* @__PURE__ */ jsx(Pencil, { size: 24 }) })
95
- ]
96
- }
97
- );
17
+ //#endregion
18
+ //#region src/NestedDocEditDecorator.tsx
19
+ var PREVIEW_NODE_LIMIT = 6;
20
+ var EMPTY_EDITOR_STATE = { root: {
21
+ children: [{
22
+ children: [],
23
+ direction: "ltr",
24
+ format: "",
25
+ indent: 0,
26
+ type: "paragraph",
27
+ version: 1,
28
+ textFormat: 0,
29
+ textStyle: ""
30
+ }],
31
+ direction: "ltr",
32
+ format: "",
33
+ indent: 0,
34
+ type: "root",
35
+ version: 1
36
+ } };
37
+ function NestedDocEditDecorator({ nodeKey, contentEditor, contentState }) {
38
+ const [editor] = useLexicalComposerContext();
39
+ const colorScheme = useColorScheme();
40
+ const { className: portalClassName } = usePortalTheme();
41
+ const DialogEditor = useNestedDocDialogEditor();
42
+ const previewState = useMemo(() => truncateEditorState(contentState, PREVIEW_NODE_LIMIT), [contentState]);
43
+ const hasPreview = hasRenderableEditorState(previewState);
44
+ const handleOpenDialog = useCallback(async () => {
45
+ if (!DialogEditor) return;
46
+ const { presentDialog } = await import("@haklex/rich-editor-ui");
47
+ presentDialog({
48
+ content: ({ dismiss }) => /* @__PURE__ */ jsx(NestedDocDialogContent, {
49
+ DialogEditor,
50
+ contentEditor,
51
+ initialState: contentEditor.getEditorState().toJSON(),
52
+ nodeKey,
53
+ parentEditor: editor,
54
+ onDismiss: dismiss
55
+ }),
56
+ className: dialogPopup,
57
+ portalClassName,
58
+ theme: colorScheme,
59
+ showCloseButton: false,
60
+ clickOutsideToDismiss: false
61
+ });
62
+ }, [
63
+ DialogEditor,
64
+ colorScheme,
65
+ contentEditor,
66
+ editor,
67
+ nodeKey,
68
+ portalClassName
69
+ ]);
70
+ return /* @__PURE__ */ jsxs("div", {
71
+ "aria-label": "Open nested document editor",
72
+ className: editOverlayRoot,
73
+ role: "button",
74
+ tabIndex: 0,
75
+ onClick: handleOpenDialog,
76
+ onKeyDown: (event) => {
77
+ if (event.key === "Enter" || event.key === " ") {
78
+ event.preventDefault();
79
+ handleOpenDialog();
80
+ }
81
+ },
82
+ children: [/* @__PURE__ */ jsx("div", {
83
+ className: `${rendererContent} rich-nested-doc-content`,
84
+ children: hasPreview ? /* @__PURE__ */ jsx("div", {
85
+ className: previewSurface,
86
+ children: /* @__PURE__ */ jsx(NestedDocRenderer, { value: previewState })
87
+ }) : /* @__PURE__ */ jsx("p", {
88
+ className: previewEmpty,
89
+ children: "Empty nested document. Click to edit."
90
+ })
91
+ }), /* @__PURE__ */ jsx("div", {
92
+ "aria-hidden": true,
93
+ className: editOverlay,
94
+ children: /* @__PURE__ */ jsx(Pencil, { size: 24 })
95
+ })]
96
+ });
98
97
  }
99
- function NestedDocDialogContent({
100
- initialState,
101
- parentEditor,
102
- nodeKey,
103
- contentEditor,
104
- onDismiss,
105
- DialogEditor
106
- }) {
107
- const dialogEditorRef = useRef(null);
108
- const [shellEl, setShellEl] = useState(null);
109
- const safeInitialState = initialState?.root?.children?.length > 0 ? initialState : EMPTY_EDITOR_STATE;
110
- const handleDone = useCallback(() => {
111
- const dialogEditor = dialogEditorRef.current;
112
- if (dialogEditor) {
113
- const newState = dialogEditor.getEditorState().toJSON();
114
- const parsed = contentEditor.parseEditorState(newState);
115
- contentEditor.setEditorState(parsed);
116
- parentEditor.update(() => {
117
- const node = $getNodeByKey(nodeKey);
118
- if ($isNestedDocNode(node)) {
119
- node.setContentState(newState);
120
- }
121
- });
122
- }
123
- onDismiss();
124
- }, [contentEditor, nodeKey, onDismiss, parentEditor]);
125
- const handleKeyDownCapture = useCallback(
126
- (event) => {
127
- const isModifier = event.metaKey || event.ctrlKey;
128
- if (!isModifier) return;
129
- if (event.key === "Enter" || event.key.toLowerCase() === "s") {
130
- event.preventDefault();
131
- handleDone();
132
- }
133
- },
134
- [handleDone]
135
- );
136
- const handleEditorReady = useCallback((editor) => {
137
- dialogEditorRef.current = editor;
138
- }, []);
139
- return /* @__PURE__ */ jsxs("div", { className: dialogShell, ref: setShellEl, onKeyDownCapture: handleKeyDownCapture, children: [
140
- /* @__PURE__ */ jsxs("div", { className: dialogHeader, children: [
141
- /* @__PURE__ */ jsx("div", { className: dialogHeaderLeft, children: /* @__PURE__ */ jsxs("h3", { className: dialogTitle, children: [
142
- /* @__PURE__ */ jsx(FileText, { size: 18 }),
143
- /* @__PURE__ */ jsx("span", { children: "Nested document" })
144
- ] }) }),
145
- /* @__PURE__ */ jsx("div", { className: dialogHeaderRight, children: /* @__PURE__ */ jsx(
146
- "button",
147
- {
148
- className: dialogHeaderCloseBtn,
149
- title: "Close",
150
- type: "button",
151
- onClick: onDismiss,
152
- children: /* @__PURE__ */ jsx(X, { size: 14 })
153
- }
154
- ) })
155
- ] }),
156
- /* @__PURE__ */ jsx("div", { className: editorArea, children: shellEl && /* @__PURE__ */ jsx(PortalContainerProvider, { value: shellEl, children: /* @__PURE__ */ jsx(DialogEditor, { initialValue: safeInitialState, onEditorReady: handleEditorReady }) }) }),
157
- /* @__PURE__ */ jsx("div", { className: dialogFooter, children: /* @__PURE__ */ jsxs(ActionBar, { children: [
158
- /* @__PURE__ */ jsx(ActionButton, { size: "md", variant: "ghost", onClick: onDismiss, children: "Cancel" }),
159
- /* @__PURE__ */ jsx(ActionButton, { size: "md", variant: "accent", onClick: handleDone, children: "Save" })
160
- ] }) })
161
- ] });
98
+ function NestedDocDialogContent({ initialState, parentEditor, nodeKey, contentEditor, onDismiss, DialogEditor }) {
99
+ const dialogEditorRef = useRef(null);
100
+ const [shellEl, setShellEl] = useState(null);
101
+ const safeInitialState = initialState?.root?.children?.length > 0 ? initialState : EMPTY_EDITOR_STATE;
102
+ const handleDone = useCallback(() => {
103
+ const dialogEditor = dialogEditorRef.current;
104
+ if (dialogEditor) {
105
+ const newState = dialogEditor.getEditorState().toJSON();
106
+ const parsed = contentEditor.parseEditorState(newState);
107
+ contentEditor.setEditorState(parsed);
108
+ parentEditor.update(() => {
109
+ const node = $getNodeByKey(nodeKey);
110
+ if ($isNestedDocNode(node)) node.setContentState(newState);
111
+ });
112
+ }
113
+ onDismiss();
114
+ }, [
115
+ contentEditor,
116
+ nodeKey,
117
+ onDismiss,
118
+ parentEditor
119
+ ]);
120
+ const handleKeyDownCapture = useCallback((event) => {
121
+ if (!(event.metaKey || event.ctrlKey)) return;
122
+ if (event.key === "Enter" || event.key.toLowerCase() === "s") {
123
+ event.preventDefault();
124
+ handleDone();
125
+ }
126
+ }, [handleDone]);
127
+ const handleEditorReady = useCallback((editor) => {
128
+ dialogEditorRef.current = editor;
129
+ }, []);
130
+ return /* @__PURE__ */ jsxs("div", {
131
+ className: dialogShell,
132
+ ref: setShellEl,
133
+ onKeyDownCapture: handleKeyDownCapture,
134
+ children: [
135
+ /* @__PURE__ */ jsxs("div", {
136
+ className: dialogHeader,
137
+ children: [/* @__PURE__ */ jsx("div", {
138
+ className: dialogHeaderLeft,
139
+ children: /* @__PURE__ */ jsxs("h3", {
140
+ className: dialogTitle,
141
+ children: [/* @__PURE__ */ jsx(FileText, { size: 18 }), /* @__PURE__ */ jsx("span", { children: "Nested document" })]
142
+ })
143
+ }), /* @__PURE__ */ jsx("div", {
144
+ className: dialogHeaderRight,
145
+ children: /* @__PURE__ */ jsx("button", {
146
+ className: dialogHeaderCloseBtn,
147
+ title: "Close",
148
+ type: "button",
149
+ onClick: onDismiss,
150
+ children: /* @__PURE__ */ jsx(X, { size: 14 })
151
+ })
152
+ })]
153
+ }),
154
+ /* @__PURE__ */ jsx("div", {
155
+ className: editorArea,
156
+ children: shellEl && /* @__PURE__ */ jsx(PortalContainerProvider, {
157
+ value: shellEl,
158
+ children: /* @__PURE__ */ jsx(DialogEditor, {
159
+ initialValue: safeInitialState,
160
+ onEditorReady: handleEditorReady
161
+ })
162
+ })
163
+ }),
164
+ /* @__PURE__ */ jsx("div", {
165
+ className: dialogFooter,
166
+ children: /* @__PURE__ */ jsxs(ActionBar, { children: [/* @__PURE__ */ jsx(ActionButton, {
167
+ size: "md",
168
+ variant: "ghost",
169
+ onClick: onDismiss,
170
+ children: "Cancel"
171
+ }), /* @__PURE__ */ jsx(ActionButton, {
172
+ size: "md",
173
+ variant: "accent",
174
+ onClick: handleDone,
175
+ children: "Save"
176
+ })] })
177
+ })
178
+ ]
179
+ });
162
180
  }
181
+ //#endregion
182
+ //#region src/NestedDocEditNode.ts
163
183
  function createContentEditor() {
164
- return createEditor({
165
- namespace: "NestedDocContent",
166
- nodes: getResolvedEditNodes(),
167
- theme: editorTheme,
168
- onError: (error) => {
169
- console.error("[NestedDocContent]", error);
170
- }
171
- });
184
+ return createEditor({
185
+ namespace: "NestedDocContent",
186
+ nodes: getResolvedEditNodes(),
187
+ theme: editorTheme,
188
+ onError: (error) => {
189
+ console.error("[NestedDocContent]", error);
190
+ }
191
+ });
172
192
  }
173
- const _NestedDocEditNode = class _NestedDocEditNode extends NestedDocNode {
174
- constructor(contentState, key) {
175
- super(contentState, key);
176
- __publicField(this, "__contentEditor");
177
- this.__contentEditor = createContentEditor();
178
- if (contentState) {
179
- const editorState = this.__contentEditor.parseEditorState(contentState);
180
- this.__contentEditor.setEditorState(editorState);
181
- }
182
- }
183
- static clone(node) {
184
- const cloned = new _NestedDocEditNode(node.__contentState, node.__key);
185
- cloned.__contentEditor = node.__contentEditor;
186
- return cloned;
187
- }
188
- getContentEditor() {
189
- return this.__contentEditor;
190
- }
191
- static importJSON(serializedNode) {
192
- return new _NestedDocEditNode(serializedNode.content);
193
- }
194
- exportJSON() {
195
- return {
196
- ...super.exportJSON(),
197
- type: "nested-doc",
198
- content: this.__contentEditor.getEditorState().toJSON(),
199
- version: 1
200
- };
201
- }
202
- decorate(_editor, _config) {
203
- return createElement(NestedDocEditDecorator, {
204
- nodeKey: this.__key,
205
- contentEditor: this.__contentEditor,
206
- contentState: this.__contentState
207
- });
208
- }
193
+ var NestedDocEditNode = class NestedDocEditNode extends NestedDocNode {
194
+ static clone(node) {
195
+ const cloned = new NestedDocEditNode(node.__contentState, node.__key);
196
+ cloned.__contentEditor = node.__contentEditor;
197
+ return cloned;
198
+ }
199
+ constructor(contentState, key) {
200
+ super(contentState, key);
201
+ _defineProperty(this, "__contentEditor", void 0);
202
+ this.__contentEditor = createContentEditor();
203
+ if (contentState) {
204
+ const editorState = this.__contentEditor.parseEditorState(contentState);
205
+ this.__contentEditor.setEditorState(editorState);
206
+ }
207
+ }
208
+ getContentEditor() {
209
+ return this.__contentEditor;
210
+ }
211
+ static importJSON(serializedNode) {
212
+ return new NestedDocEditNode(serializedNode.content);
213
+ }
214
+ exportJSON() {
215
+ return {
216
+ ...super.exportJSON(),
217
+ type: "nested-doc",
218
+ content: this.__contentEditor.getEditorState().toJSON(),
219
+ version: 1
220
+ };
221
+ }
222
+ decorate(_editor, _config) {
223
+ return createElement(NestedDocEditDecorator, {
224
+ nodeKey: this.__key,
225
+ contentEditor: this.__contentEditor,
226
+ contentState: this.__contentState
227
+ });
228
+ }
209
229
  };
210
- __publicField(_NestedDocEditNode, "commandItems", [
211
- {
212
- title: "Nested Document",
213
- icon: createElement(FileText, { size: 20 }),
214
- description: "Embed a collapsible nested document",
215
- keywords: ["nested", "document", "nested-doc", "embed"],
216
- section: "ADVANCED",
217
- placement: ["slash", "toolbar"],
218
- group: "insert",
219
- onSelect: (editor) => {
220
- editor.update(() => {
221
- $insertNodes([$createNestedDocEditNode()]);
222
- });
223
- }
224
- }
225
- ]);
226
- let NestedDocEditNode = _NestedDocEditNode;
230
+ _defineProperty(NestedDocEditNode, "commandItems", [{
231
+ title: "Nested Document",
232
+ icon: createElement(FileText, { size: 20 }),
233
+ description: "Embed a collapsible nested document",
234
+ keywords: [
235
+ "nested",
236
+ "document",
237
+ "nested-doc",
238
+ "embed"
239
+ ],
240
+ section: "ADVANCED",
241
+ placement: ["slash", "toolbar"],
242
+ group: "insert",
243
+ onSelect: (editor) => {
244
+ editor.update(() => {
245
+ $insertNodes([$createNestedDocEditNode()]);
246
+ });
247
+ }
248
+ }]);
227
249
  function $createNestedDocEditNode(contentState) {
228
- return new NestedDocEditNode(contentState);
250
+ return new NestedDocEditNode(contentState);
229
251
  }
230
252
  function $isNestedDocEditNode(node) {
231
- return node instanceof NestedDocEditNode;
253
+ return node instanceof NestedDocEditNode;
232
254
  }
233
- const INSERT_NESTED_DOC_COMMAND = createCommand("INSERT_NESTED_DOC");
255
+ //#endregion
256
+ //#region src/NestedDocPlugin.tsx
257
+ var INSERT_NESTED_DOC_COMMAND = createCommand("INSERT_NESTED_DOC");
234
258
  function NestedDocPlugin() {
235
- const [editor] = useLexicalComposerContext();
236
- useEffect(() => {
237
- return editor.registerCommand(
238
- INSERT_NESTED_DOC_COMMAND,
239
- (contentState) => {
240
- $insertNodes([$createNestedDocEditNode(contentState || void 0)]);
241
- return true;
242
- },
243
- COMMAND_PRIORITY_EDITOR
244
- );
245
- }, [editor]);
246
- return null;
259
+ const [editor] = useLexicalComposerContext();
260
+ useEffect(() => {
261
+ return editor.registerCommand(INSERT_NESTED_DOC_COMMAND, (contentState) => {
262
+ $insertNodes([$createNestedDocEditNode(contentState || void 0)]);
263
+ return true;
264
+ }, COMMAND_PRIORITY_EDITOR);
265
+ }, [editor]);
266
+ return null;
247
267
  }
248
- const nestedDocNodes = [NestedDocNode];
249
- const nestedDocEditNodes = [NestedDocEditNode];
250
- export {
251
- $createNestedDocEditNode,
252
- o as $createNestedDocNode,
253
- $isNestedDocEditNode,
254
- $isNestedDocNode,
255
- INSERT_NESTED_DOC_COMMAND,
256
- q as NESTED_DOC_BLOCK_TRANSFORMER,
257
- NestedDocDialogEditorProvider,
258
- NestedDocEditDecorator,
259
- NestedDocEditNode,
260
- NestedDocNode,
261
- NestedDocPlugin,
262
- NestedDocRenderer,
263
- s as NestedDocStaticDecorator,
264
- nestedDocEditNodes,
265
- nestedDocNodes,
266
- useNestedDocDialogEditor
267
- };
268
+ //#endregion
269
+ //#region src/index.ts
270
+ var nestedDocNodes = [NestedDocNode];
271
+ var nestedDocEditNodes = [NestedDocEditNode];
272
+ //#endregion
273
+ export { $createNestedDocEditNode, $createNestedDocNode, $isNestedDocEditNode, $isNestedDocNode, INSERT_NESTED_DOC_COMMAND, NESTED_DOC_BLOCK_TRANSFORMER, NestedDocDialogEditorProvider, NestedDocEditDecorator, NestedDocEditNode, NestedDocNode, NestedDocPlugin, NestedDocRenderer, NestedDocStaticDecorator, nestedDocEditNodes, nestedDocNodes, useNestedDocDialogEditor };