@meowdown/react 0.65.6 → 0.67.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 +10 -3
- package/dist/index.js +351 -180
- package/dist/style.css +224 -23
- package/package.json +6 -6
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactElement, ReactNode, Ref } from "react";
|
|
2
|
-
import { AcceptPendingReplacementOptions, ExitBoundaryHandler, FileClickHandler, FileInfoResolver, FileLinkResolver, FilePasteOptions, FileViewOptions, ImageClickHandler, ImageOptions, LinkClickHandler, LinkCopyHandler, ListMarker, MarkMode, PendingReplacement, PendingReplacementOutcome, PlaceholderOptions, SearchStatusHandler, StartPendingReplacementOptions, TagClickHandler, TypedEditor, WikiEmbedResolver, WikilinkClickHandler, WikilinkHoverHit } 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 } from "@meowdown/core";
|
|
3
3
|
import { SelectionJSON, SelectionJSON as SelectionJSON$1 } from "@prosekit/core";
|
|
4
4
|
import { useEditor, useExtension, useKeymap } from "@prosekit/react";
|
|
5
5
|
//#region src/utils/date-format.d.ts
|
|
@@ -347,6 +347,13 @@ interface EditorProps {
|
|
|
347
347
|
* for a toast. Pass a stable function (e.g. from `useCallback`).
|
|
348
348
|
*/
|
|
349
349
|
onLinkCopy?: LinkCopyHandler;
|
|
350
|
+
/**
|
|
351
|
+
* Resolves optional display metadata for the link popup. Failures should be
|
|
352
|
+
* represented by `undefined`; the popup keeps its URL and actions available.
|
|
353
|
+
* May be called repeatedly for the same `href`, so cache expensive work in
|
|
354
|
+
* the host. Pass a stable function (e.g. from `useCallback`).
|
|
355
|
+
*/
|
|
356
|
+
resolveLinkPreview?: LinkPreviewResolver$1;
|
|
350
357
|
/**
|
|
351
358
|
* Called with the tag name (without the leading `#`) on click of a rendered
|
|
352
359
|
* `#tag`, or on `Mod-Enter` with the caret on one. Pass a stable function
|
|
@@ -508,7 +515,7 @@ interface EditorProps {
|
|
|
508
515
|
*
|
|
509
516
|
* Callbacks and resolvers should be stable; pass them via `useCallback`.
|
|
510
517
|
*/
|
|
511
|
-
export declare function MeowdownEditor({ mode, initialMarkdown, onDocChange, onSlashMenuSearch, onTagSearch, onWikilinkSearch, onSelectionMenuSearch, selectionMenuAffordance, pendingReplacementActions, onPendingReplacementResolve, onWikilinkClick, onLinkClick, onLinkCopy, onTagClick, onExitBoundary, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveFileInfo, onFileClick, onFilePaste, onFileSaveError, onImageClick, embedPaste, linkPaste, bulletAfterHeading, substitution, frontmatter, blockHandle, caretGlide, placeholder, readOnly, spellCheck, searchQuery, onSearchChange, timeFormat, editorClassName, wrapperClassName, handleRef, children }: EditorProps): ReactElement;
|
|
518
|
+
export declare function MeowdownEditor({ mode, initialMarkdown, onDocChange, onSlashMenuSearch, onTagSearch, onWikilinkSearch, onSelectionMenuSearch, selectionMenuAffordance, pendingReplacementActions, onPendingReplacementResolve, onWikilinkClick, onLinkClick, onLinkCopy, resolveLinkPreview, onTagClick, onExitBoundary, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveFileInfo, onFileClick, onFilePaste, onFileSaveError, onImageClick, embedPaste, linkPaste, bulletAfterHeading, substitution, frontmatter, blockHandle, caretGlide, placeholder, readOnly, spellCheck, searchQuery, onSearchChange, timeFormat, editorClassName, wrapperClassName, handleRef, children }: EditorProps): ReactElement;
|
|
512
519
|
//#endregion
|
|
513
520
|
//#region src/components/markdown-view.d.ts
|
|
514
521
|
/**
|
|
@@ -654,4 +661,4 @@ interface WikilinkHoverCardProps {
|
|
|
654
661
|
*/
|
|
655
662
|
export declare function WikilinkHoverCard({ children, className }: WikilinkHoverCardProps): ReactNode;
|
|
656
663
|
//#endregion
|
|
657
|
-
export { type EditorHandle, type EditorMode, type EditorProps, type EditorStateSnapshot, type MarkdownViewProps, type PendingReplacementResolveHandler, 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, useEditor, useExtension, useKeymap };
|
|
664
|
+
export { type EditorHandle, type EditorMode, type EditorProps, type EditorStateSnapshot, type LinkPreview, type LinkPreviewResolver, type MarkdownViewProps, type PendingReplacementResolveHandler, 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, useEditor, useExtension, useKeymap };
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { clsx } from "clsx/lite";
|
|
2
2
|
import { Fragment, cloneElement, createElement, useCallback, useDeferredValue, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
3
|
-
import { buildFileMarkdown, codeBlockLanguages, collectReferenceDefinitions, defaultResolveImageUrl, defineBulletAfterHeading, defineCodeBlockPreviewPlugin, defineEditorExtension, defineEmbedPaste, defineExitBoundaryHandler, defineFileClickHandler, defineFilePaste, defineFileView, defineFollowLinkHandler, defineImage, defineImageClickHandler, defineLinkClickHandler, defineLinkEditKeymap, defineLinkHoverHandler, defineLinkPaste, definePendingReplacementHandler, definePlaceholder, defineReadonly, defineSearchStatusHandler, defineSubstitution, defineTagClickHandler, defineViewAttributes, defineVirtualCaret, defineWikilinkClickHandler, defineWikilinkHoverHandler, defineWikilinkTrigger, docToMarkdown, formatFileSize, getCodeTokens, getFileKind, getMarkBuilders, getPendingReplacement, getSearchStatus, getSelectedText, getTableColumnAlign, getTextblockDisplayText, getVirtualElementFromRange, inlineTextToMarkChunksWithContext, isCodeBlockPreviewHiddenDecoration, isModEvent, isNodeOfType, isSelectionInTableCell, listenForTweetHeight, loadKaTeX, markdownToDoc, matchEmbed, renderMathInto } from "@meowdown/core";
|
|
3
|
+
import { buildFileMarkdown, codeBlockLanguages, collectReferenceDefinitions, defaultResolveImageUrl, defineBulletAfterHeading, defineCodeBlockPreviewPlugin, defineEditorExtension, defineEmbedPaste, defineExitBoundaryHandler, defineFileClickHandler, defineFilePaste, defineFileView, defineFollowLinkHandler, defineImage, defineImageClickHandler, defineLinkClickHandler, defineLinkEditKeymap, defineLinkHoverHandler, defineLinkPaste, definePendingReplacementHandler, definePlaceholder, defineReadonly, defineSearchStatusHandler, defineSubstitution, defineTagClickHandler, defineViewAttributes, defineVirtualCaret, defineWikilinkClickHandler, defineWikilinkHoverHandler, defineWikilinkTrigger, docToMarkdown, formatFileSize, getCodeTokens, getFileKind, getLinkText, getMarkBuilders, getPendingReplacement, getSearchStatus, getSelectedText, getTableColumnAlign, getTextblockDisplayText, getVirtualElementFromRange, inlineTextToMarkChunksWithContext, isCodeBlockPreviewHiddenDecoration, isLinkTextForHref, isModEvent, isNodeOfType, isSelectionInTableCell, listenForTweetHeight, loadKaTeX, markdownToDoc, matchEmbed, normalizeHref, renderMathInto } from "@meowdown/core";
|
|
4
4
|
import { clamp } from "@ocavue/utils";
|
|
5
5
|
import { canUseRegexLookbehind, createEditor, defineDocChangeHandler, defineUpdateHandler, isTextSelection, union } from "@prosekit/core";
|
|
6
6
|
import { Selection, TextSelection } from "@prosekit/pm/state";
|
|
7
7
|
import { ProseKit, defineReactNodeView, useEditor, useEditor as useEditor$1, useEditorDerivedValue, useExtension, useExtension as useExtension$1, useKeymap } from "@prosekit/react";
|
|
8
8
|
import GithubSlugger from "github-slugger";
|
|
9
9
|
import { Combobox } from "@base-ui/react/combobox";
|
|
10
|
-
import { CheckIcon, ChevronsUpDownIcon, CopyIcon, GripHorizontalIcon, GripVerticalIcon, PencilIcon, SparklesIcon, UnlinkIcon } from "lucide-react";
|
|
10
|
+
import { CheckIcon, ChevronsUpDownIcon, CopyIcon, Globe2Icon, GripHorizontalIcon, GripVerticalIcon, PencilIcon, SparklesIcon, UnlinkIcon } from "lucide-react";
|
|
11
11
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
12
12
|
import { BlockHandleDraggable, BlockHandlePopup, BlockHandlePositioner, BlockHandleRoot } from "@prosekit/react/block-handle";
|
|
13
13
|
import { DropIndicator } from "@prosekit/react/drop-indicator";
|
|
@@ -499,70 +499,85 @@ function EditorExtensions({ markMode, onDocChange, onWikilinkClick, onLinkClick,
|
|
|
499
499
|
return null;
|
|
500
500
|
}
|
|
501
501
|
|
|
502
|
-
//#endregion
|
|
503
|
-
//#region src/hooks/use-delayed-flag.ts
|
|
504
|
-
/**
|
|
505
|
-
* Delay before the flag opens, in ms.
|
|
506
|
-
*/
|
|
507
|
-
const OPEN_DELAY$1 = 400;
|
|
508
|
-
/**
|
|
509
|
-
* Grace before the flag closes, in ms. The window lets a pointer travel from
|
|
510
|
-
* the hovered link onto the popover it anchors.
|
|
511
|
-
*/
|
|
512
|
-
const CLOSE_DELAY$1 = 300;
|
|
513
|
-
/**
|
|
514
|
-
* Mirrors `value` into a boolean that flips true `openDelay`ms after `value`
|
|
515
|
-
* becomes true and false `closeDelay`ms after it becomes false, cancelling any
|
|
516
|
-
* pending flip on each change.
|
|
517
|
-
*/
|
|
518
|
-
function useDelayedFlag(value, openDelay = OPEN_DELAY$1, closeDelay = CLOSE_DELAY$1) {
|
|
519
|
-
const [flag, setFlag] = useState(false);
|
|
520
|
-
const timerRef = useRef(void 0);
|
|
521
|
-
useEffect(() => {
|
|
522
|
-
clearTimeout(timerRef.current);
|
|
523
|
-
timerRef.current = setTimeout(() => setFlag(value), value ? openDelay : closeDelay);
|
|
524
|
-
return () => clearTimeout(timerRef.current);
|
|
525
|
-
}, [
|
|
526
|
-
value,
|
|
527
|
-
openDelay,
|
|
528
|
-
closeDelay
|
|
529
|
-
]);
|
|
530
|
-
return flag;
|
|
531
|
-
}
|
|
532
|
-
|
|
533
502
|
//#endregion
|
|
534
503
|
//#region src/components/link-menu.module.css
|
|
535
504
|
var link_menu_module_default = {
|
|
505
|
+
"Actions": "meow_Actions_IjcqKG",
|
|
536
506
|
"Button": "meow_Button_IjcqKG",
|
|
507
|
+
"Description": "meow_Description_IjcqKG",
|
|
508
|
+
"Field": "meow_Field_IjcqKG",
|
|
537
509
|
"Form": "meow_Form_IjcqKG",
|
|
510
|
+
"FormActions": "meow_FormActions_IjcqKG",
|
|
511
|
+
"Host": "meow_Host_IjcqKG",
|
|
512
|
+
"Icon": "meow_Icon_IjcqKG",
|
|
538
513
|
"Input": "meow_Input_IjcqKG",
|
|
539
514
|
"Popup": "meow_Popup_IjcqKG",
|
|
540
515
|
"Positioner": "meow_Positioner_IjcqKG",
|
|
516
|
+
"Preview": "meow_Preview_IjcqKG",
|
|
517
|
+
"PreviewBody": "meow_PreviewBody_IjcqKG",
|
|
518
|
+
"pulse": "meow_pulse_IjcqKG",
|
|
519
|
+
"RemoveButton": "meow_RemoveButton_IjcqKG",
|
|
520
|
+
"ReplaceButton": "meow_ReplaceButton_IjcqKG",
|
|
521
|
+
"ReplaceRow": "meow_ReplaceRow_IjcqKG",
|
|
541
522
|
"Row": "meow_Row_IjcqKG",
|
|
542
|
-
"
|
|
543
|
-
"
|
|
523
|
+
"SaveButton": "meow_SaveButton_IjcqKG",
|
|
524
|
+
"Skeleton": "meow_Skeleton_IjcqKG",
|
|
525
|
+
"SkeletonLine": "meow_SkeletonLine_IjcqKG",
|
|
526
|
+
"SkeletonLineShort": "meow_SkeletonLineShort_IjcqKG",
|
|
527
|
+
"Title": "meow_Title_IjcqKG",
|
|
528
|
+
"Url": "meow_Url_IjcqKG",
|
|
529
|
+
"UseTitleButton": "meow_UseTitleButton_IjcqKG"
|
|
544
530
|
};
|
|
545
531
|
|
|
546
532
|
//#endregion
|
|
547
533
|
//#region src/components/link-menu.tsx
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
534
|
+
function useLinkPreview(href, resolveLinkPreview) {
|
|
535
|
+
const [settled, setSettled] = useState();
|
|
536
|
+
useEffect(() => {
|
|
537
|
+
if (!href || !resolveLinkPreview || !isWebHref(href)) return;
|
|
538
|
+
let stale = false;
|
|
539
|
+
Promise.resolve().then(() => resolveLinkPreview(href)).then((preview) => {
|
|
540
|
+
if (!stale) setSettled({
|
|
541
|
+
href,
|
|
542
|
+
result: preview ? {
|
|
543
|
+
status: "resolved",
|
|
544
|
+
preview
|
|
545
|
+
} : { status: "failed" }
|
|
546
|
+
});
|
|
547
|
+
}).catch(() => {
|
|
548
|
+
if (!stale) setSettled({
|
|
549
|
+
href,
|
|
550
|
+
result: { status: "failed" }
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
return () => {
|
|
554
|
+
stale = true;
|
|
555
|
+
};
|
|
556
|
+
}, [href, resolveLinkPreview]);
|
|
557
|
+
if (!href || !resolveLinkPreview || !isWebHref(href)) return { status: "idle" };
|
|
558
|
+
return settled?.href === href ? settled.result : { status: "loading" };
|
|
559
|
+
}
|
|
560
|
+
function isWebHref(href) {
|
|
561
|
+
try {
|
|
562
|
+
const protocol = new URL(href).protocol;
|
|
563
|
+
return protocol === "https:" || protocol === "http:";
|
|
564
|
+
} catch {
|
|
565
|
+
return false;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
552
568
|
function selectLinkUnit(editor, link) {
|
|
553
569
|
editor.commands.selectText(link.unit.from, link.unit.to);
|
|
554
570
|
editor.focus();
|
|
555
571
|
}
|
|
556
|
-
|
|
557
|
-
* A Base UI popover anchored at `anchor`. Base UI dismisses it on an outside
|
|
558
|
-
* press or Escape, both routed through `onClose`.
|
|
559
|
-
*/
|
|
560
|
-
function LinkPopover({ anchor, onClose, onPopupHover, children }) {
|
|
572
|
+
function LinkPopover({ anchor, open, onClose, onCloseComplete, onPopupHover, children }) {
|
|
561
573
|
return /* @__PURE__ */ jsx(Popover.Root, {
|
|
562
|
-
open
|
|
574
|
+
open,
|
|
563
575
|
onOpenChange: (open) => {
|
|
564
576
|
if (!open) onClose();
|
|
565
577
|
},
|
|
578
|
+
onOpenChangeComplete: (open) => {
|
|
579
|
+
if (!open) onCloseComplete?.();
|
|
580
|
+
},
|
|
566
581
|
children: /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(Popover.Positioner, {
|
|
567
582
|
anchor,
|
|
568
583
|
side: "bottom",
|
|
@@ -580,31 +595,29 @@ function LinkPopover({ anchor, onClose, onPopupHover, children }) {
|
|
|
580
595
|
}) })
|
|
581
596
|
});
|
|
582
597
|
}
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
598
|
+
function LinkAnchor({ href, className, onLinkClick, children }) {
|
|
599
|
+
return /* @__PURE__ */ jsx("a", {
|
|
600
|
+
className,
|
|
601
|
+
href,
|
|
602
|
+
title: href,
|
|
603
|
+
target: "_blank",
|
|
604
|
+
rel: "noopener noreferrer",
|
|
605
|
+
onClick: (event) => {
|
|
606
|
+
if (!onLinkClick) return;
|
|
607
|
+
event.preventDefault();
|
|
608
|
+
onLinkClick({
|
|
609
|
+
href,
|
|
610
|
+
event: event.nativeEvent,
|
|
611
|
+
mod: isModEvent(event)
|
|
612
|
+
});
|
|
613
|
+
},
|
|
614
|
+
children
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
function LinkActions({ href, onLinkCopy, onEdit, onRemove }) {
|
|
587
618
|
return /* @__PURE__ */ jsxs("div", {
|
|
588
|
-
className: link_menu_module_default.
|
|
589
|
-
"data-testid": "link-popover-read",
|
|
619
|
+
className: link_menu_module_default.Actions,
|
|
590
620
|
children: [
|
|
591
|
-
/* @__PURE__ */ jsx("a", {
|
|
592
|
-
className: link_menu_module_default.Url,
|
|
593
|
-
href,
|
|
594
|
-
title: href,
|
|
595
|
-
target: "_blank",
|
|
596
|
-
rel: "noopener noreferrer",
|
|
597
|
-
onClick: (event) => {
|
|
598
|
-
if (!onLinkClick) return;
|
|
599
|
-
event.preventDefault();
|
|
600
|
-
onLinkClick({
|
|
601
|
-
href,
|
|
602
|
-
event: event.nativeEvent,
|
|
603
|
-
mod: isModEvent(event)
|
|
604
|
-
});
|
|
605
|
-
},
|
|
606
|
-
children: href
|
|
607
|
-
}),
|
|
608
621
|
/* @__PURE__ */ jsx(CopyButton, {
|
|
609
622
|
getText: () => href,
|
|
610
623
|
label: "Copy link",
|
|
@@ -630,150 +643,274 @@ function LinkInfoContent({ href, onLinkClick, onLinkCopy, onEdit, onRemove }) {
|
|
|
630
643
|
]
|
|
631
644
|
});
|
|
632
645
|
}
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
*/
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
646
|
+
function PreviewIcon({ preview }) {
|
|
647
|
+
const [failed, setFailed] = useState(false);
|
|
648
|
+
if (!preview.iconSrc || failed) return /* @__PURE__ */ jsx(Globe2Icon, { "aria-hidden": "true" });
|
|
649
|
+
return /* @__PURE__ */ jsx("img", {
|
|
650
|
+
src: preview.iconSrc,
|
|
651
|
+
alt: "",
|
|
652
|
+
onError: () => setFailed(true)
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
function getHostname(href) {
|
|
656
|
+
try {
|
|
657
|
+
return new URL(href).hostname;
|
|
658
|
+
} catch {
|
|
659
|
+
return href;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
function LinkInfoContent({ href, previewState, onLinkClick, onLinkCopy, onEdit, onRemove, onUseTitle }) {
|
|
663
|
+
if (previewState.status === "resolved") {
|
|
664
|
+
const { preview } = previewState;
|
|
665
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
666
|
+
"data-testid": "link-popover-read",
|
|
667
|
+
children: [
|
|
668
|
+
/* @__PURE__ */ jsxs("div", {
|
|
669
|
+
className: link_menu_module_default.Preview,
|
|
670
|
+
children: [
|
|
671
|
+
/* @__PURE__ */ jsx("div", {
|
|
672
|
+
className: link_menu_module_default.Icon,
|
|
673
|
+
children: /* @__PURE__ */ jsx(PreviewIcon, { preview }, preview.iconSrc)
|
|
674
|
+
}),
|
|
675
|
+
/* @__PURE__ */ jsxs("div", {
|
|
676
|
+
className: link_menu_module_default.PreviewBody,
|
|
677
|
+
children: [/* @__PURE__ */ jsx(LinkAnchor, {
|
|
678
|
+
href,
|
|
679
|
+
className: link_menu_module_default.Title,
|
|
680
|
+
onLinkClick,
|
|
681
|
+
children: preview.title
|
|
682
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
683
|
+
className: link_menu_module_default.Host,
|
|
684
|
+
children: getHostname(href)
|
|
685
|
+
})]
|
|
686
|
+
}),
|
|
687
|
+
/* @__PURE__ */ jsx(LinkActions, {
|
|
688
|
+
href,
|
|
689
|
+
onLinkCopy,
|
|
690
|
+
onEdit,
|
|
691
|
+
onRemove
|
|
692
|
+
})
|
|
693
|
+
]
|
|
694
|
+
}),
|
|
695
|
+
preview.description && /* @__PURE__ */ jsx("p", {
|
|
696
|
+
className: link_menu_module_default.Description,
|
|
697
|
+
children: preview.description
|
|
698
|
+
}),
|
|
699
|
+
onUseTitle && /* @__PURE__ */ jsxs("div", {
|
|
700
|
+
className: link_menu_module_default.ReplaceRow,
|
|
701
|
+
children: [
|
|
702
|
+
/* @__PURE__ */ jsx(SparklesIcon, { "aria-hidden": "true" }),
|
|
703
|
+
/* @__PURE__ */ jsx("span", { children: "Replace URL with its title?" }),
|
|
704
|
+
/* @__PURE__ */ jsx("button", {
|
|
705
|
+
type: "button",
|
|
706
|
+
className: link_menu_module_default.ReplaceButton,
|
|
707
|
+
"aria-label": "Replace URL with its title",
|
|
708
|
+
onClick: () => onUseTitle(preview.title),
|
|
709
|
+
children: "Yes"
|
|
710
|
+
})
|
|
711
|
+
]
|
|
712
|
+
})
|
|
713
|
+
]
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
717
|
+
"data-testid": "link-popover-read",
|
|
718
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
719
|
+
className: link_menu_module_default.Row,
|
|
720
|
+
children: [/* @__PURE__ */ jsx(LinkAnchor, {
|
|
721
|
+
href,
|
|
722
|
+
className: link_menu_module_default.Url,
|
|
723
|
+
onLinkClick,
|
|
724
|
+
children: href
|
|
725
|
+
}), /* @__PURE__ */ jsx(LinkActions, {
|
|
726
|
+
href,
|
|
727
|
+
onLinkCopy,
|
|
728
|
+
onEdit,
|
|
729
|
+
onRemove
|
|
730
|
+
})]
|
|
731
|
+
}), previewState.status === "loading" && /* @__PURE__ */ jsxs("div", {
|
|
732
|
+
className: link_menu_module_default.Skeleton,
|
|
733
|
+
"data-testid": "link-popover-loading",
|
|
734
|
+
role: "status",
|
|
735
|
+
"aria-label": "Loading link preview",
|
|
736
|
+
children: [/* @__PURE__ */ jsx("div", { className: link_menu_module_default.SkeletonLine }), /* @__PURE__ */ jsx("div", { className: link_menu_module_default.SkeletonLineShort })]
|
|
737
|
+
})]
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
function LinkEditContent({ edit, resolveLinkPreview, onSubmit, onRemove }) {
|
|
741
|
+
const [text, setText] = useState(edit.text);
|
|
742
|
+
const [href, setHref] = useState(edit.link?.href ?? "");
|
|
743
|
+
const [debouncedHref, setDebouncedHref] = useState(href.trim());
|
|
744
|
+
const textInputRef = useRef(null);
|
|
745
|
+
const previewHref = normalizeHref(debouncedHref);
|
|
746
|
+
const previewState = useLinkPreview(previewHref || void 0, resolveLinkPreview);
|
|
747
|
+
const canUseTitle = !!edit.link && debouncedHref === href.trim() && isLinkTextForHref(text, previewHref);
|
|
641
748
|
useEffect(() => {
|
|
642
|
-
|
|
749
|
+
const timer = window.setTimeout(() => setDebouncedHref(href.trim()), 400);
|
|
750
|
+
return () => window.clearTimeout(timer);
|
|
751
|
+
}, [href]);
|
|
752
|
+
useEffect(() => {
|
|
753
|
+
textInputRef.current?.focus();
|
|
643
754
|
}, []);
|
|
644
755
|
return /* @__PURE__ */ jsxs("form", {
|
|
645
756
|
className: link_menu_module_default.Form,
|
|
646
757
|
"data-testid": "link-popover-edit",
|
|
647
758
|
onSubmit: (event) => {
|
|
648
759
|
event.preventDefault();
|
|
649
|
-
|
|
760
|
+
if (text.trim() && href.trim()) onSubmit(text, href);
|
|
650
761
|
},
|
|
651
762
|
children: [
|
|
652
|
-
/* @__PURE__ */
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
763
|
+
/* @__PURE__ */ jsxs("label", {
|
|
764
|
+
className: link_menu_module_default.Field,
|
|
765
|
+
children: [/* @__PURE__ */ jsx("span", { children: "Text" }), /* @__PURE__ */ jsx("input", {
|
|
766
|
+
ref: textInputRef,
|
|
767
|
+
className: link_menu_module_default.Input,
|
|
768
|
+
value: text,
|
|
769
|
+
required: true,
|
|
770
|
+
"data-testid": "link-popover-text-input",
|
|
771
|
+
onChange: (event) => setText(event.target.value)
|
|
772
|
+
})]
|
|
658
773
|
}),
|
|
659
|
-
/* @__PURE__ */
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
774
|
+
/* @__PURE__ */ jsxs("label", {
|
|
775
|
+
className: link_menu_module_default.Field,
|
|
776
|
+
children: [/* @__PURE__ */ jsx("span", { children: "Link" }), /* @__PURE__ */ jsx("input", {
|
|
777
|
+
className: link_menu_module_default.Input,
|
|
778
|
+
value: href,
|
|
779
|
+
required: true,
|
|
780
|
+
placeholder: "Paste link...",
|
|
781
|
+
"data-testid": "link-popover-input",
|
|
782
|
+
onChange: (event) => setHref(event.target.value)
|
|
783
|
+
})]
|
|
664
784
|
}),
|
|
665
|
-
/* @__PURE__ */
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
785
|
+
/* @__PURE__ */ jsxs("div", {
|
|
786
|
+
className: link_menu_module_default.FormActions,
|
|
787
|
+
children: [
|
|
788
|
+
onRemove && /* @__PURE__ */ jsx("button", {
|
|
789
|
+
type: "button",
|
|
790
|
+
className: link_menu_module_default.RemoveButton,
|
|
791
|
+
onClick: onRemove,
|
|
792
|
+
children: "Remove link"
|
|
793
|
+
}),
|
|
794
|
+
canUseTitle && previewState.status === "resolved" && /* @__PURE__ */ jsx("button", {
|
|
795
|
+
type: "button",
|
|
796
|
+
className: link_menu_module_default.UseTitleButton,
|
|
797
|
+
onClick: () => setText(previewState.preview.title),
|
|
798
|
+
children: "Use page title"
|
|
799
|
+
}),
|
|
800
|
+
/* @__PURE__ */ jsx("button", {
|
|
801
|
+
type: "submit",
|
|
802
|
+
className: link_menu_module_default.SaveButton,
|
|
803
|
+
"data-testid": "link-popover-submit",
|
|
804
|
+
children: "Save"
|
|
805
|
+
})
|
|
806
|
+
]
|
|
670
807
|
})
|
|
671
808
|
]
|
|
672
809
|
});
|
|
673
810
|
}
|
|
674
|
-
|
|
675
|
-
* Owns both link triggers and shows one popover at a time:
|
|
676
|
-
*
|
|
677
|
-
* - hovering a link opens a read-only preview that follows the pointer;
|
|
678
|
-
* - `Mod-k` (or the preview's edit button) opens an edit form that stays until
|
|
679
|
-
* it is submitted, dismissed with Escape, or pressed outside.
|
|
680
|
-
*/
|
|
681
|
-
function LinkMenu({ onLinkClick, onLinkCopy }) {
|
|
811
|
+
function LinkMenu({ onLinkClick, onLinkCopy, resolveLinkPreview, readOnly = false }) {
|
|
682
812
|
const editor = useEditor$1();
|
|
683
|
-
const [
|
|
684
|
-
const [onLink, setOnLink] = useState(false);
|
|
685
|
-
const [overPopup, setOverPopup] = useState(false);
|
|
813
|
+
const [hit, setHit] = useState();
|
|
686
814
|
const [edit, setEdit] = useState();
|
|
687
|
-
const
|
|
688
|
-
const
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
}, []);
|
|
815
|
+
const [editOpen, setEditOpen] = useState(false);
|
|
816
|
+
const [displayedRead, setDisplayedRead] = useState();
|
|
817
|
+
const overPopupRef = useRef(false);
|
|
818
|
+
const linkHoverExtension = useMemo(() => defineLinkHoverHandler((nextHit) => {
|
|
819
|
+
setHit(nextHit?.payload);
|
|
820
|
+
if (nextHit) setDisplayedRead(nextHit.payload);
|
|
821
|
+
}, { canLeave: () => !overPopupRef.current }), []);
|
|
694
822
|
useExtension$1(linkHoverExtension);
|
|
695
|
-
const linkEditExtension = useMemo(() => {
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
}, []);
|
|
823
|
+
const linkEditExtension = useMemo(() => readOnly ? null : defineLinkEditKeymap((options) => {
|
|
824
|
+
setEdit(options);
|
|
825
|
+
setEditOpen(true);
|
|
826
|
+
setHit(void 0);
|
|
827
|
+
}), [readOnly]);
|
|
700
828
|
useExtension$1(linkEditExtension);
|
|
701
|
-
const
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
setHover(void 0);
|
|
829
|
+
const closeRead = useCallback(() => {
|
|
830
|
+
overPopupRef.current = false;
|
|
831
|
+
setHit(void 0);
|
|
705
832
|
}, []);
|
|
706
833
|
const closeEdit = useCallback(() => {
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
if (edit) {
|
|
714
|
-
const anchorRange = edit.link?.text ?? edit;
|
|
715
|
-
rangeFrom = anchorRange.from;
|
|
716
|
-
rangeTo = anchorRange.to;
|
|
717
|
-
} else if (hover) {
|
|
718
|
-
const anchorRange = hover.text;
|
|
719
|
-
rangeFrom = anchorRange.from;
|
|
720
|
-
rangeTo = anchorRange.to;
|
|
721
|
-
}
|
|
834
|
+
setEditOpen(false);
|
|
835
|
+
closeRead();
|
|
836
|
+
}, [closeRead]);
|
|
837
|
+
const requestedRead = hit;
|
|
838
|
+
const previewState = useLinkPreview(displayedRead?.href, resolveLinkPreview);
|
|
839
|
+
const range = edit ? edit.link?.text ?? edit : displayedRead?.text;
|
|
722
840
|
const anchor = useMemo(() => {
|
|
723
|
-
if (
|
|
724
|
-
return getVirtualElementFromRange(editor.view,
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
});
|
|
728
|
-
}, [
|
|
729
|
-
rangeFrom,
|
|
730
|
-
rangeTo,
|
|
731
|
-
editor
|
|
732
|
-
]);
|
|
733
|
-
if (edit) return /* @__PURE__ */ jsx(LinkPopover, {
|
|
841
|
+
if (!range) return;
|
|
842
|
+
return getVirtualElementFromRange(editor.view, range);
|
|
843
|
+
}, [range, editor]);
|
|
844
|
+
if (edit && !readOnly) return /* @__PURE__ */ jsx(LinkPopover, {
|
|
734
845
|
anchor,
|
|
846
|
+
open: editOpen,
|
|
735
847
|
onClose: closeEdit,
|
|
848
|
+
onCloseComplete: () => {
|
|
849
|
+
setEdit(void 0);
|
|
850
|
+
editor.focus();
|
|
851
|
+
},
|
|
736
852
|
children: /* @__PURE__ */ jsx(LinkEditContent, {
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
853
|
+
edit,
|
|
854
|
+
resolveLinkPreview,
|
|
855
|
+
onRemove: edit.link ? () => {
|
|
856
|
+
editor.commands.removeLink();
|
|
857
|
+
closeEdit();
|
|
858
|
+
} : void 0,
|
|
859
|
+
onSubmit: (text, href) => {
|
|
860
|
+
if (edit.link) editor.commands.updateLink({
|
|
861
|
+
text: text === edit.text ? void 0 : text,
|
|
746
862
|
href,
|
|
747
|
-
title
|
|
863
|
+
title: edit.link.title
|
|
864
|
+
});
|
|
865
|
+
else editor.commands.insertLink({
|
|
866
|
+
text,
|
|
867
|
+
href
|
|
748
868
|
});
|
|
749
869
|
closeEdit();
|
|
750
870
|
}
|
|
751
871
|
})
|
|
752
872
|
});
|
|
753
|
-
if (
|
|
754
|
-
const
|
|
755
|
-
const
|
|
873
|
+
if (displayedRead) {
|
|
874
|
+
const mutable = !readOnly && displayedRead.form !== "reference";
|
|
875
|
+
const text = getLinkText(editor.view.state, displayedRead);
|
|
876
|
+
const canUseTitle = mutable && isLinkTextForHref(text, displayedRead.href);
|
|
877
|
+
const editLink = () => {
|
|
878
|
+
selectLinkUnit(editor, displayedRead);
|
|
879
|
+
setEdit({
|
|
880
|
+
from: displayedRead.unit.from,
|
|
881
|
+
to: displayedRead.unit.to,
|
|
882
|
+
link: displayedRead,
|
|
883
|
+
text
|
|
884
|
+
});
|
|
885
|
+
setEditOpen(true);
|
|
886
|
+
closeRead();
|
|
887
|
+
};
|
|
888
|
+
const removeLink = () => {
|
|
889
|
+
selectLinkUnit(editor, displayedRead);
|
|
890
|
+
editor.commands.removeLink();
|
|
891
|
+
closeRead();
|
|
892
|
+
};
|
|
756
893
|
return /* @__PURE__ */ jsx(LinkPopover, {
|
|
757
894
|
anchor,
|
|
758
|
-
|
|
759
|
-
|
|
895
|
+
open: requestedRead !== void 0,
|
|
896
|
+
onClose: closeRead,
|
|
897
|
+
onCloseComplete: () => {
|
|
898
|
+
if (!requestedRead) setDisplayedRead(void 0);
|
|
899
|
+
},
|
|
900
|
+
onPopupHover: (over) => {
|
|
901
|
+
overPopupRef.current = over;
|
|
902
|
+
},
|
|
760
903
|
children: /* @__PURE__ */ jsx(LinkInfoContent, {
|
|
761
|
-
href:
|
|
904
|
+
href: displayedRead.href,
|
|
905
|
+
previewState,
|
|
762
906
|
onLinkClick,
|
|
763
907
|
onLinkCopy,
|
|
764
|
-
onEdit:
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
});
|
|
771
|
-
closeHover();
|
|
772
|
-
} : void 0,
|
|
773
|
-
onRemove: editable ? () => {
|
|
774
|
-
selectLinkUnit(editor, link);
|
|
775
|
-
editor.commands.removeLink();
|
|
776
|
-
closeHover();
|
|
908
|
+
onEdit: mutable ? editLink : void 0,
|
|
909
|
+
onRemove: mutable ? removeLink : void 0,
|
|
910
|
+
onUseTitle: canUseTitle ? (title) => {
|
|
911
|
+
selectLinkUnit(editor, displayedRead);
|
|
912
|
+
editor.commands.updateLink({ text: title });
|
|
913
|
+
closeRead();
|
|
777
914
|
} : void 0
|
|
778
915
|
})
|
|
779
916
|
});
|
|
@@ -922,6 +1059,37 @@ function PendingReplacementPreview({ actions, onResolve }) {
|
|
|
922
1059
|
});
|
|
923
1060
|
}
|
|
924
1061
|
|
|
1062
|
+
//#endregion
|
|
1063
|
+
//#region src/hooks/use-delayed-flag.ts
|
|
1064
|
+
/**
|
|
1065
|
+
* Delay before the flag opens, in ms.
|
|
1066
|
+
*/
|
|
1067
|
+
const OPEN_DELAY$1 = 300;
|
|
1068
|
+
/**
|
|
1069
|
+
* Grace before the flag closes, in ms. The window lets a pointer travel from
|
|
1070
|
+
* the hovered link onto the popover it anchors.
|
|
1071
|
+
*/
|
|
1072
|
+
const CLOSE_DELAY$1 = 100;
|
|
1073
|
+
/**
|
|
1074
|
+
* Mirrors `value` into a boolean that flips true `openDelay`ms after `value`
|
|
1075
|
+
* becomes true and false `closeDelay`ms after it becomes false, cancelling any
|
|
1076
|
+
* pending flip on each change.
|
|
1077
|
+
*/
|
|
1078
|
+
function useDelayedFlag(value, openDelay = OPEN_DELAY$1, closeDelay = CLOSE_DELAY$1) {
|
|
1079
|
+
const [flag, setFlag] = useState(false);
|
|
1080
|
+
const timerRef = useRef(void 0);
|
|
1081
|
+
useEffect(() => {
|
|
1082
|
+
clearTimeout(timerRef.current);
|
|
1083
|
+
timerRef.current = setTimeout(() => setFlag(value), value ? openDelay : closeDelay);
|
|
1084
|
+
return () => clearTimeout(timerRef.current);
|
|
1085
|
+
}, [
|
|
1086
|
+
value,
|
|
1087
|
+
openDelay,
|
|
1088
|
+
closeDelay
|
|
1089
|
+
]);
|
|
1090
|
+
return flag;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
925
1093
|
//#endregion
|
|
926
1094
|
//#region src/components/selection-menu.module.css
|
|
927
1095
|
var selection_menu_module_default = {
|
|
@@ -1727,7 +1895,7 @@ function findHeadingPosition(doc, fragment) {
|
|
|
1727
1895
|
});
|
|
1728
1896
|
return match;
|
|
1729
1897
|
}
|
|
1730
|
-
function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onSlashMenuSearch, onTagSearch, onWikilinkSearch, onSelectionMenuSearch, selectionMenuAffordance = true, pendingReplacementActions, onPendingReplacementResolve, onWikilinkClick, onLinkClick, onLinkCopy, onTagClick, onExitBoundary, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveFileInfo, onFileClick, onFilePaste, onFileSaveError, onImageClick, embedPaste, linkPaste, bulletAfterHeading, substitution = true, frontmatter = false, blockHandle = true, placeholder, readOnly, spellCheck, searchQuery = "", onSearchChange, timeFormat, editorClassName, ref, children }) {
|
|
1898
|
+
function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onSlashMenuSearch, onTagSearch, onWikilinkSearch, onSelectionMenuSearch, selectionMenuAffordance = true, pendingReplacementActions, onPendingReplacementResolve, onWikilinkClick, onLinkClick, onLinkCopy, resolveLinkPreview, onTagClick, onExitBoundary, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveFileInfo, onFileClick, onFilePaste, onFileSaveError, onImageClick, embedPaste, linkPaste, bulletAfterHeading, substitution = true, frontmatter = false, blockHandle = true, placeholder, readOnly, spellCheck, searchQuery = "", onSearchChange, timeFormat, editorClassName, ref, children }) {
|
|
1731
1899
|
const [editor] = useState(() => {
|
|
1732
1900
|
const baseExtension = defineEditorExtension({
|
|
1733
1901
|
resolveFileLink,
|
|
@@ -1918,9 +2086,11 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onSl
|
|
|
1918
2086
|
onFilePaste,
|
|
1919
2087
|
onFileSaveError
|
|
1920
2088
|
}),
|
|
1921
|
-
|
|
2089
|
+
/* @__PURE__ */ jsx(LinkMenu, {
|
|
1922
2090
|
onLinkClick,
|
|
1923
|
-
onLinkCopy
|
|
2091
|
+
onLinkCopy,
|
|
2092
|
+
resolveLinkPreview,
|
|
2093
|
+
readOnly
|
|
1924
2094
|
}),
|
|
1925
2095
|
onTagSearch && /* @__PURE__ */ jsx(TagMenu, { onTagSearch }),
|
|
1926
2096
|
onWikilinkSearch && /* @__PURE__ */ jsx(WikilinkMenu, { onWikilinkSearch }),
|
|
@@ -1949,7 +2119,7 @@ const CARET_GLIDE_OFF = { "--meowdown-caret-glide": "0ms" };
|
|
|
1949
2119
|
*
|
|
1950
2120
|
* Callbacks and resolvers should be stable; pass them via `useCallback`.
|
|
1951
2121
|
*/
|
|
1952
|
-
function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onSlashMenuSearch, onTagSearch, onWikilinkSearch, onSelectionMenuSearch, selectionMenuAffordance = true, pendingReplacementActions, onPendingReplacementResolve, onWikilinkClick, onLinkClick, onLinkCopy, onTagClick, onExitBoundary, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveFileInfo, onFileClick, onFilePaste, onFileSaveError, onImageClick, embedPaste = true, linkPaste = true, bulletAfterHeading = false, substitution = true, frontmatter = false, blockHandle = true, caretGlide = true, placeholder, readOnly, spellCheck, searchQuery, onSearchChange, timeFormat, editorClassName, wrapperClassName, handleRef, children }) {
|
|
2122
|
+
function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onSlashMenuSearch, onTagSearch, onWikilinkSearch, onSelectionMenuSearch, selectionMenuAffordance = true, pendingReplacementActions, onPendingReplacementResolve, onWikilinkClick, onLinkClick, onLinkCopy, resolveLinkPreview, onTagClick, onExitBoundary, resolveImageUrl, resolveFileLink, resolveWikiEmbed, resolveFileInfo, onFileClick, onFilePaste, onFileSaveError, onImageClick, embedPaste = true, linkPaste = true, bulletAfterHeading = false, substitution = true, frontmatter = false, blockHandle = true, caretGlide = true, placeholder, readOnly, spellCheck, searchQuery, onSearchChange, timeFormat, editorClassName, wrapperClassName, handleRef, children }) {
|
|
1953
2123
|
const childRef = useRef(null);
|
|
1954
2124
|
useImperativeHandle(handleRef, () => {
|
|
1955
2125
|
function getMarkdown() {
|
|
@@ -2060,6 +2230,7 @@ function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onSlashM
|
|
|
2060
2230
|
onWikilinkClick,
|
|
2061
2231
|
onLinkClick,
|
|
2062
2232
|
onLinkCopy,
|
|
2233
|
+
resolveLinkPreview,
|
|
2063
2234
|
onTagClick,
|
|
2064
2235
|
onExitBoundary,
|
|
2065
2236
|
resolveImageUrl,
|
package/dist/style.css
CHANGED
|
@@ -294,18 +294,43 @@
|
|
|
294
294
|
|
|
295
295
|
.meow_Popup_IjcqKG {
|
|
296
296
|
box-sizing: border-box;
|
|
297
|
-
|
|
297
|
+
width: 100%;
|
|
298
|
+
color: var(--meowdown-text);
|
|
299
|
+
border: 1px solid var(--meowdown-hover-card-border);
|
|
300
|
+
border-radius: var(--meowdown-hover-card-radius);
|
|
298
301
|
background: var(--meowdown-popover-bg);
|
|
299
|
-
|
|
302
|
+
box-shadow: var(--meowdown-hover-card-shadow);
|
|
303
|
+
transform-origin: var(--transform-origin);
|
|
304
|
+
outline: none;
|
|
300
305
|
flex-direction: column;
|
|
301
|
-
width: 100%;
|
|
302
|
-
padding: .25rem;
|
|
303
306
|
font-size: .875rem;
|
|
307
|
+
transition: opacity .15s, transform .15s;
|
|
308
|
+
display: flex;
|
|
309
|
+
overflow: hidden;
|
|
310
|
+
|
|
311
|
+
&[data-closed] {
|
|
312
|
+
transition: opacity .1s, transform .1s;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
&[data-starting-style], &[data-ending-style] {
|
|
316
|
+
opacity: 0;
|
|
317
|
+
transform: scale(.96);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
@media (prefers-reduced-motion: reduce) {
|
|
321
|
+
transition: none;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.meow_Row_IjcqKG, .meow_Preview_IjcqKG {
|
|
326
|
+
align-items: center;
|
|
327
|
+
gap: .5rem;
|
|
328
|
+
padding: .5rem;
|
|
304
329
|
display: flex;
|
|
305
|
-
box-shadow: 0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;
|
|
306
330
|
}
|
|
307
331
|
|
|
308
|
-
.
|
|
332
|
+
.meow_Actions_IjcqKG {
|
|
333
|
+
flex: none;
|
|
309
334
|
align-items: center;
|
|
310
335
|
gap: .125rem;
|
|
311
336
|
display: flex;
|
|
@@ -318,18 +343,20 @@
|
|
|
318
343
|
color: var(--meowdown-accent);
|
|
319
344
|
cursor: pointer;
|
|
320
345
|
flex: 1;
|
|
321
|
-
padding: .25rem .
|
|
346
|
+
padding: .25rem .375rem;
|
|
322
347
|
overflow: hidden;
|
|
323
348
|
}
|
|
324
349
|
|
|
325
350
|
.meow_Button_IjcqKG {
|
|
351
|
+
width: 2rem;
|
|
352
|
+
height: 2rem;
|
|
326
353
|
color: var(--meowdown-text);
|
|
327
354
|
cursor: pointer;
|
|
328
355
|
border-radius: .5rem;
|
|
329
356
|
flex: none;
|
|
330
357
|
justify-content: center;
|
|
331
358
|
align-items: center;
|
|
332
|
-
padding:
|
|
359
|
+
padding: 0;
|
|
333
360
|
display: inline-flex;
|
|
334
361
|
|
|
335
362
|
&:hover {
|
|
@@ -340,26 +367,172 @@
|
|
|
340
367
|
width: 1rem;
|
|
341
368
|
height: 1rem;
|
|
342
369
|
}
|
|
370
|
+
|
|
371
|
+
@media (pointer: coarse) {
|
|
372
|
+
width: 2.75rem;
|
|
373
|
+
height: 2.75rem;
|
|
374
|
+
}
|
|
343
375
|
}
|
|
344
376
|
|
|
345
|
-
.
|
|
377
|
+
.meow_Icon_IjcqKG {
|
|
378
|
+
width: 2rem;
|
|
379
|
+
height: 2rem;
|
|
380
|
+
color: var(--meowdown-muted);
|
|
381
|
+
border-radius: .375rem;
|
|
382
|
+
flex: none;
|
|
383
|
+
justify-content: center;
|
|
384
|
+
align-items: center;
|
|
385
|
+
display: flex;
|
|
386
|
+
overflow: hidden;
|
|
387
|
+
|
|
388
|
+
& img, & svg {
|
|
389
|
+
object-fit: contain;
|
|
390
|
+
width: 1.25rem;
|
|
391
|
+
height: 1.25rem;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.meow_PreviewBody_IjcqKG {
|
|
346
396
|
flex-direction: column;
|
|
347
|
-
|
|
348
|
-
|
|
397
|
+
flex: 1;
|
|
398
|
+
min-width: 0;
|
|
349
399
|
display: flex;
|
|
350
400
|
}
|
|
351
401
|
|
|
352
|
-
.
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
padding: 0;
|
|
359
|
-
position: absolute;
|
|
402
|
+
.meow_Title_IjcqKG {
|
|
403
|
+
white-space: nowrap;
|
|
404
|
+
text-overflow: ellipsis;
|
|
405
|
+
color: var(--meowdown-accent);
|
|
406
|
+
font-weight: 500;
|
|
407
|
+
line-height: 1.3;
|
|
360
408
|
overflow: hidden;
|
|
361
409
|
}
|
|
362
410
|
|
|
411
|
+
.meow_Host_IjcqKG {
|
|
412
|
+
white-space: nowrap;
|
|
413
|
+
text-overflow: ellipsis;
|
|
414
|
+
color: var(--meowdown-muted);
|
|
415
|
+
font-size: .8125rem;
|
|
416
|
+
line-height: 1.3;
|
|
417
|
+
overflow: hidden;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
.meow_Description_IjcqKG {
|
|
421
|
+
color: var(--meowdown-muted);
|
|
422
|
+
-webkit-line-clamp: 2;
|
|
423
|
+
-webkit-box-orient: vertical;
|
|
424
|
+
margin: 0;
|
|
425
|
+
padding: 0 .75rem .75rem 3rem;
|
|
426
|
+
line-height: 1.4;
|
|
427
|
+
display: -webkit-box;
|
|
428
|
+
overflow: hidden;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.meow_ReplaceRow_IjcqKG {
|
|
432
|
+
min-height: 2.5rem;
|
|
433
|
+
color: var(--meowdown-text);
|
|
434
|
+
border-top: 1px solid var(--meowdown-border);
|
|
435
|
+
align-items: center;
|
|
436
|
+
gap: .5rem;
|
|
437
|
+
padding: .375rem .5rem .375rem .75rem;
|
|
438
|
+
display: flex;
|
|
439
|
+
|
|
440
|
+
& > svg {
|
|
441
|
+
width: .875rem;
|
|
442
|
+
height: .875rem;
|
|
443
|
+
color: var(--meowdown-accent);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
& > span {
|
|
447
|
+
flex: 1;
|
|
448
|
+
min-width: 0;
|
|
449
|
+
font-size: .8125rem;
|
|
450
|
+
font-weight: 500;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
.meow_ReplaceButton_IjcqKG, .meow_SaveButton_IjcqKG {
|
|
455
|
+
min-height: 2rem;
|
|
456
|
+
font: inherit;
|
|
457
|
+
color: var(--meowdown-accent-contrast);
|
|
458
|
+
background: var(--meowdown-accent);
|
|
459
|
+
cursor: pointer;
|
|
460
|
+
border: 0;
|
|
461
|
+
border-radius: .5rem;
|
|
462
|
+
padding: .375rem .625rem;
|
|
463
|
+
font-weight: 500;
|
|
464
|
+
|
|
465
|
+
@media (pointer: coarse) {
|
|
466
|
+
min-height: 2.75rem;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
.meow_ReplaceButton_IjcqKG {
|
|
471
|
+
flex: none;
|
|
472
|
+
min-height: 1.75rem;
|
|
473
|
+
padding: .25rem .625rem;
|
|
474
|
+
transition: filter .1s, transform .1s ease-out;
|
|
475
|
+
|
|
476
|
+
&:hover {
|
|
477
|
+
filter: brightness(1.05);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
&:active {
|
|
481
|
+
transform: scale(.97);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.meow_Skeleton_IjcqKG {
|
|
486
|
+
flex-direction: column;
|
|
487
|
+
gap: .625rem;
|
|
488
|
+
padding: 0 .5rem .625rem;
|
|
489
|
+
display: flex;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
.meow_SkeletonLine_IjcqKG, .meow_SkeletonLineShort_IjcqKG {
|
|
493
|
+
background: var(--meowdown-popover-hover-bg);
|
|
494
|
+
border-radius: 999px;
|
|
495
|
+
height: .75rem;
|
|
496
|
+
animation: 1.4s ease-in-out infinite meow_pulse_IjcqKG;
|
|
497
|
+
|
|
498
|
+
@media (prefers-reduced-motion: reduce) {
|
|
499
|
+
animation: none;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
.meow_SkeletonLine_IjcqKG {
|
|
504
|
+
width: 90%;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
.meow_SkeletonLineShort_IjcqKG {
|
|
508
|
+
width: 70%;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
@keyframes meow_pulse_IjcqKG {
|
|
512
|
+
50% {
|
|
513
|
+
opacity: .45;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
.meow_Form_IjcqKG {
|
|
518
|
+
flex-direction: column;
|
|
519
|
+
gap: .625rem;
|
|
520
|
+
padding: .75rem;
|
|
521
|
+
display: flex;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
.meow_Field_IjcqKG {
|
|
525
|
+
flex-direction: column;
|
|
526
|
+
gap: .25rem;
|
|
527
|
+
display: flex;
|
|
528
|
+
|
|
529
|
+
& > span {
|
|
530
|
+
color: var(--meowdown-muted);
|
|
531
|
+
font-size: .75rem;
|
|
532
|
+
font-weight: 600;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
363
536
|
.meow_Input_IjcqKG {
|
|
364
537
|
box-sizing: border-box;
|
|
365
538
|
width: 100%;
|
|
@@ -368,13 +541,41 @@
|
|
|
368
541
|
border: 1px solid var(--meowdown-border);
|
|
369
542
|
background: none;
|
|
370
543
|
border-radius: .5rem;
|
|
371
|
-
padding: .
|
|
544
|
+
padding: .5rem .625rem;
|
|
372
545
|
|
|
373
546
|
&:focus {
|
|
374
547
|
outline: 2px solid var(--meowdown-accent);
|
|
375
548
|
outline-offset: -1px;
|
|
376
549
|
}
|
|
377
550
|
}
|
|
551
|
+
|
|
552
|
+
.meow_FormActions_IjcqKG {
|
|
553
|
+
align-items: center;
|
|
554
|
+
gap: .375rem;
|
|
555
|
+
padding-top: .125rem;
|
|
556
|
+
display: flex;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
.meow_RemoveButton_IjcqKG, .meow_UseTitleButton_IjcqKG {
|
|
560
|
+
min-height: 2rem;
|
|
561
|
+
font: inherit;
|
|
562
|
+
cursor: pointer;
|
|
563
|
+
border-radius: .5rem;
|
|
564
|
+
padding: .375rem .625rem;
|
|
565
|
+
|
|
566
|
+
@media (pointer: coarse) {
|
|
567
|
+
min-height: 2.75rem;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
.meow_RemoveButton_IjcqKG {
|
|
572
|
+
color: var(--meowdown-danger, #c33);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
.meow_UseTitleButton_IjcqKG {
|
|
576
|
+
color: var(--meowdown-accent);
|
|
577
|
+
margin-left: auto;
|
|
578
|
+
}
|
|
378
579
|
.meow_Positioner_DPJ5ia {
|
|
379
580
|
z-index: 50;
|
|
380
581
|
width: min(30rem, 100vw - 1rem);
|
|
@@ -794,16 +995,16 @@
|
|
|
794
995
|
.meow_Popup_HMEwgW {
|
|
795
996
|
box-sizing: border-box;
|
|
796
997
|
pointer-events: none;
|
|
797
|
-
border: 1px solid var(--meowdown-border);
|
|
998
|
+
border: 1px solid var(--meowdown-hover-card-border);
|
|
999
|
+
border-radius: var(--meowdown-hover-card-radius);
|
|
798
1000
|
background: var(--meowdown-popover-bg);
|
|
799
1001
|
width: min(20rem, 100vw - 1rem);
|
|
800
1002
|
max-height: min(12rem, 100vh - 1rem);
|
|
1003
|
+
box-shadow: var(--meowdown-hover-card-shadow);
|
|
801
1004
|
transform-origin: var(--transform-origin);
|
|
802
|
-
border-radius: .75rem;
|
|
803
1005
|
outline: none;
|
|
804
1006
|
transition: opacity .15s, transform .15s;
|
|
805
1007
|
display: flex;
|
|
806
|
-
box-shadow: 0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;
|
|
807
1008
|
}
|
|
808
1009
|
|
|
809
1010
|
.meow_Popup_HMEwgW[data-closed] {
|
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.67.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -23,15 +23,15 @@
|
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@base-ui/react": "^1.7.0",
|
|
25
25
|
"@ocavue/utils": "^1.7.0",
|
|
26
|
-
"@prosekit/core": "^0.13.
|
|
26
|
+
"@prosekit/core": "^0.13.1",
|
|
27
27
|
"@prosekit/pm": "^0.1.19",
|
|
28
|
-
"@prosekit/react": "^0.8.
|
|
28
|
+
"@prosekit/react": "^0.8.1",
|
|
29
29
|
"beautiful-mermaid": "^1.1.3",
|
|
30
30
|
"clsx": "^2.1.1",
|
|
31
31
|
"github-slugger": "^2.0.0",
|
|
32
32
|
"lucide-react": "^1.28.0",
|
|
33
33
|
"react-property": "^2.0.2",
|
|
34
|
-
"@meowdown/core": "0.
|
|
34
|
+
"@meowdown/core": "0.67.0"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"react": "^19.0.0",
|
|
@@ -51,12 +51,12 @@
|
|
|
51
51
|
"@tsdown/css": "^0.23.0-beta.2",
|
|
52
52
|
"@types/react": "^19.2.18",
|
|
53
53
|
"@types/react-dom": "^19.2.4",
|
|
54
|
-
"@vitest/browser-playwright": "^4.1.
|
|
54
|
+
"@vitest/browser-playwright": "^4.1.11",
|
|
55
55
|
"dedent": "^1.7.2",
|
|
56
56
|
"react": "^19.2.8",
|
|
57
57
|
"react-dom": "^19.2.8",
|
|
58
58
|
"tsdown": "^0.23.0-beta.2",
|
|
59
|
-
"vitest": "^4.1.
|
|
59
|
+
"vitest": "^4.1.11",
|
|
60
60
|
"vitest-browser-commands": "^0.2.1",
|
|
61
61
|
"vitest-browser-react": "^2.2.0",
|
|
62
62
|
"@meowdown/vitest": "0.0.0"
|