@meowdown/react 0.72.0 → 0.73.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
@@ -49,25 +49,25 @@ export function App() {
49
49
 
50
50
  ## Components
51
51
 
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. |
57
- | `LightboxRoot` / `LightboxImage` / `LightboxVideo` | Full-window image and video preview driven by `useLightbox()`. Compose your own close controls inside `LightboxRoot`, and call `lightbox.open(item, element)` from `onImageClick` or `onXPostMediaClick` to zoom from the clicked element. |
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. |
57
+ | `LightboxRoot` / `LightboxImage` / `LightboxVideo` / `LightboxFrame` | Full-window image, video, and embedded player preview driven by `useLightbox()`. Compose your own close controls inside `LightboxRoot`, and call `lightbox.open(item, element)` from `onImageClick`, `onXPostMediaClick`, or `onYouTubeVideoClick` to zoom from the clicked element. |
58
58
 
59
59
  Common `MeowdownEditor` props:
60
60
 
61
- | Prop | What it does |
62
- | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
63
- | `mode` | `'focus'` (default), `'show'`, or `'hide'`: how much Markdown syntax stays in view |
64
- | `searchQuery` / `onSearchChange` | Find in document, with `EditorHandle.findNext()` / `findPrevious()` |
65
- | `onWikilinkClick` / `onLinkClick` / `onTagClick` / `onImageClick` / `onFileClick` / `onXPostMediaClick` | Click handling for the rendered atoms |
66
- | `resolveImageUrl` / `resolveWikiEmbed` / `resolveWikilink` / `resolveFileLink` / `resolveFileInfo` | Resolve and classify local content |
67
- | `onFilePaste` | Persist pasted or dropped files |
68
- | `onSlashMenuSearch` / `onTagSearch` / `onWikilinkSearch` / `onSelectionMenuSearch` | Search menus for `/`, `#`, `[[`, and selection commands |
69
- | `readOnly` / `placeholder` / `blockHandle` / `caretGlide` / `embedPaste` / `linkPaste` / `bulletAfterHeading` | Behavior toggles |
70
- | `CodeBlockView` | Custom React node view component for code blocks |
61
+ | Prop | What it does |
62
+ | ------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
63
+ | `mode` | `'focus'` (default), `'show'`, or `'hide'`: how much Markdown syntax stays in view |
64
+ | `searchQuery` / `onSearchChange` | Find in document, with `EditorHandle.findNext()` / `findPrevious()` |
65
+ | `onWikilinkClick` / `onLinkClick` / `onTagClick` / `onImageClick` / `onFileClick` / `onXPostMediaClick` / `onYouTubeVideoClick` | Click handling for the rendered atoms |
66
+ | `resolveImageUrl` / `resolveWikiEmbed` / `resolveWikilink` / `resolveFileLink` / `resolveFileInfo` | Resolve and classify local content |
67
+ | `onFilePaste` | Persist pasted or dropped files |
68
+ | `onSlashMenuSearch` / `onTagSearch` / `onWikilinkSearch` / `onSelectionMenuSearch` | Search menus for `/`, `#`, `[[`, and selection commands |
69
+ | `readOnly` / `placeholder` / `blockHandle` / `caretGlide` / `embedPaste` / `linkPaste` / `bulletAfterHeading` | Behavior toggles |
70
+ | `CodeBlockView` | Custom React node view component for code blocks |
71
71
 
72
72
  Every prop, callback, and `EditorHandle` method is documented in the [API reference](https://npmx.dev/package-docs/@meowdown%2Freact/).
73
73
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ComponentProps, ReactElement, ReactNode, Ref } from "react";
2
- import { AcceptPendingReplacementOptions, ExitBoundaryHandler, FileClickHandler, FileInfoResolver, FileLinkResolver, FilePasteOptions, FileViewOptions, ImageClickHandler, ImageOptions, LinkClickHandler, LinkCopyHandler, LinkPreview, LinkPreviewResolver, LinkPreviewResolver as LinkPreviewResolver$1, ListMarker, MarkMode, PendingReplacement, PendingReplacementOutcome, PlaceholderOptions, SearchStatusHandler, StartPendingReplacementOptions, TagClickHandler, TypedEditor, WikiEmbedResolver, WikilinkClickHandler, WikilinkHoverHit, WikilinkResolver, XPostMediaClickHandler, XPostResolver, XPostResolver as XPostResolver$1, YouTubeVideoResolver, YouTubeVideoResolver as YouTubeVideoResolver$1 } from "@meowdown/core";
2
+ import { AcceptPendingReplacementOptions, ExitBoundaryHandler, FileClickHandler, FileInfoResolver, FileLinkResolver, FilePasteOptions, FileViewOptions, ImageClickHandler, ImageOptions, LinkClickHandler, LinkCopyHandler, LinkPreview, LinkPreviewResolver, LinkPreviewResolver as LinkPreviewResolver$1, ListMarker, MarkMode, PendingReplacement, PendingReplacementOutcome, PlaceholderOptions, 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
5
  //#region src/utils/date-format.d.ts
@@ -456,6 +456,15 @@ interface EditorProps {
456
456
  * a lightbox. Pass a stable function (e.g. from `useCallback`).
457
457
  */
458
458
  onXPostMediaClick?: XPostMediaClickHandler;
459
+ /**
460
+ * Called with the `meowdown-embed-youtube-click` event when the user
461
+ * activates the poster of a YouTube card. Its `detail` holds the video, the
462
+ * player URL, and the rendered thumbnail element. Call
463
+ * `event.preventDefault()` to stop the card from playing the video in
464
+ * place, then play it yourself, for example in a lightbox. Pass a stable
465
+ * function (e.g. from `useCallback`).
466
+ */
467
+ onYouTubeVideoClick?: YouTubeVideoClickHandler;
459
468
  /**
460
469
  * Auto-embeds a pasted tweet or YouTube link as a rich embed; one undo turns
461
470
  * the embed back into the raw link. On by default.
@@ -554,7 +563,7 @@ interface EditorProps {
554
563
  *
555
564
  * Callbacks and resolvers should be stable; pass them via `useCallback`.
556
565
  */
557
- export declare function MeowdownEditor({ mode, initialMarkdown, 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, embedPaste, linkPaste, bulletAfterHeading, substitution, frontmatter, blockHandle, caretGlide, placeholder, readOnly, spellCheck, searchQuery, onSearchChange, timeFormat, editorClassName, wrapperClassName, CodeBlockView, handleRef, children }: EditorProps): ReactElement;
566
+ export declare function MeowdownEditor({ mode, initialMarkdown, 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, substitution, frontmatter, blockHandle, caretGlide, placeholder, readOnly, spellCheck, searchQuery, onSearchChange, timeFormat, editorClassName, wrapperClassName, CodeBlockView, handleRef, children }: EditorProps): ReactElement;
558
567
  //#endregion
559
568
  //#region src/components/markdown-view.d.ts
560
569
  /**
@@ -675,6 +684,11 @@ interface MarkdownViewProps {
675
684
  * playing the video in place.
676
685
  */
677
686
  onXPostMediaClick?: XPostMediaClickHandler;
687
+ /**
688
+ * Called when the poster of a YouTube card is activated. Call
689
+ * `event.preventDefault()` to stop the card from playing the video in place.
690
+ */
691
+ onYouTubeVideoClick?: YouTubeVideoClickHandler;
678
692
  /**
679
693
  * Called when a rendered file pill is clicked. Pass a stable function.
680
694
  */
@@ -699,13 +713,13 @@ interface MarkdownViewProps {
699
713
  * Callbacks (`onWikilinkClick`, etc.) and resolvers should be stable; pass them via
700
714
  * `useCallback` to avoid re-rendering the whole tree.
701
715
  */
702
- export declare function MarkdownView({ markdown, markMode, frontmatter, interactive, expandCollapsed, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveWikilink, resolveFileInfo, resolveXPost, mediaUrlProtocols, resolveYouTubeVideo, onWikilinkClick, onLinkClick, onImageClick, onXPostMediaClick, onFileClick, onTaskClick, className }: MarkdownViewProps): ReactElement;
716
+ export declare function MarkdownView({ markdown, markMode, frontmatter, interactive, expandCollapsed, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveWikilink, resolveFileInfo, resolveXPost, mediaUrlProtocols, resolveYouTubeVideo, onWikilinkClick, onLinkClick, onImageClick, onXPostMediaClick, onYouTubeVideoClick, onFileClick, onTaskClick, className }: MarkdownViewProps): ReactElement;
703
717
  //#endregion
704
718
  //#region src/hooks/use-lightbox.d.ts
705
719
  /**
706
720
  * Something a lightbox can show.
707
721
  */
708
- type LightboxItem = LightboxImageItem | LightboxVideoItem;
722
+ type LightboxItem = LightboxImageItem | LightboxVideoItem | LightboxFrameItem;
709
723
  interface LightboxImageItem {
710
724
  type: 'image';
711
725
  /**
@@ -743,6 +757,26 @@ interface LightboxVideoItem {
743
757
  gif?: boolean | undefined;
744
758
  alt?: string | undefined;
745
759
  }
760
+ interface LightboxFrameItem {
761
+ type: 'frame';
762
+ /**
763
+ * The page the `<iframe>` loads, for example a video player.
764
+ */
765
+ src: string;
766
+ /**
767
+ * The accessible name of the `<iframe>`.
768
+ */
769
+ title: string;
770
+ /**
771
+ * URL of the image the frame shows until its page has painted.
772
+ */
773
+ poster?: string | undefined;
774
+ /**
775
+ * With `height`, the aspect ratio of the frame. 16:9 when either is missing.
776
+ */
777
+ width?: number | undefined;
778
+ height?: number | undefined;
779
+ }
746
780
  interface LightboxCloseOptions {
747
781
  /**
748
782
  * Close without the zoom back to the thumbnail, for example after the
@@ -782,6 +816,19 @@ interface LightboxController {
782
816
  */
783
817
  export declare function useLightbox(): LightboxController;
784
818
  //#endregion
819
+ //#region src/components/lightbox-frame.d.ts
820
+ /**
821
+ * Props for {@link LightboxFrame}. Other props land on the `<iframe>`.
822
+ */
823
+ interface LightboxFrameProps extends Omit<ComponentProps<'iframe'>, 'src' | 'title' | 'children'> {
824
+ readonly item: LightboxFrameItem;
825
+ }
826
+ /**
827
+ * The embedded page of a lightbox, such as a video player: the largest box of
828
+ * the item's aspect ratio that fits.
829
+ */
830
+ export declare function LightboxFrame({ item, className, style, ...props }: LightboxFrameProps): ReactNode;
831
+ //#endregion
785
832
  //#region src/components/lightbox-image.d.ts
786
833
  /**
787
834
  * Props for {@link LightboxImage}. Other props land on the `<img>`.
@@ -804,7 +851,7 @@ interface LightboxRootProps extends Omit<ComponentProps<'dialog'>, 'children' |
804
851
  */
805
852
  readonly lightbox: LightboxController;
806
853
  /**
807
- * Render the open item. Put a {@link LightboxImage} somewhere inside, along
854
+ * Render the open item. Put a {@link LightboxImage}, {@link LightboxVideo}, or {@link LightboxFrame} somewhere inside, along
808
855
  * with whatever closes the lightbox.
809
856
  */
810
857
  readonly children: (item: LightboxItem) => ReactNode;
@@ -853,4 +900,4 @@ interface WikilinkHoverCardProps {
853
900
  */
854
901
  export declare function WikilinkHoverCard({ children, className }: WikilinkHoverCardProps): ReactNode;
855
902
  //#endregion
856
- export { type EditorHandle, type EditorMode, type EditorProps, type EditorStateSnapshot, type LightboxCloseOptions, type LightboxController, 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 };
903
+ 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 };
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@ import { AutocompleteEmpty, AutocompleteItem, AutocompletePopup, AutocompletePos
16
16
  import { MenuItem, MenuPopup, MenuPositioner } from "@prosekit/react/menu";
17
17
  import { TableHandleColumnMenuRoot, TableHandleColumnMenuTrigger, TableHandleColumnPopup, TableHandleColumnPositioner, TableHandleDragPreview, TableHandleDropIndicator, TableHandleRoot, TableHandleRowMenuRoot, TableHandleRowMenuTrigger, TableHandleRowPopup, TableHandleRowPositioner } from "@prosekit/react/table-handle";
18
18
  import { X_POST_MEDIA_CLICK, registerXPost } from "@meowdown/embed/x";
19
- import { registerYouTubeVideo } from "@meowdown/embed/youtube";
19
+ import { YOUTUBE_VIDEO_CLICK, registerYouTubeVideo } from "@meowdown/embed/youtube";
20
20
  import { matchEmbed } from "@meowdown/markdown";
21
21
  import { Mark } from "@prosekit/pm/model";
22
22
  import { BOOLEAN, OVERLOADED_BOOLEAN, getPropertyInfo, possibleStandardNames } from "react-property";
@@ -1848,7 +1848,7 @@ function findHeadingPosition(doc, fragment) {
1848
1848
  });
1849
1849
  return match;
1850
1850
  }
1851
- function ProseKitEditor({ markMode = "focus", initialMarkdown, 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, embedPaste, linkPaste, bulletAfterHeading, substitution = true, frontmatter = false, blockHandle = true, placeholder, readOnly, spellCheck, searchQuery = "", onSearchChange, timeFormat, editorClassName, CodeBlockView, ref, children }) {
1851
+ function ProseKitEditor({ markMode = "focus", initialMarkdown, 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, substitution = true, frontmatter = false, blockHandle = true, placeholder, readOnly, spellCheck, searchQuery = "", onSearchChange, timeFormat, editorClassName, CodeBlockView, ref, children }) {
1852
1852
  const suppressDocChangeRef = useRef(false);
1853
1853
  const handleDocChange = useMemo(() => {
1854
1854
  if (!onDocChange) return;
@@ -1877,6 +1877,7 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onSl
1877
1877
  onFileSaveError,
1878
1878
  onImageClick,
1879
1879
  onXPostMediaClick,
1880
+ onYouTubeVideoClick,
1880
1881
  embedPaste,
1881
1882
  linkPaste,
1882
1883
  bulletAfterHeading,
@@ -1905,6 +1906,7 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onSl
1905
1906
  onFileSaveError,
1906
1907
  onImageClick,
1907
1908
  onXPostMediaClick,
1909
+ onYouTubeVideoClick,
1908
1910
  embedPaste,
1909
1911
  linkPaste,
1910
1912
  bulletAfterHeading,
@@ -2107,7 +2109,7 @@ const CARET_GLIDE_OFF = { "--meowdown-caret-glide": "0ms" };
2107
2109
  *
2108
2110
  * Callbacks and resolvers should be stable; pass them via `useCallback`.
2109
2111
  */
2110
- function MeowdownEditor({ mode = "focus", initialMarkdown, 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, embedPaste = true, linkPaste = true, bulletAfterHeading = false, substitution = true, frontmatter = false, blockHandle = true, caretGlide = true, placeholder, readOnly, spellCheck, searchQuery, onSearchChange, timeFormat, editorClassName, wrapperClassName, CodeBlockView, handleRef, children }) {
2112
+ function MeowdownEditor({ mode = "focus", initialMarkdown, 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, substitution = true, frontmatter = false, blockHandle = true, caretGlide = true, placeholder, readOnly, spellCheck, searchQuery, onSearchChange, timeFormat, editorClassName, wrapperClassName, CodeBlockView, handleRef, children }) {
2111
2113
  const childRef = useRef(null);
2112
2114
  useImperativeHandle(handleRef, () => {
2113
2115
  function getMarkdown() {
@@ -2234,6 +2236,7 @@ function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onSlashM
2234
2236
  onFileSaveError,
2235
2237
  onImageClick,
2236
2238
  onXPostMediaClick,
2239
+ onYouTubeVideoClick,
2237
2240
  embedPaste,
2238
2241
  linkPaste,
2239
2242
  bulletAfterHeading,
@@ -2865,7 +2868,7 @@ const MarkdownBlock = memo(function MarkdownBlock({ node, taskBase, context, ref
2865
2868
  * Callbacks (`onWikilinkClick`, etc.) and resolvers should be stable; pass them via
2866
2869
  * `useCallback` to avoid re-rendering the whole tree.
2867
2870
  */
2868
- function MarkdownView({ markdown, markMode = "hide", frontmatter = false, interactive = true, expandCollapsed = false, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveWikilink, resolveFileInfo, resolveXPost, mediaUrlProtocols, resolveYouTubeVideo, onWikilinkClick, onLinkClick, onImageClick, onXPostMediaClick, onFileClick, onTaskClick, className }) {
2871
+ function MarkdownView({ markdown, markMode = "hide", frontmatter = false, interactive = true, expandCollapsed = false, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveWikilink, resolveFileInfo, resolveXPost, mediaUrlProtocols, resolveYouTubeVideo, onWikilinkClick, onLinkClick, onImageClick, onXPostMediaClick, onYouTubeVideoClick, onFileClick, onTaskClick, className }) {
2869
2872
  const context = useMemo(() => ({
2870
2873
  interactive,
2871
2874
  expandCollapsed,
@@ -2909,11 +2912,15 @@ function MarkdownView({ markdown, markMode = "hide", frontmatter = false, intera
2909
2912
  };
2910
2913
  }, [markdown, frontmatter]);
2911
2914
  const handleXPostMediaClick = interactive ? onXPostMediaClick : void 0;
2915
+ const handleYouTubeVideoClick = interactive ? onYouTubeVideoClick : void 0;
2912
2916
  const rootRef = useCallback((root) => {
2913
- if (!handleXPostMediaClick) return;
2914
- root.addEventListener(X_POST_MEDIA_CLICK, handleXPostMediaClick);
2915
- return () => root.removeEventListener(X_POST_MEDIA_CLICK, handleXPostMediaClick);
2916
- }, [handleXPostMediaClick]);
2917
+ if (handleXPostMediaClick) root.addEventListener(X_POST_MEDIA_CLICK, handleXPostMediaClick);
2918
+ if (handleYouTubeVideoClick) root.addEventListener(YOUTUBE_VIDEO_CLICK, handleYouTubeVideoClick);
2919
+ return () => {
2920
+ if (handleXPostMediaClick) root.removeEventListener(X_POST_MEDIA_CLICK, handleXPostMediaClick);
2921
+ if (handleYouTubeVideoClick) root.removeEventListener(YOUTUBE_VIDEO_CLICK, handleYouTubeVideoClick);
2922
+ };
2923
+ }, [handleXPostMediaClick, handleYouTubeVideoClick]);
2917
2924
  return /* @__PURE__ */ jsx("div", {
2918
2925
  ref: rootRef,
2919
2926
  className: clsx("ProseMirror", "meowdown-content", className),
@@ -2993,10 +3000,37 @@ function useLightbox() {
2993
3000
  //#region src/components/lightbox.module.css
2994
3001
  var lightbox_module_default = {
2995
3002
  "Dialog": "meow_Dialog_VENw2q",
3003
+ "Frame": "meow_Frame_VENw2q",
2996
3004
  "Image": "meow_Image_VENw2q",
2997
3005
  "Video": "meow_Video_VENw2q"
2998
3006
  };
2999
3007
 
3008
+ //#endregion
3009
+ //#region src/components/lightbox-frame.tsx
3010
+ /**
3011
+ * The embedded page of a lightbox, such as a video player: the largest box of
3012
+ * the item's aspect ratio that fits.
3013
+ */
3014
+ function LightboxFrame({ item, className, style, ...props }) {
3015
+ const ratio = item.width && item.height ? item.width / item.height : 16 / 9;
3016
+ const frameStyle = {
3017
+ ...style,
3018
+ "--meowdown-lightbox-frame-ratio": String(ratio),
3019
+ backgroundImage: item.poster ? `url(${JSON.stringify(item.poster)})` : void 0,
3020
+ viewTransitionName: LIGHTBOX_TRANSITION_NAME
3021
+ };
3022
+ return /* @__PURE__ */ jsx("iframe", {
3023
+ allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen",
3024
+ allowFullScreen: true,
3025
+ referrerPolicy: "strict-origin-when-cross-origin",
3026
+ ...props,
3027
+ src: item.src,
3028
+ title: item.title,
3029
+ className: clsx(lightbox_module_default.Frame, className),
3030
+ style: frameStyle
3031
+ });
3032
+ }
3033
+
3000
3034
  //#endregion
3001
3035
  //#region src/components/lightbox-image.tsx
3002
3036
  /**
@@ -3036,7 +3070,7 @@ function LightboxRoot({ lightbox, children, className, ...props }) {
3036
3070
  default: DIALOG_TRANSITION_CLASS,
3037
3071
  onExit: () => onExited,
3038
3072
  children: /* @__PURE__ */ jsx("dialog", {
3039
- "aria-label": item.type === "video" ? "Video preview" : "Image preview",
3073
+ "aria-label": item.type === "image" ? "Image preview" : "Video preview",
3040
3074
  ...props,
3041
3075
  ref: showModal,
3042
3076
  className: clsx(lightbox_module_default.Dialog, className),
@@ -3165,4 +3199,4 @@ function WikilinkHoverCard({ children, className }) {
3165
3199
  }
3166
3200
 
3167
3201
  //#endregion
3168
- export { LightboxImage, LightboxRoot, LightboxVideo, MarkdownView, MeowdownEditor, WikilinkHoverCard, useEditor, useExtension, useKeymap, useLightbox };
3202
+ export { LightboxFrame, LightboxImage, LightboxRoot, LightboxVideo, MarkdownView, MeowdownEditor, WikilinkHoverCard, useEditor, useExtension, useKeymap, useLightbox };
package/dist/style.css CHANGED
@@ -1073,6 +1073,7 @@
1073
1073
  position: fixed;
1074
1074
  inset: 0;
1075
1075
  overflow: hidden;
1076
+ container-type: size;
1076
1077
 
1077
1078
  &::backdrop {
1078
1079
  background: none;
@@ -1092,6 +1093,14 @@
1092
1093
  max-height: 100%;
1093
1094
  position: relative;
1094
1095
  }
1096
+
1097
+ .meow_Frame_VENw2q {
1098
+ width: min(100cqw, 100cqh * var(--meowdown-lightbox-frame-ratio));
1099
+ aspect-ratio: var(--meowdown-lightbox-frame-ratio);
1100
+ background: #000 center / cover no-repeat;
1101
+ border: 0;
1102
+ display: block;
1103
+ }
1095
1104
  .meow_Positioner_HMEwgW {
1096
1105
  z-index: 50;
1097
1106
  width: var(--positioner-width);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meowdown/react",
3
3
  "type": "module",
4
- "version": "0.72.0",
4
+ "version": "0.73.1",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -22,8 +22,8 @@
22
22
  ],
23
23
  "dependencies": {
24
24
  "@base-ui/react": "^1.8.0",
25
- "@meowdown/core": "0.73.0",
26
- "@meowdown/embed": "0.1.0",
25
+ "@meowdown/core": "0.74.1",
26
+ "@meowdown/embed": "0.2.0",
27
27
  "@meowdown/markdown": "0.72.0",
28
28
  "@ocavue/utils": "^1.8.0",
29
29
  "@post-embed/types": "^0.5.0",