@meowdown/react 0.9.0 → 0.11.0

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
@@ -48,6 +48,8 @@ The Markdown editor component. Renders inside a `div.meowdown` wrapper that fill
48
48
  - `onImagePaste?: (file: File) => string | undefined | Promise<string | undefined>`: persists a pasted or dropped image file and returns its markdown `src` (or `undefined` to decline), synchronously or as a promise. Pass a stable function. Ignored in source mode.
49
49
  - `onImageSaveError?: (error: unknown, file: File) => void`: called when `onImagePaste` throws. Defaults to `console.error`. Ignored in source mode.
50
50
  - `embedPaste?: boolean`: auto-embeds a pasted tweet or YouTube link as a rich embed; one undo turns the embed back into the raw link. On by default; set `false` to disable. Only takes effect when `resolveImageUrl` is set, since embeds render through the image pipeline. Ignored in source mode.
51
+ - `bulletAfterHeading?: boolean`: pressing Enter at the end of the document's first heading (the title line) starts a fresh empty bullet on the next line instead of a plain paragraph. Off by default. Ignored in source mode.
52
+ - `blockHandle?: boolean`: shows the per-block gutter handle in the rich modes (a drag grip for reordering blocks and a `+` add button, plus the drop indicator). On by default; set `false` to hide the gutter affordance entirely, e.g. when the host does not want block reordering. Ignored in source mode and when `readOnly` is set.
51
53
  - `placeholder?: string | ((state) => string)`: placeholder text shown when the whole document is empty. Pass a stable function. Ignored in source mode.
52
54
  - `readOnly?: boolean`: makes the editor read-only, in both the rich and source modes.
53
55
  - `spellCheck?: boolean`: toggles the browser's native spell checking in the rich modes. Defaults to the browser's behavior. Ignored in source mode.
@@ -60,6 +62,14 @@ The Markdown editor component. Renders inside a `div.meowdown` wrapper that fill
60
62
 
61
63
  Re-exported from `@prosekit/react`. Call it from a component passed as `children` to read the live editor instance.
62
64
 
65
+ ### `useKeymap`
66
+
67
+ Re-exported from `@prosekit/react`. Registers a keymap on the editor from a `children` component; set its priority with `Priority` from `@meowdown/core`.
68
+
69
+ ### `useExtension`
70
+
71
+ Re-exported from `@prosekit/react`. Applies an extension to the editor from a `children` component.
72
+
63
73
  ### `EditorHandle`
64
74
 
65
75
  Imperative handle for the editor, attached via `handleRef`.
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ReactNode, Ref } from "react";
2
2
  import { ImageOptions, MarkMode, PlaceholderOptions, TypedEditor, WikilinkClickHandler } from "@meowdown/core";
3
3
  import { SelectionJSON, SelectionJSON as SelectionJSON$1 } from "@prosekit/core";
4
- import { useEditor } from "@prosekit/react";
4
+ import { useEditor, useExtension, useKeymap } from "@prosekit/react";
5
5
 
6
6
  //#region src/components/types.d.ts
7
7
  /** A selection to restore: an exact JSON selection, or a document edge. */
@@ -137,6 +137,20 @@ interface EditorProps {
137
137
  * the same image pipeline.
138
138
  */
139
139
  embedPaste?: boolean;
140
+ /**
141
+ * Pressing Enter at the end of the document's first heading (the title line)
142
+ * starts a fresh empty bullet on the next line instead of a plain paragraph.
143
+ * Off by default. Ignored in source mode.
144
+ */
145
+ bulletAfterHeading?: boolean;
146
+ /**
147
+ * Shows the per-block gutter handle in the rich modes: a drag grip for
148
+ * reordering blocks and a "+" add button, plus the drop indicator that
149
+ * visualizes where a dragged block will land. On by default. Set to `false`
150
+ * to hide the gutter affordance entirely, e.g. when the host does not want
151
+ * block reordering. Ignored in source mode and when `readOnly` is set.
152
+ */
153
+ blockHandle?: boolean;
140
154
  /**
141
155
  * Placeholder text shown when the whole document is empty. A function
142
156
  * receives the editor state. Pass a stable function. Ignored in source mode.
@@ -169,6 +183,8 @@ declare function MeowdownEditor({
169
183
  onImagePaste,
170
184
  onImageSaveError,
171
185
  embedPaste,
186
+ bulletAfterHeading,
187
+ blockHandle,
172
188
  placeholder,
173
189
  readOnly,
174
190
  spellCheck,
@@ -178,4 +194,4 @@ declare function MeowdownEditor({
178
194
  children
179
195
  }: EditorProps): import("react").JSX.Element;
180
196
  //#endregion
181
- export { type EditorHandle, type EditorMode, type EditorProps, type EditorStateSnapshot, MeowdownEditor, type SelectionHint, type SelectionJSON, type TagItem, type TagSearchHandler, type WikilinkItem, type WikilinkSearchHandler, useEditor };
197
+ export { type EditorHandle, type EditorMode, type EditorProps, type EditorStateSnapshot, MeowdownEditor, type SelectionHint, type SelectionJSON, type TagItem, type TagSearchHandler, type WikilinkItem, type WikilinkSearchHandler, useEditor, useExtension, useKeymap };
package/dist/index.js CHANGED
@@ -7,10 +7,10 @@ import { Compartment, EditorSelection, EditorState } from "@codemirror/state";
7
7
  import { EditorView, keymap } from "@codemirror/view";
8
8
  import { clamp } from "@ocavue/utils";
9
9
  import { jsx, jsxs } from "react/jsx-runtime";
10
- import { codeBlockLanguages, defineEditorExtension, defineEmbedPaste, defineImages, defineMarkMode, definePlaceholder, defineReadonly, defineWikilinkClickHandler, docToMarkdown, markdownToDoc } from "@meowdown/core";
10
+ import { codeBlockLanguages, defineBulletAfterHeading, defineEditorExtension, defineEmbedPaste, defineImages, defineMarkMode, definePlaceholder, defineReadonly, defineWikilinkClickHandler, docToMarkdown, markdownToDoc } from "@meowdown/core";
11
11
  import { canUseRegexLookbehind, createEditor, defineDocChangeHandler, union } from "@prosekit/core";
12
12
  import { Selection, TextSelection } from "@prosekit/pm/state";
13
- import { ProseKit, defineReactNodeView, useEditor, useEditor as useEditor$1, useEditorDerivedValue, useExtension } from "@prosekit/react";
13
+ import { ProseKit, defineReactNodeView, useEditor, useEditor as useEditor$1, useEditorDerivedValue, useExtension, useExtension as useExtension$1, useKeymap } from "@prosekit/react";
14
14
  import { Combobox } from "@base-ui/react/combobox";
15
15
  import { BlockHandleAdd, BlockHandleDraggable, BlockHandlePopup, BlockHandlePositioner, BlockHandleRoot } from "@prosekit/react/block-handle";
16
16
  import { DropIndicator } from "@prosekit/react/drop-indicator";
@@ -436,20 +436,20 @@ function DropIndicator$1() {
436
436
 
437
437
  //#endregion
438
438
  //#region src/components/editor-extensions.tsx
439
- function EditorExtensions({ markMode, onDocChange, onWikilinkClick, resolveImageUrl, onImagePaste, onImageSaveError, embedPaste, placeholder, readOnly }) {
440
- useExtension(useMemo(() => {
439
+ function EditorExtensions({ markMode, onDocChange, onWikilinkClick, resolveImageUrl, onImagePaste, onImageSaveError, embedPaste, bulletAfterHeading, placeholder, readOnly }) {
440
+ useExtension$1(useMemo(() => {
441
441
  return defineMarkMode(markMode);
442
442
  }, [markMode]));
443
- useExtension(useMemo(() => {
443
+ useExtension$1(useMemo(() => {
444
444
  return readOnly ? defineReadonly() : null;
445
445
  }, [readOnly]));
446
- useExtension(useMemo(() => {
446
+ useExtension$1(useMemo(() => {
447
447
  return onDocChange ? defineDocChangeHandler(onDocChange) : null;
448
448
  }, [onDocChange]));
449
- useExtension(useMemo(() => {
449
+ useExtension$1(useMemo(() => {
450
450
  return onWikilinkClick ? defineWikilinkClickHandler(onWikilinkClick) : null;
451
451
  }, [onWikilinkClick]));
452
- useExtension(useMemo(() => {
452
+ useExtension$1(useMemo(() => {
453
453
  return resolveImageUrl ? defineImages({
454
454
  resolveImageUrl,
455
455
  onImagePaste,
@@ -460,10 +460,13 @@ function EditorExtensions({ markMode, onDocChange, onWikilinkClick, resolveImage
460
460
  onImagePaste,
461
461
  onImageSaveError
462
462
  ]));
463
- useExtension(useMemo(() => {
463
+ useExtension$1(useMemo(() => {
464
464
  return embedPaste && resolveImageUrl ? defineEmbedPaste() : null;
465
465
  }, [embedPaste, resolveImageUrl]));
466
- useExtension(useMemo(() => {
466
+ useExtension$1(useMemo(() => {
467
+ return bulletAfterHeading ? defineBulletAfterHeading() : null;
468
+ }, [bulletAfterHeading]));
469
+ useExtension$1(useMemo(() => {
467
470
  return placeholder ? definePlaceholder({
468
471
  placeholder,
469
472
  strategy: "doc"
@@ -910,7 +913,7 @@ function resolveSelection(doc, selection) {
910
913
  return TextSelection.between(doc.resolve(anchor), doc.resolve(head));
911
914
  }
912
915
  }
913
- function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTagSearch, onWikilinkSearch, onWikilinkClick, resolveImageUrl, onImagePaste, onImageSaveError, embedPaste, placeholder, readOnly, spellCheck, editorClassName, ref, children }) {
916
+ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTagSearch, onWikilinkSearch, onWikilinkClick, resolveImageUrl, onImagePaste, onImageSaveError, embedPaste, bulletAfterHeading, blockHandle = true, placeholder, readOnly, spellCheck, editorClassName, ref, children }) {
914
917
  const [editor] = useState(() => {
915
918
  const editor = createEditor({ extension: union(defineEditorExtension(), defineCodeBlockView()) });
916
919
  if (initialMarkdown) editor.setContent(markdownToDoc(initialMarkdown, editor.nodes));
@@ -989,12 +992,13 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTa
989
992
  onImagePaste,
990
993
  onImageSaveError,
991
994
  embedPaste,
995
+ bulletAfterHeading,
992
996
  placeholder,
993
997
  readOnly
994
998
  }),
995
- /* @__PURE__ */ jsx(BlockHandle, {}),
999
+ blockHandle && !readOnly && /* @__PURE__ */ jsx(BlockHandle, {}),
996
1000
  !readOnly && /* @__PURE__ */ jsx(TableHandle, {}),
997
- /* @__PURE__ */ jsx(DropIndicator$1, {}),
1001
+ blockHandle && !readOnly && /* @__PURE__ */ jsx(DropIndicator$1, {}),
998
1002
  /* @__PURE__ */ jsx(SlashMenu, {}),
999
1003
  onTagSearch && /* @__PURE__ */ jsx(TagMenu, { onTagSearch }),
1000
1004
  onWikilinkSearch && /* @__PURE__ */ jsx(WikilinkMenu, { onWikilinkSearch }),
@@ -1005,7 +1009,7 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTa
1005
1009
 
1006
1010
  //#endregion
1007
1011
  //#region src/components/editor.tsx
1008
- function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onTagSearch, onWikilinkSearch, onWikilinkClick, resolveImageUrl, onImagePaste, onImageSaveError, embedPaste = true, placeholder, readOnly, spellCheck, editorClassName, wrapperClassName, handleRef, children }) {
1012
+ function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onTagSearch, onWikilinkSearch, onWikilinkClick, resolveImageUrl, onImagePaste, onImageSaveError, embedPaste = true, bulletAfterHeading = false, blockHandle = true, placeholder, readOnly, spellCheck, editorClassName, wrapperClassName, handleRef, children }) {
1009
1013
  const childRef = useRef(null);
1010
1014
  useImperativeHandle(handleRef, () => {
1011
1015
  function getMarkdown() {
@@ -1074,6 +1078,8 @@ function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onTagSea
1074
1078
  onImagePaste,
1075
1079
  onImageSaveError,
1076
1080
  embedPaste,
1081
+ bulletAfterHeading,
1082
+ blockHandle,
1077
1083
  placeholder,
1078
1084
  readOnly,
1079
1085
  spellCheck,
@@ -1084,4 +1090,4 @@ function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onTagSea
1084
1090
  }
1085
1091
 
1086
1092
  //#endregion
1087
- export { MeowdownEditor, useEditor };
1093
+ export { MeowdownEditor, useEditor, useExtension, useKeymap };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meowdown/react",
3
3
  "type": "module",
4
- "version": "0.9.0",
4
+ "version": "0.11.0",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -28,7 +28,7 @@
28
28
  "@prosekit/pm": "^0.1.18",
29
29
  "@prosekit/react": "^0.8.0-beta.2",
30
30
  "clsx": "^2.1.1",
31
- "@meowdown/core": "0.9.0"
31
+ "@meowdown/core": "0.11.0"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "react": "^19.0.0",
@@ -48,12 +48,12 @@
48
48
  "@tsdown/css": "^0.22.2",
49
49
  "@types/react": "^19.2.17",
50
50
  "@types/react-dom": "^19.2.3",
51
- "@vitest/browser-playwright": "^4.1.8",
51
+ "@vitest/browser-playwright": "^4.1.9",
52
52
  "dedent": "^1.7.2",
53
53
  "react": "^19.2.7",
54
54
  "react-dom": "^19.2.7",
55
55
  "tsdown": "^0.22.2",
56
- "vitest": "^4.1.8",
56
+ "vitest": "^4.1.9",
57
57
  "vitest-browser-commands": "^0.2.1",
58
58
  "vitest-browser-react": "^2.2.0"
59
59
  },