@stream-mdx/react 0.4.0 → 0.5.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/CHANGELOG.md +14 -4
- package/README.md +65 -15
- package/dist/components/bottom-stick-scroll-area.cjs +344 -0
- package/dist/components/bottom-stick-scroll-area.d.cts +36 -0
- package/dist/components/bottom-stick-scroll-area.d.ts +36 -0
- package/dist/components/bottom-stick-scroll-area.mjs +320 -0
- package/dist/components/index.cjs +503 -172
- package/dist/components/index.d.cts +3 -1
- package/dist/components/index.d.ts +3 -1
- package/dist/components/index.mjs +350 -22
- package/dist/{index-D2MYusAM.d.cts → index-BVhp_pcF.d.ts} +3 -0
- package/dist/{index-D2MYusAM.d.ts → index-EaeouYp2.d.cts} +3 -0
- package/dist/index.cjs +1472 -486
- package/dist/index.d.cts +6 -4
- package/dist/index.d.ts +6 -4
- package/dist/index.mjs +1256 -272
- package/dist/mdx-client.cjs +1 -1
- package/dist/mdx-client.mjs +1 -1
- package/dist/mdx-coordinator.cjs +28 -7
- package/dist/mdx-coordinator.d.cts +2 -2
- package/dist/mdx-coordinator.d.ts +2 -2
- package/dist/mdx-coordinator.mjs +28 -7
- package/dist/renderer/node-views.cjs +271 -26
- package/dist/renderer/node-views.d.cts +3 -1
- package/dist/renderer/node-views.d.ts +3 -1
- package/dist/renderer/node-views.mjs +272 -27
- package/dist/renderer/patch-batching.cjs +2 -0
- package/dist/renderer/patch-batching.d.cts +1 -1
- package/dist/renderer/patch-batching.d.ts +1 -1
- package/dist/renderer/patch-batching.mjs +2 -1
- package/dist/renderer/patch-commit-scheduler.cjs +82 -30
- package/dist/renderer/patch-commit-scheduler.d.cts +15 -3
- package/dist/renderer/patch-commit-scheduler.d.ts +15 -3
- package/dist/renderer/patch-commit-scheduler.mjs +84 -30
- package/dist/renderer/store.cjs +382 -36
- package/dist/renderer/store.d.cts +3 -0
- package/dist/renderer/store.d.ts +3 -0
- package/dist/renderer/store.mjs +382 -36
- package/dist/renderer.cjs +758 -114
- package/dist/renderer.d.cts +3 -1
- package/dist/renderer.d.ts +3 -1
- package/dist/renderer.mjs +760 -116
- package/dist/server.cjs +669 -71
- package/dist/server.d.cts +5 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.mjs +670 -72
- package/dist/{streaming-markdown-DOc2uLiP.d.ts → streaming-markdown-CEI9eDZm.d.ts} +3 -1
- package/dist/{streaming-markdown-D-JcByd9.d.cts → streaming-markdown-DRisClXb.d.cts} +3 -1
- package/dist/streaming-markdown.cjs +788 -121
- package/dist/streaming-markdown.d.cts +4 -2
- package/dist/streaming-markdown.d.ts +4 -2
- package/dist/streaming-markdown.mjs +790 -123
- package/dist/utils/inline-html.d.cts +3 -1
- package/dist/utils/inline-html.d.ts +3 -1
- package/package.json +14 -3
- package/shadcn/README.md +28 -0
- package/shadcn/bottom-stick-scroll-area.tsx +358 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { BottomStickDebugState, BottomStickJumpButtonRenderState, BottomStickMode, BottomStickScrollArea, BottomStickScrollAreaProps } from './bottom-stick-scroll-area.cjs';
|
|
1
2
|
import '@stream-mdx/core';
|
|
2
3
|
import 'react';
|
|
3
|
-
export { C as ComponentRegistry, D as DefaultLinkSafetyModal, L as LinkSafetyModalProps, e as defaultBlockComponents, d as defaultInlineComponents, m as mapHtmlToReact, r as renderInlineNodes, f as renderParagraphMixedSegments } from '../index-
|
|
4
|
+
export { C as ComponentRegistry, D as DefaultLinkSafetyModal, L as LinkSafetyModalProps, e as defaultBlockComponents, d as defaultInlineComponents, m as mapHtmlToReact, r as renderInlineNodes, f as renderParagraphMixedSegments } from '../index-EaeouYp2.cjs';
|
|
5
|
+
import 'react/jsx-runtime';
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { BottomStickDebugState, BottomStickJumpButtonRenderState, BottomStickMode, BottomStickScrollArea, BottomStickScrollAreaProps } from './bottom-stick-scroll-area.js';
|
|
1
2
|
import '@stream-mdx/core';
|
|
2
3
|
import 'react';
|
|
3
|
-
export { C as ComponentRegistry, D as DefaultLinkSafetyModal, L as LinkSafetyModalProps, e as defaultBlockComponents, d as defaultInlineComponents, m as mapHtmlToReact, r as renderInlineNodes, f as renderParagraphMixedSegments } from '../index-
|
|
4
|
+
export { C as ComponentRegistry, D as DefaultLinkSafetyModal, L as LinkSafetyModalProps, e as defaultBlockComponents, d as defaultInlineComponents, m as mapHtmlToReact, r as renderInlineNodes, f as renderParagraphMixedSegments } from '../index-BVhp_pcF.js';
|
|
5
|
+
import 'react/jsx-runtime';
|
|
@@ -81,7 +81,7 @@ var init_mdx_client = __esm({
|
|
|
81
81
|
if (block.type !== "mdx") {
|
|
82
82
|
throw new Error("Block is not MDX type");
|
|
83
83
|
}
|
|
84
|
-
const cacheKey = block.id
|
|
84
|
+
const cacheKey = `${block.id}\0${block.payload.raw ?? ""}`;
|
|
85
85
|
const cachedPromise = this.cache.get(cacheKey);
|
|
86
86
|
if (cachedPromise) {
|
|
87
87
|
return cachedPromise;
|
|
@@ -384,6 +384,321 @@ var init_mdx_client = __esm({
|
|
|
384
384
|
}
|
|
385
385
|
});
|
|
386
386
|
|
|
387
|
+
// src/components/bottom-stick-scroll-area.tsx
|
|
388
|
+
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
389
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
390
|
+
var EPS_BOTTOM_PX = 2;
|
|
391
|
+
var EPS_OVERFLOW_PX = 1;
|
|
392
|
+
var DETACH_SCROLL_DELTA_PX = 1;
|
|
393
|
+
var RETURN_MIN_MS = 180;
|
|
394
|
+
var RETURN_MAX_MS = 520;
|
|
395
|
+
var RETURN_PX_PER_MS = 2.2;
|
|
396
|
+
var RETURN_SETTLE_FRAMES = 2;
|
|
397
|
+
function clamp01(value) {
|
|
398
|
+
if (value < 0) return 0;
|
|
399
|
+
if (value > 1) return 1;
|
|
400
|
+
return value;
|
|
401
|
+
}
|
|
402
|
+
function easeOutCubic(value) {
|
|
403
|
+
return 1 - (1 - value) ** 3;
|
|
404
|
+
}
|
|
405
|
+
function joinClasses(...parts) {
|
|
406
|
+
return parts.filter(Boolean).join(" ");
|
|
407
|
+
}
|
|
408
|
+
function measure(viewport) {
|
|
409
|
+
const scrollTop = viewport.scrollTop;
|
|
410
|
+
const scrollHeight = viewport.scrollHeight;
|
|
411
|
+
const clientHeight = viewport.clientHeight;
|
|
412
|
+
const maxScrollTop = Math.max(0, scrollHeight - clientHeight);
|
|
413
|
+
const distanceToBottom = Math.max(0, maxScrollTop - scrollTop);
|
|
414
|
+
const isOverflowing = scrollHeight > clientHeight + EPS_OVERFLOW_PX;
|
|
415
|
+
return { scrollTop, scrollHeight, clientHeight, maxScrollTop, distanceToBottom, isOverflowing };
|
|
416
|
+
}
|
|
417
|
+
function DefaultJumpButton({ canJump, jumpToBottom }) {
|
|
418
|
+
return /* @__PURE__ */ jsx(
|
|
419
|
+
"button",
|
|
420
|
+
{
|
|
421
|
+
type: "button",
|
|
422
|
+
onClick: jumpToBottom,
|
|
423
|
+
"aria-label": "Scroll to bottom",
|
|
424
|
+
style: {
|
|
425
|
+
pointerEvents: canJump ? "auto" : "none",
|
|
426
|
+
borderRadius: 9999,
|
|
427
|
+
border: "1px solid color-mix(in srgb, currentColor 20%, transparent)",
|
|
428
|
+
width: 40,
|
|
429
|
+
height: 40,
|
|
430
|
+
display: "grid",
|
|
431
|
+
placeItems: "center",
|
|
432
|
+
boxShadow: "0 8px 20px rgba(0,0,0,0.18)",
|
|
433
|
+
background: "color-mix(in srgb, var(--background, #fff) 92%, transparent)",
|
|
434
|
+
color: "var(--foreground, #111)",
|
|
435
|
+
cursor: canJump ? "pointer" : "default"
|
|
436
|
+
},
|
|
437
|
+
children: /* @__PURE__ */ jsx("span", { "aria-hidden": true, children: "\u2193" })
|
|
438
|
+
}
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
function BottomStickScrollArea({
|
|
442
|
+
children,
|
|
443
|
+
className,
|
|
444
|
+
viewportClassName,
|
|
445
|
+
contentClassName,
|
|
446
|
+
showJumpToBottom = true,
|
|
447
|
+
onDebugStateChange,
|
|
448
|
+
onModeChange,
|
|
449
|
+
debugDomAttributes = false,
|
|
450
|
+
renderJumpToBottom,
|
|
451
|
+
jumpContainerClassName
|
|
452
|
+
}) {
|
|
453
|
+
const viewportRef = useRef(null);
|
|
454
|
+
const contentRef = useRef(null);
|
|
455
|
+
const modeRef = useRef("STICKY_INSTANT");
|
|
456
|
+
const [mode, setMode] = useState("STICKY_INSTANT");
|
|
457
|
+
const [isOverflowing, setIsOverflowing] = useState(false);
|
|
458
|
+
const [distanceToBottom, setDistanceToBottom] = useState(0);
|
|
459
|
+
const prevScrollTopRef = useRef(0);
|
|
460
|
+
const lastProgrammaticWriteRef = useRef(null);
|
|
461
|
+
const programmaticWriteCountRef = useRef(0);
|
|
462
|
+
const pendingStickRafRef = useRef(null);
|
|
463
|
+
const stickRequestedRef = useRef(false);
|
|
464
|
+
const returnRafRef = useRef(null);
|
|
465
|
+
const returnAnimRef = useRef(null);
|
|
466
|
+
const setModeBoth = useCallback(
|
|
467
|
+
(next) => {
|
|
468
|
+
modeRef.current = next;
|
|
469
|
+
setMode(next);
|
|
470
|
+
onModeChange?.(next);
|
|
471
|
+
},
|
|
472
|
+
[onModeChange]
|
|
473
|
+
);
|
|
474
|
+
const updateDebug = useCallback(() => {
|
|
475
|
+
const viewport = viewportRef.current;
|
|
476
|
+
if (!viewport) return;
|
|
477
|
+
const m = measure(viewport);
|
|
478
|
+
if (debugDomAttributes) {
|
|
479
|
+
viewport.dataset.stickyMode = modeRef.current;
|
|
480
|
+
viewport.dataset.distanceToBottom = String(m.distanceToBottom);
|
|
481
|
+
viewport.dataset.isOverflowing = m.isOverflowing ? "1" : "0";
|
|
482
|
+
viewport.dataset.programmaticWrites = String(programmaticWriteCountRef.current);
|
|
483
|
+
}
|
|
484
|
+
onDebugStateChange?.({
|
|
485
|
+
mode: modeRef.current,
|
|
486
|
+
isOverflowing: m.isOverflowing,
|
|
487
|
+
distanceToBottom: m.distanceToBottom,
|
|
488
|
+
scrollTop: m.scrollTop,
|
|
489
|
+
maxScrollTop: m.maxScrollTop,
|
|
490
|
+
scrollHeight: m.scrollHeight,
|
|
491
|
+
clientHeight: m.clientHeight,
|
|
492
|
+
programmaticWrites: programmaticWriteCountRef.current
|
|
493
|
+
});
|
|
494
|
+
setDistanceToBottom(
|
|
495
|
+
(previous) => Math.abs(previous - m.distanceToBottom) <= 0.1 ? previous : m.distanceToBottom
|
|
496
|
+
);
|
|
497
|
+
}, [debugDomAttributes, onDebugStateChange]);
|
|
498
|
+
const writeScrollTop = useCallback((nextTop) => {
|
|
499
|
+
const viewport = viewportRef.current;
|
|
500
|
+
if (!viewport) return;
|
|
501
|
+
viewport.scrollTop = nextTop;
|
|
502
|
+
programmaticWriteCountRef.current += 1;
|
|
503
|
+
lastProgrammaticWriteRef.current = { at: performance.now(), top: nextTop };
|
|
504
|
+
}, []);
|
|
505
|
+
const cancelPendingStick = useCallback(() => {
|
|
506
|
+
if (pendingStickRafRef.current !== null) {
|
|
507
|
+
cancelAnimationFrame(pendingStickRafRef.current);
|
|
508
|
+
pendingStickRafRef.current = null;
|
|
509
|
+
}
|
|
510
|
+
stickRequestedRef.current = false;
|
|
511
|
+
}, []);
|
|
512
|
+
const cancelReturn = useCallback(() => {
|
|
513
|
+
if (returnRafRef.current !== null) {
|
|
514
|
+
cancelAnimationFrame(returnRafRef.current);
|
|
515
|
+
returnRafRef.current = null;
|
|
516
|
+
}
|
|
517
|
+
returnAnimRef.current = null;
|
|
518
|
+
}, []);
|
|
519
|
+
const stickToBottomInstant = useCallback(() => {
|
|
520
|
+
const viewport = viewportRef.current;
|
|
521
|
+
if (!viewport) return;
|
|
522
|
+
stickRequestedRef.current = true;
|
|
523
|
+
if (pendingStickRafRef.current !== null) return;
|
|
524
|
+
pendingStickRafRef.current = requestAnimationFrame(() => {
|
|
525
|
+
pendingStickRafRef.current = null;
|
|
526
|
+
if (!stickRequestedRef.current) return;
|
|
527
|
+
stickRequestedRef.current = false;
|
|
528
|
+
if (modeRef.current !== "STICKY_INSTANT") return;
|
|
529
|
+
const m = measure(viewport);
|
|
530
|
+
writeScrollTop(m.maxScrollTop);
|
|
531
|
+
updateDebug();
|
|
532
|
+
});
|
|
533
|
+
}, [updateDebug, writeScrollTop]);
|
|
534
|
+
const startReturnToBottomSmooth = useCallback(() => {
|
|
535
|
+
const viewport = viewportRef.current;
|
|
536
|
+
if (!viewport) return;
|
|
537
|
+
cancelPendingStick();
|
|
538
|
+
cancelReturn();
|
|
539
|
+
const initial = measure(viewport);
|
|
540
|
+
if (initial.distanceToBottom <= EPS_BOTTOM_PX) {
|
|
541
|
+
setModeBoth("STICKY_INSTANT");
|
|
542
|
+
stickToBottomInstant();
|
|
543
|
+
updateDebug();
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
const durationMs = Math.max(
|
|
547
|
+
RETURN_MIN_MS,
|
|
548
|
+
Math.min(RETURN_MAX_MS, initial.distanceToBottom / RETURN_PX_PER_MS)
|
|
549
|
+
);
|
|
550
|
+
returnAnimRef.current = {
|
|
551
|
+
startTime: performance.now(),
|
|
552
|
+
startTop: initial.scrollTop,
|
|
553
|
+
durationMs,
|
|
554
|
+
settleFrames: 0
|
|
555
|
+
};
|
|
556
|
+
setModeBoth("RETURNING_SMOOTH");
|
|
557
|
+
const tick = (now2) => {
|
|
558
|
+
const viewportCurrent = viewportRef.current;
|
|
559
|
+
const anim = returnAnimRef.current;
|
|
560
|
+
if (!viewportCurrent || !anim || modeRef.current !== "RETURNING_SMOOTH") {
|
|
561
|
+
cancelReturn();
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
const before = measure(viewportCurrent);
|
|
565
|
+
const progress = clamp01((now2 - anim.startTime) / anim.durationMs);
|
|
566
|
+
const eased = easeOutCubic(progress);
|
|
567
|
+
const targetBottom = before.maxScrollTop;
|
|
568
|
+
let nextTop = anim.startTop + (targetBottom - anim.startTop) * eased;
|
|
569
|
+
if (nextTop < before.scrollTop) {
|
|
570
|
+
nextTop = before.scrollTop;
|
|
571
|
+
}
|
|
572
|
+
writeScrollTop(nextTop);
|
|
573
|
+
const after = measure(viewportCurrent);
|
|
574
|
+
if (after.distanceToBottom <= EPS_BOTTOM_PX) {
|
|
575
|
+
anim.settleFrames += 1;
|
|
576
|
+
} else {
|
|
577
|
+
anim.settleFrames = 0;
|
|
578
|
+
}
|
|
579
|
+
const doneByTime = progress >= 1;
|
|
580
|
+
const doneBySettle = anim.settleFrames >= RETURN_SETTLE_FRAMES && progress >= 0.6;
|
|
581
|
+
if (doneByTime && doneBySettle) {
|
|
582
|
+
cancelReturn();
|
|
583
|
+
setModeBoth("STICKY_INSTANT");
|
|
584
|
+
stickToBottomInstant();
|
|
585
|
+
updateDebug();
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
updateDebug();
|
|
589
|
+
returnRafRef.current = requestAnimationFrame(tick);
|
|
590
|
+
};
|
|
591
|
+
returnRafRef.current = requestAnimationFrame(tick);
|
|
592
|
+
}, [cancelPendingStick, cancelReturn, setModeBoth, stickToBottomInstant, updateDebug, writeScrollTop]);
|
|
593
|
+
const onViewportScroll = useCallback(
|
|
594
|
+
(event) => {
|
|
595
|
+
const viewport = event.currentTarget;
|
|
596
|
+
const m = measure(viewport);
|
|
597
|
+
setIsOverflowing((previous) => previous === m.isOverflowing ? previous : m.isOverflowing);
|
|
598
|
+
const previousTop = prevScrollTopRef.current;
|
|
599
|
+
const delta = m.scrollTop - previousTop;
|
|
600
|
+
const lastWrite = lastProgrammaticWriteRef.current;
|
|
601
|
+
const wroteRecently = lastWrite !== null && performance.now() - lastWrite.at < 60;
|
|
602
|
+
const isLikelyOwnWrite = wroteRecently && lastWrite !== null && Math.abs(m.scrollTop - lastWrite.top) <= 2;
|
|
603
|
+
if (modeRef.current === "RETURNING_SMOOTH") {
|
|
604
|
+
if (!isLikelyOwnWrite && delta < -DETACH_SCROLL_DELTA_PX) {
|
|
605
|
+
cancelReturn();
|
|
606
|
+
setModeBoth("DETACHED");
|
|
607
|
+
}
|
|
608
|
+
} else if (modeRef.current === "STICKY_INSTANT") {
|
|
609
|
+
if (!isLikelyOwnWrite && delta < -DETACH_SCROLL_DELTA_PX && m.isOverflowing) {
|
|
610
|
+
cancelPendingStick();
|
|
611
|
+
setModeBoth("DETACHED");
|
|
612
|
+
}
|
|
613
|
+
} else if (modeRef.current === "DETACHED") {
|
|
614
|
+
if (m.distanceToBottom <= EPS_BOTTOM_PX) {
|
|
615
|
+
setModeBoth("STICKY_INSTANT");
|
|
616
|
+
stickToBottomInstant();
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
prevScrollTopRef.current = m.scrollTop;
|
|
620
|
+
updateDebug();
|
|
621
|
+
},
|
|
622
|
+
[cancelPendingStick, cancelReturn, setModeBoth, stickToBottomInstant, updateDebug]
|
|
623
|
+
);
|
|
624
|
+
useEffect(() => {
|
|
625
|
+
const viewport = viewportRef.current;
|
|
626
|
+
const content = contentRef.current;
|
|
627
|
+
if (!viewport || !content) return;
|
|
628
|
+
const observer = new ResizeObserver(() => {
|
|
629
|
+
const m = measure(viewport);
|
|
630
|
+
setIsOverflowing((previous) => previous === m.isOverflowing ? previous : m.isOverflowing);
|
|
631
|
+
if (modeRef.current === "STICKY_INSTANT") {
|
|
632
|
+
stickToBottomInstant();
|
|
633
|
+
}
|
|
634
|
+
updateDebug();
|
|
635
|
+
});
|
|
636
|
+
observer.observe(content);
|
|
637
|
+
observer.observe(viewport);
|
|
638
|
+
return () => observer.disconnect();
|
|
639
|
+
}, [stickToBottomInstant, updateDebug]);
|
|
640
|
+
useLayoutEffect(() => {
|
|
641
|
+
const viewport = viewportRef.current;
|
|
642
|
+
if (!viewport) return;
|
|
643
|
+
setModeBoth("STICKY_INSTANT");
|
|
644
|
+
const initial = measure(viewport);
|
|
645
|
+
writeScrollTop(initial.maxScrollTop);
|
|
646
|
+
prevScrollTopRef.current = viewport.scrollTop;
|
|
647
|
+
setIsOverflowing(initial.isOverflowing);
|
|
648
|
+
setDistanceToBottom(initial.distanceToBottom);
|
|
649
|
+
updateDebug();
|
|
650
|
+
}, [setModeBoth, updateDebug, writeScrollTop]);
|
|
651
|
+
useEffect(() => {
|
|
652
|
+
return () => {
|
|
653
|
+
cancelPendingStick();
|
|
654
|
+
cancelReturn();
|
|
655
|
+
};
|
|
656
|
+
}, [cancelPendingStick, cancelReturn]);
|
|
657
|
+
const canJump = isOverflowing && mode === "DETACHED";
|
|
658
|
+
const jumpButton = renderJumpToBottom?.({
|
|
659
|
+
mode,
|
|
660
|
+
canJump,
|
|
661
|
+
isOverflowing,
|
|
662
|
+
distanceToBottom,
|
|
663
|
+
jumpToBottom: startReturnToBottomSmooth
|
|
664
|
+
}) ?? /* @__PURE__ */ jsx(DefaultJumpButton, { canJump, jumpToBottom: startReturnToBottomSmooth });
|
|
665
|
+
const jumpContainerClassNameBase = "pointer-events-none absolute z-20";
|
|
666
|
+
const jumpContainerStyle = {
|
|
667
|
+
position: "absolute",
|
|
668
|
+
zIndex: 20,
|
|
669
|
+
left: 0,
|
|
670
|
+
right: 0,
|
|
671
|
+
bottom: 12,
|
|
672
|
+
display: "flex",
|
|
673
|
+
justifyContent: "center",
|
|
674
|
+
opacity: canJump ? 1 : 0,
|
|
675
|
+
transform: canJump ? "translateY(0px)" : "translateY(4px)",
|
|
676
|
+
transition: "opacity 150ms ease, transform 150ms ease",
|
|
677
|
+
pointerEvents: "none"
|
|
678
|
+
};
|
|
679
|
+
return /* @__PURE__ */ jsxs("div", { className: joinClasses("relative h-full w-full overflow-hidden", className), children: [
|
|
680
|
+
/* @__PURE__ */ jsx(
|
|
681
|
+
"div",
|
|
682
|
+
{
|
|
683
|
+
ref: viewportRef,
|
|
684
|
+
className: joinClasses("h-full w-full overflow-auto", viewportClassName),
|
|
685
|
+
onScroll: onViewportScroll,
|
|
686
|
+
"data-testid": "sticky-scroll-viewport",
|
|
687
|
+
children: /* @__PURE__ */ jsx("div", { ref: contentRef, className: joinClasses("flex min-h-full w-full flex-col", contentClassName), children })
|
|
688
|
+
}
|
|
689
|
+
),
|
|
690
|
+
showJumpToBottom ? /* @__PURE__ */ jsx(
|
|
691
|
+
"div",
|
|
692
|
+
{
|
|
693
|
+
className: joinClasses(jumpContainerClassNameBase, jumpContainerClassName),
|
|
694
|
+
style: jumpContainerStyle,
|
|
695
|
+
"aria-hidden": !canJump,
|
|
696
|
+
children: /* @__PURE__ */ jsx("div", { className: canJump ? "pointer-events-auto" : "pointer-events-none", children: jumpButton })
|
|
697
|
+
}
|
|
698
|
+
) : null
|
|
699
|
+
] });
|
|
700
|
+
}
|
|
701
|
+
|
|
387
702
|
// src/components/index.ts
|
|
388
703
|
import { createTrustedHTML, sanitizeHTML } from "@stream-mdx/core";
|
|
389
704
|
|
|
@@ -437,11 +752,11 @@ function loadMdxRuntime() {
|
|
|
437
752
|
}
|
|
438
753
|
|
|
439
754
|
// src/renderer/use-deferred-render.ts
|
|
440
|
-
import { useEffect, useState } from "react";
|
|
755
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
441
756
|
function useDeferredRender(ref, options) {
|
|
442
757
|
const enabled = options?.enabled ?? true;
|
|
443
|
-
const [shouldRender, setShouldRender] =
|
|
444
|
-
|
|
758
|
+
const [shouldRender, setShouldRender] = useState2(!enabled);
|
|
759
|
+
useEffect2(() => {
|
|
445
760
|
if (!enabled) {
|
|
446
761
|
setShouldRender(true);
|
|
447
762
|
return;
|
|
@@ -766,12 +1081,12 @@ var INLINE_ELEMENTS = /* @__PURE__ */ new Set([
|
|
|
766
1081
|
]);
|
|
767
1082
|
|
|
768
1083
|
// src/components/link-safety-modal.tsx
|
|
769
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
1084
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
770
1085
|
var DefaultLinkSafetyModal = ({ url, isOpen, isChecking, onClose, onConfirm, onCopy }) => {
|
|
771
1086
|
if (!isOpen) {
|
|
772
1087
|
return null;
|
|
773
1088
|
}
|
|
774
|
-
return /* @__PURE__ */
|
|
1089
|
+
return /* @__PURE__ */ jsx2(
|
|
775
1090
|
"div",
|
|
776
1091
|
{
|
|
777
1092
|
className: "stream-mdx-link-modal-backdrop",
|
|
@@ -789,7 +1104,7 @@ var DefaultLinkSafetyModal = ({ url, isOpen, isChecking, onClose, onConfirm, onC
|
|
|
789
1104
|
padding: "24px"
|
|
790
1105
|
},
|
|
791
1106
|
onClick: onClose,
|
|
792
|
-
children: /* @__PURE__ */
|
|
1107
|
+
children: /* @__PURE__ */ jsxs2(
|
|
793
1108
|
"div",
|
|
794
1109
|
{
|
|
795
1110
|
className: "stream-mdx-link-modal",
|
|
@@ -804,12 +1119,12 @@ var DefaultLinkSafetyModal = ({ url, isOpen, isChecking, onClose, onConfirm, onC
|
|
|
804
1119
|
},
|
|
805
1120
|
onClick: (event) => event.stopPropagation(),
|
|
806
1121
|
children: [
|
|
807
|
-
/* @__PURE__ */
|
|
808
|
-
/* @__PURE__ */
|
|
809
|
-
/* @__PURE__ */
|
|
810
|
-
/* @__PURE__ */
|
|
811
|
-
/* @__PURE__ */
|
|
812
|
-
/* @__PURE__ */
|
|
1122
|
+
/* @__PURE__ */ jsx2("div", { style: { fontWeight: 600, marginBottom: 8 }, children: "Open external link?" }),
|
|
1123
|
+
/* @__PURE__ */ jsx2("div", { style: { fontSize: 13, opacity: 0.8, wordBreak: "break-all", marginBottom: 16 }, children: url }),
|
|
1124
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: 8, justifyContent: "flex-end" }, children: [
|
|
1125
|
+
/* @__PURE__ */ jsx2("button", { type: "button", onClick: onCopy, disabled: isChecking, style: buttonStyle, children: "Copy link" }),
|
|
1126
|
+
/* @__PURE__ */ jsx2("button", { type: "button", onClick: onConfirm, disabled: isChecking, style: primaryButtonStyle, children: "Open link" }),
|
|
1127
|
+
/* @__PURE__ */ jsx2("button", { type: "button", onClick: onClose, style: buttonStyle, children: "Cancel" })
|
|
813
1128
|
] })
|
|
814
1129
|
]
|
|
815
1130
|
}
|
|
@@ -984,7 +1299,11 @@ var defaultInlineComponents = {
|
|
|
984
1299
|
const n = number ?? "?";
|
|
985
1300
|
const href = number ? `#fn:${n}` : void 0;
|
|
986
1301
|
const id = number ? `fnref:${n}` : void 0;
|
|
987
|
-
return React4.createElement(
|
|
1302
|
+
return React4.createElement(
|
|
1303
|
+
"sup",
|
|
1304
|
+
{ className: "footnote-ref" },
|
|
1305
|
+
React4.createElement("a", { href, id, "data-label": label, style: { color: "var(--foreground)", textDecoration: "underline" } }, String(n))
|
|
1306
|
+
);
|
|
988
1307
|
}
|
|
989
1308
|
};
|
|
990
1309
|
var defaultBlockComponents = {
|
|
@@ -1127,7 +1446,7 @@ var defaultBlockComponents = {
|
|
|
1127
1446
|
dangerouslySetInnerHTML: { __html: htmlString }
|
|
1128
1447
|
});
|
|
1129
1448
|
},
|
|
1130
|
-
mdx: ({ compiledRef, compiledModule, status, errorMessage
|
|
1449
|
+
mdx: ({ compiledRef, compiledModule, status, errorMessage }) => {
|
|
1131
1450
|
const [Comp, setComp] = React4.useState(null);
|
|
1132
1451
|
const [internalError, setInternalError] = React4.useState(null);
|
|
1133
1452
|
const [renderError, setRenderError] = React4.useState(null);
|
|
@@ -1228,7 +1547,6 @@ var defaultBlockComponents = {
|
|
|
1228
1547
|
const waitingForVisibility = deferHydration && !shouldHydrate && Boolean(resolvedId);
|
|
1229
1548
|
const pendingLabel = waitingForVisibility ? "MDX ready (hydrate on view)\u2026" : compileMode === "worker" ? "Compiling MDX (client)\u2026" : "Compiling MDX (server)\u2026";
|
|
1230
1549
|
const message = failureMessage ?? (compileMode === "worker" ? "MDX compilation failed in client mode. Try switching back to server rendering or restarting the stream." : "MDX compilation failed. Try restarting the stream.");
|
|
1231
|
-
const rawFallback = typeof raw === "string" && raw.trim().length > 0 ? React4.createElement("pre", { className: "markdown-mdx-fallback" }, raw) : null;
|
|
1232
1550
|
const allowRetry = Boolean(internalError || renderError);
|
|
1233
1551
|
const retryButton = allowRetry ? React4.createElement(
|
|
1234
1552
|
"button",
|
|
@@ -1240,9 +1558,10 @@ var defaultBlockComponents = {
|
|
|
1240
1558
|
"Retry hydration"
|
|
1241
1559
|
) : null;
|
|
1242
1560
|
const errorPanel = React4.createElement(
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
React4.createElement(
|
|
1561
|
+
React4.Fragment,
|
|
1562
|
+
null,
|
|
1563
|
+
React4.createElement("strong", null, "MDX failed"),
|
|
1564
|
+
React4.createElement("div", null, message)
|
|
1246
1565
|
);
|
|
1247
1566
|
if (Comp && !failureMessage) {
|
|
1248
1567
|
return React4.createElement(
|
|
@@ -1265,14 +1584,13 @@ var defaultBlockComponents = {
|
|
|
1265
1584
|
return React4.createElement(
|
|
1266
1585
|
"div",
|
|
1267
1586
|
{
|
|
1268
|
-
className: "markdown-mdx",
|
|
1587
|
+
className: "markdown-mdx error",
|
|
1269
1588
|
ref: containerRef,
|
|
1270
1589
|
"data-mdx-ref": pendingId,
|
|
1271
1590
|
"data-mdx-status": "error",
|
|
1272
1591
|
"data-mdx-mode": compileMode
|
|
1273
1592
|
},
|
|
1274
1593
|
errorPanel,
|
|
1275
|
-
rawFallback,
|
|
1276
1594
|
retryButton
|
|
1277
1595
|
);
|
|
1278
1596
|
}
|
|
@@ -1299,7 +1617,16 @@ var defaultBlockComponents = {
|
|
|
1299
1617
|
{ key: item.number, id: `fn:${item.number}` },
|
|
1300
1618
|
renderInlineNodes(item.inlines, defaultInlineComponents),
|
|
1301
1619
|
" ",
|
|
1302
|
-
React4.createElement(
|
|
1620
|
+
React4.createElement(
|
|
1621
|
+
"a",
|
|
1622
|
+
{
|
|
1623
|
+
href: `#fnref:${item.number}`,
|
|
1624
|
+
className: "footnote-backref",
|
|
1625
|
+
"aria-label": "Back to content",
|
|
1626
|
+
style: { color: "var(--foreground)", textDecoration: "underline" }
|
|
1627
|
+
},
|
|
1628
|
+
"\u21A9"
|
|
1629
|
+
)
|
|
1303
1630
|
)
|
|
1304
1631
|
);
|
|
1305
1632
|
return React4.createElement("section", { className: "footnotes" }, React4.createElement("hr", {}), React4.createElement("ol", {}, listItems));
|
|
@@ -1834,6 +2161,7 @@ var BLOCK_LEVEL_TAGS = /* @__PURE__ */ new Set([
|
|
|
1834
2161
|
"math"
|
|
1835
2162
|
]);
|
|
1836
2163
|
export {
|
|
2164
|
+
BottomStickScrollArea,
|
|
1837
2165
|
ComponentRegistry,
|
|
1838
2166
|
DefaultLinkSafetyModal,
|
|
1839
2167
|
defaultBlockComponents,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import './components/bottom-stick-scroll-area.js';
|
|
1
2
|
import { InlineNode, TokenLineV1, CompiledMdxModule, InlineHtmlDescriptor, Block, LazyTokenizationPriority, FormatAnticipationConfig, CodeHighlightingMode, CodeHighlightOutputMode, MixedContentSegment } from '@stream-mdx/core';
|
|
2
3
|
import React from 'react';
|
|
3
4
|
|
|
@@ -144,6 +145,8 @@ interface RendererConfig {
|
|
|
144
145
|
urgentQueueThreshold?: number;
|
|
145
146
|
batch?: "rAF" | "microtask" | "timeout";
|
|
146
147
|
historyLimit?: number;
|
|
148
|
+
startupMicrotaskFlushes?: number;
|
|
149
|
+
adaptiveBudgeting?: boolean;
|
|
147
150
|
};
|
|
148
151
|
}
|
|
149
152
|
interface RendererStore {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import './components/bottom-stick-scroll-area.cjs';
|
|
1
2
|
import { InlineNode, TokenLineV1, CompiledMdxModule, InlineHtmlDescriptor, Block, LazyTokenizationPriority, FormatAnticipationConfig, CodeHighlightingMode, CodeHighlightOutputMode, MixedContentSegment } from '@stream-mdx/core';
|
|
2
3
|
import React from 'react';
|
|
3
4
|
|
|
@@ -144,6 +145,8 @@ interface RendererConfig {
|
|
|
144
145
|
urgentQueueThreshold?: number;
|
|
145
146
|
batch?: "rAF" | "microtask" | "timeout";
|
|
146
147
|
historyLimit?: number;
|
|
148
|
+
startupMicrotaskFlushes?: number;
|
|
149
|
+
adaptiveBudgeting?: boolean;
|
|
147
150
|
};
|
|
148
151
|
}
|
|
149
152
|
interface RendererStore {
|