@openeditor/native 0.0.32 → 0.0.34

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 CHANGED
@@ -1,78 +1,60 @@
1
1
  # `@openeditor/native`
2
2
 
3
- Component-first React Native SDK for OpenEditor.
3
+ React Native host for the offline OpenEditor embedded runtime.
4
4
 
5
- Pass `attachmentRuntime` to use the system picker and host storage lifecycle. The native toolbar exposes “Upload file,” native surfaces render attachment cards, and the viewer delegates opening/sharing to the runtime.
5
+ The document, selection, history, and DOM NodeViews live inside one internally
6
+ scrollable WebView. React Native owns the keyboard toolbar and application
7
+ effects such as pickers, sheets, and navigation. The bridge sends commands and
8
+ lightweight state/revision events; document JSON only crosses it when the host
9
+ explicitly calls `getDocument()` or `flushDocument()`.
6
10
 
7
- ## Public surface
11
+ On iOS, the host hides WKWebView's default previous/next/Done accessory bar so
12
+ the OpenEditor toolbar is the only bar above the software keyboard. The toolbar
13
+ is mounted only while the editable WebView is focused and the software keyboard
14
+ is visible. Consumers can opt back into the system bar with
15
+ `webViewProps={{ hideKeyboardAccessoryView: false }}`.
8
16
 
9
- - `OpenEditorNative` as the primary editing surface
10
- - `OpenEditorNativePageHeader` for host-backed page title and icon editing
11
- - `OpenEditorNativeViewer` for read-only rendering
12
- - `OpenEditorNativeEmojiPicker` for standalone native emoji selection
13
- - native document bridge helpers where renderer adaptation is required
17
+ The `theme` prop accepts the same OpenEditor theme-token contract used by the
18
+ web React surface.
14
19
 
15
- Callout and Page emoji are editable in `OpenEditorNative`: pressing the emoji
16
- opens the native picker and commits the selected Unicode value through editor
17
- history. Inline emoji continue to use the device keyboard.
20
+ ## Host integration
18
21
 
19
- ## Required peers
20
-
21
- - `@openeditor/react-native-prose-editor`
22
- - `react`
23
- - `react-native`
24
- - `react-native-keyboard-controller` (optional but recommended for keyboard toolbar placement)
25
-
26
- ## Quick start
22
+ Install the `react-native-webview` peer dependency. The self-contained offline
23
+ runtime is packaged with the component, so Metro asset customization is not required:
27
24
 
28
25
  ```tsx
29
- import { useRef } from "react";
30
- import { OpenEditorNative, type OpenEditorNativeController } from "@openeditor/native";
31
-
32
- export function Example() {
33
- const editor = useRef<OpenEditorNativeController>(null);
34
- return (
35
- <OpenEditorNative
36
- ref={editor}
37
- initialDocument={document}
38
- onChange={(document) => {
39
- console.log(document);
40
- }}
41
- />
42
- );
43
- }
44
- ```
45
-
46
- `OpenEditorNative` follows the same uncontrolled lifecycle as web:
47
- `initialDocument` is read once and `ref.current.setContent(document)` performs an
48
- undoable programmatic replacement. Undo and redo delegate directly to the Rust
49
- editor engine; the React wrapper does not keep document snapshots.
50
-
51
- Pass `enabledBlocks` to restrict authoring. Page and attachment controls are
52
- automatically omitted until their required host runtimes are present, while
53
- existing nodes remain readable.
54
-
55
- ## Standalone emoji picker
56
-
57
- The editor wires this automatically for callouts and pages. Hosts can also use
58
- the same picker for page headers or other product UI:
59
-
60
- ```tsx
61
- import { OpenEditorNativeEmojiPicker } from "@openeditor/native";
62
-
63
- <OpenEditorNativeEmojiPicker
64
- visible={pickerOpen}
65
- onEmojiSelect={setPageIcon}
66
- onRequestClose={() => setPickerOpen(false)}
67
- />;
26
+ const editor = useRef<OpenEditorNativeController>(null);
27
+
28
+ <OpenEditorNative
29
+ ref={editor}
30
+ initialDocument={document}
31
+ contentInsets={{ top: transparentHeaderHeight, bottom: 16 }}
32
+ onDocumentChanged={({ documentRevision }) => {
33
+ scheduleAutosave(async () => {
34
+ const snapshot = await editor.current?.getDocument({
35
+ minimumRevision: documentRevision,
36
+ });
37
+ if (snapshot) await save(snapshot.document);
38
+ });
39
+ }}
40
+ nativeEffects={{
41
+ pickAttachment: pickUploadAndReturnDurableAttachment,
42
+ createPage: openCreatePageSheet,
43
+ updatePage: updatePageMetadata,
44
+ openPage: navigateToPage,
45
+ }}
46
+ />
68
47
  ```
69
48
 
70
- The native picker shares OpenEditor’s Emojibase dataset with the Frimousse web
71
- picker, while using a platform-native medium bottom sheet and native controls
72
- for scrolling, search, and touch handling. Long-press an emoji that supports
73
- skin tones to choose a variant from the platform-native context menu.
49
+ The block picker derives its available page, image, and attachment commands
50
+ from the supplied effect handlers. If the application cannot upload media to a
51
+ durable URL, omit the corresponding picker effect rather than returning a
52
+ temporary `file://` URI.
74
53
 
75
- ## Internal notes
54
+ Do not wrap the component in a React Native `ScrollView`; give it a bounded
55
+ flex layout so the WebView remains the only document scroll owner. Before a
56
+ screen transition or background save, call `flushDocument()` to commit pending
57
+ composition and receive the current snapshot.
76
58
 
77
- - The native prose editor engine remains an implementation detail behind this package.
78
- - Shared contracts come from `@openeditor/core`; content definitions come from `@openeditor/extensions`.
59
+ For a read-only surface, use
60
+ `<OpenEditorNative initialDocument={document} editable={false} showToolbar={false} />`.
@@ -0,0 +1,79 @@
1
+ import type { OpenEditorDocument } from "@openeditor/core";
2
+ import { type OpenEditorCommandAck, type OpenEditorNativeAttachmentResult, type OpenEditorNativeEffectRequest, type OpenEditorNativeEffectResult, type OpenEditorNativeImageResult, type OpenEditorNativePageResult, type OpenEditorRuntimeCommand, type OpenEditorRuntimeMessage, type OpenEditorRuntimeState } from "@openeditor/embedded-runtime";
3
+ export declare class OpenEditorNativeLifecycleCancellationError extends Error {
4
+ readonly code = "OPENEDITOR_NATIVE_LIFECYCLE_CANCELLED";
5
+ constructor(message: string);
6
+ }
7
+ export declare const isOpenEditorNativeLifecycleCancellation: (error: unknown) => error is OpenEditorNativeLifecycleCancellationError;
8
+ export type OpenEditorNativeEffectHandlers = {
9
+ pickImage?: (effect: Extract<OpenEditorNativeEffectRequest["effect"], {
10
+ type: "pickImage";
11
+ }>) => Promise<OpenEditorNativeEffectResult<OpenEditorNativeImageResult>> | OpenEditorNativeEffectResult<OpenEditorNativeImageResult>;
12
+ pickAttachment?: (effect: Extract<OpenEditorNativeEffectRequest["effect"], {
13
+ type: "pickAttachment";
14
+ }>) => Promise<OpenEditorNativeEffectResult<OpenEditorNativeAttachmentResult>> | OpenEditorNativeEffectResult<OpenEditorNativeAttachmentResult>;
15
+ createPage?: (effect: Extract<OpenEditorNativeEffectRequest["effect"], {
16
+ type: "createPage";
17
+ }>) => Promise<OpenEditorNativeEffectResult<OpenEditorNativePageResult>> | OpenEditorNativeEffectResult<OpenEditorNativePageResult>;
18
+ updatePage?: (effect: Extract<OpenEditorNativeEffectRequest["effect"], {
19
+ type: "updatePage";
20
+ }>) => Promise<OpenEditorNativeEffectResult<OpenEditorNativePageResult>> | OpenEditorNativeEffectResult<OpenEditorNativePageResult>;
21
+ openPage?: (effect: Extract<OpenEditorNativeEffectRequest["effect"], {
22
+ type: "openPage";
23
+ }>) => Promise<OpenEditorNativeEffectResult<null>> | OpenEditorNativeEffectResult<null>;
24
+ openAttachment?: (effect: Extract<OpenEditorNativeEffectRequest["effect"], {
25
+ type: "openAttachment";
26
+ }>) => Promise<OpenEditorNativeEffectResult<null>> | OpenEditorNativeEffectResult<null>;
27
+ openUrl?: (effect: Extract<OpenEditorNativeEffectRequest["effect"], {
28
+ type: "openUrl";
29
+ }>) => Promise<OpenEditorNativeEffectResult<null>> | OpenEditorNativeEffectResult<null>;
30
+ };
31
+ export type OpenEditorNativeControllerEvent = Extract<OpenEditorRuntimeMessage, {
32
+ type: "ready" | "stateChanged" | "documentChanged" | "error";
33
+ }>;
34
+ export type OpenEditorDocumentSnapshot = {
35
+ document: OpenEditorDocument;
36
+ revision: number;
37
+ };
38
+ export type OpenEditorNativeController = {
39
+ readonly ready: boolean;
40
+ waitUntilReady: () => Promise<void>;
41
+ getDocument: (options?: {
42
+ minimumRevision?: number;
43
+ }) => Promise<OpenEditorDocumentSnapshot>;
44
+ flushDocument: () => Promise<OpenEditorDocumentSnapshot>;
45
+ setDocument: (document: OpenEditorDocument) => Promise<number>;
46
+ command: (command: OpenEditorRuntimeCommand) => Promise<OpenEditorCommandAck>;
47
+ focus: () => Promise<void>;
48
+ blur: () => Promise<void>;
49
+ subscribe: (listener: (event: OpenEditorNativeControllerEvent) => void) => () => void;
50
+ };
51
+ export type OpenEditorNativeBridgeOptions = {
52
+ sessionId: string;
53
+ requestTimeoutMs?: number;
54
+ send: (message: string) => void;
55
+ getEffectHandlers?: () => OpenEditorNativeEffectHandlers | undefined;
56
+ };
57
+ export declare class OpenEditorNativeBridge implements OpenEditorNativeController {
58
+ #private;
59
+ readonly sessionId: string;
60
+ constructor(options: OpenEditorNativeBridgeOptions);
61
+ get ready(): boolean;
62
+ get runtimeReady(): boolean;
63
+ waitUntilReady: () => Promise<void>;
64
+ getDocument: (options?: {
65
+ minimumRevision?: number;
66
+ }) => Promise<OpenEditorDocumentSnapshot>;
67
+ flushDocument: () => Promise<OpenEditorDocumentSnapshot>;
68
+ setDocument: (document: OpenEditorDocument) => Promise<number>;
69
+ command: (command: OpenEditorRuntimeCommand) => Promise<OpenEditorCommandAck>;
70
+ focus: () => Promise<void>;
71
+ blur: () => Promise<void>;
72
+ subscribe: (listener: (event: OpenEditorNativeControllerEvent) => void) => () => void;
73
+ initialize: (document: OpenEditorDocument, editable: boolean) => Promise<OpenEditorCommandAck>;
74
+ markInitialized: () => void;
75
+ receive: (raw: string) => boolean;
76
+ resetRuntime: () => void;
77
+ dispose: (reason?: string) => void;
78
+ }
79
+ export declare const emptyOpenEditorNativeState: OpenEditorRuntimeState;
@@ -0,0 +1,254 @@
1
+ import { OPENEDITOR_PROTOCOL, OPENEDITOR_PROTOCOL_VERSION, decodeOpenEditorRuntimeMessage, } from "@openeditor/embedded-runtime";
2
+ export class OpenEditorNativeLifecycleCancellationError extends Error {
3
+ code = "OPENEDITOR_NATIVE_LIFECYCLE_CANCELLED";
4
+ constructor(message) {
5
+ super(message);
6
+ this.name = "OpenEditorNativeLifecycleCancellationError";
7
+ }
8
+ }
9
+ export const isOpenEditorNativeLifecycleCancellation = (error) => error instanceof OpenEditorNativeLifecycleCancellationError;
10
+ export class OpenEditorNativeBridge {
11
+ #counter = 0;
12
+ #disposed = false;
13
+ #documentRevision = 0;
14
+ #effectHandlers;
15
+ #listeners = new Set();
16
+ #pending = new Map();
17
+ #ready = false;
18
+ #readyWaiters = new Set();
19
+ #revisionWaiters = new Set();
20
+ #runtimeReady = false;
21
+ #requestTimeoutMs;
22
+ #send;
23
+ sessionId;
24
+ constructor(options) {
25
+ this.sessionId = options.sessionId;
26
+ this.#send = options.send;
27
+ this.#effectHandlers = options.getEffectHandlers;
28
+ this.#requestTimeoutMs = options.requestTimeoutMs ?? 10_000;
29
+ }
30
+ get ready() { return this.#ready; }
31
+ get runtimeReady() { return this.#runtimeReady; }
32
+ waitUntilReady = () => this.#waitForReady();
33
+ getDocument = async (options) => {
34
+ await this.#waitForReady();
35
+ if ((options?.minimumRevision ?? 0) > this.#documentRevision)
36
+ await this.#waitForRevision(options.minimumRevision);
37
+ const result = await this.#sendCommand({ type: "requestDocument" }, true);
38
+ return result;
39
+ };
40
+ flushDocument = async () => {
41
+ await this.blur();
42
+ return this.getDocument();
43
+ };
44
+ setDocument = async (document) => (await this.command({ type: "replaceDocument", document })).documentRevision;
45
+ command = async (command) => {
46
+ await this.#waitForReady();
47
+ return this.#sendCommand(command, false);
48
+ };
49
+ focus = async () => { await this.command({ type: "focus" }); };
50
+ blur = async () => { await this.command({ type: "blur" }); };
51
+ subscribe = (listener) => {
52
+ this.#listeners.add(listener);
53
+ return () => { this.#listeners.delete(listener); };
54
+ };
55
+ initialize = (document, editable) => this.#sendCommand({ type: "initialize", document, editable }, false);
56
+ markInitialized = () => {
57
+ if (this.#ready)
58
+ return;
59
+ this.#ready = true;
60
+ for (const waiter of this.#readyWaiters) {
61
+ clearTimeout(waiter.timer);
62
+ waiter.resolve();
63
+ }
64
+ this.#readyWaiters.clear();
65
+ };
66
+ receive = (raw) => {
67
+ if (this.#disposed)
68
+ return false;
69
+ let message;
70
+ try {
71
+ message = decodeOpenEditorRuntimeMessage(raw);
72
+ }
73
+ catch {
74
+ return false;
75
+ }
76
+ if (message.sessionId !== this.sessionId)
77
+ return false;
78
+ if (message.type === "ready") {
79
+ this.#runtimeReady = true;
80
+ this.#updateRevision(message.state.documentRevision);
81
+ this.#emit(message);
82
+ }
83
+ else if (message.type === "ack")
84
+ this.#receiveAck(message);
85
+ else if (message.type === "documentSnapshot")
86
+ this.#receiveSnapshot(message);
87
+ else if (message.type === "nativeEffectRequest")
88
+ void this.#receiveEffectRequest(message);
89
+ else if (message.type === "error")
90
+ this.#receiveError(message);
91
+ else {
92
+ if (message.type === "stateChanged")
93
+ this.#updateRevision(message.state.documentRevision);
94
+ if (message.type === "documentChanged")
95
+ this.#updateRevision(message.documentRevision);
96
+ this.#emit(message);
97
+ }
98
+ return true;
99
+ };
100
+ resetRuntime = () => {
101
+ const replacesActiveRuntime = this.#runtimeReady || this.#ready;
102
+ this.#runtimeReady = false;
103
+ this.#ready = false;
104
+ this.#documentRevision = 0;
105
+ // onLoadStart is also emitted for the first, expected WebView load. Commands
106
+ // queued before that first load must remain waiting for initialization.
107
+ if (replacesActiveRuntime) {
108
+ this.#rejectPending(new OpenEditorNativeLifecycleCancellationError("OpenEditor runtime reloaded before responding."));
109
+ }
110
+ };
111
+ dispose = (reason = "OpenEditor native host was disposed.") => {
112
+ this.#disposed = true;
113
+ this.#runtimeReady = false;
114
+ this.#ready = false;
115
+ this.#rejectPending(new OpenEditorNativeLifecycleCancellationError(reason));
116
+ this.#listeners.clear();
117
+ };
118
+ #waitForReady() {
119
+ if (this.#disposed)
120
+ return Promise.reject(new Error("OpenEditor native host was disposed."));
121
+ if (this.#ready)
122
+ return Promise.resolve();
123
+ return new Promise((resolve, reject) => {
124
+ const waiter = {
125
+ resolve,
126
+ reject,
127
+ timer: setTimeout(() => {
128
+ this.#readyWaiters.delete(waiter);
129
+ reject(new Error("OpenEditor runtime did not become ready."));
130
+ }, this.#requestTimeoutMs),
131
+ };
132
+ this.#readyWaiters.add(waiter);
133
+ });
134
+ }
135
+ #waitForRevision(minimum) {
136
+ if (this.#documentRevision >= minimum)
137
+ return Promise.resolve();
138
+ return new Promise((resolve, reject) => {
139
+ const waiter = {
140
+ minimum,
141
+ resolve,
142
+ reject,
143
+ timer: setTimeout(() => {
144
+ this.#revisionWaiters.delete(waiter);
145
+ reject(new Error(`OpenEditor document revision ${minimum} was not reached.`));
146
+ }, this.#requestTimeoutMs),
147
+ };
148
+ this.#revisionWaiters.add(waiter);
149
+ });
150
+ }
151
+ #nextId() { this.#counter += 1; return `rn:${this.#counter}`; }
152
+ #sendCommand(command, needsSnapshot) {
153
+ const id = this.#nextId();
154
+ const envelope = { protocol: OPENEDITOR_PROTOCOL, version: OPENEDITOR_PROTOCOL_VERSION, sessionId: this.sessionId, type: "command", id, command };
155
+ return new Promise((resolve, reject) => {
156
+ const timer = setTimeout(() => { this.#pending.delete(id); reject(new Error(`OpenEditor runtime command timed out: ${command.type}`)); }, this.#requestTimeoutMs);
157
+ this.#pending.set(id, { command: command.type, resolve: (value) => resolve(value), reject, timer });
158
+ this.#send(JSON.stringify(envelope));
159
+ if (!needsSnapshot)
160
+ return;
161
+ });
162
+ }
163
+ #receiveAck(message) {
164
+ this.#updateRevision(message.documentRevision);
165
+ const pending = this.#pending.get(message.commandId);
166
+ if (!pending)
167
+ return;
168
+ pending.ack = message;
169
+ if (pending.command === "requestDocument")
170
+ this.#finishSnapshot(message.commandId, pending);
171
+ else
172
+ this.#finish(message.commandId, pending, message);
173
+ }
174
+ #receiveSnapshot(message) {
175
+ this.#updateRevision(message.documentRevision);
176
+ const pending = this.#pending.get(message.requestId);
177
+ if (!pending || pending.command !== "requestDocument")
178
+ return;
179
+ pending.snapshot = message;
180
+ this.#finishSnapshot(message.requestId, pending);
181
+ }
182
+ #finishSnapshot(id, pending) {
183
+ if (!pending.ack || !pending.snapshot)
184
+ return;
185
+ this.#finish(id, pending, { document: pending.snapshot.document, revision: pending.snapshot.documentRevision });
186
+ }
187
+ #finish(id, pending, value) {
188
+ this.#pending.delete(id);
189
+ clearTimeout(pending.timer);
190
+ pending.resolve(value);
191
+ }
192
+ #receiveError(message) {
193
+ if (message.commandId) {
194
+ const pending = this.#pending.get(message.commandId);
195
+ if (pending) {
196
+ this.#pending.delete(message.commandId);
197
+ clearTimeout(pending.timer);
198
+ pending.reject(new Error(`${message.code}: ${message.message}`));
199
+ }
200
+ }
201
+ this.#emit(message);
202
+ }
203
+ async #receiveEffectRequest(message) {
204
+ const handler = this.#effectHandlers?.()?.[message.effect.type];
205
+ let result;
206
+ try {
207
+ result = handler ? await handler(message.effect) : { status: "error", code: "missingHandler", message: `No native handler for ${message.effect.type}.` };
208
+ }
209
+ catch (error) {
210
+ result = { status: "error", code: "nativeEffectFailed", message: error instanceof Error ? error.message : "Native effect failed." };
211
+ }
212
+ const response = { protocol: OPENEDITOR_PROTOCOL, version: OPENEDITOR_PROTOCOL_VERSION, sessionId: this.sessionId, type: "nativeEffectResponse", id: this.#nextId(), requestId: message.id, effect: message.effect.type, result };
213
+ this.#send(JSON.stringify(response));
214
+ }
215
+ #updateRevision(revision) {
216
+ this.#documentRevision = Math.max(this.#documentRevision, revision);
217
+ for (const waiter of this.#revisionWaiters)
218
+ if (this.#documentRevision >= waiter.minimum) {
219
+ this.#revisionWaiters.delete(waiter);
220
+ clearTimeout(waiter.timer);
221
+ waiter.resolve();
222
+ }
223
+ }
224
+ #emit(message) { for (const listener of this.#listeners)
225
+ listener(message); }
226
+ #rejectPending(error) {
227
+ for (const pending of this.#pending.values()) {
228
+ clearTimeout(pending.timer);
229
+ pending.reject(error);
230
+ }
231
+ this.#pending.clear();
232
+ for (const waiter of this.#readyWaiters) {
233
+ clearTimeout(waiter.timer);
234
+ waiter.reject(error);
235
+ }
236
+ this.#readyWaiters.clear();
237
+ for (const waiter of this.#revisionWaiters) {
238
+ clearTimeout(waiter.timer);
239
+ waiter.reject(error);
240
+ }
241
+ this.#revisionWaiters.clear();
242
+ }
243
+ }
244
+ export const emptyOpenEditorNativeState = {
245
+ revision: 0,
246
+ documentRevision: 0,
247
+ activeMarks: [],
248
+ activeNodes: ["paragraph"],
249
+ canUndo: false,
250
+ canRedo: false,
251
+ editable: true,
252
+ focused: false,
253
+ selection: { type: "text", anchor: 1, head: 1 },
254
+ };
package/dist/index.d.ts CHANGED
@@ -1,101 +1,4 @@
1
- import { type OpenEditorDocument, type OpenEditorAttachmentRuntime, type OpenEditorAuthoringCapabilities, type OpenEditorPageRuntime, type OpenEditorPageSnapshot, type ProseMirrorNode } from "@openeditor/core";
2
- import { type ReactNode } from "react";
3
- import type { NativeRichTextEditorToolbarPlacement } from "@openeditor/react-native-prose-editor";
4
- export { normalizeNativeThemeColor } from "./theme.js";
5
- export { OpenEditorNativeEmojiPicker, type OpenEditorNativeEmojiPickerProps, type OpenEditorNativeEmojiPickerTheme, } from "./emoji-picker.js";
6
- export { emojiForNativeSkinTone, getOpenEditorNativeEmojiSections, openEditorNativeEmojiSkinToneOptions, type OpenEditorNativeEmoji, type OpenEditorNativeEmojiSection, type OpenEditorNativeEmojiSkinTone, } from "./emoji-data.js";
7
- export type OpenEditorNativeProps = OpenEditorAuthoringCapabilities & {
8
- initialDocument?: OpenEditorDocument;
9
- editable?: boolean;
10
- placeholder?: string;
11
- showToolbar?: boolean;
12
- theme?: Partial<OpenEditorNativeTheme>;
13
- toolbarPlacement?: NativeRichTextEditorToolbarPlacement;
14
- onChange?: (document: OpenEditorDocument) => void;
15
- pageRuntime?: OpenEditorPageRuntime;
16
- attachmentRuntime?: OpenEditorAttachmentRuntime<any>;
17
- };
18
- export type OpenEditorNativeViewerProps = {
19
- document: OpenEditorDocument;
20
- theme?: Partial<OpenEditorNativeTheme>;
21
- pageRuntime?: OpenEditorPageRuntime;
22
- attachmentRuntime?: OpenEditorAttachmentRuntime<any>;
23
- renderers?: Partial<Record<string, OpenEditorNativeViewerRenderer>>;
24
- };
25
- export type OpenEditorNativeController = {
26
- getContent: () => OpenEditorDocument;
27
- setContent: (document: OpenEditorDocument) => void;
28
- undo: () => void;
29
- redo: () => void;
30
- };
31
- export type OpenEditorNativeToolbarAction = {
32
- key: string;
33
- label: string;
34
- onPress?: (key: string) => void;
35
- };
36
- export type OpenEditorNativeToolbarProps = {
37
- actions?: readonly OpenEditorNativeToolbarAction[];
38
- onActionPress?: (key: string) => void;
39
- theme?: Partial<OpenEditorNativeTheme>;
40
- };
41
- export type OpenEditorNativeViewerRenderer = (context: {
42
- node: ProseMirrorNode;
43
- children: ReactNode;
44
- theme: Required<OpenEditorNativeTheme>;
45
- }) => ReactNode;
46
- export type OpenEditorNativeToolbarTheme = {
47
- height?: number;
48
- };
49
- export type OpenEditorNativeTheme = {
50
- background: string;
51
- surface: string;
52
- surfaceMuted: string;
53
- blockSurface?: string;
54
- text: string;
55
- textSoft?: string;
56
- muted: string;
57
- placeholder?: string;
58
- border: string;
59
- borderStrong?: string;
60
- structuralLine?: string;
61
- accent: string;
62
- accentText: string;
63
- accentStrong?: string;
64
- primary: string;
65
- primaryText: string;
66
- codeBackground?: string;
67
- codeText?: string;
68
- debugBackground?: string;
69
- debugText?: string;
70
- debugHeading?: string;
71
- debugBorder?: string;
72
- debugButtonBackground?: string;
73
- success?: string;
74
- shadow?: string;
75
- backdrop: string;
76
- toolbar?: OpenEditorNativeToolbarTheme;
77
- };
78
- export declare const OpenEditorNativeToolbar: ({ actions, onActionPress, theme, }: OpenEditorNativeToolbarProps) => import("react").JSX.Element;
79
- export type OpenEditorNativePageHeaderProps = {
80
- page: OpenEditorPageSnapshot;
81
- runtime: OpenEditorPageRuntime;
82
- theme?: Partial<OpenEditorNativeTheme>;
83
- onPageChange?: (page: OpenEditorPageSnapshot) => void;
84
- };
85
- /** Canonical native page-title and page-icon editor for opened page surfaces. */
86
- export declare const OpenEditorNativePageHeader: ({ page, runtime, theme, onPageChange }: OpenEditorNativePageHeaderProps) => import("react").JSX.Element;
87
- export declare const OpenEditorNative: import("react").ForwardRefExoticComponent<OpenEditorAuthoringCapabilities & {
88
- initialDocument?: OpenEditorDocument;
89
- editable?: boolean;
90
- placeholder?: string;
91
- showToolbar?: boolean;
92
- theme?: Partial<OpenEditorNativeTheme>;
93
- toolbarPlacement?: NativeRichTextEditorToolbarPlacement;
94
- onChange?: (document: OpenEditorDocument) => void;
95
- pageRuntime?: OpenEditorPageRuntime;
96
- attachmentRuntime?: OpenEditorAttachmentRuntime<any>;
97
- } & import("react").RefAttributes<OpenEditorNativeController>>;
98
- export declare const OpenEditorNativeViewer: ({ document, theme, renderers, pageRuntime, attachmentRuntime, }: OpenEditorNativeViewerProps) => import("react").JSX.Element;
99
- export { createNativeEditorDocument, fromNativeEditorDocument, sanitizeNativeEditorDocument, toNativeEditorDocument, } from "./document.js";
100
- export { createOpenEditorNativeToolbarItems, defaultDocumentForToolbarAction, nativeToolbarParityCoverage, openEditorNativeToolbarActionKeys, openEditorNativeToolbarItems, } from "./toolbar.js";
101
- export type { OpenEditorNativeToolbarActionKey } from "./toolbar.js";
1
+ export { OpenEditorNative, type OpenEditorNativeContentInsets, type OpenEditorNativeProps, type OpenEditorNativeTheme, } from "./native-editor.js";
2
+ export { type OpenEditorNativeController, type OpenEditorNativeControllerEvent, type OpenEditorNativeEffectHandlers, } from "./controller.js";
3
+ export { OpenEditorNativeToolbar, defaultOpenEditorNativeToolbarItems, openEditorNativeBlockPickerItems, type OpenEditorNativeToolbarItem, type OpenEditorNativeToolbarProps, } from "./toolbar-host.js";
4
+ export type { OpenEditorRuntimeCommand, OpenEditorRuntimeState } from "@openeditor/embedded-runtime";