@meowdown/react 0.66.0 → 0.67.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/dist/index.d.ts +10 -3
- package/dist/index.js +384 -195
- package/dist/style.css +238 -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,155 +643,297 @@ 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-info",
|
|
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-info",
|
|
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);
|
|
748
|
+
useEffect(() => {
|
|
749
|
+
const timer = window.setTimeout(() => setDebouncedHref(href.trim()), 400);
|
|
750
|
+
return () => window.clearTimeout(timer);
|
|
751
|
+
}, [href]);
|
|
641
752
|
useEffect(() => {
|
|
642
|
-
|
|
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 [
|
|
685
|
-
const [
|
|
813
|
+
const [infoOpen, setInfoOpen] = useState(false);
|
|
814
|
+
const [editOpen, setEditOpen] = useState(false);
|
|
815
|
+
const [link, setLink] = useState();
|
|
686
816
|
const [edit, setEdit] = useState();
|
|
687
|
-
const
|
|
688
|
-
const linkHoverExtension = useMemo(() => {
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
});
|
|
693
|
-
}, []);
|
|
817
|
+
const isPointerOverPopupRef = useRef(false);
|
|
818
|
+
const linkHoverExtension = useMemo(() => defineLinkHoverHandler((nextHit) => {
|
|
819
|
+
setInfoOpen(nextHit != null);
|
|
820
|
+
if (nextHit) setLink(nextHit.payload);
|
|
821
|
+
}, { canLeave: () => !isPointerOverPopupRef.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
|
+
setInfoOpen(false);
|
|
827
|
+
}), [readOnly]);
|
|
700
828
|
useExtension$1(linkEditExtension);
|
|
701
|
-
const
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
829
|
+
const handlePointerHover = useCallback((over) => {
|
|
830
|
+
isPointerOverPopupRef.current = over;
|
|
831
|
+
}, []);
|
|
832
|
+
const closeInfo = useCallback(() => {
|
|
833
|
+
isPointerOverPopupRef.current = false;
|
|
834
|
+
setInfoOpen(false);
|
|
705
835
|
}, []);
|
|
706
836
|
const closeEdit = useCallback(() => {
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
return getVirtualElementFromRange(editor.view, {
|
|
725
|
-
from: rangeFrom,
|
|
726
|
-
to: rangeTo
|
|
837
|
+
setEditOpen(false);
|
|
838
|
+
closeInfo();
|
|
839
|
+
}, [closeInfo]);
|
|
840
|
+
const handleEditRemove = useCallback(() => {
|
|
841
|
+
editor.commands.removeLink();
|
|
842
|
+
closeEdit();
|
|
843
|
+
}, [editor, closeEdit]);
|
|
844
|
+
const handleEditSubmit = useCallback((text, href) => {
|
|
845
|
+
if (!edit) return;
|
|
846
|
+
if (edit.link) editor.commands.updateLink({
|
|
847
|
+
text: text === edit.text ? void 0 : text,
|
|
848
|
+
href,
|
|
849
|
+
title: edit.link.title
|
|
850
|
+
});
|
|
851
|
+
else editor.commands.insertLink({
|
|
852
|
+
text,
|
|
853
|
+
href
|
|
727
854
|
});
|
|
855
|
+
closeEdit();
|
|
728
856
|
}, [
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
857
|
+
edit,
|
|
858
|
+
editor,
|
|
859
|
+
closeEdit
|
|
860
|
+
]);
|
|
861
|
+
const mutable = link != null && !readOnly && link.form !== "reference";
|
|
862
|
+
const linkText = useMemo(() => link ? getLinkText(link) : "", [link]);
|
|
863
|
+
const editLink = useCallback(() => {
|
|
864
|
+
if (!link) return;
|
|
865
|
+
selectLinkUnit(editor, link);
|
|
866
|
+
setEdit({
|
|
867
|
+
from: link.unit.from,
|
|
868
|
+
to: link.unit.to,
|
|
869
|
+
link,
|
|
870
|
+
text: linkText
|
|
871
|
+
});
|
|
872
|
+
setEditOpen(true);
|
|
873
|
+
closeInfo();
|
|
874
|
+
}, [
|
|
875
|
+
link,
|
|
876
|
+
editor,
|
|
877
|
+
linkText,
|
|
878
|
+
closeInfo
|
|
879
|
+
]);
|
|
880
|
+
const removeLink = useCallback(() => {
|
|
881
|
+
if (!link) return;
|
|
882
|
+
selectLinkUnit(editor, link);
|
|
883
|
+
editor.commands.removeLink();
|
|
884
|
+
closeInfo();
|
|
885
|
+
}, [
|
|
886
|
+
link,
|
|
887
|
+
editor,
|
|
888
|
+
closeInfo
|
|
889
|
+
]);
|
|
890
|
+
const handleUseTitle = useMemo(() => {
|
|
891
|
+
if (!link || !mutable || !isLinkTextForHref(linkText, link.href)) return;
|
|
892
|
+
return (title) => {
|
|
893
|
+
selectLinkUnit(editor, link);
|
|
894
|
+
editor.commands.updateLink({ text: title });
|
|
895
|
+
closeInfo();
|
|
896
|
+
};
|
|
897
|
+
}, [
|
|
898
|
+
link,
|
|
899
|
+
editor,
|
|
900
|
+
closeInfo,
|
|
901
|
+
linkText,
|
|
902
|
+
mutable
|
|
732
903
|
]);
|
|
733
|
-
|
|
904
|
+
const previewState = useLinkPreview(link?.href, resolveLinkPreview);
|
|
905
|
+
const range = edit ? edit.link?.text ?? edit : link?.text;
|
|
906
|
+
const anchor = useMemo(() => {
|
|
907
|
+
if (!range) return;
|
|
908
|
+
return getVirtualElementFromRange(editor.view, range);
|
|
909
|
+
}, [range, editor]);
|
|
910
|
+
const editing = edit != null && !readOnly;
|
|
911
|
+
return /* @__PURE__ */ jsx(LinkPopover, {
|
|
734
912
|
anchor,
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
913
|
+
open: editing ? editOpen : infoOpen,
|
|
914
|
+
onClose: editing ? closeEdit : closeInfo,
|
|
915
|
+
onCloseComplete: () => {
|
|
916
|
+
if (editing) {
|
|
917
|
+
setEdit(void 0);
|
|
918
|
+
editor.focus();
|
|
919
|
+
} else if (!infoOpen) setLink(void 0);
|
|
920
|
+
},
|
|
921
|
+
onPopupHover: handlePointerHover,
|
|
922
|
+
children: editing ? /* @__PURE__ */ jsx(LinkEditContent, {
|
|
923
|
+
edit,
|
|
924
|
+
resolveLinkPreview,
|
|
925
|
+
onRemove: handleEditRemove,
|
|
926
|
+
onSubmit: handleEditSubmit
|
|
927
|
+
}) : link ? /* @__PURE__ */ jsx(LinkInfoContent, {
|
|
928
|
+
href: link.href,
|
|
929
|
+
previewState,
|
|
930
|
+
onLinkClick,
|
|
931
|
+
onLinkCopy,
|
|
932
|
+
onEdit: mutable ? editLink : void 0,
|
|
933
|
+
onRemove: mutable ? removeLink : void 0,
|
|
934
|
+
onUseTitle: handleUseTitle
|
|
935
|
+
}) : void 0
|
|
752
936
|
});
|
|
753
|
-
if (hoverOpen && hover) {
|
|
754
|
-
const link = hover;
|
|
755
|
-
const editable = link.form === "inline";
|
|
756
|
-
return /* @__PURE__ */ jsx(LinkPopover, {
|
|
757
|
-
anchor,
|
|
758
|
-
onClose: closeHover,
|
|
759
|
-
onPopupHover: setOverPopup,
|
|
760
|
-
children: /* @__PURE__ */ jsx(LinkInfoContent, {
|
|
761
|
-
href: link.href,
|
|
762
|
-
onLinkClick,
|
|
763
|
-
onLinkCopy,
|
|
764
|
-
onEdit: editable ? () => {
|
|
765
|
-
selectLinkUnit(editor, link);
|
|
766
|
-
setEdit({
|
|
767
|
-
from: link.unit.from,
|
|
768
|
-
to: link.unit.to,
|
|
769
|
-
link
|
|
770
|
-
});
|
|
771
|
-
closeHover();
|
|
772
|
-
} : void 0,
|
|
773
|
-
onRemove: editable ? () => {
|
|
774
|
-
selectLinkUnit(editor, link);
|
|
775
|
-
editor.commands.removeLink();
|
|
776
|
-
closeHover();
|
|
777
|
-
} : void 0
|
|
778
|
-
})
|
|
779
|
-
});
|
|
780
|
-
}
|
|
781
|
-
return null;
|
|
782
937
|
}
|
|
783
938
|
|
|
784
939
|
//#endregion
|
|
@@ -922,6 +1077,37 @@ function PendingReplacementPreview({ actions, onResolve }) {
|
|
|
922
1077
|
});
|
|
923
1078
|
}
|
|
924
1079
|
|
|
1080
|
+
//#endregion
|
|
1081
|
+
//#region src/hooks/use-delayed-flag.ts
|
|
1082
|
+
/**
|
|
1083
|
+
* Delay before the flag opens, in ms.
|
|
1084
|
+
*/
|
|
1085
|
+
const OPEN_DELAY$1 = 300;
|
|
1086
|
+
/**
|
|
1087
|
+
* Grace before the flag closes, in ms. The window lets a pointer travel from
|
|
1088
|
+
* the hovered link onto the popover it anchors.
|
|
1089
|
+
*/
|
|
1090
|
+
const CLOSE_DELAY$1 = 100;
|
|
1091
|
+
/**
|
|
1092
|
+
* Mirrors `value` into a boolean that flips true `openDelay`ms after `value`
|
|
1093
|
+
* becomes true and false `closeDelay`ms after it becomes false, cancelling any
|
|
1094
|
+
* pending flip on each change.
|
|
1095
|
+
*/
|
|
1096
|
+
function useDelayedFlag(value, openDelay = OPEN_DELAY$1, closeDelay = CLOSE_DELAY$1) {
|
|
1097
|
+
const [flag, setFlag] = useState(false);
|
|
1098
|
+
const timerRef = useRef(void 0);
|
|
1099
|
+
useEffect(() => {
|
|
1100
|
+
clearTimeout(timerRef.current);
|
|
1101
|
+
timerRef.current = setTimeout(() => setFlag(value), value ? openDelay : closeDelay);
|
|
1102
|
+
return () => clearTimeout(timerRef.current);
|
|
1103
|
+
}, [
|
|
1104
|
+
value,
|
|
1105
|
+
openDelay,
|
|
1106
|
+
closeDelay
|
|
1107
|
+
]);
|
|
1108
|
+
return flag;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
925
1111
|
//#endregion
|
|
926
1112
|
//#region src/components/selection-menu.module.css
|
|
927
1113
|
var selection_menu_module_default = {
|
|
@@ -1727,7 +1913,7 @@ function findHeadingPosition(doc, fragment) {
|
|
|
1727
1913
|
});
|
|
1728
1914
|
return match;
|
|
1729
1915
|
}
|
|
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 }) {
|
|
1916
|
+
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
1917
|
const [editor] = useState(() => {
|
|
1732
1918
|
const baseExtension = defineEditorExtension({
|
|
1733
1919
|
resolveFileLink,
|
|
@@ -1918,9 +2104,11 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onSl
|
|
|
1918
2104
|
onFilePaste,
|
|
1919
2105
|
onFileSaveError
|
|
1920
2106
|
}),
|
|
1921
|
-
|
|
2107
|
+
/* @__PURE__ */ jsx(LinkMenu, {
|
|
1922
2108
|
onLinkClick,
|
|
1923
|
-
onLinkCopy
|
|
2109
|
+
onLinkCopy,
|
|
2110
|
+
resolveLinkPreview,
|
|
2111
|
+
readOnly
|
|
1924
2112
|
}),
|
|
1925
2113
|
onTagSearch && /* @__PURE__ */ jsx(TagMenu, { onTagSearch }),
|
|
1926
2114
|
onWikilinkSearch && /* @__PURE__ */ jsx(WikilinkMenu, { onWikilinkSearch }),
|
|
@@ -1949,7 +2137,7 @@ const CARET_GLIDE_OFF = { "--meowdown-caret-glide": "0ms" };
|
|
|
1949
2137
|
*
|
|
1950
2138
|
* Callbacks and resolvers should be stable; pass them via `useCallback`.
|
|
1951
2139
|
*/
|
|
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 }) {
|
|
2140
|
+
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
2141
|
const childRef = useRef(null);
|
|
1954
2142
|
useImperativeHandle(handleRef, () => {
|
|
1955
2143
|
function getMarkdown() {
|
|
@@ -2060,6 +2248,7 @@ function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onSlashM
|
|
|
2060
2248
|
onWikilinkClick,
|
|
2061
2249
|
onLinkClick,
|
|
2062
2250
|
onLinkCopy,
|
|
2251
|
+
resolveLinkPreview,
|
|
2063
2252
|
onTagClick,
|
|
2064
2253
|
onExitBoundary,
|
|
2065
2254
|
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;
|
|
304
308
|
display: flex;
|
|
305
|
-
|
|
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
|
+
}
|
|
306
323
|
}
|
|
307
324
|
|
|
308
|
-
.meow_Row_IjcqKG {
|
|
325
|
+
.meow_Row_IjcqKG, .meow_Preview_IjcqKG {
|
|
326
|
+
align-items: center;
|
|
327
|
+
gap: .5rem;
|
|
328
|
+
padding: .5rem;
|
|
329
|
+
display: flex;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.meow_Actions_IjcqKG {
|
|
333
|
+
flex: none;
|
|
309
334
|
align-items: center;
|
|
310
335
|
gap: .125rem;
|
|
311
336
|
display: flex;
|
|
@@ -318,18 +343,23 @@
|
|
|
318
343
|
color: var(--meowdown-accent);
|
|
319
344
|
cursor: pointer;
|
|
320
345
|
flex: 1;
|
|
321
|
-
padding: .25rem .
|
|
346
|
+
padding: .25rem .375rem;
|
|
347
|
+
text-decoration: none;
|
|
322
348
|
overflow: hidden;
|
|
323
349
|
}
|
|
324
350
|
|
|
325
351
|
.meow_Button_IjcqKG {
|
|
352
|
+
width: 2rem;
|
|
353
|
+
height: 2rem;
|
|
326
354
|
color: var(--meowdown-text);
|
|
327
355
|
cursor: pointer;
|
|
356
|
+
background: none;
|
|
357
|
+
border: 0;
|
|
328
358
|
border-radius: .5rem;
|
|
329
359
|
flex: none;
|
|
330
360
|
justify-content: center;
|
|
331
361
|
align-items: center;
|
|
332
|
-
padding:
|
|
362
|
+
padding: 0;
|
|
333
363
|
display: inline-flex;
|
|
334
364
|
|
|
335
365
|
&:hover {
|
|
@@ -340,26 +370,173 @@
|
|
|
340
370
|
width: 1rem;
|
|
341
371
|
height: 1rem;
|
|
342
372
|
}
|
|
373
|
+
|
|
374
|
+
@media (pointer: coarse) {
|
|
375
|
+
width: 2.75rem;
|
|
376
|
+
height: 2.75rem;
|
|
377
|
+
}
|
|
343
378
|
}
|
|
344
379
|
|
|
345
|
-
.
|
|
380
|
+
.meow_Icon_IjcqKG {
|
|
381
|
+
width: 2rem;
|
|
382
|
+
height: 2rem;
|
|
383
|
+
color: var(--meowdown-muted);
|
|
384
|
+
border-radius: .375rem;
|
|
385
|
+
flex: none;
|
|
386
|
+
justify-content: center;
|
|
387
|
+
align-items: center;
|
|
388
|
+
display: flex;
|
|
389
|
+
overflow: hidden;
|
|
390
|
+
|
|
391
|
+
& img, & svg {
|
|
392
|
+
object-fit: contain;
|
|
393
|
+
width: 1.25rem;
|
|
394
|
+
height: 1.25rem;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.meow_PreviewBody_IjcqKG {
|
|
346
399
|
flex-direction: column;
|
|
347
|
-
|
|
348
|
-
|
|
400
|
+
flex: 1;
|
|
401
|
+
min-width: 0;
|
|
349
402
|
display: flex;
|
|
350
403
|
}
|
|
351
404
|
|
|
352
|
-
.
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
405
|
+
.meow_Title_IjcqKG {
|
|
406
|
+
white-space: nowrap;
|
|
407
|
+
text-overflow: ellipsis;
|
|
408
|
+
color: var(--meowdown-accent);
|
|
409
|
+
font-weight: 500;
|
|
410
|
+
line-height: 1.3;
|
|
411
|
+
text-decoration: none;
|
|
412
|
+
overflow: hidden;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.meow_Host_IjcqKG {
|
|
416
|
+
white-space: nowrap;
|
|
417
|
+
text-overflow: ellipsis;
|
|
418
|
+
color: var(--meowdown-muted);
|
|
419
|
+
font-size: .8125rem;
|
|
420
|
+
line-height: 1.3;
|
|
421
|
+
overflow: hidden;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
.meow_Description_IjcqKG {
|
|
425
|
+
color: var(--meowdown-muted);
|
|
426
|
+
-webkit-line-clamp: 2;
|
|
427
|
+
-webkit-box-orient: vertical;
|
|
428
|
+
margin: 0;
|
|
429
|
+
padding: 0 .75rem .75rem 3rem;
|
|
430
|
+
line-height: 1.4;
|
|
431
|
+
display: -webkit-box;
|
|
360
432
|
overflow: hidden;
|
|
361
433
|
}
|
|
362
434
|
|
|
435
|
+
.meow_ReplaceRow_IjcqKG {
|
|
436
|
+
min-height: 2.5rem;
|
|
437
|
+
color: var(--meowdown-text);
|
|
438
|
+
border-top: 1px solid var(--meowdown-border);
|
|
439
|
+
align-items: center;
|
|
440
|
+
gap: .5rem;
|
|
441
|
+
padding: .375rem .5rem .375rem .75rem;
|
|
442
|
+
display: flex;
|
|
443
|
+
|
|
444
|
+
& > svg {
|
|
445
|
+
width: .875rem;
|
|
446
|
+
height: .875rem;
|
|
447
|
+
color: var(--meowdown-accent);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
& > span {
|
|
451
|
+
flex: 1;
|
|
452
|
+
min-width: 0;
|
|
453
|
+
font-size: .8125rem;
|
|
454
|
+
font-weight: 500;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
.meow_ReplaceButton_IjcqKG, .meow_SaveButton_IjcqKG {
|
|
459
|
+
min-height: 2rem;
|
|
460
|
+
font: inherit;
|
|
461
|
+
color: var(--meowdown-accent-contrast);
|
|
462
|
+
background: var(--meowdown-accent);
|
|
463
|
+
cursor: pointer;
|
|
464
|
+
border: 0;
|
|
465
|
+
border-radius: .5rem;
|
|
466
|
+
padding: .375rem .625rem;
|
|
467
|
+
font-weight: 500;
|
|
468
|
+
|
|
469
|
+
@media (pointer: coarse) {
|
|
470
|
+
min-height: 2.75rem;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
.meow_ReplaceButton_IjcqKG {
|
|
475
|
+
flex: none;
|
|
476
|
+
min-height: 1.75rem;
|
|
477
|
+
padding: .25rem .625rem;
|
|
478
|
+
transition: filter .1s, transform .1s ease-out;
|
|
479
|
+
|
|
480
|
+
&:hover {
|
|
481
|
+
filter: brightness(1.05);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
&:active {
|
|
485
|
+
transform: scale(.97);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
.meow_Skeleton_IjcqKG {
|
|
490
|
+
flex-direction: column;
|
|
491
|
+
gap: .625rem;
|
|
492
|
+
padding: 0 .5rem .625rem;
|
|
493
|
+
display: flex;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
.meow_SkeletonLine_IjcqKG, .meow_SkeletonLineShort_IjcqKG {
|
|
497
|
+
background: var(--meowdown-popover-hover-bg);
|
|
498
|
+
border-radius: 999px;
|
|
499
|
+
height: .75rem;
|
|
500
|
+
animation: 1.4s ease-in-out infinite meow_pulse_IjcqKG;
|
|
501
|
+
|
|
502
|
+
@media (prefers-reduced-motion: reduce) {
|
|
503
|
+
animation: none;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
.meow_SkeletonLine_IjcqKG {
|
|
508
|
+
width: 90%;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
.meow_SkeletonLineShort_IjcqKG {
|
|
512
|
+
width: 70%;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
@keyframes meow_pulse_IjcqKG {
|
|
516
|
+
50% {
|
|
517
|
+
opacity: .45;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
.meow_Form_IjcqKG {
|
|
522
|
+
flex-direction: column;
|
|
523
|
+
gap: .625rem;
|
|
524
|
+
padding: .75rem;
|
|
525
|
+
display: flex;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
.meow_Field_IjcqKG {
|
|
529
|
+
flex-direction: column;
|
|
530
|
+
gap: .25rem;
|
|
531
|
+
display: flex;
|
|
532
|
+
|
|
533
|
+
& > span {
|
|
534
|
+
color: var(--meowdown-muted);
|
|
535
|
+
font-size: .75rem;
|
|
536
|
+
font-weight: 600;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
363
540
|
.meow_Input_IjcqKG {
|
|
364
541
|
box-sizing: border-box;
|
|
365
542
|
width: 100%;
|
|
@@ -368,13 +545,43 @@
|
|
|
368
545
|
border: 1px solid var(--meowdown-border);
|
|
369
546
|
background: none;
|
|
370
547
|
border-radius: .5rem;
|
|
371
|
-
padding: .
|
|
548
|
+
padding: .5rem .625rem;
|
|
372
549
|
|
|
373
550
|
&:focus {
|
|
374
551
|
outline: 2px solid var(--meowdown-accent);
|
|
375
552
|
outline-offset: -1px;
|
|
376
553
|
}
|
|
377
554
|
}
|
|
555
|
+
|
|
556
|
+
.meow_FormActions_IjcqKG {
|
|
557
|
+
align-items: center;
|
|
558
|
+
gap: .375rem;
|
|
559
|
+
padding-top: .125rem;
|
|
560
|
+
display: flex;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
.meow_RemoveButton_IjcqKG, .meow_UseTitleButton_IjcqKG {
|
|
564
|
+
min-height: 2rem;
|
|
565
|
+
font: inherit;
|
|
566
|
+
cursor: pointer;
|
|
567
|
+
background: none;
|
|
568
|
+
border: 0;
|
|
569
|
+
border-radius: .5rem;
|
|
570
|
+
padding: .375rem .625rem;
|
|
571
|
+
|
|
572
|
+
@media (pointer: coarse) {
|
|
573
|
+
min-height: 2.75rem;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
.meow_RemoveButton_IjcqKG {
|
|
578
|
+
color: var(--meowdown-danger, #c33);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
.meow_UseTitleButton_IjcqKG {
|
|
582
|
+
color: var(--meowdown-accent);
|
|
583
|
+
margin-left: auto;
|
|
584
|
+
}
|
|
378
585
|
.meow_Positioner_DPJ5ia {
|
|
379
586
|
z-index: 50;
|
|
380
587
|
width: min(30rem, 100vw - 1rem);
|
|
@@ -420,9 +627,12 @@
|
|
|
420
627
|
}
|
|
421
628
|
|
|
422
629
|
.meow_Button_DPJ5ia {
|
|
630
|
+
font: inherit;
|
|
423
631
|
color: var(--meowdown-text);
|
|
424
632
|
white-space: nowrap;
|
|
425
633
|
cursor: pointer;
|
|
634
|
+
background: none;
|
|
635
|
+
border: 0;
|
|
426
636
|
border-radius: .5rem;
|
|
427
637
|
align-items: center;
|
|
428
638
|
padding: .25rem .625rem;
|
|
@@ -434,10 +644,12 @@
|
|
|
434
644
|
}
|
|
435
645
|
|
|
436
646
|
.meow_AcceptButton_DPJ5ia {
|
|
647
|
+
font: inherit;
|
|
437
648
|
color: var(--meowdown-popover-bg);
|
|
438
649
|
background: var(--meowdown-accent);
|
|
439
650
|
white-space: nowrap;
|
|
440
651
|
cursor: pointer;
|
|
652
|
+
border: 0;
|
|
441
653
|
border-radius: .5rem;
|
|
442
654
|
align-items: center;
|
|
443
655
|
padding: .25rem .625rem;
|
|
@@ -497,8 +709,11 @@
|
|
|
497
709
|
|
|
498
710
|
.meow_Item_2_4Zjq {
|
|
499
711
|
text-align: left;
|
|
712
|
+
font: inherit;
|
|
500
713
|
color: var(--meowdown-text);
|
|
501
714
|
cursor: pointer;
|
|
715
|
+
background: none;
|
|
716
|
+
border: 0;
|
|
502
717
|
border-radius: .5rem;
|
|
503
718
|
align-items: baseline;
|
|
504
719
|
gap: .5rem;
|
|
@@ -794,16 +1009,16 @@
|
|
|
794
1009
|
.meow_Popup_HMEwgW {
|
|
795
1010
|
box-sizing: border-box;
|
|
796
1011
|
pointer-events: none;
|
|
797
|
-
border: 1px solid var(--meowdown-border);
|
|
1012
|
+
border: 1px solid var(--meowdown-hover-card-border);
|
|
1013
|
+
border-radius: var(--meowdown-hover-card-radius);
|
|
798
1014
|
background: var(--meowdown-popover-bg);
|
|
799
1015
|
width: min(20rem, 100vw - 1rem);
|
|
800
1016
|
max-height: min(12rem, 100vh - 1rem);
|
|
1017
|
+
box-shadow: var(--meowdown-hover-card-shadow);
|
|
801
1018
|
transform-origin: var(--transform-origin);
|
|
802
|
-
border-radius: .75rem;
|
|
803
1019
|
outline: none;
|
|
804
1020
|
transition: opacity .15s, transform .15s;
|
|
805
1021
|
display: flex;
|
|
806
|
-
box-shadow: 0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;
|
|
807
1022
|
}
|
|
808
1023
|
|
|
809
1024
|
.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.1",
|
|
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.1"
|
|
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"
|