@meowdown/react 0.71.4 → 0.72.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 +7 -6
- package/dist/index.d.ts +150 -8
- package/dist/index.js +175 -9
- package/dist/style.css +59 -0
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -49,11 +49,12 @@ export function App() {
|
|
|
49
49
|
|
|
50
50
|
## Components
|
|
51
51
|
|
|
52
|
-
| Component
|
|
53
|
-
|
|
|
54
|
-
| `MeowdownEditor`
|
|
55
|
-
| `MarkdownView`
|
|
56
|
-
| `WikilinkHoverCard`
|
|
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. |
|
|
57
58
|
|
|
58
59
|
Common `MeowdownEditor` props:
|
|
59
60
|
|
|
@@ -61,7 +62,7 @@ Common `MeowdownEditor` props:
|
|
|
61
62
|
| ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
62
63
|
| `mode` | `'focus'` (default), `'show'`, or `'hide'`: how much Markdown syntax stays in view |
|
|
63
64
|
| `searchQuery` / `onSearchChange` | Find in document, with `EditorHandle.findNext()` / `findPrevious()` |
|
|
64
|
-
| `onWikilinkClick` / `onLinkClick` / `onTagClick` / `onImageClick` / `onFileClick`
|
|
65
|
+
| `onWikilinkClick` / `onLinkClick` / `onTagClick` / `onImageClick` / `onFileClick` / `onXPostMediaClick` | Click handling for the rendered atoms |
|
|
65
66
|
| `resolveImageUrl` / `resolveWikiEmbed` / `resolveWikilink` / `resolveFileLink` / `resolveFileInfo` | Resolve and classify local content |
|
|
66
67
|
| `onFilePaste` | Persist pasted or dropped files |
|
|
67
68
|
| `onSlashMenuSearch` / `onTagSearch` / `onWikilinkSearch` / `onSelectionMenuSearch` | Search menus for `/`, `#`, `[[`, and selection commands |
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { 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, XPostResolver, XPostResolver as XPostResolver$1, YouTubeVideoResolver, YouTubeVideoResolver as YouTubeVideoResolver$1 } from "@meowdown/core";
|
|
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";
|
|
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
|
|
@@ -419,7 +419,7 @@ interface EditorProps {
|
|
|
419
419
|
mediaUrlProtocols?: string[];
|
|
420
420
|
/**
|
|
421
421
|
* Resolves the data behind a YouTube video URL, directly or as a promise;
|
|
422
|
-
* the video renders as a `
|
|
422
|
+
* the video renders as a `meowdown-embed-youtube` card. Defaults to
|
|
423
423
|
* `defaultResolveYouTubeVideo`, which reads YouTube's oEmbed endpoint. Pass
|
|
424
424
|
* a stable function (e.g. from `useCallback`).
|
|
425
425
|
*/
|
|
@@ -447,6 +447,15 @@ interface EditorProps {
|
|
|
447
447
|
* Pass a stable function (e.g. from `useCallback`).
|
|
448
448
|
*/
|
|
449
449
|
onImageClick?: ImageClickHandler;
|
|
450
|
+
/**
|
|
451
|
+
* Called with the `meowdown-embed-media-click` event when the user
|
|
452
|
+
* activates a photo or video inside an X post card. Its `detail` holds the
|
|
453
|
+
* item, its siblings, and the rendered thumbnail element. Call
|
|
454
|
+
* `event.preventDefault()` to stop the card from opening the photo URL or
|
|
455
|
+
* playing the video in place, then show the media yourself, for example in
|
|
456
|
+
* a lightbox. Pass a stable function (e.g. from `useCallback`).
|
|
457
|
+
*/
|
|
458
|
+
onXPostMediaClick?: XPostMediaClickHandler;
|
|
450
459
|
/**
|
|
451
460
|
* Auto-embeds a pasted tweet or YouTube link as a rich embed; one undo turns
|
|
452
461
|
* the embed back into the raw link. On by default.
|
|
@@ -545,7 +554,7 @@ interface EditorProps {
|
|
|
545
554
|
*
|
|
546
555
|
* Callbacks and resolvers should be stable; pass them via `useCallback`.
|
|
547
556
|
*/
|
|
548
|
-
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, embedPaste, linkPaste, bulletAfterHeading, substitution, frontmatter, blockHandle, caretGlide, placeholder, readOnly, spellCheck, searchQuery, onSearchChange, timeFormat, editorClassName, wrapperClassName, CodeBlockView, handleRef, children }: EditorProps): ReactElement;
|
|
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;
|
|
549
558
|
//#endregion
|
|
550
559
|
//#region src/components/markdown-view.d.ts
|
|
551
560
|
/**
|
|
@@ -635,7 +644,7 @@ interface MarkdownViewProps {
|
|
|
635
644
|
*/
|
|
636
645
|
resolveFileInfo?: FileInfoResolver;
|
|
637
646
|
/**
|
|
638
|
-
* Resolve the data behind an X post URL, rendered as a `
|
|
647
|
+
* Resolve the data behind an X post URL, rendered as a `meowdown-embed-x`
|
|
639
648
|
* card. Defaults to `defaultResolveXPost`.
|
|
640
649
|
*/
|
|
641
650
|
resolveXPost?: XPostResolver$1;
|
|
@@ -645,7 +654,7 @@ interface MarkdownViewProps {
|
|
|
645
654
|
mediaUrlProtocols?: string[];
|
|
646
655
|
/**
|
|
647
656
|
* Resolve the data behind a YouTube video URL, rendered as a
|
|
648
|
-
* `
|
|
657
|
+
* `meowdown-embed-youtube` card. Defaults to `defaultResolveYouTubeVideo`.
|
|
649
658
|
*/
|
|
650
659
|
resolveYouTubeVideo?: YouTubeVideoResolver$1;
|
|
651
660
|
/**
|
|
@@ -660,6 +669,12 @@ interface MarkdownViewProps {
|
|
|
660
669
|
* Called when a rendered image is clicked. Pass a stable function.
|
|
661
670
|
*/
|
|
662
671
|
onImageClick?: ImageClickHandler;
|
|
672
|
+
/**
|
|
673
|
+
* Called when a photo or video inside an X post card is activated. Call
|
|
674
|
+
* `event.preventDefault()` to stop the card from opening the photo URL or
|
|
675
|
+
* playing the video in place.
|
|
676
|
+
*/
|
|
677
|
+
onXPostMediaClick?: XPostMediaClickHandler;
|
|
663
678
|
/**
|
|
664
679
|
* Called when a rendered file pill is clicked. Pass a stable function.
|
|
665
680
|
*/
|
|
@@ -684,7 +699,134 @@ interface MarkdownViewProps {
|
|
|
684
699
|
* Callbacks (`onWikilinkClick`, etc.) and resolvers should be stable; pass them via
|
|
685
700
|
* `useCallback` to avoid re-rendering the whole tree.
|
|
686
701
|
*/
|
|
687
|
-
export declare function MarkdownView({ markdown, markMode, frontmatter, interactive, expandCollapsed, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveWikilink, resolveFileInfo, resolveXPost, mediaUrlProtocols, resolveYouTubeVideo, onWikilinkClick, onLinkClick, onImageClick, onFileClick, onTaskClick, className }: MarkdownViewProps): ReactElement;
|
|
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;
|
|
703
|
+
//#endregion
|
|
704
|
+
//#region src/hooks/use-lightbox.d.ts
|
|
705
|
+
/**
|
|
706
|
+
* Something a lightbox can show.
|
|
707
|
+
*/
|
|
708
|
+
type LightboxItem = LightboxImageItem | LightboxVideoItem;
|
|
709
|
+
interface LightboxImageItem {
|
|
710
|
+
type: 'image';
|
|
711
|
+
/**
|
|
712
|
+
* A URL the browser can load, already resolved from the Markdown `src`.
|
|
713
|
+
*/
|
|
714
|
+
src: string;
|
|
715
|
+
alt?: string | undefined;
|
|
716
|
+
}
|
|
717
|
+
interface LightboxVideoItem {
|
|
718
|
+
type: 'video';
|
|
719
|
+
/**
|
|
720
|
+
* In the order the browser should try them.
|
|
721
|
+
*/
|
|
722
|
+
sources: Array<{
|
|
723
|
+
src: string;
|
|
724
|
+
type?: string | undefined;
|
|
725
|
+
}>;
|
|
726
|
+
/**
|
|
727
|
+
* URL of the image the player shows until the first video frame is ready.
|
|
728
|
+
*/
|
|
729
|
+
poster?: string | undefined;
|
|
730
|
+
/**
|
|
731
|
+
* Width of the video itself, in pixels (not the size it is displayed at).
|
|
732
|
+
* With `height` it gives the player its aspect ratio before the video's
|
|
733
|
+
* metadata loads, so the open zoom ends on the right box.
|
|
734
|
+
*/
|
|
735
|
+
width?: number | undefined;
|
|
736
|
+
/**
|
|
737
|
+
* Height of the video itself, in pixels.
|
|
738
|
+
*/
|
|
739
|
+
height?: number | undefined;
|
|
740
|
+
/**
|
|
741
|
+
* Play like a GIF: muted, looping, without controls.
|
|
742
|
+
*/
|
|
743
|
+
gif?: boolean | undefined;
|
|
744
|
+
alt?: string | undefined;
|
|
745
|
+
}
|
|
746
|
+
interface LightboxCloseOptions {
|
|
747
|
+
/**
|
|
748
|
+
* Close without the zoom back to the thumbnail, for example after the
|
|
749
|
+
* content was dragged off screen.
|
|
750
|
+
*/
|
|
751
|
+
instant?: boolean | undefined;
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* State and commands for a {@link LightboxRoot}, from {@link useLightbox}.
|
|
755
|
+
*/
|
|
756
|
+
interface LightboxController {
|
|
757
|
+
readonly item: LightboxItem | null;
|
|
758
|
+
/**
|
|
759
|
+
* Show `item`. Pass the clicked thumbnail as `element` to zoom the lightbox
|
|
760
|
+
* out of it, and back into it on close. The element only has to be in the
|
|
761
|
+
* document; React does not need to render it. Without an element, in a
|
|
762
|
+
* browser without View Transitions, or under reduced motion, the lightbox
|
|
763
|
+
* opens and closes without the zoom.
|
|
764
|
+
*/
|
|
765
|
+
readonly open: (item: LightboxItem, element?: HTMLElement | null) => void;
|
|
766
|
+
readonly close: (options?: LightboxCloseOptions) => void;
|
|
767
|
+
/**
|
|
768
|
+
* The zoom back to the thumbnail is over.
|
|
769
|
+
*
|
|
770
|
+
* @internal
|
|
771
|
+
*/
|
|
772
|
+
readonly onExited: () => void;
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* Owns which item a {@link LightboxRoot} shows. Opening and closing run as
|
|
776
|
+
* React transitions, so the `<ViewTransition>` inside the root animates them.
|
|
777
|
+
*
|
|
778
|
+
* The thumbnail is not rendered by this hook's component (it may not be
|
|
779
|
+
* rendered by React at all), so its half of the shared transition is set by
|
|
780
|
+
* hand: it carries the name while the browser captures the page without the
|
|
781
|
+
* lightbox, and loses it while the lightbox is mounted.
|
|
782
|
+
*/
|
|
783
|
+
export declare function useLightbox(): LightboxController;
|
|
784
|
+
//#endregion
|
|
785
|
+
//#region src/components/lightbox-image.d.ts
|
|
786
|
+
/**
|
|
787
|
+
* Props for {@link LightboxImage}. Other props land on the `<img>`.
|
|
788
|
+
*/
|
|
789
|
+
interface LightboxImageProps extends Omit<ComponentProps<'img'>, 'src' | 'alt'> {
|
|
790
|
+
readonly item: LightboxImageItem;
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* The image of a lightbox. It is the element the opened thumbnail zooms into.
|
|
794
|
+
*/
|
|
795
|
+
export declare function LightboxImage({ item, className, style, ...props }: LightboxImageProps): ReactNode;
|
|
796
|
+
//#endregion
|
|
797
|
+
//#region src/components/lightbox-root.d.ts
|
|
798
|
+
/**
|
|
799
|
+
* Props for {@link LightboxRoot}. Other props land on the `<dialog>`.
|
|
800
|
+
*/
|
|
801
|
+
interface LightboxRootProps extends Omit<ComponentProps<'dialog'>, 'children' | 'ref' | 'open' | 'onCancel' | 'onClose'> {
|
|
802
|
+
/**
|
|
803
|
+
* From {@link useLightbox}.
|
|
804
|
+
*/
|
|
805
|
+
readonly lightbox: LightboxController;
|
|
806
|
+
/**
|
|
807
|
+
* Render the open item. Put a {@link LightboxImage} somewhere inside, along
|
|
808
|
+
* with whatever closes the lightbox.
|
|
809
|
+
*/
|
|
810
|
+
readonly children: (item: LightboxItem) => ReactNode;
|
|
811
|
+
}
|
|
812
|
+
/**
|
|
813
|
+
* The full-window modal shell of a lightbox. It renders nothing while no item
|
|
814
|
+
* is open, and `Escape` closes it.
|
|
815
|
+
*/
|
|
816
|
+
export declare function LightboxRoot({ lightbox, children, className, ...props }: LightboxRootProps): ReactNode;
|
|
817
|
+
//#endregion
|
|
818
|
+
//#region src/components/lightbox-video.d.ts
|
|
819
|
+
/**
|
|
820
|
+
* Props for {@link LightboxVideo}. Other props land on the `<video>`.
|
|
821
|
+
*/
|
|
822
|
+
interface LightboxVideoProps extends Omit<ComponentProps<'video'>, 'src' | 'poster' | 'children'> {
|
|
823
|
+
readonly item: LightboxVideoItem;
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* The video of a lightbox. It starts playing as soon as it opens: the click
|
|
827
|
+
* that opened the lightbox is the user gesture that allows sound.
|
|
828
|
+
*/
|
|
829
|
+
export declare function LightboxVideo({ item, className, style, ...props }: LightboxVideoProps): ReactNode;
|
|
688
830
|
//#endregion
|
|
689
831
|
//#region src/components/wikilink-hover-card.d.ts
|
|
690
832
|
/**
|
|
@@ -711,4 +853,4 @@ interface WikilinkHoverCardProps {
|
|
|
711
853
|
*/
|
|
712
854
|
export declare function WikilinkHoverCard({ children, className }: WikilinkHoverCardProps): ReactNode;
|
|
713
855
|
//#endregion
|
|
714
|
-
export { type EditorHandle, type EditorMode, type EditorProps, type EditorStateSnapshot, 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 };
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { clsx } from "clsx/lite";
|
|
2
|
-
import { Fragment, cloneElement, createElement, memo, useCallback, useDeferredValue, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
2
|
+
import { Fragment, ViewTransition, cloneElement, createElement, memo, startTransition, useCallback, useDeferredValue, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
3
3
|
import { buildFileMarkdown, codeBlockLanguages, collectReferenceDefinitions, defaultResolveImageUrl, defaultResolveXPost, defaultResolveYouTubeVideo, defineCodeBlockPreviewPlugin, defineEditorExtension, defineLinkEditKeymap, defineLinkHoverHandler, definePendingReplacementHandler, defineSearchStatusHandler, defineVirtualCaret, defineWikilinkHoverHandler, docToMarkdown, formatFileSize, getCodeTokens, getFileKind, getLinkText, getMarkBuilders, getPendingReplacement, getSearchStatus, getSelectedText, getTableColumnAlign, getTextblockDisplayText, getVirtualElementFromRange, inlineTextToMarkChunksWithContext, isCodeBlockPreviewHiddenDecoration, isLinkTextForHref, isModEvent, isNodeOfType, isReferenceDefinitionNode, isSelectionInTableCell, loadKaTeX, markdownToDoc, normalizeHref, 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";
|
|
@@ -15,9 +15,9 @@ import { Popover } from "@base-ui/react/popover";
|
|
|
15
15
|
import { AutocompleteEmpty, AutocompleteItem, AutocompletePopup, AutocompletePositioner, AutocompleteRoot } from "@prosekit/react/autocomplete";
|
|
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
|
+
import { X_POST_MEDIA_CLICK, registerXPost } from "@meowdown/embed/x";
|
|
19
|
+
import { registerYouTubeVideo } from "@meowdown/embed/youtube";
|
|
18
20
|
import { matchEmbed } from "@meowdown/markdown";
|
|
19
|
-
import { registerXPost } from "@post-embed/elements/x";
|
|
20
|
-
import { registerYouTubeVideo } from "@post-embed/elements/youtube";
|
|
21
21
|
import { Mark } from "@prosekit/pm/model";
|
|
22
22
|
import { BOOLEAN, OVERLOADED_BOOLEAN, getPropertyInfo, possibleStandardNames } from "react-property";
|
|
23
23
|
import { PreviewCard } from "@base-ui/react/preview-card";
|
|
@@ -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, 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, 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;
|
|
@@ -1876,6 +1876,7 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onSl
|
|
|
1876
1876
|
onFilePaste,
|
|
1877
1877
|
onFileSaveError,
|
|
1878
1878
|
onImageClick,
|
|
1879
|
+
onXPostMediaClick,
|
|
1879
1880
|
embedPaste,
|
|
1880
1881
|
linkPaste,
|
|
1881
1882
|
bulletAfterHeading,
|
|
@@ -1903,6 +1904,7 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onSl
|
|
|
1903
1904
|
onFilePaste,
|
|
1904
1905
|
onFileSaveError,
|
|
1905
1906
|
onImageClick,
|
|
1907
|
+
onXPostMediaClick,
|
|
1906
1908
|
embedPaste,
|
|
1907
1909
|
linkPaste,
|
|
1908
1910
|
bulletAfterHeading,
|
|
@@ -2105,7 +2107,7 @@ const CARET_GLIDE_OFF = { "--meowdown-caret-glide": "0ms" };
|
|
|
2105
2107
|
*
|
|
2106
2108
|
* Callbacks and resolvers should be stable; pass them via `useCallback`.
|
|
2107
2109
|
*/
|
|
2108
|
-
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, 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 }) {
|
|
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 }) {
|
|
2109
2111
|
const childRef = useRef(null);
|
|
2110
2112
|
useImperativeHandle(handleRef, () => {
|
|
2111
2113
|
function getMarkdown() {
|
|
@@ -2231,6 +2233,7 @@ function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onSlashM
|
|
|
2231
2233
|
onFilePaste,
|
|
2232
2234
|
onFileSaveError,
|
|
2233
2235
|
onImageClick,
|
|
2236
|
+
onXPostMediaClick,
|
|
2234
2237
|
embedPaste,
|
|
2235
2238
|
linkPaste,
|
|
2236
2239
|
bulletAfterHeading,
|
|
@@ -2388,12 +2391,12 @@ function PostEmbed(props) {
|
|
|
2388
2391
|
contentEditable: false,
|
|
2389
2392
|
"data-testid": `${kind}-embed`,
|
|
2390
2393
|
"data-post-embed": kind,
|
|
2391
|
-
children: kind === "x-post" ? createElement("
|
|
2394
|
+
children: kind === "x-post" ? createElement("meowdown-embed-x", {
|
|
2392
2395
|
data: null,
|
|
2393
2396
|
url: src,
|
|
2394
2397
|
resolver: resolveXPost ?? defaultResolveXPost,
|
|
2395
2398
|
mediaUrlProtocols: mediaUrlProtocols ?? null
|
|
2396
|
-
}) : createElement("
|
|
2399
|
+
}) : createElement("meowdown-embed-youtube", {
|
|
2397
2400
|
data: saved?.kind === "youtube-video" ? saved.data : null,
|
|
2398
2401
|
url: src,
|
|
2399
2402
|
resolver: resolveYouTubeVideo,
|
|
@@ -2435,6 +2438,7 @@ function ImagePreview(props) {
|
|
|
2435
2438
|
src,
|
|
2436
2439
|
alt,
|
|
2437
2440
|
event: event.nativeEvent,
|
|
2441
|
+
element: event.currentTarget,
|
|
2438
2442
|
mod: isModEvent(event)
|
|
2439
2443
|
});
|
|
2440
2444
|
} : void 0,
|
|
@@ -2861,7 +2865,7 @@ const MarkdownBlock = memo(function MarkdownBlock({ node, taskBase, context, ref
|
|
|
2861
2865
|
* Callbacks (`onWikilinkClick`, etc.) and resolvers should be stable; pass them via
|
|
2862
2866
|
* `useCallback` to avoid re-rendering the whole tree.
|
|
2863
2867
|
*/
|
|
2864
|
-
function MarkdownView({ markdown, markMode = "hide", frontmatter = false, interactive = true, expandCollapsed = false, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveWikilink, resolveFileInfo, resolveXPost, mediaUrlProtocols, resolveYouTubeVideo, onWikilinkClick, onLinkClick, onImageClick, onFileClick, onTaskClick, className }) {
|
|
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 }) {
|
|
2865
2869
|
const context = useMemo(() => ({
|
|
2866
2870
|
interactive,
|
|
2867
2871
|
expandCollapsed,
|
|
@@ -2904,7 +2908,14 @@ function MarkdownView({ markdown, markMode = "hide", frontmatter = false, intera
|
|
|
2904
2908
|
definitionsKey: definitionsSignature(referenceDefinitions)
|
|
2905
2909
|
};
|
|
2906
2910
|
}, [markdown, frontmatter]);
|
|
2911
|
+
const handleXPostMediaClick = interactive ? onXPostMediaClick : void 0;
|
|
2912
|
+
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]);
|
|
2907
2917
|
return /* @__PURE__ */ jsx("div", {
|
|
2918
|
+
ref: rootRef,
|
|
2908
2919
|
className: clsx("ProseMirror", "meowdown-content", className),
|
|
2909
2920
|
"data-mark-mode": markMode,
|
|
2910
2921
|
children: blocks.map(({ node, taskBase }, index) => /* @__PURE__ */ jsx(MarkdownBlock, {
|
|
@@ -2917,6 +2928,161 @@ function MarkdownView({ markdown, markMode = "hide", frontmatter = false, intera
|
|
|
2917
2928
|
});
|
|
2918
2929
|
}
|
|
2919
2930
|
|
|
2931
|
+
//#endregion
|
|
2932
|
+
//#region src/hooks/use-lightbox.ts
|
|
2933
|
+
/**
|
|
2934
|
+
* The `view-transition-name` shared by the opened thumbnail and the lightbox
|
|
2935
|
+
* content, so the browser zooms between them.
|
|
2936
|
+
*/
|
|
2937
|
+
const LIGHTBOX_TRANSITION_NAME = "meowdown-lightbox-media";
|
|
2938
|
+
function setTransitionName(element, name) {
|
|
2939
|
+
if (element) element.style.viewTransitionName = name;
|
|
2940
|
+
}
|
|
2941
|
+
/**
|
|
2942
|
+
* Owns which item a {@link LightboxRoot} shows. Opening and closing run as
|
|
2943
|
+
* React transitions, so the `<ViewTransition>` inside the root animates them.
|
|
2944
|
+
*
|
|
2945
|
+
* The thumbnail is not rendered by this hook's component (it may not be
|
|
2946
|
+
* rendered by React at all), so its half of the shared transition is set by
|
|
2947
|
+
* hand: it carries the name while the browser captures the page without the
|
|
2948
|
+
* lightbox, and loses it while the lightbox is mounted.
|
|
2949
|
+
*/
|
|
2950
|
+
function useLightbox() {
|
|
2951
|
+
const [item, setItem] = useState(null);
|
|
2952
|
+
const sourceRef = useRef(null);
|
|
2953
|
+
const instantRef = useRef(false);
|
|
2954
|
+
const open = useCallback((nextItem, element) => {
|
|
2955
|
+
setTransitionName(sourceRef.current, "");
|
|
2956
|
+
sourceRef.current = element ?? null;
|
|
2957
|
+
setTransitionName(sourceRef.current, LIGHTBOX_TRANSITION_NAME);
|
|
2958
|
+
startTransition(() => setItem(nextItem));
|
|
2959
|
+
}, []);
|
|
2960
|
+
const close = useCallback((options) => {
|
|
2961
|
+
instantRef.current = options?.instant === true;
|
|
2962
|
+
if (instantRef.current) setItem(null);
|
|
2963
|
+
else startTransition(() => setItem(null));
|
|
2964
|
+
}, []);
|
|
2965
|
+
const isOpen = item != null;
|
|
2966
|
+
useLayoutEffect(() => {
|
|
2967
|
+
if (!isOpen) return;
|
|
2968
|
+
setTransitionName(sourceRef.current, "");
|
|
2969
|
+
return () => {
|
|
2970
|
+
const source = sourceRef.current;
|
|
2971
|
+
if (!instantRef.current && source?.isConnected) setTransitionName(source, LIGHTBOX_TRANSITION_NAME);
|
|
2972
|
+
else sourceRef.current = null;
|
|
2973
|
+
};
|
|
2974
|
+
}, [isOpen]);
|
|
2975
|
+
const onExited = useCallback(() => {
|
|
2976
|
+
setTransitionName(sourceRef.current, "");
|
|
2977
|
+
sourceRef.current = null;
|
|
2978
|
+
}, []);
|
|
2979
|
+
return useMemo(() => ({
|
|
2980
|
+
item,
|
|
2981
|
+
open,
|
|
2982
|
+
close,
|
|
2983
|
+
onExited
|
|
2984
|
+
}), [
|
|
2985
|
+
item,
|
|
2986
|
+
open,
|
|
2987
|
+
close,
|
|
2988
|
+
onExited
|
|
2989
|
+
]);
|
|
2990
|
+
}
|
|
2991
|
+
|
|
2992
|
+
//#endregion
|
|
2993
|
+
//#region src/components/lightbox.module.css
|
|
2994
|
+
var lightbox_module_default = {
|
|
2995
|
+
"Dialog": "meow_Dialog_VENw2q",
|
|
2996
|
+
"Image": "meow_Image_VENw2q",
|
|
2997
|
+
"Video": "meow_Video_VENw2q"
|
|
2998
|
+
};
|
|
2999
|
+
|
|
3000
|
+
//#endregion
|
|
3001
|
+
//#region src/components/lightbox-image.tsx
|
|
3002
|
+
/**
|
|
3003
|
+
* The image of a lightbox. It is the element the opened thumbnail zooms into.
|
|
3004
|
+
*/
|
|
3005
|
+
function LightboxImage({ item, className, style, ...props }) {
|
|
3006
|
+
return /* @__PURE__ */ jsx("img", {
|
|
3007
|
+
draggable: false,
|
|
3008
|
+
...props,
|
|
3009
|
+
src: item.src,
|
|
3010
|
+
alt: item.alt ?? "",
|
|
3011
|
+
className: clsx(lightbox_module_default.Image, className),
|
|
3012
|
+
style: {
|
|
3013
|
+
...style,
|
|
3014
|
+
viewTransitionName: LIGHTBOX_TRANSITION_NAME
|
|
3015
|
+
}
|
|
3016
|
+
});
|
|
3017
|
+
}
|
|
3018
|
+
|
|
3019
|
+
//#endregion
|
|
3020
|
+
//#region src/components/lightbox-root.tsx
|
|
3021
|
+
const DIALOG_TRANSITION_CLASS = "meowdown-lightbox-dialog";
|
|
3022
|
+
function showModal(dialog) {
|
|
3023
|
+
const active = document.activeElement;
|
|
3024
|
+
if (active instanceof HTMLElement && active.isContentEditable) active.blur();
|
|
3025
|
+
dialog.showModal();
|
|
3026
|
+
return () => dialog.close();
|
|
3027
|
+
}
|
|
3028
|
+
/**
|
|
3029
|
+
* The full-window modal shell of a lightbox. It renders nothing while no item
|
|
3030
|
+
* is open, and `Escape` closes it.
|
|
3031
|
+
*/
|
|
3032
|
+
function LightboxRoot({ lightbox, children, className, ...props }) {
|
|
3033
|
+
const { item, close, onExited } = lightbox;
|
|
3034
|
+
if (!item) return null;
|
|
3035
|
+
return /* @__PURE__ */ jsx(ViewTransition, {
|
|
3036
|
+
default: DIALOG_TRANSITION_CLASS,
|
|
3037
|
+
onExit: () => onExited,
|
|
3038
|
+
children: /* @__PURE__ */ jsx("dialog", {
|
|
3039
|
+
"aria-label": item.type === "video" ? "Video preview" : "Image preview",
|
|
3040
|
+
...props,
|
|
3041
|
+
ref: showModal,
|
|
3042
|
+
className: clsx(lightbox_module_default.Dialog, className),
|
|
3043
|
+
onCancel: (event) => {
|
|
3044
|
+
event.preventDefault();
|
|
3045
|
+
close();
|
|
3046
|
+
},
|
|
3047
|
+
onClose: (event) => {
|
|
3048
|
+
if (!event.currentTarget.open) close({ instant: true });
|
|
3049
|
+
},
|
|
3050
|
+
children: children(item)
|
|
3051
|
+
})
|
|
3052
|
+
});
|
|
3053
|
+
}
|
|
3054
|
+
|
|
3055
|
+
//#endregion
|
|
3056
|
+
//#region src/components/lightbox-video.tsx
|
|
3057
|
+
/**
|
|
3058
|
+
* The video of a lightbox. It starts playing as soon as it opens: the click
|
|
3059
|
+
* that opened the lightbox is the user gesture that allows sound.
|
|
3060
|
+
*/
|
|
3061
|
+
function LightboxVideo({ item, className, style, ...props }) {
|
|
3062
|
+
const gif = item.gif === true;
|
|
3063
|
+
return /* @__PURE__ */ jsx("video", {
|
|
3064
|
+
controls: !gif,
|
|
3065
|
+
loop: gif,
|
|
3066
|
+
muted: gif,
|
|
3067
|
+
autoPlay: true,
|
|
3068
|
+
playsInline: true,
|
|
3069
|
+
"aria-label": item.alt,
|
|
3070
|
+
...props,
|
|
3071
|
+
poster: item.poster,
|
|
3072
|
+
width: item.width,
|
|
3073
|
+
height: item.height,
|
|
3074
|
+
className: clsx(lightbox_module_default.Video, className),
|
|
3075
|
+
style: {
|
|
3076
|
+
...style,
|
|
3077
|
+
viewTransitionName: LIGHTBOX_TRANSITION_NAME
|
|
3078
|
+
},
|
|
3079
|
+
children: item.sources.map((source) => /* @__PURE__ */ jsx("source", {
|
|
3080
|
+
src: source.src,
|
|
3081
|
+
type: source.type
|
|
3082
|
+
}, source.src))
|
|
3083
|
+
});
|
|
3084
|
+
}
|
|
3085
|
+
|
|
2920
3086
|
//#endregion
|
|
2921
3087
|
//#region src/components/wikilink-hover-card.module.css
|
|
2922
3088
|
var wikilink_hover_card_module_default = {
|
|
@@ -2999,4 +3165,4 @@ function WikilinkHoverCard({ children, className }) {
|
|
|
2999
3165
|
}
|
|
3000
3166
|
|
|
3001
3167
|
//#endregion
|
|
3002
|
-
export { MarkdownView, MeowdownEditor, WikilinkHoverCard, useEditor, useExtension, useKeymap };
|
|
3168
|
+
export { LightboxImage, LightboxRoot, LightboxVideo, MarkdownView, MeowdownEditor, WikilinkHoverCard, useEditor, useExtension, useKeymap, useLightbox };
|
package/dist/style.css
CHANGED
|
@@ -1058,6 +1058,40 @@
|
|
|
1058
1058
|
display: block;
|
|
1059
1059
|
}
|
|
1060
1060
|
}
|
|
1061
|
+
.meow_Dialog_VENw2q {
|
|
1062
|
+
all: revert;
|
|
1063
|
+
box-sizing: border-box;
|
|
1064
|
+
width: 100dvw;
|
|
1065
|
+
max-width: none;
|
|
1066
|
+
height: 100dvh;
|
|
1067
|
+
max-height: none;
|
|
1068
|
+
padding: var(--meowdown-lightbox-padding, 1.5rem);
|
|
1069
|
+
background: var(--meowdown-lightbox-backdrop, #000c);
|
|
1070
|
+
border: 0;
|
|
1071
|
+
outline: none;
|
|
1072
|
+
margin: 0;
|
|
1073
|
+
position: fixed;
|
|
1074
|
+
inset: 0;
|
|
1075
|
+
overflow: hidden;
|
|
1076
|
+
|
|
1077
|
+
&::backdrop {
|
|
1078
|
+
background: none;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
.meow_Image_VENw2q {
|
|
1083
|
+
user-select: none;
|
|
1084
|
+
max-width: 100%;
|
|
1085
|
+
max-height: 100%;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
.meow_Video_VENw2q {
|
|
1089
|
+
width: auto;
|
|
1090
|
+
max-width: 100%;
|
|
1091
|
+
height: auto;
|
|
1092
|
+
max-height: 100%;
|
|
1093
|
+
position: relative;
|
|
1094
|
+
}
|
|
1061
1095
|
.meow_Positioner_HMEwgW {
|
|
1062
1096
|
z-index: 50;
|
|
1063
1097
|
width: var(--positioner-width);
|
|
@@ -1114,3 +1148,28 @@
|
|
|
1114
1148
|
flex: 1 0 auto;
|
|
1115
1149
|
}
|
|
1116
1150
|
}
|
|
1151
|
+
|
|
1152
|
+
::view-transition-group(.meowdown-lightbox-dialog), ::view-transition-group(meowdown-lightbox-media) {
|
|
1153
|
+
animation-duration: var(--meowdown-lightbox-duration, .18s);
|
|
1154
|
+
animation-timing-function: cubic-bezier(.22, 1, .36, 1);
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
::view-transition-group(.meowdown-lightbox-dialog) {
|
|
1158
|
+
z-index: 1;
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
::view-transition-group(meowdown-lightbox-media) {
|
|
1162
|
+
z-index: 2;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
::view-transition-old(meowdown-lightbox-media), ::view-transition-new(meowdown-lightbox-media) {
|
|
1166
|
+
object-fit: contain;
|
|
1167
|
+
height: 100%;
|
|
1168
|
+
overflow: clip;
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1172
|
+
::view-transition-group(meowdown-lightbox-media), ::view-transition-old(meowdown-lightbox-media), ::view-transition-new(meowdown-lightbox-media), ::view-transition-group(.meowdown-lightbox-dialog), ::view-transition-old(.meowdown-lightbox-dialog), ::view-transition-new(.meowdown-lightbox-dialog) {
|
|
1173
|
+
animation: none;
|
|
1174
|
+
}
|
|
1175
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meowdown/react",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.72.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@base-ui/react": "^1.8.0",
|
|
25
|
-
"@meowdown/core": "0.
|
|
25
|
+
"@meowdown/core": "0.73.0",
|
|
26
|
+
"@meowdown/embed": "0.1.0",
|
|
26
27
|
"@meowdown/markdown": "0.72.0",
|
|
27
28
|
"@ocavue/utils": "^1.8.0",
|
|
28
|
-
"@post-embed/
|
|
29
|
-
"@
|
|
30
|
-
"@prosekit/
|
|
31
|
-
"@prosekit/
|
|
32
|
-
"@prosekit/react": "^0.8.2",
|
|
29
|
+
"@post-embed/types": "^0.5.0",
|
|
30
|
+
"@prosekit/core": "^0.13.3",
|
|
31
|
+
"@prosekit/pm": "^0.1.20",
|
|
32
|
+
"@prosekit/react": "^0.8.3",
|
|
33
33
|
"beautiful-mermaid": "^1.1.3",
|
|
34
34
|
"clsx": "^2.1.1",
|
|
35
35
|
"github-slugger": "^2.0.0",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"react-property": "^2.0.2"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"react": "^19.
|
|
41
|
-
"react-dom": "^19.
|
|
40
|
+
"react": "^19.3.0",
|
|
41
|
+
"react-dom": "^19.3.0"
|
|
42
42
|
},
|
|
43
43
|
"peerDependenciesMeta": {
|
|
44
44
|
"react": {
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"react-dom": "^19.3.0",
|
|
62
62
|
"tsdown": "^0.23.0",
|
|
63
63
|
"vitest": "^5.0.1",
|
|
64
|
-
"vitest-browser-commands": "^0.
|
|
64
|
+
"vitest-browser-commands": "^0.5.0",
|
|
65
65
|
"vitest-browser-react": "^2.3.0"
|
|
66
66
|
},
|
|
67
67
|
"publishConfig": {
|