@meowdown/react 0.80.2 → 0.81.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/dist/index.d.ts CHANGED
@@ -2,6 +2,14 @@ import { ComponentProps, ReactElement, ReactNode, Ref } from "react";
2
2
  import { AcceptPendingReplacementOptions, EditorConfig, ExitBoundaryHandler, FileClickHandler, FileInfoResolver, FileLinkResolver, FilePasteOptions, FileViewOptions, ImageClickHandler, ImageOptions, ImageUrlResolver, LinkClickHandler, LinkCopyHandler, LinkPreview, LinkPreviewResolver, LinkPreviewResolver as LinkPreviewResolver$1, ListMarker, MarkMode, PendingReplacement, PendingReplacementOutcome, PlaceholderOptions, ReferenceDefinitions, SearchStatusHandler, StartPendingReplacementOptions, TagClickHandler, TypedEditor, WikiEmbedResolver, WikilinkClickHandler, WikilinkHoverHit, WikilinkResolver, XPostMediaClickHandler, XPostResolver, XPostResolver as XPostResolver$1, YouTubeVideoClickHandler, YouTubeVideoResolver, YouTubeVideoResolver as YouTubeVideoResolver$1 } from "@meowdown/core";
3
3
  import { SelectionJSON, SelectionJSON as SelectionJSON$1 } from "@prosekit/core";
4
4
  import { ReactNodeViewComponent, ReactNodeViewComponent as ReactNodeViewComponent$1, useEditor, useExtension, useKeymap } from "@prosekit/react";
5
+ import { Popover } from "@base-ui/react/popover";
6
+ //#region src/components/collision-boundary.d.ts
7
+ /**
8
+ * The area the editor's floating menus and popovers stay inside. Same as the
9
+ * `collisionBoundary` prop of Base UI positioners.
10
+ */
11
+ type CollisionBoundary = NonNullable<Popover.Positioner.Props['collisionBoundary']>;
12
+ //#endregion
5
13
  //#region src/utils/date-format.d.ts
6
14
  type TimeFormat = '12' | '24';
7
15
  //#endregion
@@ -330,6 +338,12 @@ interface EditorProps {
330
338
  * is set. Ignored when `readOnly` is set.
331
339
  */
332
340
  selectionMenuAffordance?: boolean | undefined;
341
+ /**
342
+ * The element the editor's menus and popovers stay inside, for example one
343
+ * that leaves out the area under a phone's status bar. Defaults to the
344
+ * viewport.
345
+ */
346
+ collisionBoundary?: CollisionBoundary | undefined;
333
347
  /**
334
348
  * Extra controls rendered in the pending-replacement preview footer, next to
335
349
  * the built-in accept ("Replace selection" / "Insert below", per the staged
@@ -583,7 +597,7 @@ interface EditorProps {
583
597
  *
584
598
  * Callbacks and resolvers should be stable; pass them via `useCallback`.
585
599
  */
586
- export declare function MarkdownEditor({ mode, initialMarkdown, singleParagraph, referenceDefinitions, onDocChange, onSlashMenuSearch, onTagSearch, onWikilinkSearch, onSelectionMenuSearch, selectionMenuAffordance, pendingReplacementActions, onPendingReplacementResolve, onWikilinkClick, onLinkClick, onLinkCopy, resolveLinkPreview, onTagClick, onExitBoundary, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveWikilink, resolveFileInfo, resolveXPost, mediaUrlProtocols, resolveYouTubeVideo, onFileClick, onFilePaste, onFileSaveError, onImageClick, onXPostMediaClick, onYouTubeVideoClick, embedPaste, linkPaste, bulletAfterHeading, backspaceDeletesEmptyFirstBlock, substitution, frontmatter, blockHandle, caretGlide, placeholder, readOnly, spellCheck, searchQuery, onSearchChange, timeFormat, editorClassName, wrapperClassName, CodeBlockView, handleRef, children }: EditorProps): ReactElement;
600
+ export declare function MarkdownEditor({ mode, initialMarkdown, singleParagraph, referenceDefinitions, onDocChange, onSlashMenuSearch, onTagSearch, onWikilinkSearch, onSelectionMenuSearch, selectionMenuAffordance, collisionBoundary, pendingReplacementActions, onPendingReplacementResolve, onWikilinkClick, onLinkClick, onLinkCopy, resolveLinkPreview, onTagClick, onExitBoundary, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveWikilink, resolveFileInfo, resolveXPost, mediaUrlProtocols, resolveYouTubeVideo, onFileClick, onFilePaste, onFileSaveError, onImageClick, onXPostMediaClick, onYouTubeVideoClick, embedPaste, linkPaste, bulletAfterHeading, backspaceDeletesEmptyFirstBlock, substitution, frontmatter, blockHandle, caretGlide, placeholder, readOnly, spellCheck, searchQuery, onSearchChange, timeFormat, editorClassName, wrapperClassName, CodeBlockView, handleRef, children }: EditorProps): ReactElement;
587
601
  //#endregion
588
602
  //#region src/components/markdown-view.d.ts
589
603
  /**
@@ -930,4 +944,4 @@ interface WikilinkHoverCardProps {
930
944
  */
931
945
  export declare function WikilinkHoverCard({ children, className }: WikilinkHoverCardProps): ReactNode;
932
946
  //#endregion
933
- export { type EditorHandle, type EditorMode, type EditorProps, type EditorStateSnapshot, type LightboxCloseOptions, type LightboxController, type LightboxFrameItem, type LightboxFrameProps, type LightboxImageItem, type LightboxImageProps, type LightboxItem, type LightboxRootProps, type LightboxVideoItem, type LightboxVideoProps, type LinkPreview, type LinkPreviewResolver, type MarkdownViewProps, type PendingReplacementResolveHandler, type ReactNodeViewComponent, type SelectionHint, type SelectionJSON, type SelectionMenuContext, type SelectionMenuItem, type SelectionMenuSearchHandler, type SlashMenuItem, type SlashMenuSearchHandler, type TagItem, type TagSearchHandler, type TaskClickHandler, type TaskClickPayload, type TimeFormat, type WikilinkHoverCardProps, type WikilinkItem, type WikilinkSearchHandler, type XPostResolver, type YouTubeVideoResolver, useEditor, useExtension, useKeymap };
947
+ export { type CollisionBoundary, type EditorHandle, type EditorMode, type EditorProps, type EditorStateSnapshot, type LightboxCloseOptions, type LightboxController, type LightboxFrameItem, type LightboxFrameProps, type LightboxImageItem, type LightboxImageProps, type LightboxItem, type LightboxRootProps, type LightboxVideoItem, type LightboxVideoProps, type LinkPreview, type LinkPreviewResolver, type MarkdownViewProps, type PendingReplacementResolveHandler, type ReactNodeViewComponent, type SelectionHint, type SelectionJSON, type SelectionMenuContext, type SelectionMenuItem, type SelectionMenuSearchHandler, type SlashMenuItem, type SlashMenuSearchHandler, type TagItem, type TagSearchHandler, type TaskClickHandler, type TaskClickPayload, type TimeFormat, type WikilinkHoverCardProps, type WikilinkItem, type WikilinkSearchHandler, type XPostResolver, type YouTubeVideoResolver, useEditor, useExtension, useKeymap };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { clsx } from "clsx/lite";
2
- import { Fragment, ViewTransition, cloneElement, createElement, memo, startTransition, useCallback, useDeferredValue, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
2
+ import { Fragment, ViewTransition, cloneElement, createContext, createElement, memo, startTransition, use, useCallback, useDeferredValue, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
3
3
  import { buildFileMarkdown, codeBlockLanguages, collectReferenceDefinitions, defaultResolveImageUrl, defaultResolveXPost, defaultResolveYouTubeVideo, defineCodeBlockPreviewPlugin, defineEditorExtension, defineLinkEditKeymap, defineLinkHoverHandler, definePendingReplacementHandler, defineSearchStatusHandler, defineVirtualCaret, defineWikilinkHoverHandler, dismissLinkHover, docToMarkdown, docToParagraphMarkdown, formatFileSize, getCodeTokens, getFileKind, getLinkText, getMarkBuilders, getPendingReplacement, getSearchStatus, getSelectedText, getTableColumnAlign, getTextblockDisplayText, getVirtualElementFromRange, inlineTextToMarkChunksWithContext, isCodeBlockPreviewHiddenDecoration, isLinkTextForHref, isModEvent, isNodeOfType, isReferenceDefinitionNode, isSelectionInTableCell, loadKaTeX, markdownToDoc, normalizeHref, paragraphMarkdownToDoc, parsePostEmbedSnapshot, renderMathInto, updateEditorConfig } from "@meowdown/core";
4
4
  import { clamp } from "@ocavue/utils";
5
5
  import { canUseRegexLookbehind, createEditor, defineDocChangeHandler, defineUpdateHandler, isTextSelection, union } from "@prosekit/core";
@@ -98,6 +98,20 @@ var code_block_view_module_default = {
98
98
  "TriggerIcon": "meow_TriggerIcon_D3j_9q"
99
99
  };
100
100
 
101
+ //#endregion
102
+ //#region src/components/collision-boundary.ts
103
+ /**
104
+ * See `EditorProps.collisionBoundary`.
105
+ */
106
+ const CollisionBoundaryContext = createContext(void 0);
107
+ /**
108
+ * Converts a {@link CollisionBoundary} to the `boundary` prop of ProseKit
109
+ * positioners, which spell the keyword the floating-ui way.
110
+ */
111
+ function toFloatingBoundary(boundary) {
112
+ return boundary === "clipping-ancestors" ? "clippingAncestors" : boundary;
113
+ }
114
+
101
115
  //#endregion
102
116
  //#region src/components/copy-button.tsx
103
117
  const COPIED_RESET_MS = 1500;
@@ -240,6 +254,8 @@ function CodeBlockView(props) {
240
254
  return /* @__PURE__ */ jsxs("div", {
241
255
  className: code_block_view_module_default.Root,
242
256
  "data-preview": previewOnly || void 0,
257
+ "data-selected": selected || void 0,
258
+ "data-testid": "code-block",
243
259
  children: [
244
260
  /* @__PURE__ */ jsx("pre", {
245
261
  ref: contentRef,
@@ -270,6 +286,7 @@ function CodeBlockView(props) {
270
286
  });
271
287
  }
272
288
  function CodeBlockToolbar({ code, language, setLanguage }) {
289
+ const collisionBoundary = use(CollisionBoundaryContext);
273
290
  const selected = useMemo(() => {
274
291
  return codeBlockLanguages.find((item) => item.value === language) ?? {
275
292
  value: language,
@@ -314,6 +331,7 @@ function CodeBlockToolbar({ code, language, setLanguage }) {
314
331
  }), /* @__PURE__ */ jsx(Combobox.Portal, { children: /* @__PURE__ */ jsx(Combobox.Positioner, {
315
332
  className: code_block_view_module_default.Positioner,
316
333
  sideOffset: 4,
334
+ collisionBoundary,
317
335
  children: /* @__PURE__ */ jsxs(Combobox.Popup, {
318
336
  className: code_block_view_module_default.Popup,
319
337
  children: [
@@ -532,6 +550,7 @@ function selectLinkUnit(editor, link) {
532
550
  editor.focus();
533
551
  }
534
552
  function LinkPopover({ anchor, open, onClose, onCloseComplete, onPopupHover, children }) {
553
+ const collisionBoundary = use(CollisionBoundaryContext);
535
554
  return /* @__PURE__ */ jsx(Popover.Root, {
536
555
  open,
537
556
  onOpenChange: (open) => {
@@ -544,6 +563,7 @@ function LinkPopover({ anchor, open, onClose, onCloseComplete, onPopupHover, chi
544
563
  anchor,
545
564
  side: "bottom",
546
565
  sideOffset: 8,
566
+ collisionBoundary,
547
567
  className: link_menu_module_default.Positioner,
548
568
  children: /* @__PURE__ */ jsx(Popover.Popup, {
549
569
  className: link_menu_module_default.Popup,
@@ -1097,6 +1117,7 @@ var selection_menu_module_default = {
1097
1117
  */
1098
1118
  function SelectionMenu({ onSelectionMenuSearch, context, onOpen, onClose, affordance = true }) {
1099
1119
  const editor = useEditor$1();
1120
+ const collisionBoundary = use(CollisionBoundaryContext);
1100
1121
  const [selection, setSelection] = useState();
1101
1122
  useExtension$1(useMemo(() => {
1102
1123
  return defineUpdateHandler((view) => {
@@ -1118,10 +1139,7 @@ function SelectionMenu({ onSelectionMenuSearch, context, onOpen, onClose, afford
1118
1139
  }, [onClose, editor]);
1119
1140
  const menuAnchor = useMemo(() => {
1120
1141
  if (!context) return;
1121
- return getVirtualElementFromRange(editor.view, {
1122
- from: context.from,
1123
- to: context.to
1124
- });
1142
+ return getMenuAnchor(editor.view, context.from, context.to);
1125
1143
  }, [context, editor]);
1126
1144
  const showAffordance = affordance && !!!context && !!selection?.anchorable;
1127
1145
  const affordanceVisible = useDelayedFlag(showAffordance, 250, 0);
@@ -1145,6 +1163,7 @@ function SelectionMenu({ onSelectionMenuSearch, context, onOpen, onClose, afford
1145
1163
  anchor: menuAnchor,
1146
1164
  side: "bottom",
1147
1165
  sideOffset: 8,
1166
+ collisionBoundary,
1148
1167
  className: selection_menu_module_default.Positioner,
1149
1168
  children: /* @__PURE__ */ jsx(Popover.Popup, {
1150
1169
  className: selection_menu_module_default.Popup,
@@ -1165,6 +1184,7 @@ function SelectionMenu({ onSelectionMenuSearch, context, onOpen, onClose, afford
1165
1184
  anchor: affordanceAnchor,
1166
1185
  side: "bottom",
1167
1186
  sideOffset: 4,
1187
+ collisionBoundary,
1168
1188
  className: selection_menu_module_default.AffordancePositioner,
1169
1189
  children: /* @__PURE__ */ jsx(Popover.Popup, {
1170
1190
  className: selection_menu_module_default.AffordancePopup,
@@ -1186,6 +1206,30 @@ function SelectionMenu({ onSelectionMenuSearch, context, onOpen, onClose, afford
1186
1206
  return null;
1187
1207
  }
1188
1208
  /**
1209
+ * Anchors the menu to the selected range, or to the range's end when the range
1210
+ * is taller than a third of the visible height: such a range leaves no room
1211
+ * for the menu above or below it.
1212
+ */
1213
+ function getMenuAnchor(view, from, to) {
1214
+ const range = getVirtualElementFromRange(view, {
1215
+ from,
1216
+ to
1217
+ });
1218
+ if (from === to) return range;
1219
+ const end = getVirtualElementFromRange(view, {
1220
+ from: to,
1221
+ to
1222
+ });
1223
+ const pickAnchor = () => {
1224
+ const visibleHeight = view.dom.ownerDocument.defaultView?.visualViewport?.height ?? Infinity;
1225
+ return range.getBoundingClientRect().height > visibleHeight / 3 ? end : range;
1226
+ };
1227
+ return {
1228
+ getBoundingClientRect: () => pickAnchor().getBoundingClientRect(),
1229
+ contextElement: view.dom
1230
+ };
1231
+ }
1232
+ /**
1189
1233
  * The menu content. Mounted only while the menu is open, so its filter state
1190
1234
  * resets naturally on close.
1191
1235
  */
@@ -1322,6 +1366,7 @@ function selectionInTableCell(editor) {
1322
1366
  }
1323
1367
  function SlashMenu({ timeFormat = "12", onSlashMenuSearch, onFilePaste, onFileSaveError }) {
1324
1368
  const editor = useEditor$1();
1369
+ const collisionBoundary = use(CollisionBoundaryContext);
1325
1370
  const fileInputRef = useRef(null);
1326
1371
  const inTableCell = useEditorDerivedValue(selectionInTableCell);
1327
1372
  const [open, setOpen] = useState(false);
@@ -1384,6 +1429,7 @@ function SlashMenu({ timeFormat = "12", onSlashMenuSearch, onFilePaste, onFileSa
1384
1429
  onChange: handleFileInputChange
1385
1430
  }) : null, /* @__PURE__ */ jsx(AutocompletePositioner, {
1386
1431
  className: autocomplete_menu_module_default.Positioner,
1432
+ boundary: toFloatingBoundary(collisionBoundary),
1387
1433
  children: /* @__PURE__ */ jsxs(AutocompletePopup, {
1388
1434
  className: autocomplete_menu_module_default.Popup,
1389
1435
  "data-testid": "slash-menu",
@@ -1703,6 +1749,7 @@ function returnsTrue() {
1703
1749
  const regex$1 = new RegExp((canUseRegexLookbehind() ? String.raw`(?<!\S)` : "") + String.raw`#[\da-z]+$`, "iu");
1704
1750
  function TagMenu({ onTagSearch }) {
1705
1751
  const editor = useEditor$1();
1752
+ const collisionBoundary = use(CollisionBoundaryContext);
1706
1753
  const [open, setOpen] = useState(false);
1707
1754
  const [query, setQuery] = useState("");
1708
1755
  const [items, setItems] = useState([]);
@@ -1736,6 +1783,7 @@ function TagMenu({ onTagSearch }) {
1736
1783
  onQueryChange: (event) => setQuery(event.detail),
1737
1784
  children: /* @__PURE__ */ jsx(AutocompletePositioner, {
1738
1785
  className: autocomplete_menu_module_default.Positioner,
1786
+ boundary: toFloatingBoundary(collisionBoundary),
1739
1787
  children: /* @__PURE__ */ jsxs(AutocompletePopup, {
1740
1788
  className: autocomplete_menu_module_default.Popup,
1741
1789
  "data-testid": "tag-menu",
@@ -1778,6 +1826,7 @@ function queryFromRegexMatch(match) {
1778
1826
  }
1779
1827
  function WikilinkMenu({ onWikilinkSearch }) {
1780
1828
  const editor = useEditor$1();
1829
+ const collisionBoundary = use(CollisionBoundaryContext);
1781
1830
  const [open, setOpen] = useState(false);
1782
1831
  const [query, setQuery] = useState("");
1783
1832
  const [items, setItems] = useState([]);
@@ -1813,6 +1862,7 @@ function WikilinkMenu({ onWikilinkSearch }) {
1813
1862
  onQueryChange: (event) => setQuery(event.detail),
1814
1863
  children: /* @__PURE__ */ jsx(AutocompletePositioner, {
1815
1864
  className: autocomplete_menu_module_default.Positioner,
1865
+ boundary: toFloatingBoundary(collisionBoundary),
1816
1866
  children: /* @__PURE__ */ jsxs(AutocompletePopup, {
1817
1867
  className: autocomplete_menu_module_default.Popup,
1818
1868
  "data-testid": "wikilink-menu",
@@ -1885,7 +1935,7 @@ function findHeadingPosition(doc, fragment) {
1885
1935
  });
1886
1936
  return match;
1887
1937
  }
1888
- function ProseKitEditor({ markMode = "focus", initialMarkdown, singleParagraph = false, referenceDefinitions, onDocChange, onSlashMenuSearch, onTagSearch, onWikilinkSearch, onSelectionMenuSearch, selectionMenuAffordance = true, pendingReplacementActions, onPendingReplacementResolve, onWikilinkClick, onLinkClick, onLinkCopy, resolveLinkPreview, onTagClick, onExitBoundary, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveWikilink, resolveFileInfo, resolveXPost, mediaUrlProtocols, resolveYouTubeVideo, onFileClick, onFilePaste, onFileSaveError, onImageClick, onXPostMediaClick, onYouTubeVideoClick, embedPaste, linkPaste, bulletAfterHeading, backspaceDeletesEmptyFirstBlock, substitution = true, frontmatter = false, blockHandle = true, placeholder, readOnly, spellCheck, searchQuery = "", onSearchChange, timeFormat, editorClassName, CodeBlockView, ref, children }) {
1938
+ function ProseKitEditor({ markMode = "focus", initialMarkdown, singleParagraph = false, referenceDefinitions, onDocChange, onSlashMenuSearch, onTagSearch, onWikilinkSearch, onSelectionMenuSearch, selectionMenuAffordance = true, collisionBoundary, pendingReplacementActions, onPendingReplacementResolve, onWikilinkClick, onLinkClick, onLinkCopy, resolveLinkPreview, onTagClick, onExitBoundary, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveWikilink, resolveFileInfo, resolveXPost, mediaUrlProtocols, resolveYouTubeVideo, onFileClick, onFilePaste, onFileSaveError, onImageClick, onXPostMediaClick, onYouTubeVideoClick, embedPaste, linkPaste, bulletAfterHeading, backspaceDeletesEmptyFirstBlock, substitution = true, frontmatter = false, blockHandle = true, placeholder, readOnly, spellCheck, searchQuery = "", onSearchChange, timeFormat, editorClassName, CodeBlockView, ref, children }) {
1889
1939
  const suppressDocChangeRef = useRef(false);
1890
1940
  const handleDocChange = useMemo(() => {
1891
1941
  if (!onDocChange) return;
@@ -2109,47 +2159,50 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, singleParagraph =
2109
2159
  const mount = useCallback((element) => {
2110
2160
  return editor.mount(element);
2111
2161
  }, [editor]);
2112
- return /* @__PURE__ */ jsxs(ProseKit, {
2113
- editor,
2114
- children: [
2115
- /* @__PURE__ */ jsx(VirtualCaret, {}),
2116
- /* @__PURE__ */ jsx("div", { ref: mount }),
2117
- /* @__PURE__ */ jsx(EditorExtensions, {
2118
- config,
2119
- searchQuery,
2120
- onDocChange: handleDocChange,
2121
- onSearchChange
2122
- }),
2123
- blockHandle && !readOnly && /* @__PURE__ */ jsx(BlockHandle, {}),
2124
- !readOnly && /* @__PURE__ */ jsx(TableHandle, {}),
2125
- blockHandle && !readOnly && /* @__PURE__ */ jsx(DropIndicator$1, {}),
2126
- /* @__PURE__ */ jsx(SlashMenu, {
2127
- timeFormat,
2128
- onSlashMenuSearch,
2129
- onFilePaste,
2130
- onFileSaveError
2131
- }),
2132
- /* @__PURE__ */ jsx(LinkMenu, {
2133
- onLinkClick,
2134
- onLinkCopy,
2135
- resolveLinkPreview,
2136
- readOnly
2137
- }, String(readOnly)),
2138
- onTagSearch && /* @__PURE__ */ jsx(TagMenu, { onTagSearch }),
2139
- onWikilinkSearch && /* @__PURE__ */ jsx(WikilinkMenu, { onWikilinkSearch }),
2140
- onSelectionMenuSearch && !readOnly && /* @__PURE__ */ jsx(SelectionMenu, {
2141
- onSelectionMenuSearch,
2142
- context: selectionMenuContext,
2143
- onOpen: openSelectionMenu,
2144
- onClose: closeSelectionMenu,
2145
- affordance: selectionMenuAffordance
2146
- }),
2147
- !readOnly && /* @__PURE__ */ jsx(PendingReplacementPreview, {
2148
- actions: pendingReplacementActions,
2149
- onResolve: onPendingReplacementResolve
2150
- }),
2151
- children
2152
- ]
2162
+ return /* @__PURE__ */ jsx(CollisionBoundaryContext, {
2163
+ value: collisionBoundary,
2164
+ children: /* @__PURE__ */ jsxs(ProseKit, {
2165
+ editor,
2166
+ children: [
2167
+ /* @__PURE__ */ jsx(VirtualCaret, {}),
2168
+ /* @__PURE__ */ jsx("div", { ref: mount }),
2169
+ /* @__PURE__ */ jsx(EditorExtensions, {
2170
+ config,
2171
+ searchQuery,
2172
+ onDocChange: handleDocChange,
2173
+ onSearchChange
2174
+ }),
2175
+ blockHandle && !readOnly && /* @__PURE__ */ jsx(BlockHandle, {}),
2176
+ !readOnly && /* @__PURE__ */ jsx(TableHandle, {}),
2177
+ blockHandle && !readOnly && /* @__PURE__ */ jsx(DropIndicator$1, {}),
2178
+ /* @__PURE__ */ jsx(SlashMenu, {
2179
+ timeFormat,
2180
+ onSlashMenuSearch,
2181
+ onFilePaste,
2182
+ onFileSaveError
2183
+ }),
2184
+ /* @__PURE__ */ jsx(LinkMenu, {
2185
+ onLinkClick,
2186
+ onLinkCopy,
2187
+ resolveLinkPreview,
2188
+ readOnly
2189
+ }, String(readOnly)),
2190
+ onTagSearch && /* @__PURE__ */ jsx(TagMenu, { onTagSearch }),
2191
+ onWikilinkSearch && /* @__PURE__ */ jsx(WikilinkMenu, { onWikilinkSearch }),
2192
+ onSelectionMenuSearch && !readOnly && /* @__PURE__ */ jsx(SelectionMenu, {
2193
+ onSelectionMenuSearch,
2194
+ context: selectionMenuContext,
2195
+ onOpen: openSelectionMenu,
2196
+ onClose: closeSelectionMenu,
2197
+ affordance: selectionMenuAffordance
2198
+ }),
2199
+ !readOnly && /* @__PURE__ */ jsx(PendingReplacementPreview, {
2200
+ actions: pendingReplacementActions,
2201
+ onResolve: onPendingReplacementResolve
2202
+ }),
2203
+ children
2204
+ ]
2205
+ })
2153
2206
  });
2154
2207
  }
2155
2208
 
@@ -2162,7 +2215,7 @@ const CARET_GLIDE_OFF = { "--meowdown-caret-glide": "0ms" };
2162
2215
  *
2163
2216
  * Callbacks and resolvers should be stable; pass them via `useCallback`.
2164
2217
  */
2165
- function MarkdownEditor({ mode = "focus", initialMarkdown, singleParagraph, referenceDefinitions, onDocChange, onSlashMenuSearch, onTagSearch, onWikilinkSearch, onSelectionMenuSearch, selectionMenuAffordance = true, pendingReplacementActions, onPendingReplacementResolve, onWikilinkClick, onLinkClick, onLinkCopy, resolveLinkPreview, onTagClick, onExitBoundary, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveWikilink, resolveFileInfo, resolveXPost, mediaUrlProtocols, resolveYouTubeVideo, onFileClick, onFilePaste, onFileSaveError, onImageClick, onXPostMediaClick, onYouTubeVideoClick, embedPaste = true, linkPaste = true, bulletAfterHeading = false, backspaceDeletesEmptyFirstBlock = false, substitution = true, frontmatter = false, blockHandle = true, caretGlide = true, placeholder, readOnly, spellCheck, searchQuery, onSearchChange, timeFormat, editorClassName, wrapperClassName, CodeBlockView, handleRef, children }) {
2218
+ function MarkdownEditor({ mode = "focus", initialMarkdown, singleParagraph, referenceDefinitions, onDocChange, onSlashMenuSearch, onTagSearch, onWikilinkSearch, onSelectionMenuSearch, selectionMenuAffordance = true, collisionBoundary, pendingReplacementActions, onPendingReplacementResolve, onWikilinkClick, onLinkClick, onLinkCopy, resolveLinkPreview, onTagClick, onExitBoundary, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveWikilink, resolveFileInfo, resolveXPost, mediaUrlProtocols, resolveYouTubeVideo, onFileClick, onFilePaste, onFileSaveError, onImageClick, onXPostMediaClick, onYouTubeVideoClick, embedPaste = true, linkPaste = true, bulletAfterHeading = false, backspaceDeletesEmptyFirstBlock = false, substitution = true, frontmatter = false, blockHandle = true, caretGlide = true, placeholder, readOnly, spellCheck, searchQuery, onSearchChange, timeFormat, editorClassName, wrapperClassName, CodeBlockView, handleRef, children }) {
2166
2219
  const childRef = useRef(null);
2167
2220
  useImperativeHandle(handleRef, () => {
2168
2221
  function getMarkdown() {
@@ -2275,6 +2328,7 @@ function MarkdownEditor({ mode = "focus", initialMarkdown, singleParagraph, refe
2275
2328
  onWikilinkSearch,
2276
2329
  onSelectionMenuSearch,
2277
2330
  selectionMenuAffordance,
2331
+ collisionBoundary,
2278
2332
  pendingReplacementActions,
2279
2333
  onPendingReplacementResolve,
2280
2334
  onWikilinkClick,
package/dist/style.css CHANGED
@@ -2,6 +2,16 @@
2
2
  position: relative;
3
3
  }
4
4
 
5
+ .meow_Root_D3j_9q[data-selected] {
6
+ outline: 1px solid var(--meowdown-node-outline);
7
+ background: var(--meowdown-node-selection);
8
+ border-radius: .6rem;
9
+ }
10
+
11
+ .prosekit-dragging .meow_Root_D3j_9q[data-selected] {
12
+ background: none;
13
+ }
14
+
5
15
  .meow_Root_D3j_9q[data-preview] pre, .meow_Root_D3j_9q[data-preview] .meow_Toolbar_D3j_9q {
6
16
  display: none;
7
17
  }
@@ -736,11 +746,12 @@
736
746
 
737
747
  .meow_Popup_2_4Zjq {
738
748
  box-sizing: border-box;
749
+ width: 100%;
750
+ max-height: var(--available-height);
739
751
  border: 1px solid var(--meowdown-border);
740
752
  background: var(--meowdown-popover-bg);
741
753
  border-radius: .75rem;
742
754
  flex-direction: column;
743
- width: 100%;
744
755
  padding: .25rem;
745
756
  font-size: .875rem;
746
757
  display: flex;
@@ -755,6 +766,7 @@
755
766
  border: 1px solid var(--meowdown-border);
756
767
  background: none;
757
768
  border-radius: .5rem;
769
+ flex: none;
758
770
  margin-bottom: .25rem;
759
771
  padding: .375rem .5rem;
760
772
 
@@ -766,6 +778,8 @@
766
778
 
767
779
  .meow_List_2_4Zjq {
768
780
  flex-direction: column;
781
+ flex: auto;
782
+ min-height: 6rem;
769
783
  max-height: 16rem;
770
784
  display: flex;
771
785
  overflow-y: auto;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meowdown/react",
3
3
  "type": "module",
4
- "version": "0.80.2",
4
+ "version": "0.81.0",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -22,7 +22,7 @@
22
22
  ],
23
23
  "dependencies": {
24
24
  "@base-ui/react": "^1.9.0",
25
- "@meowdown/core": "0.81.1",
25
+ "@meowdown/core": "0.81.2",
26
26
  "@meowdown/embed": "0.3.1",
27
27
  "@meowdown/markdown": "0.77.0",
28
28
  "@ocavue/utils": "^1.9.0",