@openeditor/react 0.0.29 → 0.0.31

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
@@ -2,17 +2,48 @@
2
2
 
3
3
  Headless React bindings for OpenEditor's web editor runtime.
4
4
 
5
- Pass `attachmentRuntime` to `useOpenEditorController` for editable attachments and to `OpenEditorViewer` for identity-based resolution/opening. Progress, cancellation, retry input, and errors remain transient node-view state and are never emitted through document JSON.
5
+ Pass `imageRuntime` and `attachmentRuntime` to `useOpenEditorController` for
6
+ host-backed media and to `OpenEditorViewer` for identity-based URL resolution.
7
+ Progress, cancellation, retry input, and errors remain transient node-view state
8
+ and are never emitted through document JSON.
9
+
10
+ An inserted image starts as an empty image node—never a fake placeholder URL.
11
+ The built-in node view offers upload, drag/drop, URL embedding, replacement,
12
+ alternative-text editing, progress, retry, and removal. The upload button is
13
+ shown only when the host supplies `selectImage` and `uploadImage`:
14
+
15
+ ```tsx
16
+ const imageRuntime = {
17
+ selectImage: () => chooseImageFromYourPicker(),
18
+ validateImage: (input) => input.size && input.size > 15_000_000
19
+ ? { accepted: false, message: "Image is too large." }
20
+ : { accepted: true },
21
+ uploadImage: (input, { signal, onProgress } = {}) =>
22
+ uploadToYourStorage(input.source, { signal, onProgress }),
23
+ resolveImage: (imageId, { signal } = {}) =>
24
+ resolveImageFromYourStorage(imageId, { signal }),
25
+ replaceImage: (imageId, input, options) =>
26
+ replaceImageInYourStorage(imageId, input.source, options),
27
+ };
28
+
29
+ const controller = useOpenEditorController({ imageRuntime });
30
+ ```
31
+
32
+ `uploadImage` and `replaceImage` return an `OpenEditorImageSnapshot`. Store a
33
+ durable `imageId`, public `src`, or both; `resolveImage` may return a temporary
34
+ owner-preview URL such as a `blob:` URL without serializing it.
6
35
 
7
36
  ## Public surface
8
37
 
9
38
  - `useOpenEditorController` for editor state, commands, document exports, and selection state
10
39
  - `OpenEditorContent` for the editable Tiptap-backed content surface
40
+ - `OpenEditorBubbleMenu` for Tiptap-owned selection visibility and positioning
11
41
  - `OpenEditorViewer` for read-only React rendering
12
42
  - `OpenEditorPageHeader` for host-backed page title and icon editing
13
43
  - `getDefaultBlockPickerItems` for host-owned block rails, pickers, and command palettes
14
44
  - `getDefaultSlashMenuItems` for UI packages that want the built-in insert actions
15
45
  - stable-identity block targeting and transaction-backed copy, duplicate, move, and delete commands
46
+ - a first-class `controller.table` domain API for selection-aware row, column, header, cell, and table commands
16
47
  - `OpenEditorBlockDragHandle` and `useOpenEditorBlockInteraction` for headless block-handle UIs
17
48
  - `defineOpenEditorReactNode` for consumer-owned React blocks
18
49
  - `defineOpenEditorReactExtension` for advanced integrations that contribute multiple Tiptap extensions
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, CSSProperties, RefObject, ComponentType } from 'react';
3
- import { OpenEditorBlockRef, OpenEditorDocument, BlockSpec, ProseMirrorNode, OpenEditorUrlPolicy, OpenEditorUrlContext, OpenEditorPageRuntime, OpenEditorAttachmentRuntime, OpenEditorPageSnapshot, OpenEditorAuthoringCapabilities } from '@openeditor/core';
4
- export { OpenEditorBlockRef, OpenEditorPageRuntime, OpenEditorPageSnapshot, OpenEditorUrlContext, OpenEditorUrlPolicy, openEditorPublicUrlPolicy, openEditorUnsafeUrlPolicy } from '@openeditor/core';
3
+ import { OpenEditorBlockRef, OpenEditorDocument, BlockSpec, ProseMirrorNode, OpenEditorUrlPolicy, OpenEditorUrlContext, OpenEditorPageRuntime, OpenEditorAttachmentRuntime, OpenEditorImageRuntime, OpenEditorPageSnapshot, OpenEditorAuthoringCapabilities } from '@openeditor/core';
4
+ export { OpenEditorBlockRef, OpenEditorImageRuntime, OpenEditorImageSnapshot, OpenEditorImageUploadInput, OpenEditorPageRuntime, OpenEditorPageSnapshot, OpenEditorUrlContext, OpenEditorUrlPolicy, openEditorPublicUrlPolicy, openEditorUnsafeUrlPolicy } from '@openeditor/core';
5
5
  import { ExportFormat, OpenEditorExporters } from '@openeditor/exporters';
6
6
  export { seedDocument } from '@openeditor/extensions';
7
- import { AnyExtension, NodeConfig } from '@tiptap/core';
7
+ import { Editor, 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
 
@@ -29,6 +29,27 @@ declare function OpenEditorThemeProvider({ children, className, theme }: {
29
29
  theme: OpenEditorTheme;
30
30
  }): react.JSX.Element;
31
31
 
32
+ declare const openEditorTableCommands: readonly ["addRowBefore", "addRowAfter", "deleteRow", "addColumnBefore", "addColumnAfter", "deleteColumn", "toggleHeaderRow", "toggleHeaderColumn", "mergeCells", "splitCell", "deleteTable"];
33
+ type OpenEditorTableCommand = (typeof openEditorTableCommands)[number];
34
+ type OpenEditorTableState = {
35
+ active: boolean;
36
+ rows: number;
37
+ columns: number;
38
+ headerRow: boolean;
39
+ headerColumn: boolean;
40
+ cellSelection: boolean;
41
+ canMergeCells: boolean;
42
+ canSplitCell: boolean;
43
+ };
44
+ type OpenEditorTableController = {
45
+ getState: () => OpenEditorTableState;
46
+ can: (command: OpenEditorTableCommand) => boolean;
47
+ run: (command: OpenEditorTableCommand) => boolean;
48
+ };
49
+ declare const getOpenEditorTableState: (editor: Editor | null) => OpenEditorTableState;
50
+ declare const canRunOpenEditorTableCommand: (editor: Editor | null, command: OpenEditorTableCommand) => boolean;
51
+ declare const runOpenEditorTableCommand: (editor: Editor | null, command: OpenEditorTableCommand) => boolean;
52
+
32
53
  type OpenEditorReactProps = OpenEditorAuthoringCapabilities & {
33
54
  initialDocument?: OpenEditorDocument;
34
55
  editable?: boolean;
@@ -37,6 +58,7 @@ type OpenEditorReactProps = OpenEditorAuthoringCapabilities & {
37
58
  onFilePasteDrop?: (file: File) => boolean;
38
59
  pageRuntime?: OpenEditorPageRuntime;
39
60
  attachmentRuntime?: OpenEditorAttachmentRuntime<any>;
61
+ imageRuntime?: OpenEditorImageRuntime<any>;
40
62
  slashMenuItems?: readonly OpenEditorSlashMenuItem[];
41
63
  /** Consumer-owned blocks. Extension names and node types must be unique. */
42
64
  extensions?: readonly OpenEditorReactExtension[];
@@ -65,6 +87,8 @@ type OpenEditorController = {
65
87
  setSelectedBlock: (blockName: string) => void;
66
88
  getContent: () => OpenEditorDocument;
67
89
  setContent: (document: OpenEditorDocument) => void;
90
+ focus: () => void;
91
+ getPositionRect: (position: number) => OpenEditorOverlayRect | null;
68
92
  setParagraph: () => void;
69
93
  toggleHeading: (level: 1 | 2 | 3 | 4 | 5 | 6) => void;
70
94
  toggleBold: () => void;
@@ -77,6 +101,7 @@ type OpenEditorController = {
77
101
  toggleTaskList: () => void;
78
102
  toggleBlockquote: () => void;
79
103
  toggleCodeBlock: () => void;
104
+ table: OpenEditorTableController;
80
105
  undo: () => void;
81
106
  redo: () => void;
82
107
  insertBlock: (blockName?: string, range?: InsertRange) => boolean;
@@ -98,9 +123,11 @@ type OpenEditorController = {
98
123
  extensions: readonly OpenEditorReactExtension[];
99
124
  pageRuntime?: OpenEditorPageRuntime;
100
125
  attachmentRuntime?: OpenEditorAttachmentRuntime<any>;
126
+ imageRuntime?: OpenEditorImageRuntime<any>;
101
127
  enabledBlocks?: readonly string[];
102
128
  slashState: SlashState | null;
103
- selectionBubbleState: SelectionBubbleState | null;
129
+ dismissSlashMenu: () => void;
130
+ registerSlashMenuKeyboardHandler: (handler: (event: globalThis.KeyboardEvent) => boolean) => () => void;
104
131
  };
105
132
  type OpenEditorContentProps = {
106
133
  controller: OpenEditorController;
@@ -126,11 +153,6 @@ type SlashState = {
126
153
  top: number;
127
154
  anchorRect?: OpenEditorOverlayRect;
128
155
  };
129
- type SelectionBubbleState = {
130
- left: number;
131
- top: number;
132
- anchorRect?: OpenEditorOverlayRect;
133
- };
134
156
  type OpenEditorSlashMenuIconProps = {
135
157
  "aria-hidden"?: boolean;
136
158
  className?: string;
@@ -212,6 +234,7 @@ type OpenEditorViewerProps = {
212
234
  extensions?: readonly OpenEditorReactExtension[];
213
235
  pageRuntime?: OpenEditorPageRuntime;
214
236
  attachmentRuntime?: OpenEditorAttachmentRuntime<any>;
237
+ imageRuntime?: OpenEditorImageRuntime<any>;
215
238
  /** Safe by default. Supply an explicit host policy for trusted preview URLs such as `blob:`. */
216
239
  urlPolicy?: OpenEditorUrlPolicy;
217
240
  };
@@ -231,7 +254,26 @@ type OpenEditorPageHeaderProps = {
231
254
  };
232
255
  /** Canonical Notion-style page metadata editor shared by host page surfaces. */
233
256
  declare const OpenEditorPageHeader: ({ page, runtime, className, onPageChange, }: OpenEditorPageHeaderProps) => react.JSX.Element;
234
- declare const useOpenEditorController: ({ initialDocument, editable, placeholder, onChange, onFilePasteDrop, pageRuntime, attachmentRuntime, enabledBlocks, slashMenuItems, extensions, blockActions, }?: OpenEditorReactProps) => OpenEditorController;
257
+ declare const useOpenEditorController: ({ initialDocument, editable, placeholder, onChange, onFilePasteDrop, pageRuntime, attachmentRuntime, imageRuntime, enabledBlocks, slashMenuItems, extensions, blockActions, }?: OpenEditorReactProps) => OpenEditorController;
258
+ type OpenEditorBubbleMenuProps = {
259
+ controller: OpenEditorController;
260
+ children: ReactNode;
261
+ className?: string;
262
+ container?: HTMLElement | null;
263
+ scrollTarget?: HTMLElement | Window | null;
264
+ style?: CSSProperties;
265
+ };
266
+ type OpenEditorTableBubbleMenuProps = {
267
+ controller: OpenEditorController;
268
+ children: (state: OpenEditorTableState) => ReactNode;
269
+ className?: string;
270
+ container?: HTMLElement | null;
271
+ style?: CSSProperties;
272
+ };
273
+ /** Selection-aware positioning and lifecycle owned by Tiptap's BubbleMenu plugin. */
274
+ declare const OpenEditorBubbleMenu: ({ controller, children, className, container, scrollTarget, style, }: OpenEditorBubbleMenuProps) => react.JSX.Element | null;
275
+ /** A table-owned contextual surface, anchored to the complete selected table. */
276
+ declare const OpenEditorTableBubbleMenu: ({ controller, children, className, container, style, }: OpenEditorTableBubbleMenuProps) => react.JSX.Element | null;
235
277
  declare const useOpenEditorBlockInteraction: (controller: OpenEditorController) => OpenEditorBlockInteractionSnapshot;
236
278
  type OpenEditorBlockDragHandleProps = {
237
279
  controller: OpenEditorController;
@@ -254,7 +296,7 @@ declare const sortBlockPickerItems: (items: readonly OpenEditorBlockPickerItem[]
254
296
  declare const getDefaultBlockPickerItems: (controller: OpenEditorController) => OpenEditorBlockPickerItem[];
255
297
  declare const getDefaultSlashMenuItems: (controller: OpenEditorController) => OpenEditorSlashMenuItem[];
256
298
  declare const OpenEditorContent: ({ controller, className, }: OpenEditorContentProps) => react.JSX.Element;
257
- declare const OpenEditorViewer: ({ document, className, renderers, extensions, pageRuntime, attachmentRuntime, urlPolicy, }: OpenEditorViewerProps) => react.JSX.Element;
258
- declare const useOpenEditor: ({ initialDocument, editable, placeholder, onChange, onFilePasteDrop, pageRuntime, attachmentRuntime, enabledBlocks, slashMenuItems, extensions, blockActions, }?: OpenEditorReactProps) => OpenEditorController;
299
+ declare const OpenEditorViewer: ({ document, className, renderers, extensions, pageRuntime, attachmentRuntime, imageRuntime, urlPolicy, }: OpenEditorViewerProps) => react.JSX.Element;
300
+ declare const useOpenEditor: ({ initialDocument, editable, placeholder, onChange, onFilePasteDrop, pageRuntime, attachmentRuntime, imageRuntime, enabledBlocks, slashMenuItems, extensions, blockActions, }?: OpenEditorReactProps) => OpenEditorController;
259
301
 
260
- 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 };
302
+ export { type InsertRange, type OpenEditorBlockAction, type OpenEditorBlockActionContext, OpenEditorBlockDragHandle, type OpenEditorBlockDragHandleProps, type OpenEditorBlockPickerItem, OpenEditorBubbleMenu, type OpenEditorBubbleMenuProps, 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, OpenEditorTableBubbleMenu, type OpenEditorTableBubbleMenuProps, type OpenEditorTableCommand, type OpenEditorTableController, type OpenEditorTableState, type OpenEditorTheme, OpenEditorThemeProvider, type OpenEditorThemeStyle, type OpenEditorThemeToken, OpenEditorViewer, type OpenEditorViewerProps, type OpenEditorViewerRenderer, type SlashState, canRunOpenEditorTableCommand, createOpenEditorThemeStyle, defineOpenEditorReactExtension, defineOpenEditorReactNode, formatAttachmentSize, getDefaultBlockPickerItems, getDefaultSlashMenuItems, getOpenEditorTableState, openEditorTableCommands, openEditorThemeTokenNames, runOpenEditorTableCommand, sortBlockPickerItems, sortSlashMenuItems, useOpenEditor, useOpenEditorBlockInteraction, useOpenEditorController, useOpenEditorThemeStyle };