@meowdown/react 0.33.0 → 0.34.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 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 Accept and Discard buttons (e.g. a retry button).
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
@@ -493,11 +493,13 @@ function LinkMenu({ onLinkClick, onLinkCopy }) {
493
493
  let rangeFrom;
494
494
  let rangeTo;
495
495
  if (edit) {
496
- rangeFrom = edit.from;
497
- rangeTo = edit.to;
496
+ const anchorRange = edit.link?.label ?? edit;
497
+ rangeFrom = anchorRange.from;
498
+ rangeTo = anchorRange.to;
498
499
  } else if (hover) {
499
- rangeFrom = hover.unit.from;
500
- rangeTo = hover.unit.to;
500
+ const anchorRange = hover.label ?? hover.unit;
501
+ rangeFrom = anchorRange.from;
502
+ rangeTo = anchorRange.to;
501
503
  }
502
504
  const anchor = useMemo(() => {
503
505
  if (rangeFrom == null || rangeTo == null) return;
@@ -575,10 +577,27 @@ var pending_replacement_preview_module_default = {
575
577
  //#endregion
576
578
  //#region src/components/pending-replacement-preview.tsx
577
579
  /**
580
+ * Vertical room (px) the popover needs under its anchor: the text area's
581
+ * 14rem max-height plus the footer, borders, and the anchor offset.
582
+ */
583
+ const PREVIEW_CLEARANCE = 320;
584
+ /** Minimum gap (px) kept above the anchor line when scrolling to make room. */
585
+ const SCROLL_TOP_MARGIN = 16;
586
+ /** The nearest ancestor that can scroll vertically, or the page scroller. */
587
+ function closestScrollable(element) {
588
+ for (let node = element.parentElement; node; node = node.parentElement) {
589
+ const { overflowY } = getComputedStyle(node);
590
+ if (/(auto|scroll|overlay)/.test(overflowY) && node.scrollHeight > node.clientHeight) return node;
591
+ }
592
+ return document.scrollingElement;
593
+ }
594
+ /**
578
595
  * The preview for a staged (pending) replacement: a popover anchored to the
579
- * source range showing the accumulated text, with Accept and Discard controls
580
- * plus a host-provided `actions` slot. Dismissing the popover (Escape or an
581
- * outside press) discards the stage; the document is only touched on accept.
596
+ * end of the source range showing the accumulated text, with a Discard control
597
+ * and an accept control labeled by what accepting does ("Replace selection" or
598
+ * "Insert below", per the staged mode), plus a host-provided `actions` slot.
599
+ * Dismissing the popover (Escape or an outside press) discards the stage; the
600
+ * document is only touched on accept.
582
601
  */
583
602
  function PendingReplacementPreview({ actions, onResolve }) {
584
603
  const editor = useEditor$1();
@@ -592,19 +611,35 @@ function PendingReplacementPreview({ actions, onResolve }) {
592
611
  }
593
612
  });
594
613
  }, [onResolve]));
595
- const from = pending?.from;
596
614
  const to = pending?.to;
597
615
  const anchor = useMemo(() => {
598
- if (from == null || to == null) return;
616
+ if (to == null) return;
599
617
  return getVirtualElementFromRange(editor.view, {
600
- from,
618
+ from: to,
601
619
  to
602
620
  });
603
- }, [
604
- from,
605
- to,
606
- editor
607
- ]);
621
+ }, [to, editor]);
622
+ const staged = pending !== null;
623
+ useEffect(() => {
624
+ if (!staged) return;
625
+ const view = editor.view;
626
+ const position = getPendingReplacement(view.state)?.to;
627
+ if (position == null) return;
628
+ const clearanceBottom = window.innerHeight - PREVIEW_CLEARANCE;
629
+ let coords = view.coordsAtPos(position);
630
+ if (coords.top >= 0 && coords.bottom <= clearanceBottom) return;
631
+ const { node } = view.domAtPos(position);
632
+ const element = node instanceof Element ? node : node.parentElement;
633
+ if (!element) return;
634
+ element.scrollIntoView({ block: "center" });
635
+ coords = view.coordsAtPos(position);
636
+ const overflow = coords.bottom - clearanceBottom;
637
+ const nudge = Math.min(overflow, Math.max(0, coords.top - SCROLL_TOP_MARGIN));
638
+ if (nudge > 0) {
639
+ const scroller = closestScrollable(element);
640
+ if (scroller) scroller.scrollTop += nudge;
641
+ }
642
+ }, [staged, editor]);
608
643
  if (!pending) return null;
609
644
  const discard = () => {
610
645
  editor.commands.discardPendingReplacement();
@@ -654,7 +689,7 @@ function PendingReplacementPreview({ actions, onResolve }) {
654
689
  "data-testid": "pending-replacement-accept",
655
690
  disabled: !pending.text.trim(),
656
691
  onClick: accept,
657
- children: "Accept"
692
+ children: pending.mode === "replace" ? "Replace selection" : "Insert below"
658
693
  })
659
694
  ]
660
695
  })]
package/dist/style.css CHANGED
@@ -346,7 +346,7 @@
346
346
  }
347
347
  .meow_Positioner_DPJ5ia {
348
348
  z-index: 50;
349
- width: min(24rem, 100vw - 1rem);
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;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meowdown/react",
3
3
  "type": "module",
4
- "version": "0.33.0",
4
+ "version": "0.34.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.4",
24
- "@prosekit/pm": "^0.1.19-beta.1",
25
- "@prosekit/react": "^0.8.0-beta.15",
23
+ "@prosekit/core": "^0.13.0-beta.5",
24
+ "@prosekit/pm": "^0.1.19-beta.2",
25
+ "@prosekit/react": "^0.8.0-beta.16",
26
26
  "clsx": "^2.1.1",
27
27
  "lucide-react": "^1.21.0",
28
- "@meowdown/core": "0.33.0"
28
+ "@meowdown/core": "0.34.0"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "react": "^19.0.0",