@domternal/react 0.8.0 → 0.9.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.d.ts +19 -10
- package/dist/index.js +31 -5
- package/dist/index.js.map +1 -1
- package/package.json +12 -11
- package/dist/Domternal.d.ts.map +0 -1
- package/dist/DomternalEditor.d.ts.map +0 -1
- package/dist/DomternalFloatingMenu.d.ts.map +0 -1
- package/dist/EditorContent.d.ts.map +0 -1
- package/dist/EditorContext.d.ts.map +0 -1
- package/dist/bubble-menu/DomternalBubbleMenu.d.ts.map +0 -1
- package/dist/bubble-menu/useBubbleMenu.d.ts.map +0 -1
- package/dist/emoji-picker/DomternalEmojiPicker.d.ts.map +0 -1
- package/dist/emoji-picker/useEmojiPicker.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/node-views/ReactNodeViewRenderer.d.ts.map +0 -1
- package/dist/notion-color-picker/DomternalNotionColorPicker.d.ts.map +0 -1
- package/dist/notion-color-picker/index.d.ts.map +0 -1
- package/dist/notion-color-picker/useNotionColorPicker.d.ts.map +0 -1
- package/dist/toolbar/DomternalToolbar.d.ts.map +0 -1
- package/dist/toolbar/ToolbarButton.d.ts.map +0 -1
- package/dist/toolbar/ToolbarDropdown.d.ts.map +0 -1
- package/dist/toolbar/ToolbarDropdownPanel.d.ts.map +0 -1
- package/dist/toolbar/useComputedStyle.d.ts.map +0 -1
- package/dist/toolbar/useKeyboardNav.d.ts.map +0 -1
- package/dist/toolbar/useToolbarController.d.ts.map +0 -1
- package/dist/toolbar/useToolbarIcons.d.ts.map +0 -1
- package/dist/toolbar/useTooltip.d.ts.map +0 -1
- package/dist/useEditor.d.ts.map +0 -1
- package/dist/useEditorState.d.ts.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { DependencyList, ReactNode, HTMLAttributes, Ref, RefObject, KeyboardEvent, ElementType, RefCallback } from 'react';
|
|
3
|
-
import { AnyExtension, Content, FocusPosition, Editor, JSONContent, IconSet, ToolbarLayoutEntry, BubbleMenuOptions, FloatingMenuItemsOverride } from '@domternal/core';
|
|
3
|
+
import { AnyExtension, Content, FocusPosition, Editor, JSONContent, IconSet, ToolbarLayoutEntry, BubbleMenuOptions, FloatingMenuOptions, FloatingMenuItemsOverride, FloatingMenuKeymap } from '@domternal/core';
|
|
4
4
|
export { AnyExtension, Content, Editor, FocusPosition, GenerateHTMLOptions, GenerateJSONOptions, GenerateTextOptions, JSONContent, generateHTML, generateJSON, generateText } from '@domternal/core';
|
|
5
|
-
import { FloatingMenuOptions, FloatingMenuKeymap } from '@domternal/extension-block-menu';
|
|
6
5
|
|
|
7
6
|
declare const DEFAULT_EXTENSIONS: AnyExtension[];
|
|
8
7
|
interface UseEditorOptions {
|
|
@@ -17,10 +16,12 @@ interface UseEditorOptions {
|
|
|
17
16
|
/** Output format for content comparison. @default 'html' */
|
|
18
17
|
outputFormat?: 'html' | 'json';
|
|
19
18
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
19
|
+
* Create the editor synchronously during the first render so `editor`
|
|
20
|
+
* is available immediately, with no null flash on first paint. The view
|
|
21
|
+
* starts in a detached element and is adopted into the mount point by
|
|
22
|
+
* the mount effect. Client-only: the default defers creation to a mount
|
|
23
|
+
* effect, which never runs during server-side rendering.
|
|
24
|
+
* @default false
|
|
24
25
|
*/
|
|
25
26
|
immediatelyRender?: boolean;
|
|
26
27
|
/** Called when the editor instance is created. */
|
|
@@ -60,12 +61,12 @@ interface UseEditorOptions {
|
|
|
60
61
|
* return <div className="dm-editor"><div ref={editorRef} /></div>;
|
|
61
62
|
* ```
|
|
62
63
|
*
|
|
63
|
-
* @example
|
|
64
|
+
* @example Editor available on the very first render (client-only apps)
|
|
64
65
|
* ```tsx
|
|
65
66
|
* const { editor, editorRef } = useEditor({
|
|
66
67
|
* extensions,
|
|
67
68
|
* content,
|
|
68
|
-
* immediatelyRender:
|
|
69
|
+
* immediatelyRender: true,
|
|
69
70
|
* });
|
|
70
71
|
* ```
|
|
71
72
|
*
|
|
@@ -238,14 +239,22 @@ interface DomternalProps extends UseEditorOptions {
|
|
|
238
239
|
* </Domternal>
|
|
239
240
|
* ```
|
|
240
241
|
*
|
|
241
|
-
* @example SSR
|
|
242
|
+
* @example Loading state (shown during SSR and until the editor exists)
|
|
242
243
|
* ```tsx
|
|
243
|
-
* <Domternal extensions={extensions}
|
|
244
|
+
* <Domternal extensions={extensions}>
|
|
244
245
|
* <Domternal.Loading>Loading editor...</Domternal.Loading>
|
|
245
246
|
* <Domternal.Toolbar />
|
|
246
247
|
* <Domternal.Content />
|
|
247
248
|
* </Domternal>
|
|
248
249
|
* ```
|
|
250
|
+
*
|
|
251
|
+
* @example Editor on the very first render (client-only apps)
|
|
252
|
+
* ```tsx
|
|
253
|
+
* <Domternal extensions={extensions} immediatelyRender>
|
|
254
|
+
* <Domternal.Toolbar />
|
|
255
|
+
* <Domternal.Content />
|
|
256
|
+
* </Domternal>
|
|
257
|
+
* ```
|
|
249
258
|
*/
|
|
250
259
|
declare function Domternal({ children, deps, ...options }: DomternalProps): ReactNode;
|
|
251
260
|
declare namespace Domternal {
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { createContext, forwardRef, useImperativeHandle, useRef, useEffect, useState, useMemo, useCallback, useSyncExternalStore, useContext, Fragment, useLayoutEffect, createElement } from 'react';
|
|
2
|
-
import { Editor, Document, Paragraph, Text, BaseKeymap, History, positionFloatingOnce, PluginKey, FloatingMenuController, defaultIcons, positionFloating, ToolbarController, defaultBubbleContexts, createBubbleMenuPlugin } from '@domternal/core';
|
|
2
|
+
import { Editor, Document, Paragraph, Text, BaseKeymap, History, positionFloatingOnce, PluginKey, createFloatingMenuPlugin, FloatingMenuController, defaultIcons, positionFloating, ToolbarController, defaultBubbleContexts, createBubbleMenuPlugin } from '@domternal/core';
|
|
3
3
|
export { Editor, generateHTML, generateJSON, generateText } from '@domternal/core';
|
|
4
4
|
import { jsxs, jsx, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
5
|
-
import { createFloatingMenuPlugin } from '@domternal/extension-block-menu';
|
|
6
5
|
import { createPortal } from 'react-dom';
|
|
7
6
|
import { createRoot } from 'react-dom/client';
|
|
8
7
|
|
|
@@ -14,9 +13,9 @@ function useEditor(options = {}, deps) {
|
|
|
14
13
|
content = "",
|
|
15
14
|
editable = true,
|
|
16
15
|
autofocus = false,
|
|
17
|
-
outputFormat = "html"
|
|
16
|
+
outputFormat = "html",
|
|
17
|
+
immediatelyRender = false
|
|
18
18
|
} = options;
|
|
19
|
-
const [editor, setEditor] = useState(null);
|
|
20
19
|
const editorRef = useRef(null);
|
|
21
20
|
const instanceRef = useRef(null);
|
|
22
21
|
const pendingContentRef = useRef(null);
|
|
@@ -45,7 +44,7 @@ function useEditor(options = {}, deps) {
|
|
|
45
44
|
callbacksRef.current.onBlur?.({ editor: ed, event });
|
|
46
45
|
});
|
|
47
46
|
}
|
|
48
|
-
function
|
|
47
|
+
function buildEditorInstance(element, initialContent, focus) {
|
|
49
48
|
const ed = new Editor({
|
|
50
49
|
element,
|
|
51
50
|
extensions: [...DEFAULT_EXTENSIONS, ...extensions],
|
|
@@ -57,6 +56,10 @@ function useEditor(options = {}, deps) {
|
|
|
57
56
|
instanceRef.current = ed;
|
|
58
57
|
extensionsRef.current = extensions;
|
|
59
58
|
depsRef.current = deps;
|
|
59
|
+
return ed;
|
|
60
|
+
}
|
|
61
|
+
function createEditorInstance(element, initialContent, focus) {
|
|
62
|
+
const ed = buildEditorInstance(element, initialContent, focus);
|
|
60
63
|
setEditor(ed);
|
|
61
64
|
callbacksRef.current.onCreate?.(ed);
|
|
62
65
|
return ed;
|
|
@@ -71,7 +74,30 @@ function useEditor(options = {}, deps) {
|
|
|
71
74
|
instanceRef.current = null;
|
|
72
75
|
setEditor(null);
|
|
73
76
|
}
|
|
77
|
+
const [editor, setEditor] = useState(() => {
|
|
78
|
+
if (!immediatelyRender) return null;
|
|
79
|
+
if (typeof window === "undefined") {
|
|
80
|
+
throw new Error(
|
|
81
|
+
"[@domternal/react] immediatelyRender: true creates the editor during render, which cannot work during server-side rendering. Remove the option for SSR; the editor is then created after mount."
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
if (instanceRef.current && !instanceRef.current.isDestroyed) {
|
|
85
|
+
return instanceRef.current;
|
|
86
|
+
}
|
|
87
|
+
return buildEditorInstance(document.createElement("div"), content, autofocus);
|
|
88
|
+
});
|
|
74
89
|
useEffect(() => {
|
|
90
|
+
const existing = instanceRef.current;
|
|
91
|
+
if (existing && !existing.isDestroyed) {
|
|
92
|
+
const mount = editorRef.current;
|
|
93
|
+
if (mount && existing.view.dom.parentElement !== mount) {
|
|
94
|
+
mount.appendChild(existing.view.dom);
|
|
95
|
+
}
|
|
96
|
+
callbacksRef.current.onCreate?.(existing);
|
|
97
|
+
return () => {
|
|
98
|
+
destroyCurrentEditor();
|
|
99
|
+
};
|
|
100
|
+
}
|
|
75
101
|
const element = editorRef.current ?? document.createElement("div");
|
|
76
102
|
const initialContent = pendingContentRef.current ?? content;
|
|
77
103
|
pendingContentRef.current = null;
|