@meowdown/react 0.16.1 → 0.17.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
@@ -32,7 +32,7 @@ export function App() {
32
32
 
33
33
  ### `<MeowdownEditor>`
34
34
 
35
- The Markdown editor component. Renders inside a `div.meowdown` wrapper that fills a flex parent. In rich modes, typing `/` opens a slash menu for inserting blocks (headings, blockquote, lists, code block, table). Hovering a block shows a handle to its left: the plus button inserts an empty paragraph below the block, and the grip selects the block and can be dragged to move it, with a drop indicator line marking the target.
35
+ The Markdown editor component. Renders inside a `div.meowdown` wrapper that fills a flex parent. In rich modes, typing `/` opens a slash menu for inserting blocks (headings, blockquote, lists, code block, table). Hovering a block shows a handle to its left: the grip selects the block and can be dragged to move it, with a drop indicator line marking the target.
36
36
 
37
37
  - `mode?: 'focus' | 'show' | 'hide' | 'source'`: defaults to `'focus'`.
38
38
  - `'focus'`: Markdown syntax is hidden, revealed around the cursor.
@@ -51,7 +51,7 @@ The Markdown editor component. Renders inside a `div.meowdown` wrapper that fill
51
51
  - `onImageClick?: (payload: { src: string; alt: string; event: MouseEvent }) => void`: called when a rendered image is clicked, with its markdown `src`, `alt`, and the originating `MouseEvent`. Pass a stable function (e.g. from `useCallback`). Ignored in source mode.
52
52
  - `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.
53
53
  - `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.
54
- - `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.
54
+ - `blockHandle?: boolean`: shows the per-block gutter handle in the rich modes (a drag grip for reordering blocks, 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.
55
55
  - `placeholder?: string | ((state) => string)`: placeholder text shown when the whole document is empty. Pass a stable function. Ignored in source mode.
56
56
  - `readOnly?: boolean`: makes the editor read-only, in both the rich and source modes.
57
57
  - `spellCheck?: boolean`: toggles the browser's native spell checking in the rich modes. Defaults to the browser's behavior. Ignored in source mode.
package/dist/index.d.ts CHANGED
@@ -155,6 +155,8 @@ interface EditorProps {
155
155
  * Off by default. Ignored in source mode.
156
156
  */
157
157
  bulletAfterHeading?: boolean;
158
+ /** Handles a leading `---` frontmatter block in the rich modes (off by default, ignored in source mode). */
159
+ frontmatter?: boolean;
158
160
  /**
159
161
  * Shows the per-block gutter handle in the rich modes: a drag grip for
160
162
  * reordering blocks and a "+" add button, plus the drop indicator that
@@ -198,6 +200,7 @@ declare function MeowdownEditor({
198
200
  onImageClick,
199
201
  embedPaste,
200
202
  bulletAfterHeading,
203
+ frontmatter,
201
204
  blockHandle,
202
205
  placeholder,
203
206
  readOnly,
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ import { canUseRegexLookbehind, createEditor, defineDocChangeHandler, union } fr
12
12
  import { Selection, TextSelection } from "@prosekit/pm/state";
13
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
- import { BlockHandleAdd, BlockHandleDraggable, BlockHandlePopup, BlockHandlePositioner, BlockHandleRoot } from "@prosekit/react/block-handle";
15
+ import { BlockHandleDraggable, BlockHandlePopup, BlockHandlePositioner, BlockHandleRoot } from "@prosekit/react/block-handle";
16
16
  import { DropIndicator } from "@prosekit/react/drop-indicator";
17
17
  import { AutocompleteEmpty, AutocompleteItem, AutocompletePopup, AutocompletePositioner, AutocompleteRoot } from "@prosekit/react/autocomplete";
18
18
  import { MenuItem, MenuPopup, MenuPositioner } from "@prosekit/react/menu";
@@ -333,7 +333,6 @@ function defineCodeBlockView() {
333
333
  //#endregion
334
334
  //#region src/components/block-handle.module.css
335
335
  var block_handle_module_default = {
336
- "Add": "meow_Add_EvUpOG",
337
336
  "Draggable": "meow_Draggable_EvUpOG",
338
337
  "Popup": "meow_Popup_EvUpOG",
339
338
  "Positioner": "meow_Positioner_EvUpOG"
@@ -385,38 +384,19 @@ function GripVerticalIcon() {
385
384
  });
386
385
  }
387
386
 
388
- //#endregion
389
- //#region src/components/icons/plus-icon.tsx
390
- function PlusIcon() {
391
- return /* @__PURE__ */ jsxs("svg", {
392
- viewBox: "0 0 24 24",
393
- fill: "none",
394
- stroke: "currentColor",
395
- strokeWidth: 2,
396
- strokeLinecap: "round",
397
- strokeLinejoin: "round",
398
- "aria-hidden": "true",
399
- children: [/* @__PURE__ */ jsx("path", { d: "M5 12h14" }), /* @__PURE__ */ jsx("path", { d: "M12 5v14" })]
400
- });
401
- }
402
-
403
387
  //#endregion
404
388
  //#region src/components/block-handle.tsx
405
389
  function BlockHandle() {
406
390
  return /* @__PURE__ */ jsx(BlockHandleRoot, { children: /* @__PURE__ */ jsx(BlockHandlePositioner, {
407
391
  className: block_handle_module_default.Positioner,
408
- children: /* @__PURE__ */ jsxs(BlockHandlePopup, {
392
+ children: /* @__PURE__ */ jsx(BlockHandlePopup, {
409
393
  className: block_handle_module_default.Popup,
410
394
  "data-testid": "block-handle",
411
- children: [/* @__PURE__ */ jsx(BlockHandleAdd, {
412
- className: block_handle_module_default.Add,
413
- "data-testid": "block-handle-add",
414
- children: /* @__PURE__ */ jsx(PlusIcon, {})
415
- }), /* @__PURE__ */ jsx(BlockHandleDraggable, {
395
+ children: /* @__PURE__ */ jsx(BlockHandleDraggable, {
416
396
  className: block_handle_module_default.Draggable,
417
397
  "data-testid": "block-handle-drag",
418
398
  children: /* @__PURE__ */ jsx(GripVerticalIcon, {})
419
- })]
399
+ })
420
400
  })
421
401
  }) });
422
402
  }
@@ -926,16 +906,19 @@ function resolveSelection(doc, selection) {
926
906
  return TextSelection.between(doc.resolve(anchor), doc.resolve(head));
927
907
  }
928
908
  }
929
- function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTagSearch, onWikilinkSearch, onWikilinkClick, onLinkClick, resolveImageUrl, onImagePaste, onImageSaveError, onImageClick, embedPaste, bulletAfterHeading, blockHandle = true, placeholder, readOnly, spellCheck, editorClassName, ref, children }) {
909
+ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTagSearch, onWikilinkSearch, onWikilinkClick, onLinkClick, resolveImageUrl, onImagePaste, onImageSaveError, onImageClick, embedPaste, bulletAfterHeading, frontmatter = false, blockHandle = true, placeholder, readOnly, spellCheck, editorClassName, ref, children }) {
930
910
  const [editor] = useState(() => {
931
911
  const editor = createEditor({ extension: union(defineEditorExtension(), defineCodeBlockView()) });
932
- if (initialMarkdown) editor.setContent(markdownToDoc(initialMarkdown, editor.nodes));
912
+ if (initialMarkdown) editor.setContent(markdownToDoc(initialMarkdown, {
913
+ nodes: editor.nodes,
914
+ frontmatter
915
+ }));
933
916
  return editor;
934
917
  });
935
918
  const suppressDocChangeRef = useRef(false);
936
919
  useImperativeHandle(ref, () => {
937
920
  function getMarkdown() {
938
- return docToMarkdown(editor.state.doc);
921
+ return docToMarkdown(editor.state.doc, { frontmatter });
939
922
  }
940
923
  function getSelection() {
941
924
  return editor.state.selection.toJSON();
@@ -947,7 +930,10 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTa
947
930
  if (markdown == null && !selection) return;
948
931
  const transaction = editor.state.tr;
949
932
  if (markdown != null) {
950
- const doc = markdownToDoc(markdown, editor.nodes);
933
+ const doc = markdownToDoc(markdown, {
934
+ nodes: editor.nodes,
935
+ frontmatter
936
+ });
951
937
  transaction.replaceWith(0, transaction.doc.content.size, doc.content);
952
938
  }
953
939
  if (selection) transaction.setSelection(resolveSelection(transaction.doc, selection)).scrollIntoView();
@@ -981,7 +967,7 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTa
981
967
  scrollIntoView,
982
968
  editor
983
969
  };
984
- }, [editor]);
970
+ }, [editor, frontmatter]);
985
971
  const handleDocChange = useMemo(() => {
986
972
  if (!onDocChange) return;
987
973
  return () => {
@@ -995,7 +981,7 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTa
995
981
  /* @__PURE__ */ jsx("div", {
996
982
  ref: editor.mount,
997
983
  spellCheck,
998
- className: editorClassName
984
+ className: clsx("meowdown-content", editorClassName)
999
985
  }),
1000
986
  /* @__PURE__ */ jsx(EditorExtensions, {
1001
987
  markMode,
@@ -1024,7 +1010,7 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTa
1024
1010
 
1025
1011
  //#endregion
1026
1012
  //#region src/components/editor.tsx
1027
- function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onTagSearch, onWikilinkSearch, onWikilinkClick, onLinkClick, resolveImageUrl, onImagePaste, onImageSaveError, onImageClick, embedPaste = true, bulletAfterHeading = false, blockHandle = true, placeholder, readOnly, spellCheck, editorClassName, wrapperClassName, handleRef, children }) {
1013
+ function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onTagSearch, onWikilinkSearch, onWikilinkClick, onLinkClick, resolveImageUrl, onImagePaste, onImageSaveError, onImageClick, embedPaste = true, bulletAfterHeading = false, frontmatter = false, blockHandle = true, placeholder, readOnly, spellCheck, editorClassName, wrapperClassName, handleRef, children }) {
1028
1014
  const childRef = useRef(null);
1029
1015
  useImperativeHandle(handleRef, () => {
1030
1016
  function getMarkdown() {
@@ -1096,6 +1082,7 @@ function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onTagSea
1096
1082
  onImageClick,
1097
1083
  embedPaste,
1098
1084
  bulletAfterHeading,
1085
+ frontmatter,
1099
1086
  blockHandle,
1100
1087
  placeholder,
1101
1088
  readOnly,
package/dist/style.css CHANGED
@@ -228,10 +228,12 @@
228
228
  }
229
229
  }
230
230
 
231
- .meow_Add_EvUpOG, .meow_Draggable_EvUpOG {
231
+ .meow_Draggable_EvUpOG {
232
232
  box-sizing: border-box;
233
+ width: 1.25rem;
233
234
  height: 1.5rem;
234
235
  color: color-mix(in oklab, var(--meowdown-muted) 50%, transparent);
236
+ cursor: grab;
235
237
  border-radius: .25rem;
236
238
  justify-content: center;
237
239
  align-items: center;
@@ -247,16 +249,6 @@
247
249
  display: block;
248
250
  }
249
251
  }
250
-
251
- .meow_Add_EvUpOG {
252
- cursor: pointer;
253
- width: 1.5rem;
254
- }
255
-
256
- .meow_Draggable_EvUpOG {
257
- cursor: grab;
258
- width: 1.25rem;
259
- }
260
252
  .meow_DropIndicator_urNIwW {
261
253
  z-index: 50;
262
254
  background: var(--meowdown-accent);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meowdown/react",
3
3
  "type": "module",
4
- "version": "0.16.1",
4
+ "version": "0.17.0",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -26,9 +26,9 @@
26
26
  "@ocavue/utils": "^1.7.0",
27
27
  "@prosekit/core": "^0.13.0-beta.3",
28
28
  "@prosekit/pm": "^0.1.19-beta.0",
29
- "@prosekit/react": "^0.8.0-beta.5",
29
+ "@prosekit/react": "^0.8.0-beta.7",
30
30
  "clsx": "^2.1.1",
31
- "@meowdown/core": "0.16.1"
31
+ "@meowdown/core": "0.17.0"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "react": "^19.0.0",