@openeditor/native 0.0.33 → 0.0.35

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,101 @@
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 SDK
13
+ sticks that toolbar to the keyboard, reserves its document inset, and enables
14
+ interactive keyboard dismissal while the editor scrolls. Consumers can opt
15
+ back into the system bar with
16
+ `webViewProps={{ hideKeyboardAccessoryView: false }}`.
8
17
 
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
18
+ The `theme` prop accepts the same OpenEditor theme-token contract used by the
19
+ web React surface.
14
20
 
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.
21
+ ## Host integration
18
22
 
19
- ## Required peers
23
+ Install the native peer dependencies:
20
24
 
21
- - `@openeditor/react-native-prose-editor`
22
- - `react`
23
- - `react-native`
24
- - `react-native-keyboard-controller` (optional but recommended for keyboard toolbar placement)
25
+ ```sh
26
+ pnpm add expo-glass-effect react-native-keyboard-controller react-native-reanimated react-native-svg react-native-webview
27
+ ```
25
28
 
26
- ## Quick start
29
+ For Expo, install the SDK plugin so iOS WebViews receive interactive keyboard
30
+ dismissal:
27
31
 
28
- ```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
- );
32
+ ```json
33
+ {
34
+ "expo": {
35
+ "plugins": ["@openeditor/native/plugin"]
36
+ }
43
37
  }
44
38
  ```
45
39
 
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:
40
+ Rebuild the native application after adding the plugin or a native dependency.
41
+ Mount the SDK provider once at the app root:
59
42
 
60
43
  ```tsx
61
- import { OpenEditorNativeEmojiPicker } from "@openeditor/native";
44
+ import { OpenEditorNativeProvider } from "@openeditor/native";
62
45
 
63
- <OpenEditorNativeEmojiPicker
64
- visible={pickerOpen}
65
- onEmojiSelect={setPageIcon}
66
- onRequestClose={() => setPickerOpen(false)}
67
- />;
46
+ export default function RootLayout() {
47
+ return <OpenEditorNativeProvider>{/* app routes */}</OpenEditorNativeProvider>;
48
+ }
68
49
  ```
69
50
 
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.
51
+ The self-contained offline runtime is packaged with the component, so Metro
52
+ asset customization is not required:
74
53
 
75
- ## Internal notes
54
+ ```tsx
55
+ const editor = useRef<OpenEditorNativeController>(null);
56
+
57
+ <OpenEditorNative
58
+ ref={editor}
59
+ initialDocument={document}
60
+ contentInsets={{ top: transparentHeaderHeight, bottom: 16 }}
61
+ onDocumentChanged={({ documentRevision }) => {
62
+ scheduleAutosave(async () => {
63
+ const snapshot = await editor.current?.getDocument({
64
+ minimumRevision: documentRevision,
65
+ });
66
+ if (snapshot) await save(snapshot.document);
67
+ });
68
+ }}
69
+ nativeEffects={{
70
+ pickAttachment: pickUploadAndReturnDurableAttachment,
71
+ createPage: openCreatePageSheet,
72
+ updatePage: updatePageMetadata,
73
+ openPage: navigateToPage,
74
+ }}
75
+ />
76
+ ```
76
77
 
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`.
78
+ The default toolbar is a keyboard-sticky, inset pill that meets the keyboard
79
+ edge without a synthetic spacer. It uses native iOS glass and a theme-aware
80
+ material fallback elsewhere. A custom `renderToolbar` returns only the toolbar
81
+ content; the SDK still owns its glass surface and positioning, so do not add
82
+ another `KeyboardStickyView` or outer background. Use `toolbarContentInset`
83
+ when the custom toolbar needs more than the default 76-point document clearance,
84
+ and `toolbarOffset` only when the keyboard edge itself needs a different gap.
85
+
86
+ The editor host must reach the screen's bottom edge. Do not wrap the editor in
87
+ a bottom-padding `SafeAreaView`; the keyboard owns that edge while editing, and
88
+ reserving the home-indicator inset there creates a visible toolbar gap.
89
+
90
+ The block picker derives its available page, image, and attachment commands
91
+ from the supplied effect handlers. If the application cannot upload media to a
92
+ durable URL, omit the corresponding picker effect rather than returning a
93
+ temporary `file://` URI.
94
+
95
+ Do not wrap the component in a React Native `ScrollView`; give it a bounded
96
+ flex layout so the WebView remains the only document scroll owner. Before a
97
+ screen transition or background save, call `flushDocument()` to commit pending
98
+ composition and receive the current snapshot.
99
+
100
+ For a read-only surface, use
101
+ `<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,6 @@
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 { OpenEditorNativeProvider, type OpenEditorNativeProviderProps, } from "./native-provider.js";
3
+ export { type OpenEditorNativeController, type OpenEditorNativeControllerEvent, type OpenEditorNativeEffectHandlers, } from "./controller.js";
4
+ export { OpenEditorNativeToolbar, defaultOpenEditorNativeToolbarItems, openEditorNativeBlockPickerItems, type OpenEditorNativeToolbarItem, type OpenEditorNativeToolbarProps, } from "./toolbar-host.js";
5
+ export { resolveOpenEditorNativeTheme, type OpenEditorNativeColorScheme, type ResolvedOpenEditorNativeTheme, } from "./theme.js";
6
+ export type { OpenEditorRuntimeCommand, OpenEditorRuntimeState } from "@openeditor/embedded-runtime";