@openeditor/native 0.0.10 → 0.0.12

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 CHANGED
@@ -10,6 +10,12 @@ export type OpenEditorNativeProps = {
10
10
  theme?: Partial<OpenEditorNativeTheme>;
11
11
  toolbarPlacement?: NativeRichTextEditorToolbarPlacement;
12
12
  onChange?: (document: OpenEditorDocument) => void;
13
+ onOpenPage?: (page: {
14
+ pageId: string;
15
+ title: string;
16
+ icon?: string | null;
17
+ href?: string | null;
18
+ }) => void;
13
19
  };
14
20
  export type OpenEditorNativeViewerProps = Omit<OpenEditorNativeProps, "editable" | "showToolbar" | "onChange"> & {
15
21
  showToolbar?: false;
@@ -61,8 +67,8 @@ export type OpenEditorNativeTheme = {
61
67
  toolbar?: OpenEditorNativeToolbarTheme;
62
68
  };
63
69
  export declare const OpenEditorNativeToolbar: ({ actions, onActionPress, theme, }: OpenEditorNativeToolbarProps) => import("react").JSX.Element;
64
- export declare const OpenEditorNative: ({ document, editable, placeholder, showToolbar, theme, toolbarPlacement, onChange, }: OpenEditorNativeProps) => import("react").JSX.Element;
65
- export declare const OpenEditorNativeViewer: ({ document, theme, renderers, }: OpenEditorNativeViewerProps) => import("react").JSX.Element;
70
+ export declare const OpenEditorNative: ({ document, editable, placeholder, showToolbar, theme, toolbarPlacement, onChange, onOpenPage, }: OpenEditorNativeProps) => import("react").JSX.Element;
71
+ export declare const OpenEditorNativeViewer: ({ document, theme, renderers, onOpenPage, }: OpenEditorNativeViewerProps) => import("react").JSX.Element;
66
72
  export { createNativeEditorDocument, fromNativeEditorDocument, sanitizeNativeEditorDocument, toNativeEditorDocument, } from "./document.js";
67
73
  export { createOpenEditorNativeToolbarItems, defaultDocumentForToolbarAction, nativeToolbarParityCoverage, openEditorNativeToolbarActionKeys, openEditorNativeToolbarItems, } from "./toolbar.js";
68
74
  export type { OpenEditorNativeToolbarActionKey } from "./toolbar.js";
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { createDocument, findBlockSpecForNode, moveTopLevelBlock, textBlock, } from "@openeditor/core";
3
3
  import { useMemo, useRef, useState } from "react";
4
4
  import { Image as NativeImage, Keyboard, Modal, Platform, Pressable, StyleSheet, Text, TextInput, View } from "react-native";
@@ -58,6 +58,34 @@ const openEditorNativeSchema = {
58
58
  htmlTag: "li",
59
59
  attrs: { checked: { default: false } },
60
60
  },
61
+ { name: "toggleList", content: "toggleListItem+", group: "block", role: "list", htmlTag: "ul" },
62
+ {
63
+ name: "toggleListItem",
64
+ content: "paragraph block*",
65
+ role: "listItem",
66
+ htmlTag: "li",
67
+ attrs: { open: { default: true } },
68
+ },
69
+ {
70
+ name: "callout",
71
+ content: "block+",
72
+ group: "block",
73
+ role: "block",
74
+ htmlTag: "aside",
75
+ attrs: { tone: { default: "info" } },
76
+ },
77
+ {
78
+ name: "page",
79
+ content: "inline*",
80
+ group: "block",
81
+ role: "textBlock",
82
+ htmlTag: "p",
83
+ attrs: {
84
+ pageId: { default: null },
85
+ icon: { default: "📄" },
86
+ href: { default: null },
87
+ },
88
+ },
61
89
  { name: "codeBlock", content: "text*", group: "block", role: "textBlock", htmlTag: "pre" },
62
90
  { name: "horizontalRule", content: "", group: "block", role: "block", htmlTag: "hr", isVoid: true },
63
91
  {
@@ -291,11 +319,11 @@ const nativeSeedDocument = createDocument([
291
319
  { type: "horizontalRule" },
292
320
  { type: "image", attrs: { src: "https://placehold.co/960x420/png", alt: "Placeholder" } },
293
321
  ]);
294
- const renderNativeViewerNode = (node, key, theme, renderers) => {
322
+ const renderNativeViewerNode = (node, key, theme, renderers, onOpenPage) => {
295
323
  if (node.type === "text") {
296
324
  return _jsx(Text, { style: { color: theme.text }, children: node.text ?? "" }, key);
297
325
  }
298
- const children = node.content?.map((child, index) => renderNativeViewerNode(child, `${key}-${index}`, theme, renderers)) ?? null;
326
+ const children = node.content?.map((child, index) => renderNativeViewerNode(child, `${key}-${index}`, theme, renderers, onOpenPage)) ?? null;
299
327
  const blockKey = findBlockSpecForNode(defaultBlockRegistry, node)?.name ?? node.type;
300
328
  const customRenderer = renderers?.[blockKey];
301
329
  if (customRenderer) {
@@ -325,6 +353,13 @@ const renderNativeViewerNode = (node, key, theme, renderers) => {
325
353
  return _jsx(View, { style: { flexDirection: "row", gap: 12, marginBottom: 12 }, children: children }, key);
326
354
  case "table":
327
355
  return _jsx(View, { style: { borderColor: theme.border, borderRadius: 8, borderWidth: 1, marginBottom: 12, overflow: "hidden" }, children: children }, key);
356
+ case "page": {
357
+ const pageId = typeof node.attrs?.pageId === "string" ? node.attrs.pageId : "";
358
+ const title = node.content?.map((child) => child.text ?? "").join("") || "Untitled";
359
+ const icon = typeof node.attrs?.icon === "string" ? node.attrs.icon : "📄";
360
+ const content = _jsxs(_Fragment, { children: [_jsx(Text, { style: { fontSize: 18 }, children: icon }), _jsx(Text, { style: { color: theme.text, flex: 1, fontWeight: "600", textDecorationLine: "underline" }, children: title }), _jsx(Text, { style: { color: theme.muted }, children: "\u2192" })] });
361
+ return onOpenPage && pageId ? (_jsx(Pressable, { accessibilityRole: "button", onPress: () => onOpenPage({ pageId, title, icon, href: typeof node.attrs?.href === "string" ? node.attrs.href : null }), style: { alignItems: "center", borderRadius: 8, flexDirection: "row", gap: 8, marginBottom: 8, padding: 8 }, children: content }, key)) : _jsx(View, { style: { alignItems: "center", flexDirection: "row", gap: 8, marginBottom: 8, padding: 8 }, children: content }, key);
362
+ }
328
363
  default:
329
364
  if (node.type === "column") {
330
365
  return _jsx(View, { style: { flex: 1 }, children: children }, key);
@@ -361,7 +396,7 @@ export const OpenEditorNativeToolbar = ({ actions = [
361
396
  onActionPress?.(action.key);
362
397
  }, style: [styles.toolbarButton, { backgroundColor: resolvedTheme.accent, borderColor: resolvedTheme.borderStrong }], children: _jsx(Text, { style: [styles.toolbarButtonText, { color: resolvedTheme.accentText }], children: action.label }) }, action.key))) }));
363
398
  };
364
- export const OpenEditorNative = ({ document = nativeSeedDocument, editable = true, placeholder = "Start writing...", showToolbar = true, theme, toolbarPlacement = "keyboard", onChange, }) => {
399
+ export const OpenEditorNative = ({ document = nativeSeedDocument, editable = true, placeholder = "Start writing...", showToolbar = true, theme, toolbarPlacement = "keyboard", onChange, onOpenPage, }) => {
365
400
  const editorRef = useRef(null);
366
401
  const [currentDocument, setCurrentDocument] = useState(() => normalizeForNativeEditor(document));
367
402
  const [selection, setSelection] = useState();
@@ -501,11 +536,11 @@ export const OpenEditorNative = ({ document = nativeSeedDocument, editable = tru
501
536
  }, onRequestImage: (request) => {
502
537
  setImageUrl("https://placehold.co/960x420/png");
503
538
  setImageRequest(request);
504
- }, onSelectionChange: setSelection, onContentChangeJSON: (json) => {
539
+ }, onOpenPage: onOpenPage, onSelectionChange: setSelection, onContentChangeJSON: (json) => {
505
540
  syncDocument(contentFromNativeJson(json), false);
506
541
  }, style: styles.nativeEditor }), _jsx(UrlDialog, { title: "Link", value: linkUrl, visible: linkRequest !== null, placeholder: "https://", confirmLabel: linkUrl.trim() ? "Apply" : "Remove", onChangeText: setLinkUrl, onCancel: () => setLinkRequest(null), onSubmit: submitLinkDialog, theme: resolvedTheme }), _jsx(UrlDialog, { title: "Image", value: imageUrl, visible: imageRequest !== null, placeholder: "https://", confirmLabel: "Insert", onChangeText: setImageUrl, onCancel: () => setImageRequest(null), onSubmit: submitImageDialog, theme: resolvedTheme })] }));
507
542
  };
508
- export const OpenEditorNativeViewer = ({ document = nativeSeedDocument, theme, renderers, }) => {
543
+ export const OpenEditorNativeViewer = ({ document = nativeSeedDocument, theme, renderers, onOpenPage, }) => {
509
544
  const resolvedTheme = {
510
545
  ...defaultNativeTheme,
511
546
  ...theme,
@@ -515,7 +550,7 @@ export const OpenEditorNativeViewer = ({ document = nativeSeedDocument, theme, r
515
550
  },
516
551
  };
517
552
  const normalizedDocument = normalizeForNativeEditor(document);
518
- return (_jsx(View, { style: [styles.viewer, { backgroundColor: resolvedTheme.surface, borderColor: resolvedTheme.border }], children: normalizedDocument.content.map((node, index) => renderNativeViewerNode(node, `native-viewer-${index}`, resolvedTheme, renderers)) }));
553
+ return (_jsx(View, { style: [styles.viewer, { backgroundColor: resolvedTheme.surface, borderColor: resolvedTheme.border }], children: normalizedDocument.content.map((node, index) => renderNativeViewerNode(node, `native-viewer-${index}`, resolvedTheme, renderers, onOpenPage)) }));
519
554
  };
520
555
  const CommandButton = ({ label, active = false, primary = false, theme, onPress, }) => (_jsx(Pressable, { accessibilityRole: "button", accessibilityState: { selected: active }, onPress: onPress, style: [
521
556
  styles.commandButton,
package/dist/toolbar.d.ts CHANGED
@@ -6,6 +6,9 @@ export declare const openEditorNativeToolbarActionKeys: {
6
6
  readonly orderedList: "orderedList";
7
7
  readonly columns: "columns";
8
8
  readonly table: "table";
9
+ readonly toggleList: "toggleList";
10
+ readonly callout: "callout";
11
+ readonly page: "page";
9
12
  readonly moveBlockUp: "openeditor:block:moveUp";
10
13
  readonly moveBlockDown: "openeditor:block:moveDown";
11
14
  readonly undo: "openeditor:history:undo";
package/dist/toolbar.js CHANGED
@@ -14,6 +14,9 @@ export const openEditorNativeToolbarActionKeys = {
14
14
  orderedList: "orderedList",
15
15
  columns: "columns",
16
16
  table: "table",
17
+ toggleList: "toggleList",
18
+ callout: "callout",
19
+ page: "page",
17
20
  moveBlockUp: "openeditor:block:moveUp",
18
21
  moveBlockDown: "openeditor:block:moveDown",
19
22
  undo: "openeditor:history:undo",
@@ -77,6 +80,9 @@ export const createOpenEditorNativeToolbarItems = ({ canUndo = true, canRedo = t
77
80
  { type: "node", nodeType: "horizontalRule", label: "Divider", icon: defaultIcon("horizontalRule") },
78
81
  { type: "action", key: openEditorNativeToolbarActionKeys.columns, label: "Columns", icon: glyphIcon("Cols") },
79
82
  { type: "action", key: openEditorNativeToolbarActionKeys.table, label: "Table", icon: glyphIcon("Tbl") },
83
+ { type: "action", key: openEditorNativeToolbarActionKeys.toggleList, label: "Toggle List", icon: glyphIcon("Tgl") },
84
+ { type: "action", key: openEditorNativeToolbarActionKeys.callout, label: "Callout", icon: glyphIcon("!") },
85
+ { type: "action", key: openEditorNativeToolbarActionKeys.page, label: "Page", icon: glyphIcon("Pg") },
80
86
  { type: "command", command: "insertTableRowAfter", label: "Add Row", icon: glyphIcon("+R") },
81
87
  { type: "command", command: "insertTableColumnAfter", label: "Add Column", icon: glyphIcon("+C") },
82
88
  { type: "command", command: "deleteTableRow", label: "Delete Row", icon: glyphIcon("-R") },
@@ -162,6 +168,9 @@ export const nativeToolbarParityCoverage = () => {
162
168
  ["divider", "horizontalRule"],
163
169
  ["image", "image"],
164
170
  ["table", openEditorNativeToolbarActionKeys.table],
171
+ ["toggleList", openEditorNativeToolbarActionKeys.toggleList],
172
+ ["callout", openEditorNativeToolbarActionKeys.callout],
173
+ ["page", openEditorNativeToolbarActionKeys.page],
165
174
  ]);
166
175
  const markControls = new Map([
167
176
  ["bold", "bold"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openeditor/native",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "repository": {
@@ -27,14 +27,14 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@expo/vector-icons": "15.0.3",
30
- "@openeditor/core": "0.0.10",
31
- "@openeditor/exporters": "0.0.10",
32
- "@openeditor/extensions": "0.0.10",
30
+ "@openeditor/core": "0.0.12",
31
+ "@openeditor/exporters": "0.0.12",
32
+ "@openeditor/extensions": "0.0.12",
33
33
  "react": "19.2.3",
34
34
  "react-native": "0.85.3"
35
35
  },
36
36
  "peerDependencies": {
37
- "@openeditor/react-native-prose-editor": "0.0.10",
37
+ "@openeditor/react-native-prose-editor": "0.0.12",
38
38
  "react-native-keyboard-controller": ">=1.21",
39
39
  "react": ">=19",
40
40
  "react-native": ">=0.85"