@meowdown/react 0.33.1 → 0.35.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 +2 -1
- package/dist/index.js +92 -17
- package/dist/style.css +11 -1
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -226,7 +226,8 @@ interface EditorProps {
|
|
|
226
226
|
selectionMenuAffordance?: boolean;
|
|
227
227
|
/**
|
|
228
228
|
* Extra controls rendered in the pending-replacement preview footer, next to
|
|
229
|
-
* the built-in
|
|
229
|
+
* the built-in accept ("Replace selection" / "Insert below", per the staged
|
|
230
|
+
* mode) and Discard buttons (e.g. a retry button).
|
|
230
231
|
*/
|
|
231
232
|
pendingReplacementActions?: ReactNode;
|
|
232
233
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { clsx } from "clsx/lite";
|
|
2
2
|
import { Fragment, createElement, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
|
|
3
|
-
import { codeBlockLanguages, defaultResolveImageUrl, defineBulletAfterHeading, defineEditorExtension, defineEmbedPaste, defineExitBoundaryHandler, defineFileClickHandler, defineFilePaste, defineFileView, defineFollowLinkHandler, defineHTMLPaste, defineImage, defineImageClickHandler, defineLinkClickHandler, defineLinkEditKeymap, defineLinkHoverHandler,
|
|
3
|
+
import { codeBlockLanguages, defaultResolveImageUrl, defineBulletAfterHeading, defineEditorExtension, defineEmbedPaste, defineExitBoundaryHandler, defineFileClickHandler, defineFilePaste, defineFileView, defineFollowLinkHandler, defineHTMLPaste, defineImage, defineImageClickHandler, defineLinkClickHandler, defineLinkEditKeymap, defineLinkHoverHandler, defineMarkdownCopy, definePendingReplacementHandler, definePlaceholder, defineReadonly, defineSpellCheckPlugin, defineTagClickHandler, defineWikilinkClickHandler, defineWikilinkTrigger, docToMarkdown, getCodeTokens, getMarkBuilders, getPendingReplacement, getSelectedText, getTableColumnAlign, getVirtualElementFromRange, inlineTextToMarkChunks, isSelectionInTableCell, listenForTweetHeight, markdownToDoc, matchEmbed } 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";
|
|
@@ -217,9 +217,10 @@ function DropIndicator$1() {
|
|
|
217
217
|
//#endregion
|
|
218
218
|
//#region src/components/editor-extensions.tsx
|
|
219
219
|
function EditorExtensions({ markMode, onDocChange, onWikilinkClick, onLinkClick, onTagClick, onExitBoundary, resolveImageUrl, resolveFileInfo, onFileClick, onFilePaste, onFileSaveError, onImageClick, embedPaste, bulletAfterHeading, placeholder, readOnly, wikilinkEnabled, spellCheck }) {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
220
|
+
const editor = useEditor$1();
|
|
221
|
+
useEffect(() => {
|
|
222
|
+
editor.commands.setMarkMode(markMode);
|
|
223
|
+
}, [editor, markMode]);
|
|
223
224
|
useExtension$1(useMemo(() => {
|
|
224
225
|
return readOnly ? defineReadonly() : null;
|
|
225
226
|
}, [readOnly]));
|
|
@@ -577,10 +578,27 @@ var pending_replacement_preview_module_default = {
|
|
|
577
578
|
//#endregion
|
|
578
579
|
//#region src/components/pending-replacement-preview.tsx
|
|
579
580
|
/**
|
|
581
|
+
* Vertical room (px) the popover needs under its anchor: the text area's
|
|
582
|
+
* 14rem max-height plus the footer, borders, and the anchor offset.
|
|
583
|
+
*/
|
|
584
|
+
const PREVIEW_CLEARANCE = 320;
|
|
585
|
+
/** Minimum gap (px) kept above the anchor line when scrolling to make room. */
|
|
586
|
+
const SCROLL_TOP_MARGIN = 16;
|
|
587
|
+
/** The nearest ancestor that can scroll vertically, or the page scroller. */
|
|
588
|
+
function closestScrollable(element) {
|
|
589
|
+
for (let node = element.parentElement; node; node = node.parentElement) {
|
|
590
|
+
const { overflowY } = getComputedStyle(node);
|
|
591
|
+
if (/(auto|scroll|overlay)/.test(overflowY) && node.scrollHeight > node.clientHeight) return node;
|
|
592
|
+
}
|
|
593
|
+
return document.scrollingElement;
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
580
596
|
* The preview for a staged (pending) replacement: a popover anchored to the
|
|
581
|
-
* source range showing the accumulated text, with
|
|
582
|
-
*
|
|
583
|
-
*
|
|
597
|
+
* end of the source range showing the accumulated text, with a Discard control
|
|
598
|
+
* and an accept control labeled by what accepting does ("Replace selection" or
|
|
599
|
+
* "Insert below", per the staged mode), plus a host-provided `actions` slot.
|
|
600
|
+
* Dismissing the popover (Escape or an outside press) discards the stage; the
|
|
601
|
+
* document is only touched on accept.
|
|
584
602
|
*/
|
|
585
603
|
function PendingReplacementPreview({ actions, onResolve }) {
|
|
586
604
|
const editor = useEditor$1();
|
|
@@ -594,19 +612,35 @@ function PendingReplacementPreview({ actions, onResolve }) {
|
|
|
594
612
|
}
|
|
595
613
|
});
|
|
596
614
|
}, [onResolve]));
|
|
597
|
-
const from = pending?.from;
|
|
598
615
|
const to = pending?.to;
|
|
599
616
|
const anchor = useMemo(() => {
|
|
600
|
-
if (
|
|
617
|
+
if (to == null) return;
|
|
601
618
|
return getVirtualElementFromRange(editor.view, {
|
|
602
|
-
from,
|
|
619
|
+
from: to,
|
|
603
620
|
to
|
|
604
621
|
});
|
|
605
|
-
}, [
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
622
|
+
}, [to, editor]);
|
|
623
|
+
const staged = pending !== null;
|
|
624
|
+
useEffect(() => {
|
|
625
|
+
if (!staged) return;
|
|
626
|
+
const view = editor.view;
|
|
627
|
+
const position = getPendingReplacement(view.state)?.to;
|
|
628
|
+
if (position == null) return;
|
|
629
|
+
const clearanceBottom = window.innerHeight - PREVIEW_CLEARANCE;
|
|
630
|
+
let coords = view.coordsAtPos(position);
|
|
631
|
+
if (coords.top >= 0 && coords.bottom <= clearanceBottom) return;
|
|
632
|
+
const { node } = view.domAtPos(position);
|
|
633
|
+
const element = node instanceof Element ? node : node.parentElement;
|
|
634
|
+
if (!element) return;
|
|
635
|
+
element.scrollIntoView({ block: "center" });
|
|
636
|
+
coords = view.coordsAtPos(position);
|
|
637
|
+
const overflow = coords.bottom - clearanceBottom;
|
|
638
|
+
const nudge = Math.min(overflow, Math.max(0, coords.top - SCROLL_TOP_MARGIN));
|
|
639
|
+
if (nudge > 0) {
|
|
640
|
+
const scroller = closestScrollable(element);
|
|
641
|
+
if (scroller) scroller.scrollTop += nudge;
|
|
642
|
+
}
|
|
643
|
+
}, [staged, editor]);
|
|
610
644
|
if (!pending) return null;
|
|
611
645
|
const discard = () => {
|
|
612
646
|
editor.commands.discardPendingReplacement();
|
|
@@ -656,7 +690,7 @@ function PendingReplacementPreview({ actions, onResolve }) {
|
|
|
656
690
|
"data-testid": "pending-replacement-accept",
|
|
657
691
|
disabled: !pending.text.trim(),
|
|
658
692
|
onClick: accept,
|
|
659
|
-
children: "
|
|
693
|
+
children: pending.mode === "replace" ? "Replace selection" : "Insert below"
|
|
660
694
|
})
|
|
661
695
|
]
|
|
662
696
|
})]
|
|
@@ -1037,7 +1071,13 @@ var table_handle_module_default = {
|
|
|
1037
1071
|
//#region src/components/table-handle.tsx
|
|
1038
1072
|
function getTableHandleState(editor) {
|
|
1039
1073
|
const commands = editor.commands;
|
|
1074
|
+
const columnAlign = getTableColumnAlign(editor.state);
|
|
1040
1075
|
return {
|
|
1076
|
+
columnAlign,
|
|
1077
|
+
setTableColumnAlign: {
|
|
1078
|
+
canExec: commands.setTableColumnAlign.canExec("left"),
|
|
1079
|
+
command: (align) => commands.setTableColumnAlign(columnAlign === align ? null : align)
|
|
1080
|
+
},
|
|
1041
1081
|
addTableColumnBefore: {
|
|
1042
1082
|
canExec: commands.addTableColumnBefore.canExec(),
|
|
1043
1083
|
command: () => commands.addTableColumnBefore()
|
|
@@ -1072,6 +1112,21 @@ function getTableHandleState(editor) {
|
|
|
1072
1112
|
}
|
|
1073
1113
|
};
|
|
1074
1114
|
}
|
|
1115
|
+
const COLUMN_ALIGN_LABELS = {
|
|
1116
|
+
left: "Align Left",
|
|
1117
|
+
center: "Align Center",
|
|
1118
|
+
right: "Align Right"
|
|
1119
|
+
};
|
|
1120
|
+
function ColumnAlignMenuItem({ align, columnAlign, onSelect }) {
|
|
1121
|
+
const active = columnAlign === align;
|
|
1122
|
+
return /* @__PURE__ */ jsxs(MenuItem, {
|
|
1123
|
+
className: table_handle_module_default.MenuItem,
|
|
1124
|
+
"data-testid": `table-align-${align}`,
|
|
1125
|
+
"data-active": active ? "" : void 0,
|
|
1126
|
+
onSelect,
|
|
1127
|
+
children: [/* @__PURE__ */ jsx("span", { children: COLUMN_ALIGN_LABELS[align] }), active && /* @__PURE__ */ jsx(CheckIcon, {})]
|
|
1128
|
+
});
|
|
1129
|
+
}
|
|
1075
1130
|
function TableHandle() {
|
|
1076
1131
|
const state = useEditorDerivedValue(getTableHandleState);
|
|
1077
1132
|
return /* @__PURE__ */ jsxs(TableHandleRoot, { children: [
|
|
@@ -1103,6 +1158,23 @@ function TableHandle() {
|
|
|
1103
1158
|
onSelect: state.addTableColumnAfter.command,
|
|
1104
1159
|
children: /* @__PURE__ */ jsx("span", { children: "Insert Right" })
|
|
1105
1160
|
}),
|
|
1161
|
+
state.setTableColumnAlign.canExec && /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
1162
|
+
/* @__PURE__ */ jsx(ColumnAlignMenuItem, {
|
|
1163
|
+
align: "left",
|
|
1164
|
+
columnAlign: state.columnAlign,
|
|
1165
|
+
onSelect: () => state.setTableColumnAlign.command("left")
|
|
1166
|
+
}),
|
|
1167
|
+
/* @__PURE__ */ jsx(ColumnAlignMenuItem, {
|
|
1168
|
+
align: "center",
|
|
1169
|
+
columnAlign: state.columnAlign,
|
|
1170
|
+
onSelect: () => state.setTableColumnAlign.command("center")
|
|
1171
|
+
}),
|
|
1172
|
+
/* @__PURE__ */ jsx(ColumnAlignMenuItem, {
|
|
1173
|
+
align: "right",
|
|
1174
|
+
columnAlign: state.columnAlign,
|
|
1175
|
+
onSelect: () => state.setTableColumnAlign.command("right")
|
|
1176
|
+
})
|
|
1177
|
+
] }),
|
|
1106
1178
|
state.deleteCellSelection.canExec && /* @__PURE__ */ jsxs(MenuItem, {
|
|
1107
1179
|
className: table_handle_module_default.MenuItem,
|
|
1108
1180
|
"data-testid": "table-clear-column",
|
|
@@ -1333,7 +1405,10 @@ function resolveSelection(doc, selection) {
|
|
|
1333
1405
|
}
|
|
1334
1406
|
function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onSlashMenuSearch, onTagSearch, onWikilinkSearch, onSelectionMenuSearch, selectionMenuAffordance = true, pendingReplacementActions, onPendingReplacementResolve, onWikilinkClick, onLinkClick, onLinkCopy, onTagClick, onExitBoundary, resolveImageUrl, resolveFileLink, resolveFileInfo, onFileClick, onFilePaste, onFileSaveError, onImageClick, embedPaste, bulletAfterHeading, frontmatter = false, blockHandle = true, placeholder, readOnly, spellCheck, timeFormat, editorClassName, ref, children }) {
|
|
1335
1407
|
const [editor] = useState(() => {
|
|
1336
|
-
const editor = createEditor({ extension: union(defineEditorExtension({
|
|
1408
|
+
const editor = createEditor({ extension: union(defineEditorExtension({
|
|
1409
|
+
resolveFileLink,
|
|
1410
|
+
markMode
|
|
1411
|
+
}), defineCodeBlockView()) });
|
|
1337
1412
|
if (initialMarkdown) editor.setContent(markdownToDoc(initialMarkdown, {
|
|
1338
1413
|
nodes: editor.nodes,
|
|
1339
1414
|
frontmatter
|
package/dist/style.css
CHANGED
|
@@ -346,7 +346,7 @@
|
|
|
346
346
|
}
|
|
347
347
|
.meow_Positioner_DPJ5ia {
|
|
348
348
|
z-index: 50;
|
|
349
|
-
width: min(
|
|
349
|
+
width: min(30rem, 100vw - 1rem);
|
|
350
350
|
display: block;
|
|
351
351
|
}
|
|
352
352
|
|
|
@@ -377,6 +377,7 @@
|
|
|
377
377
|
|
|
378
378
|
.meow_Footer_DPJ5ia {
|
|
379
379
|
border-top: 1px solid var(--meowdown-border);
|
|
380
|
+
flex-wrap: wrap;
|
|
380
381
|
align-items: center;
|
|
381
382
|
gap: .25rem;
|
|
382
383
|
padding: .375rem;
|
|
@@ -389,6 +390,7 @@
|
|
|
389
390
|
|
|
390
391
|
.meow_Button_DPJ5ia {
|
|
391
392
|
color: var(--meowdown-text);
|
|
393
|
+
white-space: nowrap;
|
|
392
394
|
cursor: pointer;
|
|
393
395
|
border-radius: .5rem;
|
|
394
396
|
align-items: center;
|
|
@@ -403,6 +405,7 @@
|
|
|
403
405
|
.meow_AcceptButton_DPJ5ia {
|
|
404
406
|
color: var(--meowdown-popover-bg);
|
|
405
407
|
background: var(--meowdown-accent);
|
|
408
|
+
white-space: nowrap;
|
|
406
409
|
cursor: pointer;
|
|
407
410
|
border-radius: .5rem;
|
|
408
411
|
align-items: center;
|
|
@@ -737,6 +740,13 @@
|
|
|
737
740
|
opacity: .8;
|
|
738
741
|
font-size: .75rem;
|
|
739
742
|
}
|
|
743
|
+
|
|
744
|
+
& svg {
|
|
745
|
+
width: 1rem;
|
|
746
|
+
height: 1rem;
|
|
747
|
+
color: var(--meowdown-muted);
|
|
748
|
+
display: block;
|
|
749
|
+
}
|
|
740
750
|
}
|
|
741
751
|
.meowdown {
|
|
742
752
|
flex-direction: column;
|
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.35.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -20,12 +20,12 @@
|
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@base-ui/react": "^1.6.0",
|
|
22
22
|
"@ocavue/utils": "^1.7.0",
|
|
23
|
-
"@prosekit/core": "^0.13.0-beta.
|
|
24
|
-
"@prosekit/pm": "^0.1.19-beta.
|
|
25
|
-
"@prosekit/react": "^0.8.0-beta.
|
|
23
|
+
"@prosekit/core": "^0.13.0-beta.5",
|
|
24
|
+
"@prosekit/pm": "^0.1.19-beta.2",
|
|
25
|
+
"@prosekit/react": "^0.8.0-beta.17",
|
|
26
26
|
"clsx": "^2.1.1",
|
|
27
27
|
"lucide-react": "^1.21.0",
|
|
28
|
-
"@meowdown/core": "0.
|
|
28
|
+
"@meowdown/core": "0.35.0"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"react": "^19.0.0",
|