@meowdown/react 0.58.3 → 0.59.1

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
@@ -101,6 +101,32 @@ file embeds; return `false` to keep it as a normal link.
101
101
  />
102
102
  ```
103
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
+
104
130
  ### Wiki-link hover cards
105
131
 
106
132
  Mount `WikilinkHoverCard` inside `MeowdownEditor` and render host-owned preview
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ReactElement, ReactNode, Ref } from "react";
2
- import { AcceptPendingReplacementOptions, ExitBoundaryHandler, FileClickHandler, FileInfoResolver, FileLinkResolver, FilePasteOptions, FileViewOptions, ImageClickHandler, ImageOptions, LinkClickHandler, LinkCopyHandler, ListMarker, MarkMode, PendingReplacement, PendingReplacementOutcome, PlaceholderOptions, StartPendingReplacementOptions, TagClickHandler, TypedEditor, WikiEmbedResolver, WikilinkClickHandler, WikilinkHoverHit } from "@meowdown/core";
2
+ import { AcceptPendingReplacementOptions, ExitBoundaryHandler, FileClickHandler, FileInfoResolver, FileLinkResolver, FilePasteOptions, FileViewOptions, ImageClickHandler, ImageOptions, LinkClickHandler, LinkCopyHandler, ListMarker, MarkMode, PendingReplacement, PendingReplacementOutcome, PlaceholderOptions, SearchStatusHandler, StartPendingReplacementOptions, TagClickHandler, TypedEditor, WikiEmbedResolver, WikilinkClickHandler, WikilinkHoverHit } from "@meowdown/core";
3
3
  import { SelectionJSON, SelectionJSON as SelectionJSON$1 } from "@prosekit/core";
4
4
  import { useEditor, useExtension, useKeymap } from "@prosekit/react";
5
5
  //#region src/utils/date-format.d.ts
@@ -97,6 +97,10 @@ interface EditorHandle {
97
97
  acceptPendingReplacement: (options?: AcceptPendingReplacementOptions) => void;
98
98
  /** Clears the staged replacement without touching the document. */
99
99
  discardPendingReplacement: () => void;
100
+ /** Selects the next match of the current search query, wrapping at the document end. */
101
+ findNext: () => void;
102
+ /** Selects the previous match of the current search query, wrapping at the document start. */
103
+ findPrevious: () => void;
100
104
  /**
101
105
  * Escape hatch: the underlying ProseKit editor, or `undefined` when the
102
106
  * handle does not wrap one.
@@ -389,6 +393,18 @@ interface EditorProps {
389
393
  * behavior.
390
394
  */
391
395
  spellCheck?: boolean;
396
+ /**
397
+ * The search query. Every match is highlighted, and the first match at or
398
+ * after the caret is selected whenever the query changes. An empty string
399
+ * (the default) clears the highlights and leaves the selection alone. A match
400
+ * that the current mode hides reveals itself while it is the selected one.
401
+ */
402
+ searchQuery?: string;
403
+ /**
404
+ * Called when the number of matches or the selected match changes. Pass a
405
+ * stable function (e.g. from `useCallback`).
406
+ */
407
+ onSearchChange?: SearchStatusHandler;
392
408
  /**
393
409
  * Clock format the `/now` slash command inserts: '12' for "3:45pm" or '24'
394
410
  * for "15:45". Defaults to '12'.
@@ -409,7 +425,7 @@ interface EditorProps {
409
425
  *
410
426
  * Callbacks and resolvers should be stable; pass them via `useCallback`.
411
427
  */
412
- declare function MeowdownEditor({ mode, initialMarkdown, onDocChange, onSlashMenuSearch, onTagSearch, onWikilinkSearch, onSelectionMenuSearch, selectionMenuAffordance, pendingReplacementActions, onPendingReplacementResolve, onWikilinkClick, onLinkClick, onLinkCopy, onTagClick, onExitBoundary, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveFileInfo, onFileClick, onFilePaste, onFileSaveError, onImageClick, embedPaste, linkPaste, bulletAfterHeading, substitution, frontmatter, blockHandle, caretGlide, placeholder, readOnly, spellCheck, timeFormat, editorClassName, wrapperClassName, handleRef, children }: EditorProps): ReactElement;
428
+ declare function MeowdownEditor({ mode, initialMarkdown, onDocChange, onSlashMenuSearch, onTagSearch, onWikilinkSearch, onSelectionMenuSearch, selectionMenuAffordance, pendingReplacementActions, onPendingReplacementResolve, onWikilinkClick, onLinkClick, onLinkCopy, onTagClick, onExitBoundary, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveFileInfo, onFileClick, onFilePaste, onFileSaveError, onImageClick, embedPaste, linkPaste, bulletAfterHeading, substitution, frontmatter, blockHandle, caretGlide, placeholder, readOnly, spellCheck, searchQuery, onSearchChange, timeFormat, editorClassName, wrapperClassName, handleRef, children }: EditorProps): ReactElement;
413
429
  //#endregion
414
430
  //#region src/components/markdown-view.d.ts
415
431
  /** Payload for {@link TaskClickHandler}. */
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { clsx } from "clsx/lite";
2
2
  import { Fragment, cloneElement, createElement, useCallback, useDeferredValue, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react";
3
- import { buildFileMarkdown, codeBlockLanguages, collectReferenceDefinitions, defaultResolveImageUrl, defineBulletAfterHeading, defineCodeBlockPreviewPlugin, defineEditorExtension, defineEmbedPaste, defineExitBoundaryHandler, defineFileClickHandler, defineFilePaste, defineFileView, defineFollowLinkHandler, defineImage, defineImageClickHandler, defineLinkClickHandler, defineLinkEditKeymap, defineLinkHoverHandler, defineLinkPaste, definePendingReplacementHandler, definePlaceholder, defineReadonly, defineSpellCheckPlugin, defineSubstitution, defineTagClickHandler, defineViewAttributes, defineWikilinkClickHandler, defineWikilinkHoverHandler, defineWikilinkTrigger, docToMarkdown, formatFileSize, getCodeTokens, getFileKind, getMarkBuilders, getPendingReplacement, getSelectedText, getTableColumnAlign, getTextblockDisplayText, getVirtualElementFromRange, inlineTextToMarkChunksWithContext, isCodeBlockPreviewHiddenDecoration, isNodeOfType, isSelectionInTableCell, listenForTweetHeight, loadKaTeX, markdownToDoc, matchEmbed, renderMathInto } from "@meowdown/core";
3
+ import { buildFileMarkdown, codeBlockLanguages, collectReferenceDefinitions, defaultResolveImageUrl, defineBulletAfterHeading, defineCodeBlockPreviewPlugin, defineEditorExtension, defineEmbedPaste, defineExitBoundaryHandler, defineFileClickHandler, defineFilePaste, defineFileView, defineFollowLinkHandler, defineImage, defineImageClickHandler, defineLinkClickHandler, defineLinkEditKeymap, defineLinkHoverHandler, defineLinkPaste, definePendingReplacementHandler, definePlaceholder, defineReadonly, defineSearchStatusHandler, defineSpellCheckPlugin, defineSubstitution, defineTagClickHandler, defineViewAttributes, defineWikilinkClickHandler, defineWikilinkHoverHandler, defineWikilinkTrigger, docToMarkdown, formatFileSize, getCodeTokens, getFileKind, getMarkBuilders, getPendingReplacement, getSearchStatus, getSelectedText, getTableColumnAlign, getTextblockDisplayText, getVirtualElementFromRange, inlineTextToMarkChunksWithContext, isCodeBlockPreviewHiddenDecoration, isNodeOfType, isSelectionInTableCell, listenForTweetHeight, loadKaTeX, markdownToDoc, matchEmbed, renderMathInto } from "@meowdown/core";
4
4
  import { clamp } from "@ocavue/utils";
5
5
  import { canUseRegexLookbehind, createEditor, defineDocChangeHandler, defineUpdateHandler, isTextSelection, union } from "@prosekit/core";
6
6
  import { Selection, TextSelection } from "@prosekit/pm/state";
@@ -391,11 +391,24 @@ function DropIndicator$1() {
391
391
 
392
392
  //#endregion
393
393
  //#region src/components/editor-extensions.tsx
394
- function EditorExtensions({ markMode, onDocChange, onWikilinkClick, onLinkClick, onTagClick, onExitBoundary, resolveImageUrl, resolveFileInfo, onFileClick, onFilePaste, onFileSaveError, onImageClick, embedPaste, linkPaste, bulletAfterHeading, substitution, placeholder, readOnly, wikilinkEnabled, spellCheck, editorClassName }) {
394
+ function EditorExtensions({ markMode, onDocChange, onWikilinkClick, onLinkClick, onTagClick, onExitBoundary, resolveImageUrl, resolveFileInfo, onFileClick, onFilePaste, onFileSaveError, onImageClick, embedPaste, linkPaste, bulletAfterHeading, substitution, placeholder, readOnly, wikilinkEnabled, spellCheck, searchQuery, onSearchChange, editorClassName }) {
395
395
  const editor = useEditor$1();
396
- useEffect(() => {
396
+ useLayoutEffect(() => {
397
397
  editor.commands.setMarkMode(markMode);
398
398
  }, [editor, markMode]);
399
+ useLayoutEffect(() => {
400
+ if (!editorClassName) return;
401
+ const extension = defineViewAttributes({ class: editorClassName });
402
+ return editor.use(extension);
403
+ }, [editor, editorClassName]);
404
+ const deferredSearchQuery = useDeferredValue(searchQuery);
405
+ useEffect(() => {
406
+ editor.commands.setSearchQuery({
407
+ search: deferredSearchQuery,
408
+ literal: true
409
+ });
410
+ }, [editor, deferredSearchQuery]);
411
+ useExtension$1(useMemo(() => onSearchChange ? defineSearchStatusHandler(onSearchChange) : null, [onSearchChange]));
399
412
  useExtension$1(useMemo(() => {
400
413
  return readOnly ? defineReadonly() : null;
401
414
  }, [readOnly]));
@@ -469,9 +482,6 @@ function EditorExtensions({ markMode, onDocChange, onWikilinkClick, onLinkClick,
469
482
  useExtension$1(useMemo(() => {
470
483
  return spellCheck == null ? null : defineSpellCheckPlugin(spellCheck);
471
484
  }, [spellCheck]));
472
- useExtension$1(useMemo(() => {
473
- return editorClassName ? defineViewAttributes({ class: editorClassName }) : null;
474
- }, [editorClassName]));
475
485
  return null;
476
486
  }
477
487
 
@@ -908,7 +918,7 @@ function SelectionMenu({ onSelectionMenuSearch, context, onOpen, onClose, afford
908
918
  useExtension$1(useMemo(() => {
909
919
  return defineUpdateHandler((view) => {
910
920
  const { from, to, empty } = view.state.selection;
911
- const anchorable = !empty && isTextSelection(view.state.selection) && !getPendingReplacement(view.state);
921
+ const anchorable = !empty && isTextSelection(view.state.selection) && !getPendingReplacement(view.state) && getSearchStatus(view.state).active === 0;
912
922
  setSelection((previous) => {
913
923
  if (previous?.from === from && previous?.to === to && previous?.anchorable === anchorable) return previous;
914
924
  return {
@@ -1681,7 +1691,7 @@ function findHeadingPosition(doc, fragment) {
1681
1691
  });
1682
1692
  return match;
1683
1693
  }
1684
- 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, timeFormat, editorClassName, ref, children }) {
1694
+ 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 }) {
1685
1695
  const [editor] = useState(() => {
1686
1696
  const editor = createEditor({ extension: union(defineEditorExtension({
1687
1697
  resolveFileLink,
@@ -1791,6 +1801,12 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onSl
1791
1801
  function discardPendingReplacement() {
1792
1802
  editor.commands.discardPendingReplacement();
1793
1803
  }
1804
+ function findNext() {
1805
+ editor.commands.findNext();
1806
+ }
1807
+ function findPrevious() {
1808
+ editor.commands.findPrev();
1809
+ }
1794
1810
  return {
1795
1811
  getMarkdown,
1796
1812
  setMarkdown,
@@ -1809,6 +1825,8 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onSl
1809
1825
  appendPendingReplacementText,
1810
1826
  acceptPendingReplacement,
1811
1827
  discardPendingReplacement,
1828
+ findNext,
1829
+ findPrevious,
1812
1830
  editor
1813
1831
  };
1814
1832
  }, [
@@ -1849,6 +1867,8 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onSl
1849
1867
  readOnly,
1850
1868
  wikilinkEnabled: !!onWikilinkSearch,
1851
1869
  spellCheck,
1870
+ searchQuery,
1871
+ onSearchChange,
1852
1872
  editorClassName
1853
1873
  }),
1854
1874
  blockHandle && !readOnly && /* @__PURE__ */ jsx(BlockHandle, {}),
@@ -1891,7 +1911,7 @@ const CARET_GLIDE_OFF = { "--meowdown-caret-glide": "0ms" };
1891
1911
  *
1892
1912
  * Callbacks and resolvers should be stable; pass them via `useCallback`.
1893
1913
  */
1894
- function MeowdownEditor({ mode = "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 = true, linkPaste = true, bulletAfterHeading = false, substitution = true, frontmatter = false, blockHandle = true, caretGlide = true, placeholder, readOnly, spellCheck, timeFormat, editorClassName, wrapperClassName, handleRef, children }) {
1914
+ function MeowdownEditor({ mode = "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 = true, linkPaste = true, bulletAfterHeading = false, substitution = true, frontmatter = false, blockHandle = true, caretGlide = true, placeholder, readOnly, spellCheck, searchQuery, onSearchChange, timeFormat, editorClassName, wrapperClassName, handleRef, children }) {
1895
1915
  const childRef = useRef(null);
1896
1916
  useImperativeHandle(handleRef, () => {
1897
1917
  function getMarkdown() {
@@ -1953,6 +1973,12 @@ function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onSlashM
1953
1973
  function discardPendingReplacement() {
1954
1974
  childRef.current?.discardPendingReplacement();
1955
1975
  }
1976
+ function findNext() {
1977
+ childRef.current?.findNext();
1978
+ }
1979
+ function findPrevious() {
1980
+ childRef.current?.findPrevious();
1981
+ }
1956
1982
  return {
1957
1983
  getMarkdown,
1958
1984
  setMarkdown,
@@ -1971,6 +1997,8 @@ function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onSlashM
1971
1997
  appendPendingReplacementText,
1972
1998
  acceptPendingReplacement,
1973
1999
  discardPendingReplacement,
2000
+ findNext,
2001
+ findPrevious,
1974
2002
  get editor() {
1975
2003
  return childRef.current?.editor;
1976
2004
  }
@@ -2013,6 +2041,8 @@ function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onSlashM
2013
2041
  placeholder,
2014
2042
  readOnly,
2015
2043
  spellCheck,
2044
+ searchQuery,
2045
+ onSearchChange,
2016
2046
  timeFormat,
2017
2047
  editorClassName,
2018
2048
  children
@@ -2478,48 +2508,54 @@ function renderInline(node, context) {
2478
2508
  marks: Mark.setFrom(marks)
2479
2509
  })), 0, context);
2480
2510
  }
2511
+ /** A collapsed list renders as an expanded one */
2512
+ function expandCollapsedList(node) {
2513
+ const attrs = node.attrs;
2514
+ if (!attrs.collapsed) return node;
2515
+ return node.type.create({
2516
+ ...attrs,
2517
+ collapsed: false
2518
+ }, node.content, node.marks);
2519
+ }
2520
+ function createTaskClickHandler(node, context) {
2521
+ const attrs = node.attrs;
2522
+ const { onTaskClick } = context;
2523
+ if (attrs.kind !== "task" || !onTaskClick) return void 0;
2524
+ const index = context.taskCounter.value++;
2525
+ const checked = attrs.checked === true;
2526
+ const marker = attrs.marker ?? null;
2527
+ const text = node.firstChild?.isTextblock ? node.firstChild.textContent.split("\n", 1)[0] ?? "" : "";
2528
+ return (event) => {
2529
+ event.preventDefault();
2530
+ onTaskClick({
2531
+ index,
2532
+ checked,
2533
+ marker,
2534
+ text,
2535
+ event: event.nativeEvent
2536
+ });
2537
+ };
2538
+ }
2539
+ function renderCodeBlock(node, key) {
2540
+ const attrs = node.attrs;
2541
+ const language = typeof attrs.language === "string" ? attrs.language : "";
2542
+ if (language === "math") return /* @__PURE__ */ jsx(MathCodeBlock, { code: node.textContent }, key);
2543
+ if (language === "mermaid") return /* @__PURE__ */ jsx(MermaidCodeBlock, { code: node.textContent }, key);
2544
+ return /* @__PURE__ */ jsx(CodeBlock, {
2545
+ code: node.textContent,
2546
+ language
2547
+ }, key);
2548
+ }
2481
2549
  function renderBlock(node, context) {
2482
2550
  if (context.referenceDefinitionNodes.has(node)) return null;
2483
2551
  const key = context.keyCounter.value++;
2484
2552
  const typeName = node.type.name;
2485
2553
  let handleTaskClick;
2486
2554
  if (typeName === "list") {
2487
- let attrs = node.attrs;
2488
- if (context.expandCollapsed && attrs.collapsed) {
2489
- attrs = {
2490
- ...attrs,
2491
- collapsed: false
2492
- };
2493
- node = node.type.create(attrs, node.content, node.marks);
2494
- }
2495
- const { onTaskClick } = context;
2496
- if (attrs.kind === "task" && onTaskClick) {
2497
- const index = context.taskCounter.value++;
2498
- const checked = attrs.checked === true;
2499
- const marker = attrs.marker ?? null;
2500
- const text = node.firstChild?.isTextblock ? node.firstChild.textContent.split("\n", 1)[0] ?? "" : "";
2501
- handleTaskClick = (event) => {
2502
- event.preventDefault();
2503
- onTaskClick({
2504
- index,
2505
- checked,
2506
- marker,
2507
- text,
2508
- event: event.nativeEvent
2509
- });
2510
- };
2511
- }
2512
- }
2513
- if (typeName === "codeBlock") {
2514
- const attrs = node.attrs;
2515
- const language = typeof attrs.language === "string" ? attrs.language : "";
2516
- if (language === "math") return /* @__PURE__ */ jsx(MathCodeBlock, { code: node.textContent }, key);
2517
- if (language === "mermaid") return /* @__PURE__ */ jsx(MermaidCodeBlock, { code: node.textContent }, key);
2518
- return /* @__PURE__ */ jsx(CodeBlock, {
2519
- code: node.textContent,
2520
- language
2521
- }, key);
2555
+ if (context.expandCollapsed) node = expandCollapsedList(node);
2556
+ handleTaskClick = createTaskClickHandler(node, context);
2522
2557
  }
2558
+ if (typeName === "codeBlock") return renderCodeBlock(node, key);
2523
2559
  const toDOM = node.type.spec.toDOM;
2524
2560
  if (node.isTextblock) {
2525
2561
  const inline = renderInline(node, context);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meowdown/react",
3
3
  "type": "module",
4
- "version": "0.58.3",
4
+ "version": "0.59.1",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -25,13 +25,13 @@
25
25
  "@ocavue/utils": "^1.7.0",
26
26
  "@prosekit/core": "^0.13.0-beta.7",
27
27
  "@prosekit/pm": "^0.1.19-beta.4",
28
- "@prosekit/react": "^0.8.0-beta.23",
28
+ "@prosekit/react": "^0.8.0-beta.24",
29
29
  "beautiful-mermaid": "^1.1.3",
30
30
  "clsx": "^2.1.1",
31
31
  "github-slugger": "^2.0.0",
32
- "lucide-react": "^1.24.0",
32
+ "lucide-react": "^1.27.0",
33
33
  "react-property": "^2.0.2",
34
- "@meowdown/core": "0.58.3"
34
+ "@meowdown/core": "0.59.1"
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.8",
51
+ "@tsdown/css": "^0.22.14",
52
52
  "@types/react": "^19.2.17",
53
53
  "@types/react-dom": "^19.2.3",
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.8",
58
+ "tsdown": "^0.22.14",
59
59
  "vitest": "^4.1.10",
60
60
  "vitest-browser-commands": "^0.2.1",
61
61
  "vitest-browser-react": "^2.2.0",