@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 +10 -0
- package/dist/index.d.ts +18 -2
- package/dist/index.js +21 -15
- package/package.json +4 -4
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.
|
|
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.
|
|
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.
|
|
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.
|
|
56
|
+
"vitest": "^4.1.9",
|
|
57
57
|
"vitest-browser-commands": "^0.2.1",
|
|
58
58
|
"vitest-browser-react": "^2.2.0"
|
|
59
59
|
},
|