@openeditor/react 0.0.26 → 0.0.28
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/README.md +66 -17
- package/dist/index.d.ts +65 -47
- package/dist/index.js +1612 -2792
- package/dist/index.js.map +1 -1
- package/package.json +9 -7
package/README.md
CHANGED
|
@@ -9,9 +9,11 @@ Pass `attachmentRuntime` to `useOpenEditorController` for editable attachments a
|
|
|
9
9
|
- `useOpenEditorController` for editor state, commands, document exports, and selection state
|
|
10
10
|
- `OpenEditorContent` for the editable Tiptap-backed content surface
|
|
11
11
|
- `OpenEditorViewer` for read-only React rendering
|
|
12
|
+
- `OpenEditorPageHeader` for host-backed page title and icon editing
|
|
12
13
|
- `getDefaultBlockPickerItems` for host-owned block rails, pickers, and command palettes
|
|
13
14
|
- `getDefaultSlashMenuItems` for UI packages that want the built-in insert actions
|
|
14
|
-
-
|
|
15
|
+
- stable-identity block targeting and transaction-backed copy, duplicate, move, and delete commands
|
|
16
|
+
- `OpenEditorBlockDragHandle` and `useOpenEditorBlockInteraction` for headless block-handle UIs
|
|
15
17
|
- `defineOpenEditorReactNode` for consumer-owned React blocks
|
|
16
18
|
- `defineOpenEditorReactExtension` for advanced integrations that contribute multiple Tiptap extensions
|
|
17
19
|
|
|
@@ -19,21 +21,52 @@ This package intentionally does not import CSS and does not render styled menus.
|
|
|
19
21
|
|
|
20
22
|
## Block actions
|
|
21
23
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
Every addressable node has a persistent `openeditor-id`. The block interaction
|
|
25
|
+
snapshot publishes the stable block reference under the handle without
|
|
26
|
+
putting pointer-frequency state into the editor controller. Mutating commands
|
|
27
|
+
resolve that identity against the current ProseMirror document immediately
|
|
28
|
+
before dispatch, preserving history and avoiding stale positions:
|
|
25
29
|
|
|
26
30
|
```tsx
|
|
27
|
-
controller
|
|
28
|
-
|
|
29
|
-
controller.
|
|
30
|
-
controller.
|
|
31
|
+
const { activeBlock } = useOpenEditorBlockInteraction(controller);
|
|
32
|
+
if (activeBlock) {
|
|
33
|
+
controller.selectBlock(activeBlock);
|
|
34
|
+
await controller.copyBlock(activeBlock);
|
|
35
|
+
controller.duplicateBlock(activeBlock);
|
|
36
|
+
controller.moveBlock(1, activeBlock);
|
|
37
|
+
controller.deleteBlock(activeBlock);
|
|
38
|
+
}
|
|
31
39
|
```
|
|
32
40
|
|
|
33
41
|
Pass `blockActions` to contribute product-specific actions. The optional
|
|
34
42
|
`OpenEditorBlockMenu` from `@openeditor/ui` combines those contributions with
|
|
35
|
-
Copy, Duplicate, and Delete.
|
|
36
|
-
|
|
43
|
+
Move Up, Move Down, Copy, Duplicate, and Delete. Action contexts receive
|
|
44
|
+
`context.block`, never a ProseMirror position or DOM rectangle. Clipboard copies
|
|
45
|
+
use a versioned OpenEditor block envelope so blocks can move between independent
|
|
46
|
+
editor instances and documents while receiving fresh identities.
|
|
47
|
+
|
|
48
|
+
Handle ownership is structural, not inferred from pointer proximity. Callouts,
|
|
49
|
+
quotes, tables, and consumer blocks own a single handle for their content by
|
|
50
|
+
default. Lists, toggles, and columns expose their independent nested blocks.
|
|
51
|
+
Set `blockHandle: "nested"` on a consumer extension whose child blocks should
|
|
52
|
+
receive their own handles. Placement always follows the live DOM element for the
|
|
53
|
+
resolved ProseMirror node, including through scrolling, resizing, and reflow.
|
|
54
|
+
|
|
55
|
+
Hover targeting is owned by OpenEditor rather than the Tiptap drag-handle
|
|
56
|
+
extension. The editor's interaction surface is one continuous hover region:
|
|
57
|
+
content, the reserved left gutter, and the handle itself. Pointer coordinates
|
|
58
|
+
resolve to the deepest structurally addressable block, with collapsed outer
|
|
59
|
+
margins included so gaps between blocks do not become dead zones. A short hide
|
|
60
|
+
delay lets the pointer cross from content to the handle, while pressing,
|
|
61
|
+
dragging, or opening the block menu freezes the active target. Pointer movement
|
|
62
|
+
is coalesced to one resolution per animation frame and identity changes are the
|
|
63
|
+
only changes published to React.
|
|
64
|
+
|
|
65
|
+
The gutter is part of layout, not a collision workaround. Its reservation is
|
|
66
|
+
continuous rather than breakpoint-based: the editor borrows only the portion
|
|
67
|
+
of the 42px gutter that physically fits to its left and reserves the remainder
|
|
68
|
+
inside its width. Floating placement may correct vertical overflow but must
|
|
69
|
+
never shift horizontally into block content.
|
|
37
70
|
|
|
38
71
|
## Host-owned block pickers
|
|
39
72
|
|
|
@@ -88,12 +121,24 @@ themeable SVG rendering and retain their canonical Mermaid source in the documen
|
|
|
88
121
|
import { OpenEditorContent, useOpenEditorController } from "@openeditor/react";
|
|
89
122
|
|
|
90
123
|
export function Example() {
|
|
91
|
-
const controller = useOpenEditorController();
|
|
124
|
+
const controller = useOpenEditorController({ initialDocument });
|
|
92
125
|
|
|
93
126
|
return <OpenEditorContent controller={controller} />;
|
|
94
127
|
}
|
|
95
128
|
```
|
|
96
129
|
|
|
130
|
+
Editors are uncontrolled on both web and native. `initialDocument` is read once;
|
|
131
|
+
use `controller.setContent(document)` for an undoable programmatic replacement.
|
|
132
|
+
It emits `onChange` and preserves the current selection where possible. Runtime
|
|
133
|
+
changes to callbacks, `editable`, and `placeholder` are applied without remounting.
|
|
134
|
+
|
|
135
|
+
Exports are lazy. `controller.export("html")` returns publishing-safe built-in
|
|
136
|
+
HTML. `controller.exportUnsafe("html")` opts into trusted custom extension HTML.
|
|
137
|
+
|
|
138
|
+
Pass `enabledBlocks` to restrict authoring without removing nodes from the
|
|
139
|
+
schema. Existing disabled blocks remain readable. Runtime-dependent insertion
|
|
140
|
+
is automatically disabled unless page creation or attachment upload is wired.
|
|
141
|
+
|
|
97
142
|
## Custom blocks
|
|
98
143
|
|
|
99
144
|
Custom blocks belong to the consuming product. OpenEditor hosts them without
|
|
@@ -183,8 +228,9 @@ export function ProductEditor() {
|
|
|
183
228
|
}
|
|
184
229
|
```
|
|
185
230
|
|
|
186
|
-
Pass the same extension array to `OpenEditorViewer`. The controller
|
|
187
|
-
|
|
231
|
+
Pass the same extension array to `OpenEditorViewer`. The controller uses
|
|
232
|
+
registered exporters only through the explicit `controller.exportUnsafe(...)`
|
|
233
|
+
path, and registered blocks appear
|
|
188
234
|
in `getDefaultSlashMenuItems`, which powers `@openeditor/ui`.
|
|
189
235
|
|
|
190
236
|
Insert-menu entries accept an optional React `icon` component and numeric `order`.
|
|
@@ -193,8 +239,7 @@ blocks can be placed between them (for example, `order: 250` appears between
|
|
|
193
239
|
Heading 1 and Heading 2). Entries with the same order retain their declaration
|
|
194
240
|
order, and entries without an order appear after ordered entries. This metadata
|
|
195
241
|
is shared by slash menus and `getDefaultBlockPickerItems`; use `insertMenu: false`
|
|
196
|
-
to keep a block out of both discovery surfaces. The
|
|
197
|
-
field remains supported. The same fields are available on direct
|
|
242
|
+
to keep a block out of both discovery surfaces. The same fields are available on direct
|
|
198
243
|
`slashMenuItems`; a slash menu's explicit `items` prop is also sorted by this rule.
|
|
199
244
|
|
|
200
245
|
Block `name` is the stable public identifier. Namespace consumer blocks to avoid
|
|
@@ -206,19 +251,23 @@ Duplicate names and node types fail immediately during editor construction.
|
|
|
206
251
|
|
|
207
252
|
The first-party `page` block models a Notion-style child page as a reference to
|
|
208
253
|
a separately persisted document. Supply `pageRuntime` to connect creation,
|
|
209
|
-
resolution,
|
|
254
|
+
resolution, metadata updates, and navigation to your application:
|
|
210
255
|
|
|
211
256
|
```tsx
|
|
212
257
|
const controller = useOpenEditorController({
|
|
213
258
|
pageRuntime: {
|
|
214
259
|
createPage: async ({ title, icon }) => api.pages.create({ title, icon }),
|
|
215
260
|
resolvePage: async (pageId) => api.pages.get(pageId),
|
|
216
|
-
|
|
261
|
+
updatePage: async (pageId, update) => api.pages.update(pageId, update),
|
|
217
262
|
openPage: (page) => router.push(`/pages/${page.pageId}`),
|
|
218
263
|
},
|
|
219
264
|
});
|
|
220
265
|
```
|
|
221
266
|
|
|
267
|
+
Render `OpenEditorPageHeader` on the opened page surface to provide the canonical
|
|
268
|
+
editable title and icon. Both fields call `pageRuntime.updatePage`; page references
|
|
269
|
+
resolve the same page entity instead of owning independent metadata.
|
|
270
|
+
|
|
222
271
|
The document stores only the stable reference and cached presentation. Page
|
|
223
272
|
contents, hierarchy, permissions, routing, and deletion remain host-owned.
|
|
224
273
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { ReactNode, CSSProperties, ComponentType } from 'react';
|
|
3
|
-
import { OpenEditorDocument, BlockSpec, ProseMirrorNode, OpenEditorAttachmentRuntime } from '@openeditor/core';
|
|
4
|
-
|
|
2
|
+
import { ReactNode, CSSProperties, RefObject, ComponentType } from 'react';
|
|
3
|
+
import { OpenEditorBlockRef, OpenEditorDocument, BlockSpec, ProseMirrorNode, OpenEditorPageRuntime, OpenEditorAttachmentRuntime, OpenEditorPageSnapshot, OpenEditorAuthoringCapabilities } from '@openeditor/core';
|
|
4
|
+
export { OpenEditorBlockRef, OpenEditorPageRuntime, OpenEditorPageSnapshot } from '@openeditor/core';
|
|
5
|
+
import { ExportFormat, OpenEditorExporters } from '@openeditor/exporters';
|
|
5
6
|
export { seedDocument } from '@openeditor/extensions';
|
|
6
|
-
import {
|
|
7
|
-
export { DragHandle as OpenEditorDragHandle } from '@tiptap/extension-drag-handle-react';
|
|
7
|
+
import { AnyExtension, NodeConfig } from '@tiptap/core';
|
|
8
8
|
import { ReactNodeViewProps } from '@tiptap/react';
|
|
9
9
|
export { NodeViewContent, NodeViewWrapper, ReactNodeViewProps as OpenEditorNodeViewProps } from '@tiptap/react';
|
|
10
10
|
|
|
11
|
+
type OpenEditorBlockInteractionSnapshot = {
|
|
12
|
+
activeBlock: OpenEditorBlockRef | null;
|
|
13
|
+
dragging: boolean;
|
|
14
|
+
};
|
|
15
|
+
type OpenEditorBlockInteractionStore = {
|
|
16
|
+
getSnapshot: () => OpenEditorBlockInteractionSnapshot;
|
|
17
|
+
subscribe: (listener: () => void) => () => void;
|
|
18
|
+
};
|
|
19
|
+
|
|
11
20
|
declare const openEditorThemeTokenNames: readonly ["surface", "surfaceRaised", "surfaceMuted", "blockSurface", "text", "textSoft", "heading", "muted", "placeholder", "border", "borderStrong", "structuralLine", "accent", "accentText", "accentStrong", "buttonBackground", "buttonText", "codeBackground", "codeText", "link", "linkHover", "shadow", "fontSans", "fontMono", "radiusSmall", "radiusMedium", "radiusLarge", "spaceBlock", "spaceInline"];
|
|
12
21
|
type OpenEditorThemeToken = (typeof openEditorThemeTokenNames)[number];
|
|
13
22
|
type OpenEditorTheme = Partial<Record<OpenEditorThemeToken, string>>;
|
|
@@ -20,23 +29,7 @@ declare function OpenEditorThemeProvider({ children, className, theme }: {
|
|
|
20
29
|
theme: OpenEditorTheme;
|
|
21
30
|
}): react.JSX.Element;
|
|
22
31
|
|
|
23
|
-
type
|
|
24
|
-
pageId: string;
|
|
25
|
-
title: string;
|
|
26
|
-
icon?: string | null;
|
|
27
|
-
href?: string | null;
|
|
28
|
-
};
|
|
29
|
-
type OpenEditorPageRuntime = {
|
|
30
|
-
createPage?: (input: {
|
|
31
|
-
title: string;
|
|
32
|
-
icon?: string | null;
|
|
33
|
-
}) => Promise<OpenEditorPageSnapshot>;
|
|
34
|
-
resolvePage?: (pageId: string) => Promise<OpenEditorPageSnapshot | null>;
|
|
35
|
-
renamePage?: (pageId: string, title: string) => Promise<void> | void;
|
|
36
|
-
updatePageIcon?: (pageId: string, icon: string) => Promise<void> | void;
|
|
37
|
-
openPage?: (page: OpenEditorPageSnapshot) => Promise<void> | void;
|
|
38
|
-
};
|
|
39
|
-
type OpenEditorReactProps = {
|
|
32
|
+
type OpenEditorReactProps = OpenEditorAuthoringCapabilities & {
|
|
40
33
|
initialDocument?: OpenEditorDocument;
|
|
41
34
|
editable?: boolean;
|
|
42
35
|
placeholder?: string;
|
|
@@ -49,16 +42,9 @@ type OpenEditorReactProps = {
|
|
|
49
42
|
extensions?: readonly OpenEditorReactExtension[];
|
|
50
43
|
blockActions?: readonly OpenEditorBlockAction[];
|
|
51
44
|
};
|
|
52
|
-
type OpenEditorBlockTarget = {
|
|
53
|
-
pos: number;
|
|
54
|
-
depth: number;
|
|
55
|
-
nodeType: string;
|
|
56
|
-
blockName?: string;
|
|
57
|
-
rect: OpenEditorOverlayRect;
|
|
58
|
-
};
|
|
59
45
|
type OpenEditorBlockActionContext = {
|
|
60
46
|
controller: OpenEditorController;
|
|
61
|
-
|
|
47
|
+
block: OpenEditorBlockRef;
|
|
62
48
|
};
|
|
63
49
|
type OpenEditorBlockAction = {
|
|
64
50
|
id: string;
|
|
@@ -69,9 +55,10 @@ type OpenEditorBlockAction = {
|
|
|
69
55
|
};
|
|
70
56
|
type OpenEditorReactConfig = OpenEditorReactProps;
|
|
71
57
|
type OpenEditorController = {
|
|
72
|
-
editor: Editor | null;
|
|
73
58
|
document: OpenEditorDocument;
|
|
74
|
-
|
|
59
|
+
export: (format: ExportFormat) => string;
|
|
60
|
+
exportUnsafe: (format: ExportFormat) => string;
|
|
61
|
+
ready: boolean;
|
|
75
62
|
editable: boolean;
|
|
76
63
|
placeholder: string;
|
|
77
64
|
selectedBlock: string;
|
|
@@ -93,23 +80,25 @@ type OpenEditorController = {
|
|
|
93
80
|
undo: () => void;
|
|
94
81
|
redo: () => void;
|
|
95
82
|
insertBlock: (blockName?: string, range?: InsertRange) => boolean;
|
|
83
|
+
isBlockEnabled: (blockName: string) => boolean;
|
|
96
84
|
setLink: (url?: string | null) => void;
|
|
97
85
|
getActiveLink: () => string | undefined;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
deleteBlock: (target?: OpenEditorBlockTarget) => boolean;
|
|
105
|
-
moveBlock: (direction: -1 | 1, target?: OpenEditorBlockTarget) => boolean;
|
|
86
|
+
selectBlock: (block: OpenEditorBlockRef) => boolean;
|
|
87
|
+
copyBlock: (block?: OpenEditorBlockRef) => Promise<boolean>;
|
|
88
|
+
duplicateBlock: (block?: OpenEditorBlockRef) => boolean;
|
|
89
|
+
deleteBlock: (block?: OpenEditorBlockRef) => boolean;
|
|
90
|
+
moveBlock: (direction: -1 | 1, block?: OpenEditorBlockRef) => boolean;
|
|
91
|
+
canMoveBlock: (direction: -1 | 1, block?: OpenEditorBlockRef) => boolean;
|
|
106
92
|
blockActions: readonly OpenEditorBlockAction[];
|
|
107
|
-
|
|
108
|
-
|
|
93
|
+
blockInteraction: OpenEditorBlockInteractionStore;
|
|
94
|
+
getRootElement: () => HTMLElement | null;
|
|
95
|
+
setBlockHandleLocked: (locked: boolean) => void;
|
|
96
|
+
isActive: (name: string, attributes?: Record<string, unknown>) => boolean;
|
|
109
97
|
slashMenuItems: readonly OpenEditorSlashMenuItem[];
|
|
110
98
|
extensions: readonly OpenEditorReactExtension[];
|
|
111
99
|
pageRuntime?: OpenEditorPageRuntime;
|
|
112
100
|
attachmentRuntime?: OpenEditorAttachmentRuntime<any>;
|
|
101
|
+
enabledBlocks?: readonly string[];
|
|
113
102
|
slashState: SlashState | null;
|
|
114
103
|
selectionBubbleState: SelectionBubbleState | null;
|
|
115
104
|
};
|
|
@@ -196,10 +185,14 @@ type OpenEditorExtensionMenu = {
|
|
|
196
185
|
type OpenEditorReactExtension = {
|
|
197
186
|
block: BlockSpec;
|
|
198
187
|
tiptapExtensions: readonly AnyExtension[];
|
|
188
|
+
/**
|
|
189
|
+
* Controls ownership when this block contains other block nodes. Containers
|
|
190
|
+
* own one handle by default; use `nested` when their children are independent
|
|
191
|
+
* draggable blocks, as in column layouts.
|
|
192
|
+
*/
|
|
193
|
+
blockHandle?: "self" | "nested";
|
|
199
194
|
/** Discovery metadata shared by slash menus and host-owned block pickers. */
|
|
200
195
|
insertMenu?: false | OpenEditorExtensionMenu;
|
|
201
|
-
/** @deprecated Use `insertMenu`. */
|
|
202
|
-
slashMenu?: false | OpenEditorExtensionMenu;
|
|
203
196
|
viewer: OpenEditorViewerRenderer;
|
|
204
197
|
exporters?: OpenEditorExporters;
|
|
205
198
|
};
|
|
@@ -226,13 +219,38 @@ declare module "@tiptap/core" {
|
|
|
226
219
|
}
|
|
227
220
|
}
|
|
228
221
|
declare const formatAttachmentSize: (size: number | null) => string;
|
|
229
|
-
|
|
222
|
+
type OpenEditorPageHeaderProps = {
|
|
223
|
+
page: OpenEditorPageSnapshot;
|
|
224
|
+
runtime: OpenEditorPageRuntime;
|
|
225
|
+
className?: string;
|
|
226
|
+
onPageChange?: (page: OpenEditorPageSnapshot) => void;
|
|
227
|
+
};
|
|
228
|
+
/** Canonical Notion-style page metadata editor shared by host page surfaces. */
|
|
229
|
+
declare const OpenEditorPageHeader: ({ page, runtime, className, onPageChange, }: OpenEditorPageHeaderProps) => react.JSX.Element;
|
|
230
|
+
declare const useOpenEditorController: ({ initialDocument, editable, placeholder, onChange, onFilePasteDrop, pageRuntime, attachmentRuntime, enabledBlocks, slashMenuItems, extensions, blockActions, }?: OpenEditorReactProps) => OpenEditorController;
|
|
231
|
+
declare const useOpenEditorBlockInteraction: (controller: OpenEditorController) => OpenEditorBlockInteractionSnapshot;
|
|
232
|
+
type OpenEditorBlockDragHandleProps = {
|
|
233
|
+
controller: OpenEditorController;
|
|
234
|
+
children: ReactNode;
|
|
235
|
+
className?: string;
|
|
236
|
+
ariaLabel?: string;
|
|
237
|
+
elementRef?: RefObject<HTMLDivElement | null>;
|
|
238
|
+
expanded?: boolean;
|
|
239
|
+
onActivate?: () => void;
|
|
240
|
+
onDraggingChange?: (dragging: boolean) => void;
|
|
241
|
+
};
|
|
242
|
+
/**
|
|
243
|
+
* Headless block handle whose outer DOM element owns both native dragging and
|
|
244
|
+
* activation. Keep visual children pointer-transparent so nested controls do
|
|
245
|
+
* not intercept the dragstart gesture.
|
|
246
|
+
*/
|
|
247
|
+
declare const OpenEditorBlockDragHandle: ({ controller, children, className, ariaLabel, elementRef, expanded, onActivate, onDraggingChange, }: OpenEditorBlockDragHandleProps) => react.ReactPortal | null;
|
|
230
248
|
declare const sortSlashMenuItems: (items: readonly OpenEditorSlashMenuItem[]) => OpenEditorSlashMenuItem[];
|
|
231
249
|
declare const sortBlockPickerItems: (items: readonly OpenEditorBlockPickerItem[]) => OpenEditorBlockPickerItem[];
|
|
232
250
|
declare const getDefaultBlockPickerItems: (controller: OpenEditorController) => OpenEditorBlockPickerItem[];
|
|
233
251
|
declare const getDefaultSlashMenuItems: (controller: OpenEditorController) => OpenEditorSlashMenuItem[];
|
|
234
252
|
declare const OpenEditorContent: ({ controller, className, }: OpenEditorContentProps) => react.JSX.Element;
|
|
235
253
|
declare const OpenEditorViewer: ({ document, className, renderers, extensions, pageRuntime, attachmentRuntime, }: OpenEditorViewerProps) => react.JSX.Element;
|
|
236
|
-
declare const useOpenEditor: ({ initialDocument, editable, placeholder, onChange, onFilePasteDrop, pageRuntime, attachmentRuntime, slashMenuItems, extensions, blockActions, }?: OpenEditorReactProps) => OpenEditorController;
|
|
254
|
+
declare const useOpenEditor: ({ initialDocument, editable, placeholder, onChange, onFilePasteDrop, pageRuntime, attachmentRuntime, enabledBlocks, slashMenuItems, extensions, blockActions, }?: OpenEditorReactProps) => OpenEditorController;
|
|
237
255
|
|
|
238
|
-
export { type InsertRange, type OpenEditorBlockAction, type OpenEditorBlockActionContext, type
|
|
256
|
+
export { type InsertRange, type OpenEditorBlockAction, type OpenEditorBlockActionContext, OpenEditorBlockDragHandle, type OpenEditorBlockDragHandleProps, type OpenEditorBlockPickerItem, OpenEditorContent, type OpenEditorContentProps, type OpenEditorController, type OpenEditorExtensionMenu, type OpenEditorOverlayRect, OpenEditorPageHeader, type OpenEditorPageHeaderProps, type OpenEditorReactConfig, type OpenEditorReactExtension, type OpenEditorReactNodeExtension, type OpenEditorReactProps, type OpenEditorSlashMenuIcon, type OpenEditorSlashMenuIconProps, type OpenEditorSlashMenuItem, type OpenEditorTheme, OpenEditorThemeProvider, type OpenEditorThemeStyle, type OpenEditorThemeToken, OpenEditorViewer, type OpenEditorViewerProps, type OpenEditorViewerRenderer, type SelectionBubbleState, type SlashState, createOpenEditorThemeStyle, defineOpenEditorReactExtension, defineOpenEditorReactNode, formatAttachmentSize, getDefaultBlockPickerItems, getDefaultSlashMenuItems, openEditorThemeTokenNames, sortBlockPickerItems, sortSlashMenuItems, useOpenEditor, useOpenEditorBlockInteraction, useOpenEditorController, useOpenEditorThemeStyle };
|