@openeditor/react 0.0.20 → 0.0.22

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
@@ -66,6 +66,7 @@ Keep the extension array referentially stable. Defining extensions at module
66
66
  scope, as below, is the simplest option.
67
67
 
68
68
  ```tsx
69
+ import { PackageOpen } from "lucide-react";
69
70
  import {
70
71
  defineOpenEditorReactNode,
71
72
  NodeViewWrapper,
@@ -113,7 +114,11 @@ const productCard = defineOpenEditorReactNode({
113
114
  ],
114
115
  },
115
116
  component: ProductCardNode,
116
- slashMenu: { keywords: ["product", "commerce", "card"] },
117
+ slashMenu: {
118
+ icon: PackageOpen,
119
+ keywords: ["product", "commerce", "card"],
120
+ order: 250,
121
+ },
117
122
  viewer: ({ node }) => <article>{String(node.attrs?.title ?? "")}</article>,
118
123
  exporters: {
119
124
  html: {
@@ -138,6 +143,14 @@ Pass the same extension array to `OpenEditorViewer`. The controller automaticall
138
143
  uses registered exporters for `controller.exports` and registered blocks appear
139
144
  in `getDefaultSlashMenuItems`, which powers `@openeditor/ui`.
140
145
 
146
+ Slash-menu entries accept an optional React `icon` component and numeric `order`.
147
+ OpenEditor assigns built-in entries orders in increments of 100, so consumer
148
+ blocks can be placed between them (for example, `order: 250` appears between
149
+ Heading 1 and Heading 2). Entries with the same order retain their declaration
150
+ order, and entries without an order appear after ordered entries. The same fields
151
+ are available on direct `slashMenuItems`; a menu's explicit `items` prop is also
152
+ sorted by this rule.
153
+
141
154
  Block `name` is the stable public identifier. Namespace consumer blocks to avoid
142
155
  collisions. `nodeType` is the serialized ProseMirror node type and defaults to
143
156
  `name`; use an identifier without punctuation when interoperability requires it.
package/dist/index.d.ts CHANGED
@@ -142,11 +142,20 @@ type SelectionBubbleState = {
142
142
  top: number;
143
143
  anchorRect?: OpenEditorOverlayRect;
144
144
  };
145
+ type OpenEditorSlashMenuIconProps = {
146
+ "aria-hidden"?: boolean;
147
+ className?: string;
148
+ size?: number;
149
+ strokeWidth?: number;
150
+ };
151
+ type OpenEditorSlashMenuIcon = (props: OpenEditorSlashMenuIconProps) => ReactNode;
145
152
  type OpenEditorSlashMenuItem = {
146
153
  key: string;
147
154
  label: string;
148
155
  group: string;
156
+ icon?: OpenEditorSlashMenuIcon;
149
157
  keywords?: readonly string[];
158
+ order?: number;
150
159
  execute: (context: {
151
160
  controller: OpenEditorController;
152
161
  range: InsertRange;
@@ -159,7 +168,9 @@ type OpenEditorViewerRenderer = (context: {
159
168
  type OpenEditorExtensionMenu = {
160
169
  label?: string;
161
170
  group?: string;
171
+ icon?: OpenEditorSlashMenuIcon;
162
172
  keywords?: readonly string[];
173
+ order?: number;
163
174
  };
164
175
  /**
165
176
  * Complete web integration for a consumer-owned block. The portable `block`
@@ -197,9 +208,10 @@ declare module "@tiptap/core" {
197
208
  }
198
209
  declare const formatAttachmentSize: (size: number | null) => string;
199
210
  declare const useOpenEditorController: ({ initialDocument, editable, placeholder, onChange, onFilePasteDrop, pageRuntime, attachmentRuntime, slashMenuItems, extensions, blockActions, }?: OpenEditorReactProps) => OpenEditorController;
211
+ declare const sortSlashMenuItems: (items: readonly OpenEditorSlashMenuItem[]) => OpenEditorSlashMenuItem[];
200
212
  declare const getDefaultSlashMenuItems: (controller: OpenEditorController) => OpenEditorSlashMenuItem[];
201
213
  declare const OpenEditorContent: ({ controller, className, }: OpenEditorContentProps) => react.JSX.Element;
202
214
  declare const OpenEditorViewer: ({ document, className, renderers, extensions, pageRuntime, attachmentRuntime, }: OpenEditorViewerProps) => react.JSX.Element;
203
215
  declare const useOpenEditor: ({ initialDocument, editable, placeholder, onChange, onFilePasteDrop, pageRuntime, attachmentRuntime, slashMenuItems, extensions, blockActions, }?: OpenEditorReactProps) => OpenEditorController;
204
216
 
205
- export { type InsertRange, type OpenEditorBlockAction, type OpenEditorBlockActionContext, type OpenEditorBlockTarget, OpenEditorContent, type OpenEditorContentProps, type OpenEditorController, type OpenEditorExtensionMenu, type OpenEditorOverlayRect, type OpenEditorPageRuntime, type OpenEditorPageSnapshot, type OpenEditorReactConfig, type OpenEditorReactExtension, type OpenEditorReactNodeExtension, type OpenEditorReactProps, type OpenEditorSlashMenuItem, type OpenEditorTheme, OpenEditorThemeProvider, type OpenEditorThemeStyle, type OpenEditorThemeToken, OpenEditorViewer, type OpenEditorViewerProps, type OpenEditorViewerRenderer, type SelectionBubbleState, type SlashState, createOpenEditorThemeStyle, defineOpenEditorReactExtension, defineOpenEditorReactNode, formatAttachmentSize, getDefaultSlashMenuItems, openEditorThemeTokenNames, useOpenEditor, useOpenEditorController, useOpenEditorThemeStyle };
217
+ export { type InsertRange, type OpenEditorBlockAction, type OpenEditorBlockActionContext, type OpenEditorBlockTarget, OpenEditorContent, type OpenEditorContentProps, type OpenEditorController, type OpenEditorExtensionMenu, type OpenEditorOverlayRect, type OpenEditorPageRuntime, type OpenEditorPageSnapshot, 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, getDefaultSlashMenuItems, openEditorThemeTokenNames, sortSlashMenuItems, useOpenEditor, useOpenEditorController, useOpenEditorThemeStyle };
package/dist/index.js CHANGED
@@ -32944,10 +32944,11 @@ var OpenEditorPageNodeView = ({ editor, node, updateAttributes: updateAttributes
32944
32944
  className: "oe-page",
32945
32945
  "data-page-id": snapshot?.pageId ?? "",
32946
32946
  onClick: (event) => {
32947
- if (event.target.closest(".oe-emoji-trigger")) return;
32947
+ if (event.target.closest(".oe-emoji-trigger, .oe-emoji-popover")) return;
32948
32948
  openPage();
32949
32949
  },
32950
32950
  onKeyDown: (event) => {
32951
+ if (event.target.closest(".oe-emoji-trigger, .oe-emoji-popover")) return;
32951
32952
  if (snapshot && (event.key === "Enter" || event.key === " ")) {
32952
32953
  event.preventDefault();
32953
32954
  openPage();
@@ -33130,7 +33131,7 @@ var createEditorExtensions = (placeholder, customExtensions) => [
33130
33131
  index_default6,
33131
33132
  index_default5,
33132
33133
  index_default10.configure({ types: ["heading", "paragraph"] }),
33133
- index_default4.configure({ placeholder }),
33134
+ index_default4.configure({ placeholder, showOnlyCurrent: true }),
33134
33135
  Columns,
33135
33136
  Column,
33136
33137
  ToggleList,
@@ -33256,7 +33257,7 @@ var escapeClipboardHtml = (value) => value.replaceAll("&", "&amp;").replaceAll("
33256
33257
  var useOpenEditorController = ({
33257
33258
  initialDocument = seedDocument,
33258
33259
  editable = true,
33259
- placeholder = "Start writing...",
33260
+ placeholder = "Type '/' for commands",
33260
33261
  onChange,
33261
33262
  onFilePasteDrop,
33262
33263
  pageRuntime,
@@ -33650,20 +33651,28 @@ var useOpenEditorController = ({
33650
33651
  };
33651
33652
  return controller;
33652
33653
  };
33654
+ var sortSlashMenuItems = (items) => [...items].sort((left, right) => {
33655
+ const leftOrder = typeof left.order === "number" && Number.isFinite(left.order) ? left.order : Number.POSITIVE_INFINITY;
33656
+ const rightOrder = typeof right.order === "number" && Number.isFinite(right.order) ? right.order : Number.POSITIVE_INFINITY;
33657
+ if (leftOrder === rightOrder) return 0;
33658
+ return leftOrder - rightOrder;
33659
+ });
33653
33660
  var getDefaultSlashMenuItems = (controller) => {
33654
33661
  const internalController = controller;
33655
- return [
33656
- ...openEditorInsertPresets.map((preset) => ({
33662
+ return sortSlashMenuItems([
33663
+ ...openEditorInsertPresets.map((preset, index) => ({
33657
33664
  key: preset.key,
33658
33665
  label: preset.label,
33659
33666
  group: preset.group,
33660
33667
  keywords: [preset.key],
33668
+ order: (index + 1) * 100,
33661
33669
  execute: ({ controller: current, range }) => current.insertBlock(preset.key, range)
33662
33670
  })),
33663
33671
  {
33664
33672
  key: "moveBlockUp",
33665
33673
  label: "Move Block Up",
33666
33674
  group: "block",
33675
+ order: (openEditorInsertPresets.length + 1) * 100,
33667
33676
  execute: ({ range }) => {
33668
33677
  if (!internalController.editor) return false;
33669
33678
  internalController.editor.chain().focus().deleteRange(range).run();
@@ -33675,6 +33684,7 @@ var getDefaultSlashMenuItems = (controller) => {
33675
33684
  key: "moveBlockDown",
33676
33685
  label: "Move Block Down",
33677
33686
  group: "block",
33687
+ order: (openEditorInsertPresets.length + 2) * 100,
33678
33688
  execute: ({ range }) => {
33679
33689
  if (!internalController.editor) return false;
33680
33690
  internalController.editor.chain().focus().deleteRange(range).run();
@@ -33688,12 +33698,14 @@ var getDefaultSlashMenuItems = (controller) => {
33688
33698
  key: extension.block.name,
33689
33699
  label: menu?.label ?? extension.block.label,
33690
33700
  group: menu?.group ?? extension.block.group,
33701
+ icon: menu?.icon,
33691
33702
  keywords: menu?.keywords ?? [extension.block.name],
33703
+ order: menu?.order,
33692
33704
  execute: ({ controller: current, range }) => current.insertBlock(extension.block.name, range)
33693
33705
  };
33694
33706
  }),
33695
33707
  ...controller.slashMenuItems
33696
- ];
33708
+ ]);
33697
33709
  };
33698
33710
  var renderTextWithMarks = (text, marks = [], key) => marks.reduceRight((children, mark, index) => {
33699
33711
  const nodeKey = `${key}-${mark.type}-${index}`;
@@ -33835,6 +33847,6 @@ var OpenEditorViewer = ({
33835
33847
  };
33836
33848
  var useOpenEditor = useOpenEditorController;
33837
33849
 
33838
- export { NodeViewContent, NodeViewWrapper, OpenEditorContent, DragHandle2 as OpenEditorDragHandle, OpenEditorThemeProvider, OpenEditorViewer, createOpenEditorThemeStyle, defineOpenEditorReactExtension, defineOpenEditorReactNode, formatAttachmentSize, getDefaultSlashMenuItems, openEditorThemeTokenNames, useOpenEditor, useOpenEditorController, useOpenEditorThemeStyle };
33850
+ export { NodeViewContent, NodeViewWrapper, OpenEditorContent, DragHandle2 as OpenEditorDragHandle, OpenEditorThemeProvider, OpenEditorViewer, createOpenEditorThemeStyle, defineOpenEditorReactExtension, defineOpenEditorReactNode, formatAttachmentSize, getDefaultSlashMenuItems, openEditorThemeTokenNames, sortSlashMenuItems, useOpenEditor, useOpenEditorController, useOpenEditorThemeStyle };
33839
33851
  //# sourceMappingURL=index.js.map
33840
33852
  //# sourceMappingURL=index.js.map