@meowdown/react 0.63.1 → 0.64.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.
Files changed (3) hide show
  1. package/README.md +17 -118
  2. package/dist/index.js +13 -10
  3. package/package.json +7 -7
package/README.md CHANGED
@@ -27,9 +27,6 @@ export function App() {
27
27
  ## Usage
28
28
 
29
29
  ```tsx
30
- import '@meowdown/core/style.css'
31
- import '@meowdown/react/style.css'
32
-
33
30
  import { MeowdownEditor, type EditorHandle } from '@meowdown/react'
34
31
  import { useRef, useCallback } from 'react'
35
32
 
@@ -50,125 +47,27 @@ export function App() {
50
47
  }
51
48
  ```
52
49
 
53
- ## API
54
-
55
- See the full API reference [here](https://npmx.dev/package-docs/@meowdown%2Freact/).
56
-
57
- Slash menu host items can include `keywords` to match hidden terms without changing the displayed label.
58
-
59
- The caret glides between positions by default; pass `caretGlide={false}` to move it instantly (hosts can also tune the duration via the `--meowdown-caret-glide` CSS variable).
60
-
61
- `MarkdownView` folds collapsed (`+`) bullets like the editor; pass `expandCollapsed` to render them expanded at every depth, for views that show slices of a note (e.g. a backlinks panel) where the source's fold state must not hide the content the view exists to show.
62
-
63
- Both `MeowdownEditor` and `MarkdownView` resolve CommonMark full, collapsed,
64
- and shortcut reference links and images. The editor keeps reference definitions
65
- visible as editable source and preserves them through `getMarkdown()`.
66
- `MarkdownView` uses the same first-definition-wins resolution but omits
67
- definition paragraphs from its rendered output. Reference links are read-only
68
- in the editor's link menu; edit their definition source to change the target.
69
-
70
- ### Wiki embeds
71
-
72
- Obsidian-style wiki embeds (`![[path]]`, with optional `|width` or
73
- `|widthxheight`) stay literal and editable unless the host classifies them.
74
- `resolveWikiEmbed` is a pure, creation-time resolver: return an image, file, or
75
- note result to reuse the corresponding Meowdown atom and its existing click
76
- hook; return `undefined` for missing or ambiguous targets.
77
-
78
- ```tsx
79
- <MeowdownEditor
80
- initialMarkdown="![[assets/photo.png|320]]"
81
- resolveWikiEmbed={({ target }) => (target.endsWith('.png') ? { kind: 'image' } : undefined)}
82
- resolveImageUrl={resolveLocalImageUrl}
83
- onImageClick={openLightbox}
84
- />
85
- ```
86
-
87
- Use `EditorHandle.revealHeading('#Section%20name')` to move the selection to a
88
- matching heading and scroll it into view after following a heading link.
50
+ ## Components
89
51
 
90
- Both `MeowdownEditor` and the read-only `MarkdownView` accept
91
- `resolveFileLink`. Return `true` to render a standard `[label](path)` Markdown
92
- link with the same file pill, metadata resolver, and click hook used by wiki
93
- file embeds; return `false` to keep it as a normal link.
94
-
95
- ```tsx
96
- <MarkdownView
97
- markdown="[Quarterly report](docs/report.pdf)"
98
- resolveFileLink={({ href }) => href.startsWith('docs/')}
99
- resolveFileInfo={resolveLocalFileInfo}
100
- onFileClick={openLocalFile}
101
- />
102
- ```
103
-
104
- ### Find in document
105
-
106
- `searchQuery` highlights every match and selects the first one at or after the
107
- caret; changing it re-anchors from wherever the selection is, so refining a
108
- query keeps the match the user is looking at. A query that matches nothing
109
- collapses the previous match selection to a caret, and an empty string (the
110
- default) clears the highlights and leaves the selection alone. `onSearchChange` reports
111
- `{ total, active }` for a match counter (`active` is one-based; `0` means the
112
- selection is not on a match), and `EditorHandle.findNext()` /
113
- `EditorHandle.findPrevious()` walk the matches and wrap at the document edges.
114
- The query is applied through `useDeferredValue`, so fast typing may skip
115
- intermediate values on a slow device.
116
-
117
- ```tsx
118
- const [query, setQuery] = useState('')
119
- const [status, setStatus] = useState({ total: 0, active: 0 })
120
-
121
- <input value={query} onChange={(event) => setQuery(event.target.value)} />
122
- <span>{status.active} / {status.total}</span>
123
- <MeowdownEditor
124
- handleRef={editorRef}
125
- searchQuery={query}
126
- onSearchChange={setStatus}
127
- />
128
- ```
129
-
130
- ### Wiki-link hover cards
131
-
132
- Mount `WikilinkHoverCard` inside `MeowdownEditor` and render host-owned preview
133
- content from the hovered wiki link's `target`. Returning `null` renders no
134
- card. The render function may also return a promise: the card stays closed
135
- until it resolves, resolving to `null` (or rejecting) renders no card, and a
136
- result that lands after the pointer moved on is discarded, so a host can look
137
- up local content without ever flashing an empty card.
138
-
139
- ```tsx
140
- <MeowdownEditor initialMarkdown="See [[Project plan]]">
141
- <WikilinkHoverCard>
142
- {async (hit) => {
143
- const note = await readLocalNote(hit.target)
144
- return note == null ? null : <LocalNotePreview note={note} />
145
- }}
146
- </WikilinkHoverCard>
147
- </MeowdownEditor>
148
- ```
149
-
150
- For local-only passive preview content, render Markdown with interaction
151
- disabled: the tree contains no anchors or focusable controls, and recognized
152
- tweet and YouTube embeds are omitted before any image resolver runs. Supply a
153
- resolver that accepts only trusted local image sources.
154
-
155
- ```tsx
156
- <MarkdownView markdown={markdown} interactive={false} resolveImageUrl={resolveLocalImageUrl} />
157
- ```
52
+ | Component | Description |
53
+ | ------------------- | -------------------------------------------------------------------------------------------------------------------------- |
54
+ | `MeowdownEditor` | The editor. Callbacks and resolvers must be stable; pass them via `useCallback`. |
55
+ | `MarkdownView` | Read-only Markdown renderer. `interactive={false}` renders passive content for previews. |
56
+ | `WikilinkHoverCard` | Mount inside `MeowdownEditor`; renders host content for the hovered wiki link's `target`. Return `null` to render no card. |
158
57
 
159
- ### Mermaid code blocks
58
+ Common `MeowdownEditor` props:
160
59
 
161
- Fenced `mermaid` code blocks render as diagrams in both `MeowdownEditor` and
162
- `MarkdownView`. The editor shows only the preview while the caret is outside
163
- the block, then shows source and a live preview while editing it.
60
+ | Prop | What it does |
61
+ | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
62
+ | `mode` | `'focus'` (default), `'show'`, or `'hide'`: how much Markdown syntax stays in view |
63
+ | `searchQuery` / `onSearchChange` | Find in document, with `EditorHandle.findNext()` / `findPrevious()` |
64
+ | `onWikilinkClick` / `onLinkClick` / `onTagClick` / `onImageClick` / `onFileClick` | Click handling for the rendered atoms |
65
+ | `resolveImageUrl` / `resolveWikiEmbed` / `resolveFileLink` / `resolveFileInfo` | Resolve and classify local content |
66
+ | `onFilePaste` | Persist pasted or dropped files |
67
+ | `onSlashMenuSearch` / `onTagSearch` / `onWikilinkSearch` / `onSelectionMenuSearch` | Search menus for `/`, `#`, `[[`, and selection commands |
68
+ | `readOnly` / `placeholder` / `blockHandle` / `caretGlide` / `embedPaste` / `linkPaste` / `bulletAfterHeading` | Behavior toggles |
164
69
 
165
- Rendering uses `beautiful-mermaid`, which currently supports Flowchart, State,
166
- Sequence, Class, ER, and XY Chart diagrams. Unsupported syntax renders an error
167
- instead of an empty preview. Override `--meowdown-mermaid-bg`,
168
- `--meowdown-mermaid-fg`, `--meowdown-mermaid-line`,
169
- `--meowdown-mermaid-accent`, `--meowdown-mermaid-muted`,
170
- `--meowdown-mermaid-surface`, `--meowdown-mermaid-border`, or
171
- `--meowdown-mermaid-error` to customize the diagram palette.
70
+ Every prop, callback, and `EditorHandle` method is documented in the [API reference](https://npmx.dev/package-docs/@meowdown%2Freact/).
172
71
 
173
72
  ## Styling
174
73
 
package/dist/index.js CHANGED
@@ -658,17 +658,19 @@ function LinkMenu({ onLinkClick, onLinkCopy }) {
658
658
  const [overPopup, setOverPopup] = useState(false);
659
659
  const [edit, setEdit] = useState();
660
660
  const hoverOpen = useDelayedFlag(onLink || overPopup);
661
- useExtension$1(useMemo(() => {
661
+ const linkHoverExtension = useMemo(() => {
662
662
  return defineLinkHoverHandler((hit) => {
663
663
  setOnLink(!!hit);
664
664
  if (hit) setHover(hit.payload);
665
665
  });
666
- }, []));
667
- useExtension$1(useMemo(() => {
666
+ }, []);
667
+ useExtension$1(linkHoverExtension);
668
+ const linkEditExtension = useMemo(() => {
668
669
  return defineLinkEditKeymap((options) => {
669
670
  setEdit(options);
670
671
  });
671
- }, []));
672
+ }, []);
673
+ useExtension$1(linkEditExtension);
672
674
  const closeHover = useCallback(() => {
673
675
  setOnLink(false);
674
676
  setOverPopup(false);
@@ -1689,11 +1691,13 @@ function findHeadingPosition(doc, fragment) {
1689
1691
  }
1690
1692
  function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onSlashMenuSearch, onTagSearch, onWikilinkSearch, onSelectionMenuSearch, selectionMenuAffordance = true, pendingReplacementActions, onPendingReplacementResolve, onWikilinkClick, onLinkClick, onLinkCopy, onTagClick, onExitBoundary, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveFileInfo, onFileClick, onFilePaste, onFileSaveError, onImageClick, embedPaste, linkPaste, bulletAfterHeading, substitution = true, frontmatter = false, blockHandle = true, placeholder, readOnly, spellCheck, searchQuery = "", onSearchChange, timeFormat, editorClassName, ref, children }) {
1691
1693
  const [editor] = useState(() => {
1692
- const editor = createEditor({ extension: union(defineEditorExtension({
1694
+ const baseExtension = defineEditorExtension({
1693
1695
  resolveFileLink,
1694
1696
  resolveWikiEmbed,
1695
1697
  markMode
1696
- }), defineCodeBlockView()) });
1698
+ });
1699
+ const extension = union(baseExtension, defineCodeBlockView());
1700
+ const editor = createEditor({ extension });
1697
1701
  if (initialMarkdown) editor.setContent(markdownToDoc(initialMarkdown, {
1698
1702
  nodes: editor.nodes,
1699
1703
  frontmatter
@@ -2082,9 +2086,7 @@ function attributesToProps(attributes = {}, nodeName) {
2082
2086
  case BOOLEAN:
2083
2087
  props[propName] = true;
2084
2088
  break;
2085
- case OVERLOADED_BOOLEAN:
2086
- if (attributeValue === "") props[propName] = true;
2087
- break;
2089
+ case OVERLOADED_BOOLEAN: if (attributeValue === "") props[propName] = true;
2088
2090
  }
2089
2091
  continue;
2090
2092
  }
@@ -2147,7 +2149,8 @@ function outputSpecToReact(spec, content, context) {
2147
2149
  reactProps.tabIndex = -1;
2148
2150
  }
2149
2151
  }
2150
- return createElement(tag, reactProps, ...rest.map((child) => outputSpecToReact(child, content, context)));
2152
+ const reactChildren = rest.map((child) => outputSpecToReact(child, content, context));
2153
+ return createElement(tag, reactProps, ...reactChildren);
2151
2154
  }
2152
2155
  function WikilinkChip(props) {
2153
2156
  const { target, display, onWikilinkClick, children } = props;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meowdown/react",
3
3
  "type": "module",
4
- "version": "0.63.1",
4
+ "version": "0.64.0",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -29,9 +29,9 @@
29
29
  "beautiful-mermaid": "^1.1.3",
30
30
  "clsx": "^2.1.1",
31
31
  "github-slugger": "^2.0.0",
32
- "lucide-react": "^1.27.0",
32
+ "lucide-react": "^1.28.0",
33
33
  "react-property": "^2.0.2",
34
- "@meowdown/core": "0.63.1"
34
+ "@meowdown/core": "0.64.0"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "react": "^19.0.0",
@@ -48,14 +48,14 @@
48
48
  "devDependencies": {
49
49
  "@css-modules-kit/codegen": "^1.4.0",
50
50
  "@ocavue/tsconfig": "^0.7.1",
51
- "@tsdown/css": "^0.22.14",
52
- "@types/react": "^19.2.17",
53
- "@types/react-dom": "^19.2.3",
51
+ "@tsdown/css": "^0.23.0-beta.2",
52
+ "@types/react": "^19.2.18",
53
+ "@types/react-dom": "^19.2.4",
54
54
  "@vitest/browser-playwright": "^4.1.10",
55
55
  "dedent": "^1.7.2",
56
56
  "react": "^19.2.8",
57
57
  "react-dom": "^19.2.8",
58
- "tsdown": "^0.22.14",
58
+ "tsdown": "^0.23.0-beta.2",
59
59
  "vitest": "^4.1.10",
60
60
  "vitest-browser-commands": "^0.2.1",
61
61
  "vitest-browser-react": "^2.2.0",