@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.
Files changed (57) hide show
  1. package/CHANGELOG.md +14 -4
  2. package/README.md +65 -15
  3. package/dist/components/bottom-stick-scroll-area.cjs +344 -0
  4. package/dist/components/bottom-stick-scroll-area.d.cts +36 -0
  5. package/dist/components/bottom-stick-scroll-area.d.ts +36 -0
  6. package/dist/components/bottom-stick-scroll-area.mjs +320 -0
  7. package/dist/components/index.cjs +503 -172
  8. package/dist/components/index.d.cts +3 -1
  9. package/dist/components/index.d.ts +3 -1
  10. package/dist/components/index.mjs +350 -22
  11. package/dist/{index-D2MYusAM.d.cts → index-BVhp_pcF.d.ts} +3 -0
  12. package/dist/{index-D2MYusAM.d.ts → index-EaeouYp2.d.cts} +3 -0
  13. package/dist/index.cjs +1472 -486
  14. package/dist/index.d.cts +6 -4
  15. package/dist/index.d.ts +6 -4
  16. package/dist/index.mjs +1256 -272
  17. package/dist/mdx-client.cjs +1 -1
  18. package/dist/mdx-client.mjs +1 -1
  19. package/dist/mdx-coordinator.cjs +28 -7
  20. package/dist/mdx-coordinator.d.cts +2 -2
  21. package/dist/mdx-coordinator.d.ts +2 -2
  22. package/dist/mdx-coordinator.mjs +28 -7
  23. package/dist/renderer/node-views.cjs +271 -26
  24. package/dist/renderer/node-views.d.cts +3 -1
  25. package/dist/renderer/node-views.d.ts +3 -1
  26. package/dist/renderer/node-views.mjs +272 -27
  27. package/dist/renderer/patch-batching.cjs +2 -0
  28. package/dist/renderer/patch-batching.d.cts +1 -1
  29. package/dist/renderer/patch-batching.d.ts +1 -1
  30. package/dist/renderer/patch-batching.mjs +2 -1
  31. package/dist/renderer/patch-commit-scheduler.cjs +82 -30
  32. package/dist/renderer/patch-commit-scheduler.d.cts +15 -3
  33. package/dist/renderer/patch-commit-scheduler.d.ts +15 -3
  34. package/dist/renderer/patch-commit-scheduler.mjs +84 -30
  35. package/dist/renderer/store.cjs +382 -36
  36. package/dist/renderer/store.d.cts +3 -0
  37. package/dist/renderer/store.d.ts +3 -0
  38. package/dist/renderer/store.mjs +382 -36
  39. package/dist/renderer.cjs +758 -114
  40. package/dist/renderer.d.cts +3 -1
  41. package/dist/renderer.d.ts +3 -1
  42. package/dist/renderer.mjs +760 -116
  43. package/dist/server.cjs +669 -71
  44. package/dist/server.d.cts +5 -0
  45. package/dist/server.d.ts +5 -0
  46. package/dist/server.mjs +670 -72
  47. package/dist/{streaming-markdown-DOc2uLiP.d.ts → streaming-markdown-CEI9eDZm.d.ts} +3 -1
  48. package/dist/{streaming-markdown-D-JcByd9.d.cts → streaming-markdown-DRisClXb.d.cts} +3 -1
  49. package/dist/streaming-markdown.cjs +788 -121
  50. package/dist/streaming-markdown.d.cts +4 -2
  51. package/dist/streaming-markdown.d.ts +4 -2
  52. package/dist/streaming-markdown.mjs +790 -123
  53. package/dist/utils/inline-html.d.cts +3 -1
  54. package/dist/utils/inline-html.d.ts +3 -1
  55. package/package.json +14 -3
  56. package/shadcn/README.md +28 -0
  57. package/shadcn/bottom-stick-scroll-area.tsx +358 -0
package/dist/index.cjs CHANGED
@@ -46,11 +46,11 @@ function assignMdxChildKey(child, index) {
46
46
  if (Array.isArray(child)) {
47
47
  return child.map((entry, subIndex) => assignMdxChildKey(entry, `${index}-${subIndex}`));
48
48
  }
49
- if (import_react2.default.isValidElement(child)) {
49
+ if (import_react3.default.isValidElement(child)) {
50
50
  if (child.key !== null && child.key !== void 0) {
51
51
  return child;
52
52
  }
53
- return import_react2.default.cloneElement(child, { key: index });
53
+ return import_react3.default.cloneElement(child, { key: index });
54
54
  }
55
55
  return child;
56
56
  }
@@ -79,14 +79,14 @@ function registerInlineMdxModule(compiled) {
79
79
  dependencies: compiled.dependencies ?? []
80
80
  });
81
81
  }
82
- var import_react2, ReactJsxRuntime, withClassName, MDXClient, MDXComponentFactory, globalMDXClient, globalComponentFactory;
82
+ var import_react3, ReactJsxRuntime, withClassName, MDXClient, MDXComponentFactory, globalMDXClient, globalComponentFactory;
83
83
  var init_mdx_client = __esm({
84
84
  "src/mdx-client.ts"() {
85
85
  "use strict";
86
- import_react2 = __toESM(require("react"), 1);
86
+ import_react3 = __toESM(require("react"), 1);
87
87
  ReactJsxRuntime = __toESM(require("react/jsx-runtime"), 1);
88
88
  withClassName = (tag, className) => {
89
- return (props) => import_react2.default.createElement(tag, { className, ...props });
89
+ return (props) => import_react3.default.createElement(tag, { className, ...props });
90
90
  };
91
91
  MDXClient = class {
92
92
  constructor(compileEndpoint = "/api/mdx-compile-v2") {
@@ -103,7 +103,7 @@ var init_mdx_client = __esm({
103
103
  if (block.type !== "mdx") {
104
104
  throw new Error("Block is not MDX type");
105
105
  }
106
- const cacheKey = block.id;
106
+ const cacheKey = `${block.id}\0${block.payload.raw ?? ""}`;
107
107
  const cachedPromise = this.cache.get(cacheKey);
108
108
  if (cachedPromise) {
109
109
  return cachedPromise;
@@ -261,14 +261,14 @@ var init_mdx_client = __esm({
261
261
  const registryComponents = this.getComponents();
262
262
  const incomingComponents = props?.components;
263
263
  const mergedComponents = incomingComponents ? { ...registryComponents, ...incomingComponents } : registryComponents;
264
- return import_react2.default.createElement(MDXComponent, {
264
+ return import_react3.default.createElement(MDXComponent, {
265
265
  ...props,
266
266
  components: mergedComponents
267
267
  });
268
268
  };
269
269
  } catch (error) {
270
270
  console.error("Failed to evaluate MDX:", error);
271
- return () => import_react2.default.createElement(
271
+ return () => import_react3.default.createElement(
272
272
  "div",
273
273
  {
274
274
  className: "mdx-error"
@@ -288,7 +288,7 @@ var init_mdx_client = __esm({
288
288
  if (Array.isArray(finalProps.children)) {
289
289
  finalProps.children = finalProps.children.map((child, index) => assignMdxChildKey(child, index));
290
290
  }
291
- return import_react2.default.createElement(type, finalProps);
291
+ return import_react3.default.createElement(type, finalProps);
292
292
  };
293
293
  const runtimeJsx = typeof runtime.jsx === "function" ? runtime.jsx.bind(runtime) : createElementWithChildren;
294
294
  const runtimeJsxs = typeof runtime.jsxs === "function" ? runtime.jsxs.bind(runtime) : createElementWithChildren;
@@ -297,20 +297,20 @@ var init_mdx_client = __esm({
297
297
  jsx: runtimeJsx,
298
298
  jsxs: runtimeJsxs,
299
299
  jsxDEV: runtimeJsxDEV,
300
- Fragment: runtime.Fragment ?? import_react2.default.Fragment
300
+ Fragment: runtime.Fragment ?? import_react3.default.Fragment
301
301
  };
302
302
  return {
303
303
  __mdx_runtime: jsxRuntime,
304
- React: import_react2.default,
305
- Fragment: import_react2.default.Fragment,
306
- useState: import_react2.default.useState,
307
- useEffect: import_react2.default.useEffect,
308
- useMemo: import_react2.default.useMemo,
309
- useCallback: import_react2.default.useCallback,
310
- useRef: import_react2.default.useRef,
311
- useContext: import_react2.default.useContext,
312
- useReducer: import_react2.default.useReducer,
313
- useLayoutEffect: import_react2.default.useLayoutEffect,
304
+ React: import_react3.default,
305
+ Fragment: import_react3.default.Fragment,
306
+ useState: import_react3.default.useState,
307
+ useEffect: import_react3.default.useEffect,
308
+ useMemo: import_react3.default.useMemo,
309
+ useCallback: import_react3.default.useCallback,
310
+ useRef: import_react3.default.useRef,
311
+ useContext: import_react3.default.useContext,
312
+ useReducer: import_react3.default.useReducer,
313
+ useLayoutEffect: import_react3.default.useLayoutEffect,
314
314
  console: {
315
315
  log: console.log,
316
316
  warn: console.warn,
@@ -376,13 +376,13 @@ var init_mdx_client = __esm({
376
376
  ol: withClassName("ol", "mdx-ol"),
377
377
  li: withClassName("li", "mdx-li"),
378
378
  blockquote: withClassName("blockquote", "mdx-blockquote"),
379
- a: (props) => import_react2.default.createElement("a", {
379
+ a: (props) => import_react3.default.createElement("a", {
380
380
  className: "mdx-link",
381
381
  target: props.href?.startsWith("http") ? "_blank" : void 0,
382
382
  rel: props.href?.startsWith("http") ? "noopener noreferrer" : void 0,
383
383
  ...props
384
384
  }),
385
- img: (props) => import_react2.default.createElement("img", { className: "mdx-img", ...props }),
385
+ img: (props) => import_react3.default.createElement("img", { className: "mdx-img", ...props }),
386
386
  table: withClassName("table", "mdx-table"),
387
387
  thead: withClassName("thead", "mdx-thead"),
388
388
  tbody: withClassName("tbody", "mdx-tbody"),
@@ -409,6 +409,7 @@ var init_mdx_client = __esm({
409
409
  // src/index.ts
410
410
  var index_exports = {};
411
411
  __export(index_exports, {
412
+ BottomStickScrollArea: () => BottomStickScrollArea,
412
413
  ComponentRegistry: () => ComponentRegistry,
413
414
  DEFAULT_COALESCE_CONFIG: () => import_core3.DEFAULT_COALESCE_CONFIG,
414
415
  DEFAULT_VIRTUALIZED_CODE_CONFIG: () => DEFAULT_VIRTUALIZED_CODE_CONFIG,
@@ -434,6 +435,7 @@ __export(index_exports, {
434
435
  defaultInlineComponents: () => defaultInlineComponents,
435
436
  getMDXClient: () => getMDXClient,
436
437
  getMDXComponentFactory: () => getMDXComponentFactory,
438
+ getPatchKind: () => import_patch_batching.getPatchKind,
437
439
  isHeavyPatch: () => import_patch_batching.isHeavyPatch,
438
440
  isListPatchDebugEnabled: () => isListPatchDebugEnabled,
439
441
  mapHtmlToReact: () => mapHtmlToReact,
@@ -454,6 +456,321 @@ __export(index_exports, {
454
456
  });
455
457
  module.exports = __toCommonJS(index_exports);
456
458
 
459
+ // src/components/bottom-stick-scroll-area.tsx
460
+ var import_react = require("react");
461
+ var import_jsx_runtime = require("react/jsx-runtime");
462
+ var EPS_BOTTOM_PX = 2;
463
+ var EPS_OVERFLOW_PX = 1;
464
+ var DETACH_SCROLL_DELTA_PX = 1;
465
+ var RETURN_MIN_MS = 180;
466
+ var RETURN_MAX_MS = 520;
467
+ var RETURN_PX_PER_MS = 2.2;
468
+ var RETURN_SETTLE_FRAMES = 2;
469
+ function clamp01(value) {
470
+ if (value < 0) return 0;
471
+ if (value > 1) return 1;
472
+ return value;
473
+ }
474
+ function easeOutCubic(value) {
475
+ return 1 - (1 - value) ** 3;
476
+ }
477
+ function joinClasses(...parts) {
478
+ return parts.filter(Boolean).join(" ");
479
+ }
480
+ function measure(viewport) {
481
+ const scrollTop = viewport.scrollTop;
482
+ const scrollHeight = viewport.scrollHeight;
483
+ const clientHeight = viewport.clientHeight;
484
+ const maxScrollTop = Math.max(0, scrollHeight - clientHeight);
485
+ const distanceToBottom = Math.max(0, maxScrollTop - scrollTop);
486
+ const isOverflowing = scrollHeight > clientHeight + EPS_OVERFLOW_PX;
487
+ return { scrollTop, scrollHeight, clientHeight, maxScrollTop, distanceToBottom, isOverflowing };
488
+ }
489
+ function DefaultJumpButton({ canJump, jumpToBottom }) {
490
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
491
+ "button",
492
+ {
493
+ type: "button",
494
+ onClick: jumpToBottom,
495
+ "aria-label": "Scroll to bottom",
496
+ style: {
497
+ pointerEvents: canJump ? "auto" : "none",
498
+ borderRadius: 9999,
499
+ border: "1px solid color-mix(in srgb, currentColor 20%, transparent)",
500
+ width: 40,
501
+ height: 40,
502
+ display: "grid",
503
+ placeItems: "center",
504
+ boxShadow: "0 8px 20px rgba(0,0,0,0.18)",
505
+ background: "color-mix(in srgb, var(--background, #fff) 92%, transparent)",
506
+ color: "var(--foreground, #111)",
507
+ cursor: canJump ? "pointer" : "default"
508
+ },
509
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": true, children: "\u2193" })
510
+ }
511
+ );
512
+ }
513
+ function BottomStickScrollArea({
514
+ children,
515
+ className,
516
+ viewportClassName,
517
+ contentClassName,
518
+ showJumpToBottom = true,
519
+ onDebugStateChange,
520
+ onModeChange,
521
+ debugDomAttributes = false,
522
+ renderJumpToBottom,
523
+ jumpContainerClassName
524
+ }) {
525
+ const viewportRef = (0, import_react.useRef)(null);
526
+ const contentRef = (0, import_react.useRef)(null);
527
+ const modeRef = (0, import_react.useRef)("STICKY_INSTANT");
528
+ const [mode, setMode] = (0, import_react.useState)("STICKY_INSTANT");
529
+ const [isOverflowing, setIsOverflowing] = (0, import_react.useState)(false);
530
+ const [distanceToBottom, setDistanceToBottom] = (0, import_react.useState)(0);
531
+ const prevScrollTopRef = (0, import_react.useRef)(0);
532
+ const lastProgrammaticWriteRef = (0, import_react.useRef)(null);
533
+ const programmaticWriteCountRef = (0, import_react.useRef)(0);
534
+ const pendingStickRafRef = (0, import_react.useRef)(null);
535
+ const stickRequestedRef = (0, import_react.useRef)(false);
536
+ const returnRafRef = (0, import_react.useRef)(null);
537
+ const returnAnimRef = (0, import_react.useRef)(null);
538
+ const setModeBoth = (0, import_react.useCallback)(
539
+ (next) => {
540
+ modeRef.current = next;
541
+ setMode(next);
542
+ onModeChange?.(next);
543
+ },
544
+ [onModeChange]
545
+ );
546
+ const updateDebug = (0, import_react.useCallback)(() => {
547
+ const viewport = viewportRef.current;
548
+ if (!viewport) return;
549
+ const m = measure(viewport);
550
+ if (debugDomAttributes) {
551
+ viewport.dataset.stickyMode = modeRef.current;
552
+ viewport.dataset.distanceToBottom = String(m.distanceToBottom);
553
+ viewport.dataset.isOverflowing = m.isOverflowing ? "1" : "0";
554
+ viewport.dataset.programmaticWrites = String(programmaticWriteCountRef.current);
555
+ }
556
+ onDebugStateChange?.({
557
+ mode: modeRef.current,
558
+ isOverflowing: m.isOverflowing,
559
+ distanceToBottom: m.distanceToBottom,
560
+ scrollTop: m.scrollTop,
561
+ maxScrollTop: m.maxScrollTop,
562
+ scrollHeight: m.scrollHeight,
563
+ clientHeight: m.clientHeight,
564
+ programmaticWrites: programmaticWriteCountRef.current
565
+ });
566
+ setDistanceToBottom(
567
+ (previous) => Math.abs(previous - m.distanceToBottom) <= 0.1 ? previous : m.distanceToBottom
568
+ );
569
+ }, [debugDomAttributes, onDebugStateChange]);
570
+ const writeScrollTop = (0, import_react.useCallback)((nextTop) => {
571
+ const viewport = viewportRef.current;
572
+ if (!viewport) return;
573
+ viewport.scrollTop = nextTop;
574
+ programmaticWriteCountRef.current += 1;
575
+ lastProgrammaticWriteRef.current = { at: performance.now(), top: nextTop };
576
+ }, []);
577
+ const cancelPendingStick = (0, import_react.useCallback)(() => {
578
+ if (pendingStickRafRef.current !== null) {
579
+ cancelAnimationFrame(pendingStickRafRef.current);
580
+ pendingStickRafRef.current = null;
581
+ }
582
+ stickRequestedRef.current = false;
583
+ }, []);
584
+ const cancelReturn = (0, import_react.useCallback)(() => {
585
+ if (returnRafRef.current !== null) {
586
+ cancelAnimationFrame(returnRafRef.current);
587
+ returnRafRef.current = null;
588
+ }
589
+ returnAnimRef.current = null;
590
+ }, []);
591
+ const stickToBottomInstant = (0, import_react.useCallback)(() => {
592
+ const viewport = viewportRef.current;
593
+ if (!viewport) return;
594
+ stickRequestedRef.current = true;
595
+ if (pendingStickRafRef.current !== null) return;
596
+ pendingStickRafRef.current = requestAnimationFrame(() => {
597
+ pendingStickRafRef.current = null;
598
+ if (!stickRequestedRef.current) return;
599
+ stickRequestedRef.current = false;
600
+ if (modeRef.current !== "STICKY_INSTANT") return;
601
+ const m = measure(viewport);
602
+ writeScrollTop(m.maxScrollTop);
603
+ updateDebug();
604
+ });
605
+ }, [updateDebug, writeScrollTop]);
606
+ const startReturnToBottomSmooth = (0, import_react.useCallback)(() => {
607
+ const viewport = viewportRef.current;
608
+ if (!viewport) return;
609
+ cancelPendingStick();
610
+ cancelReturn();
611
+ const initial = measure(viewport);
612
+ if (initial.distanceToBottom <= EPS_BOTTOM_PX) {
613
+ setModeBoth("STICKY_INSTANT");
614
+ stickToBottomInstant();
615
+ updateDebug();
616
+ return;
617
+ }
618
+ const durationMs = Math.max(
619
+ RETURN_MIN_MS,
620
+ Math.min(RETURN_MAX_MS, initial.distanceToBottom / RETURN_PX_PER_MS)
621
+ );
622
+ returnAnimRef.current = {
623
+ startTime: performance.now(),
624
+ startTop: initial.scrollTop,
625
+ durationMs,
626
+ settleFrames: 0
627
+ };
628
+ setModeBoth("RETURNING_SMOOTH");
629
+ const tick = (now2) => {
630
+ const viewportCurrent = viewportRef.current;
631
+ const anim = returnAnimRef.current;
632
+ if (!viewportCurrent || !anim || modeRef.current !== "RETURNING_SMOOTH") {
633
+ cancelReturn();
634
+ return;
635
+ }
636
+ const before = measure(viewportCurrent);
637
+ const progress = clamp01((now2 - anim.startTime) / anim.durationMs);
638
+ const eased = easeOutCubic(progress);
639
+ const targetBottom = before.maxScrollTop;
640
+ let nextTop = anim.startTop + (targetBottom - anim.startTop) * eased;
641
+ if (nextTop < before.scrollTop) {
642
+ nextTop = before.scrollTop;
643
+ }
644
+ writeScrollTop(nextTop);
645
+ const after = measure(viewportCurrent);
646
+ if (after.distanceToBottom <= EPS_BOTTOM_PX) {
647
+ anim.settleFrames += 1;
648
+ } else {
649
+ anim.settleFrames = 0;
650
+ }
651
+ const doneByTime = progress >= 1;
652
+ const doneBySettle = anim.settleFrames >= RETURN_SETTLE_FRAMES && progress >= 0.6;
653
+ if (doneByTime && doneBySettle) {
654
+ cancelReturn();
655
+ setModeBoth("STICKY_INSTANT");
656
+ stickToBottomInstant();
657
+ updateDebug();
658
+ return;
659
+ }
660
+ updateDebug();
661
+ returnRafRef.current = requestAnimationFrame(tick);
662
+ };
663
+ returnRafRef.current = requestAnimationFrame(tick);
664
+ }, [cancelPendingStick, cancelReturn, setModeBoth, stickToBottomInstant, updateDebug, writeScrollTop]);
665
+ const onViewportScroll = (0, import_react.useCallback)(
666
+ (event) => {
667
+ const viewport = event.currentTarget;
668
+ const m = measure(viewport);
669
+ setIsOverflowing((previous) => previous === m.isOverflowing ? previous : m.isOverflowing);
670
+ const previousTop = prevScrollTopRef.current;
671
+ const delta = m.scrollTop - previousTop;
672
+ const lastWrite = lastProgrammaticWriteRef.current;
673
+ const wroteRecently = lastWrite !== null && performance.now() - lastWrite.at < 60;
674
+ const isLikelyOwnWrite = wroteRecently && lastWrite !== null && Math.abs(m.scrollTop - lastWrite.top) <= 2;
675
+ if (modeRef.current === "RETURNING_SMOOTH") {
676
+ if (!isLikelyOwnWrite && delta < -DETACH_SCROLL_DELTA_PX) {
677
+ cancelReturn();
678
+ setModeBoth("DETACHED");
679
+ }
680
+ } else if (modeRef.current === "STICKY_INSTANT") {
681
+ if (!isLikelyOwnWrite && delta < -DETACH_SCROLL_DELTA_PX && m.isOverflowing) {
682
+ cancelPendingStick();
683
+ setModeBoth("DETACHED");
684
+ }
685
+ } else if (modeRef.current === "DETACHED") {
686
+ if (m.distanceToBottom <= EPS_BOTTOM_PX) {
687
+ setModeBoth("STICKY_INSTANT");
688
+ stickToBottomInstant();
689
+ }
690
+ }
691
+ prevScrollTopRef.current = m.scrollTop;
692
+ updateDebug();
693
+ },
694
+ [cancelPendingStick, cancelReturn, setModeBoth, stickToBottomInstant, updateDebug]
695
+ );
696
+ (0, import_react.useEffect)(() => {
697
+ const viewport = viewportRef.current;
698
+ const content = contentRef.current;
699
+ if (!viewport || !content) return;
700
+ const observer = new ResizeObserver(() => {
701
+ const m = measure(viewport);
702
+ setIsOverflowing((previous) => previous === m.isOverflowing ? previous : m.isOverflowing);
703
+ if (modeRef.current === "STICKY_INSTANT") {
704
+ stickToBottomInstant();
705
+ }
706
+ updateDebug();
707
+ });
708
+ observer.observe(content);
709
+ observer.observe(viewport);
710
+ return () => observer.disconnect();
711
+ }, [stickToBottomInstant, updateDebug]);
712
+ (0, import_react.useLayoutEffect)(() => {
713
+ const viewport = viewportRef.current;
714
+ if (!viewport) return;
715
+ setModeBoth("STICKY_INSTANT");
716
+ const initial = measure(viewport);
717
+ writeScrollTop(initial.maxScrollTop);
718
+ prevScrollTopRef.current = viewport.scrollTop;
719
+ setIsOverflowing(initial.isOverflowing);
720
+ setDistanceToBottom(initial.distanceToBottom);
721
+ updateDebug();
722
+ }, [setModeBoth, updateDebug, writeScrollTop]);
723
+ (0, import_react.useEffect)(() => {
724
+ return () => {
725
+ cancelPendingStick();
726
+ cancelReturn();
727
+ };
728
+ }, [cancelPendingStick, cancelReturn]);
729
+ const canJump = isOverflowing && mode === "DETACHED";
730
+ const jumpButton = renderJumpToBottom?.({
731
+ mode,
732
+ canJump,
733
+ isOverflowing,
734
+ distanceToBottom,
735
+ jumpToBottom: startReturnToBottomSmooth
736
+ }) ?? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DefaultJumpButton, { canJump, jumpToBottom: startReturnToBottomSmooth });
737
+ const jumpContainerClassNameBase = "pointer-events-none absolute z-20";
738
+ const jumpContainerStyle = {
739
+ position: "absolute",
740
+ zIndex: 20,
741
+ left: 0,
742
+ right: 0,
743
+ bottom: 12,
744
+ display: "flex",
745
+ justifyContent: "center",
746
+ opacity: canJump ? 1 : 0,
747
+ transform: canJump ? "translateY(0px)" : "translateY(4px)",
748
+ transition: "opacity 150ms ease, transform 150ms ease",
749
+ pointerEvents: "none"
750
+ };
751
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: joinClasses("relative h-full w-full overflow-hidden", className), children: [
752
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
753
+ "div",
754
+ {
755
+ ref: viewportRef,
756
+ className: joinClasses("h-full w-full overflow-auto", viewportClassName),
757
+ onScroll: onViewportScroll,
758
+ "data-testid": "sticky-scroll-viewport",
759
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: contentRef, className: joinClasses("flex min-h-full w-full flex-col", contentClassName), children })
760
+ }
761
+ ),
762
+ showJumpToBottom ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
763
+ "div",
764
+ {
765
+ className: joinClasses(jumpContainerClassNameBase, jumpContainerClassName),
766
+ style: jumpContainerStyle,
767
+ "aria-hidden": !canJump,
768
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: canJump ? "pointer-events-auto" : "pointer-events-none", children: jumpButton })
769
+ }
770
+ ) : null
771
+ ] });
772
+ }
773
+
457
774
  // src/components/index.ts
458
775
  var import_core = require("@stream-mdx/core");
459
776
 
@@ -630,7 +947,7 @@ function percentile(values, ratio) {
630
947
  }
631
948
 
632
949
  // src/mdx-hydration-context.ts
633
- var import_react = __toESM(require("react"), 1);
950
+ var import_react2 = __toESM(require("react"), 1);
634
951
  var MdxHydrationController = class {
635
952
  constructor(options) {
636
953
  this.active = 0;
@@ -668,7 +985,7 @@ var MdxHydrationController = class {
668
985
  next();
669
986
  }
670
987
  };
671
- var MdxHydrationContext = import_react.default.createContext({ controller: null });
988
+ var MdxHydrationContext = import_react2.default.createContext({ controller: null });
672
989
  function createMdxHydrationController(options) {
673
990
  if (!options || options.strategy === "immediate") {
674
991
  return null;
@@ -689,11 +1006,11 @@ function prefetchMdxRuntime() {
689
1006
  }
690
1007
 
691
1008
  // src/renderer/use-deferred-render.ts
692
- var import_react3 = require("react");
1009
+ var import_react4 = require("react");
693
1010
  function useDeferredRender(ref, options) {
694
1011
  const enabled = options?.enabled ?? true;
695
- const [shouldRender, setShouldRender] = (0, import_react3.useState)(!enabled);
696
- (0, import_react3.useEffect)(() => {
1012
+ const [shouldRender, setShouldRender] = (0, import_react4.useState)(!enabled);
1013
+ (0, import_react4.useEffect)(() => {
697
1014
  if (!enabled) {
698
1015
  setShouldRender(true);
699
1016
  return;
@@ -746,10 +1063,10 @@ function useDeferredRender(ref, options) {
746
1063
 
747
1064
  // src/components/index.ts
748
1065
  var import_core2 = require("@stream-mdx/core");
749
- var import_react5 = __toESM(require("react"), 1);
1066
+ var import_react6 = __toESM(require("react"), 1);
750
1067
 
751
1068
  // src/utils/inline-html.ts
752
- var import_react4 = __toESM(require("react"), 1);
1069
+ var import_react5 = __toESM(require("react"), 1);
753
1070
  var BACKTICK_CONTENT = /^`([\s\S]+)`$/;
754
1071
  var DEFAULT_INLINE_HTML_RENDERERS = {
755
1072
  kbd: (descriptor, ctx) => {
@@ -761,7 +1078,7 @@ var DEFAULT_INLINE_HTML_RENDERERS = {
761
1078
  if (ctx.key !== void 0 && ctx.key !== null) {
762
1079
  props.key = ctx.key;
763
1080
  }
764
- return import_react4.default.createElement("kbd", props, import_react4.default.createElement("code", { className: "inline-code" }, codeText));
1081
+ return import_react5.default.createElement("kbd", props, import_react5.default.createElement("code", { className: "inline-code" }, codeText));
765
1082
  }
766
1083
  return ctx.defaultRender();
767
1084
  }
@@ -779,9 +1096,9 @@ function renderInlineHtmlSegment(raw, sanitized, options = {}) {
779
1096
  return null;
780
1097
  }
781
1098
  if (options.key !== void 0 && options.key !== null) {
782
- return import_react4.default.createElement(import_react4.default.Fragment, { key: options.key }, descriptor.text);
1099
+ return import_react5.default.createElement(import_react5.default.Fragment, { key: options.key }, descriptor.text);
783
1100
  }
784
- return import_react4.default.createElement(import_react4.default.Fragment, {}, descriptor.text);
1101
+ return import_react5.default.createElement(import_react5.default.Fragment, {}, descriptor.text);
785
1102
  }
786
1103
  if (isInlineTag) {
787
1104
  const parsedElement = renderSanitizedHtmlTree(descriptor.sanitized, options.key);
@@ -796,15 +1113,15 @@ function renderInlineHtmlSegment(raw, sanitized, options = {}) {
796
1113
  if (options.key !== void 0 && options.key !== null) {
797
1114
  props.key = options.key;
798
1115
  }
799
- return import_react4.default.createElement("span", props);
1116
+ return import_react5.default.createElement("span", props);
800
1117
  };
801
1118
  const allRenderers = options.renderers ? { ...DEFAULT_INLINE_HTML_RENDERERS, ...options.renderers } : DEFAULT_INLINE_HTML_RENDERERS;
802
1119
  const renderer = allRenderers[descriptor.tagName];
803
1120
  if (renderer) {
804
1121
  const rendered = renderer(descriptor, { key: options.key, defaultRender });
805
1122
  if (rendered) {
806
- if (options.key !== void 0 && options.key !== null && import_react4.default.isValidElement(rendered) && rendered.key === null) {
807
- return import_react4.default.cloneElement(rendered, { key: options.key });
1123
+ if (options.key !== void 0 && options.key !== null && import_react5.default.isValidElement(rendered) && rendered.key === null) {
1124
+ return import_react5.default.cloneElement(rendered, { key: options.key });
808
1125
  }
809
1126
  return rendered;
810
1127
  }
@@ -916,21 +1233,21 @@ function renderSanitizedHtmlTree(html, key) {
916
1233
  }
917
1234
  if (children.length === 1) {
918
1235
  const [child] = children;
919
- if (import_react4.default.isValidElement(child)) {
1236
+ if (import_react5.default.isValidElement(child)) {
920
1237
  if (key !== void 0 && key !== null) {
921
- return import_react4.default.cloneElement(child, { key });
1238
+ return import_react5.default.cloneElement(child, { key });
922
1239
  }
923
1240
  return child;
924
1241
  }
925
1242
  if (typeof child === "string" || typeof child === "number") {
926
1243
  if (key !== void 0 && key !== null) {
927
- return import_react4.default.createElement(import_react4.default.Fragment, { key }, child);
1244
+ return import_react5.default.createElement(import_react5.default.Fragment, { key }, child);
928
1245
  }
929
- return import_react4.default.createElement(import_react4.default.Fragment, {}, child);
1246
+ return import_react5.default.createElement(import_react5.default.Fragment, {}, child);
930
1247
  }
931
- return import_react4.default.createElement(import_react4.default.Fragment, { key }, child);
1248
+ return import_react5.default.createElement(import_react5.default.Fragment, { key }, child);
932
1249
  }
933
- return import_react4.default.createElement(import_react4.default.Fragment, { key }, ...children);
1250
+ return import_react5.default.createElement(import_react5.default.Fragment, { key }, ...children);
934
1251
  } catch {
935
1252
  return null;
936
1253
  }
@@ -955,9 +1272,9 @@ function convertDomNode(node, key) {
955
1272
  }
956
1273
  });
957
1274
  if (children.length === 0) {
958
- return import_react4.default.createElement(tagName, props);
1275
+ return import_react5.default.createElement(tagName, props);
959
1276
  }
960
- return import_react4.default.createElement(tagName, props, ...children);
1277
+ return import_react5.default.createElement(tagName, props, ...children);
961
1278
  }
962
1279
  function getElementAttributes(element) {
963
1280
  const attrs = {};
@@ -1018,12 +1335,12 @@ var INLINE_ELEMENTS = /* @__PURE__ */ new Set([
1018
1335
  ]);
1019
1336
 
1020
1337
  // src/components/link-safety-modal.tsx
1021
- var import_jsx_runtime = require("react/jsx-runtime");
1338
+ var import_jsx_runtime2 = require("react/jsx-runtime");
1022
1339
  var DefaultLinkSafetyModal = ({ url, isOpen, isChecking, onClose, onConfirm, onCopy }) => {
1023
1340
  if (!isOpen) {
1024
1341
  return null;
1025
1342
  }
1026
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1343
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1027
1344
  "div",
1028
1345
  {
1029
1346
  className: "stream-mdx-link-modal-backdrop",
@@ -1041,7 +1358,7 @@ var DefaultLinkSafetyModal = ({ url, isOpen, isChecking, onClose, onConfirm, onC
1041
1358
  padding: "24px"
1042
1359
  },
1043
1360
  onClick: onClose,
1044
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1361
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1045
1362
  "div",
1046
1363
  {
1047
1364
  className: "stream-mdx-link-modal",
@@ -1056,12 +1373,12 @@ var DefaultLinkSafetyModal = ({ url, isOpen, isChecking, onClose, onConfirm, onC
1056
1373
  },
1057
1374
  onClick: (event) => event.stopPropagation(),
1058
1375
  children: [
1059
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontWeight: 600, marginBottom: 8 }, children: "Open external link?" }),
1060
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 13, opacity: 0.8, wordBreak: "break-all", marginBottom: 16 }, children: url }),
1061
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: 8, justifyContent: "flex-end" }, children: [
1062
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: onCopy, disabled: isChecking, style: buttonStyle, children: "Copy link" }),
1063
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: onConfirm, disabled: isChecking, style: primaryButtonStyle, children: "Open link" }),
1064
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: onClose, style: buttonStyle, children: "Cancel" })
1376
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontWeight: 600, marginBottom: 8 }, children: "Open external link?" }),
1377
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 13, opacity: 0.8, wordBreak: "break-all", marginBottom: 16 }, children: url }),
1378
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: 8, justifyContent: "flex-end" }, children: [
1379
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", onClick: onCopy, disabled: isChecking, style: buttonStyle, children: "Copy link" }),
1380
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", onClick: onConfirm, disabled: isChecking, style: primaryButtonStyle, children: "Open link" }),
1381
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", onClick: onClose, style: buttonStyle, children: "Cancel" })
1065
1382
  ] })
1066
1383
  ]
1067
1384
  }
@@ -1085,7 +1402,7 @@ var primaryButtonStyle = {
1085
1402
  };
1086
1403
 
1087
1404
  // src/components/index.ts
1088
- var MdxRuntimeBoundary = class extends import_react5.default.Component {
1405
+ var MdxRuntimeBoundary = class extends import_react6.default.Component {
1089
1406
  constructor() {
1090
1407
  super(...arguments);
1091
1408
  this.state = { hasError: false };
@@ -1115,31 +1432,31 @@ function renderInlineNodes(nodes, components) {
1115
1432
  case "text": {
1116
1433
  const textComponent = components.text;
1117
1434
  if (textComponent && textComponent !== defaultInlineComponents.text) {
1118
- return import_react5.default.createElement(textComponent, { key, text: node.text });
1435
+ return import_react6.default.createElement(textComponent, { key, text: node.text });
1119
1436
  }
1120
- return import_react5.default.createElement(import_react5.default.Fragment, { key, children: node.text });
1437
+ return import_react6.default.createElement(import_react6.default.Fragment, { key, children: node.text });
1121
1438
  }
1122
1439
  case "strong":
1123
- return import_react5.default.createElement(components.strong, {
1440
+ return import_react6.default.createElement(components.strong, {
1124
1441
  key,
1125
1442
  children: renderInlineNodes(node.children, components)
1126
1443
  });
1127
1444
  case "em":
1128
- return import_react5.default.createElement(components.em, {
1445
+ return import_react6.default.createElement(components.em, {
1129
1446
  key,
1130
1447
  children: renderInlineNodes(node.children, components)
1131
1448
  });
1132
1449
  case "strike": {
1133
- const StrikeComponent = components.strike ?? ((props) => import_react5.default.createElement("del", {}, props.children));
1134
- return import_react5.default.createElement(StrikeComponent, {
1450
+ const StrikeComponent = components.strike ?? ((props) => import_react6.default.createElement("del", {}, props.children));
1451
+ return import_react6.default.createElement(StrikeComponent, {
1135
1452
  key,
1136
1453
  children: renderInlineNodes(node.children, components)
1137
1454
  });
1138
1455
  }
1139
1456
  case "code":
1140
- return import_react5.default.createElement(components.code, { key, text: node.text });
1457
+ return import_react6.default.createElement(components.code, { key, text: node.text });
1141
1458
  case "link":
1142
- return import_react5.default.createElement(
1459
+ return import_react6.default.createElement(
1143
1460
  components.link,
1144
1461
  {
1145
1462
  key,
@@ -1149,18 +1466,18 @@ function renderInlineNodes(nodes, components) {
1149
1466
  }
1150
1467
  );
1151
1468
  case "image":
1152
- return import_react5.default.createElement(components.image, {
1469
+ return import_react6.default.createElement(components.image, {
1153
1470
  key,
1154
1471
  src: node.src,
1155
1472
  alt: node.alt,
1156
1473
  title: node.title
1157
1474
  });
1158
1475
  case "br":
1159
- return import_react5.default.createElement(import_react5.default.Fragment, { key }, import_react5.default.createElement(components.br, {}));
1476
+ return import_react6.default.createElement(import_react6.default.Fragment, { key }, import_react6.default.createElement(components.br, {}));
1160
1477
  default: {
1161
1478
  const component = components[node.kind];
1162
1479
  if (component) {
1163
- return import_react5.default.createElement(component, { key, ...node });
1480
+ return import_react6.default.createElement(component, { key, ...node });
1164
1481
  }
1165
1482
  return null;
1166
1483
  }
@@ -1168,18 +1485,18 @@ function renderInlineNodes(nodes, components) {
1168
1485
  });
1169
1486
  }
1170
1487
  var defaultInlineComponents = {
1171
- text: ({ text }) => import_react5.default.createElement(import_react5.default.Fragment, {}, text),
1172
- strong: ({ children }) => import_react5.default.createElement("strong", {}, children),
1173
- em: ({ children }) => import_react5.default.createElement("em", {}, children),
1174
- strike: ({ children }) => import_react5.default.createElement("del", {}, children),
1175
- code: ({ text }) => import_react5.default.createElement(
1488
+ text: ({ text }) => import_react6.default.createElement(import_react6.default.Fragment, {}, text),
1489
+ strong: ({ children }) => import_react6.default.createElement("strong", {}, children),
1490
+ em: ({ children }) => import_react6.default.createElement("em", {}, children),
1491
+ strike: ({ children }) => import_react6.default.createElement("del", {}, children),
1492
+ code: ({ text }) => import_react6.default.createElement(
1176
1493
  "code",
1177
1494
  {
1178
1495
  className: "inline-code"
1179
1496
  },
1180
1497
  text
1181
1498
  ),
1182
- link: ({ href, title, children }) => import_react5.default.createElement(
1499
+ link: ({ href, title, children }) => import_react6.default.createElement(
1183
1500
  "a",
1184
1501
  {
1185
1502
  href,
@@ -1190,15 +1507,15 @@ var defaultInlineComponents = {
1190
1507
  },
1191
1508
  children
1192
1509
  ),
1193
- image: ({ src, alt, title }) => import_react5.default.createElement("img", {
1510
+ image: ({ src, alt, title }) => import_react6.default.createElement("img", {
1194
1511
  src,
1195
1512
  alt,
1196
1513
  title,
1197
1514
  className: "markdown-image"
1198
1515
  }),
1199
- br: () => import_react5.default.createElement("br"),
1516
+ br: () => import_react6.default.createElement("br"),
1200
1517
  // Custom extensible components
1201
- mention: ({ handle }) => import_react5.default.createElement(
1518
+ mention: ({ handle }) => import_react6.default.createElement(
1202
1519
  "span",
1203
1520
  {
1204
1521
  className: "mention",
@@ -1206,7 +1523,7 @@ var defaultInlineComponents = {
1206
1523
  },
1207
1524
  `@${handle}`
1208
1525
  ),
1209
- citation: ({ id }) => import_react5.default.createElement(
1526
+ citation: ({ id }) => import_react6.default.createElement(
1210
1527
  "span",
1211
1528
  {
1212
1529
  className: "citation",
@@ -1214,7 +1531,7 @@ var defaultInlineComponents = {
1214
1531
  },
1215
1532
  `[${id}]`
1216
1533
  ),
1217
- "math-inline": ({ tex }) => import_react5.default.createElement(
1534
+ "math-inline": ({ tex }) => import_react6.default.createElement(
1218
1535
  "span",
1219
1536
  {
1220
1537
  className: "math-inline",
@@ -1222,27 +1539,31 @@ var defaultInlineComponents = {
1222
1539
  },
1223
1540
  `$${tex}$`
1224
1541
  ),
1225
- "math-display": ({ tex }) => import_react5.default.createElement(
1542
+ "math-display": ({ tex }) => import_react6.default.createElement(
1226
1543
  "div",
1227
1544
  {
1228
1545
  className: "math-display markdown-math-display",
1229
1546
  "data-tex": tex,
1230
1547
  style: { overflowX: "auto" }
1231
1548
  },
1232
- import_react5.default.createElement("span", { className: "math-display-content" }, `$$${tex}$$`)
1549
+ import_react6.default.createElement("span", { className: "math-display-content" }, `$$${tex}$$`)
1233
1550
  ),
1234
1551
  // Footnote inline reference (superscript anchor)
1235
1552
  "footnote-ref": ({ label, number }) => {
1236
1553
  const n = number ?? "?";
1237
1554
  const href = number ? `#fn:${n}` : void 0;
1238
1555
  const id = number ? `fnref:${n}` : void 0;
1239
- return import_react5.default.createElement("sup", { className: "footnote-ref" }, import_react5.default.createElement("a", { href, id, "data-label": label }, String(n)));
1556
+ return import_react6.default.createElement(
1557
+ "sup",
1558
+ { className: "footnote-ref" },
1559
+ import_react6.default.createElement("a", { href, id, "data-label": label, style: { color: "var(--foreground)", textDecoration: "underline" } }, String(n))
1560
+ );
1240
1561
  }
1241
1562
  };
1242
1563
  var defaultBlockComponents = {
1243
1564
  paragraph: ({ inlines, raw, meta, children }) => {
1244
1565
  if (children !== void 0) {
1245
- return import_react5.default.createElement(
1566
+ return import_react6.default.createElement(
1246
1567
  "p",
1247
1568
  {
1248
1569
  className: "markdown-paragraph"
@@ -1256,7 +1577,7 @@ var defaultBlockComponents = {
1256
1577
  if (structured.length === 1) {
1257
1578
  return structured[0];
1258
1579
  }
1259
- return import_react5.default.createElement(import_react5.default.Fragment, {}, ...structured);
1580
+ return import_react6.default.createElement(import_react6.default.Fragment, {}, ...structured);
1260
1581
  }
1261
1582
  const filteredInlines = inlines && raw && inlines.length > 0 ? inlines.filter((node) => !(node.kind === "text" && node.text === raw)) : inlines ?? [];
1262
1583
  const effectiveInlines = filteredInlines.length > 0 ? filteredInlines : raw ? [
@@ -1265,7 +1586,7 @@ var defaultBlockComponents = {
1265
1586
  text: raw
1266
1587
  }
1267
1588
  ] : [];
1268
- return import_react5.default.createElement(
1589
+ return import_react6.default.createElement(
1269
1590
  "p",
1270
1591
  {
1271
1592
  className: "markdown-paragraph"
@@ -1278,7 +1599,7 @@ var defaultBlockComponents = {
1278
1599
  const onlyPlainText = Array.isArray(inlines) && inlines.length > 0 && inlines.every((node) => node.kind === "text");
1279
1600
  const children = onlyPlainText ? inlines.map((node) => node.kind === "text" ? node.text : "").join("") : renderInlineNodes(inlines, defaultInlineComponents);
1280
1601
  const headingId = typeof meta?.headingId === "string" && meta.headingId.length > 0 ? meta.headingId : void 0;
1281
- return import_react5.default.createElement(
1602
+ return import_react6.default.createElement(
1282
1603
  tag,
1283
1604
  {
1284
1605
  className: `markdown-heading markdown-h${level}`,
@@ -1291,7 +1612,7 @@ var defaultBlockComponents = {
1291
1612
  code: ({ html, meta, lines, lang, preAttrs, codeAttrs }) => {
1292
1613
  const language = typeof lang === "string" ? lang : typeof meta?.lang === "string" ? String(meta.lang) : "text";
1293
1614
  if (html) {
1294
- return import_react5.default.createElement("div", {
1615
+ return import_react6.default.createElement("div", {
1295
1616
  className: `markdown-code-block language-${language || "text"}`,
1296
1617
  /* biome-ignore lint/security/noDangerouslySetInnerHtml: highlighted HTML is generated by our sanitizer */
1297
1618
  dangerouslySetInnerHTML: { __html: html }
@@ -1301,20 +1622,20 @@ var defaultBlockComponents = {
1301
1622
  if (lines && lines.length > 0) {
1302
1623
  const preAttributes = attrsToProps(preAttrs);
1303
1624
  const codeAttributes = attrsToProps(codeAttrs);
1304
- return import_react5.default.createElement(
1625
+ return import_react6.default.createElement(
1305
1626
  "pre",
1306
1627
  {
1307
1628
  ...preAttributes,
1308
1629
  className: preAttributes.className ? `${preAttributes.className} markdown-code-block language-${language || "text"}` : `markdown-code-block language-${language || "text"}`
1309
1630
  },
1310
- import_react5.default.createElement(
1631
+ import_react6.default.createElement(
1311
1632
  "code",
1312
1633
  {
1313
1634
  ...codeAttributes,
1314
1635
  className: codeAttributes.className ? `${codeAttributes.className} language-${language || "text"}` : `language-${language || "text"}`
1315
1636
  },
1316
1637
  lines.map(
1317
- (line) => import_react5.default.createElement("span", {
1638
+ (line) => import_react6.default.createElement("span", {
1318
1639
  key: line.id,
1319
1640
  className: "line",
1320
1641
  /* biome-ignore lint/security/noDangerouslySetInnerHtml: line HTML is sanitized server-side */
@@ -1324,19 +1645,19 @@ var defaultBlockComponents = {
1324
1645
  )
1325
1646
  );
1326
1647
  }
1327
- return import_react5.default.createElement("pre", {
1648
+ return import_react6.default.createElement("pre", {
1328
1649
  className: `markdown-code-block language-${language || "text"}`,
1329
1650
  children: code
1330
1651
  });
1331
1652
  },
1332
- blockquote: ({ inlines, renderedContent }) => import_react5.default.createElement(
1653
+ blockquote: ({ inlines, renderedContent }) => import_react6.default.createElement(
1333
1654
  "blockquote",
1334
1655
  {
1335
1656
  className: "markdown-blockquote"
1336
1657
  },
1337
1658
  renderedContent ?? renderInlineNodes(inlines, defaultInlineComponents)
1338
1659
  ),
1339
- hr: (props) => import_react5.default.createElement("hr", props),
1660
+ hr: (props) => import_react6.default.createElement("hr", props),
1340
1661
  list: ({ ordered, items }) => {
1341
1662
  if (items.length === 0) {
1342
1663
  return null;
@@ -1346,7 +1667,7 @@ var defaultBlockComponents = {
1346
1667
  ["--list-indent"]: `calc(2.5rem + ${String(items.length).length}ch)`
1347
1668
  } : void 0;
1348
1669
  const listItems = items.map(
1349
- (item, index) => import_react5.default.createElement(
1670
+ (item, index) => import_react6.default.createElement(
1350
1671
  "li",
1351
1672
  {
1352
1673
  key: index,
@@ -1357,7 +1678,7 @@ var defaultBlockComponents = {
1357
1678
  renderInlineNodes(item, defaultInlineComponents)
1358
1679
  )
1359
1680
  );
1360
- return import_react5.default.createElement(
1681
+ return import_react6.default.createElement(
1361
1682
  tag,
1362
1683
  {
1363
1684
  className: `markdown-list ${ordered ? "ordered" : "unordered"}`,
@@ -1371,23 +1692,23 @@ var defaultBlockComponents = {
1371
1692
  const htmlString = typeof window === "undefined" ? raw : (0, import_core.sanitizeHTML)(raw);
1372
1693
  if (typeof window !== "undefined" && elements) {
1373
1694
  const content = mapHtmlToReact(htmlString, elements);
1374
- return import_react5.default.createElement("div", { className: "markdown-html" }, content);
1695
+ return import_react6.default.createElement("div", { className: "markdown-html" }, content);
1375
1696
  }
1376
- return import_react5.default.createElement("div", {
1697
+ return import_react6.default.createElement("div", {
1377
1698
  className: "markdown-html",
1378
1699
  /* biome-ignore lint/security/noDangerouslySetInnerHtml: htmlString is sanitized before injection */
1379
1700
  dangerouslySetInnerHTML: { __html: htmlString }
1380
1701
  });
1381
1702
  },
1382
- mdx: ({ compiledRef, compiledModule, status, errorMessage, raw }) => {
1383
- const [Comp, setComp] = import_react5.default.useState(null);
1384
- const [internalError, setInternalError] = import_react5.default.useState(null);
1385
- const [renderError, setRenderError] = import_react5.default.useState(null);
1386
- const [retryKey, setRetryKey] = import_react5.default.useState(0);
1387
- const hydrationContext = import_react5.default.useContext(MdxHydrationContext);
1703
+ mdx: ({ compiledRef, compiledModule, status, errorMessage }) => {
1704
+ const [Comp, setComp] = import_react6.default.useState(null);
1705
+ const [internalError, setInternalError] = import_react6.default.useState(null);
1706
+ const [renderError, setRenderError] = import_react6.default.useState(null);
1707
+ const [retryKey, setRetryKey] = import_react6.default.useState(0);
1708
+ const hydrationContext = import_react6.default.useContext(MdxHydrationContext);
1388
1709
  const hydrationController = hydrationContext?.controller ?? null;
1389
1710
  const hydrationOptions = hydrationContext?.options;
1390
- const containerRef = import_react5.default.useRef(null);
1711
+ const containerRef = import_react6.default.useRef(null);
1391
1712
  const deferHydration = hydrationOptions?.strategy === "visible";
1392
1713
  const shouldHydrate = useDeferredRender(
1393
1714
  containerRef,
@@ -1399,13 +1720,13 @@ var defaultBlockComponents = {
1399
1720
  } : { enabled: false }
1400
1721
  );
1401
1722
  const resolvedId = compiledModule?.id ?? (compiledRef?.id && compiledRef.id !== "pending" ? compiledRef.id : void 0);
1402
- const handleRetry = import_react5.default.useCallback(() => {
1723
+ const handleRetry = import_react6.default.useCallback(() => {
1403
1724
  setInternalError(null);
1404
1725
  setRenderError(null);
1405
1726
  setComp(null);
1406
1727
  setRetryKey((prev) => prev + 1);
1407
1728
  }, []);
1408
- const handleRuntimeError = import_react5.default.useCallback(
1729
+ const handleRuntimeError = import_react6.default.useCallback(
1409
1730
  (error) => {
1410
1731
  const message2 = error instanceof Error ? error.message : String(error);
1411
1732
  setRenderError(message2);
@@ -1416,7 +1737,7 @@ var defaultBlockComponents = {
1416
1737
  const effectiveStatus = status ? status : resolvedId ? "compiled" : "pending";
1417
1738
  const failureMessage = errorMessage ?? internalError ?? renderError ?? null;
1418
1739
  const moduleDependencies = compiledModule?.dependencies;
1419
- import_react5.default.useEffect(() => {
1740
+ import_react6.default.useEffect(() => {
1420
1741
  if (!shouldHydrate) {
1421
1742
  return;
1422
1743
  }
@@ -1480,9 +1801,8 @@ var defaultBlockComponents = {
1480
1801
  const waitingForVisibility = deferHydration && !shouldHydrate && Boolean(resolvedId);
1481
1802
  const pendingLabel = waitingForVisibility ? "MDX ready (hydrate on view)\u2026" : compileMode === "worker" ? "Compiling MDX (client)\u2026" : "Compiling MDX (server)\u2026";
1482
1803
  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.");
1483
- const rawFallback = typeof raw === "string" && raw.trim().length > 0 ? import_react5.default.createElement("pre", { className: "markdown-mdx-fallback" }, raw) : null;
1484
1804
  const allowRetry = Boolean(internalError || renderError);
1485
- const retryButton = allowRetry ? import_react5.default.createElement(
1805
+ const retryButton = allowRetry ? import_react6.default.createElement(
1486
1806
  "button",
1487
1807
  {
1488
1808
  type: "button",
@@ -1491,13 +1811,14 @@ var defaultBlockComponents = {
1491
1811
  },
1492
1812
  "Retry hydration"
1493
1813
  ) : null;
1494
- const errorPanel = import_react5.default.createElement(
1495
- "div",
1496
- { className: "markdown-mdx-error" },
1497
- import_react5.default.createElement(import_react5.default.Fragment, null, import_react5.default.createElement("strong", null, "MDX failed"), import_react5.default.createElement("div", null, message))
1814
+ const errorPanel = import_react6.default.createElement(
1815
+ import_react6.default.Fragment,
1816
+ null,
1817
+ import_react6.default.createElement("strong", null, "MDX failed"),
1818
+ import_react6.default.createElement("div", null, message)
1498
1819
  );
1499
1820
  if (Comp && !failureMessage) {
1500
- return import_react5.default.createElement(
1821
+ return import_react6.default.createElement(
1501
1822
  "div",
1502
1823
  {
1503
1824
  className: "markdown-mdx",
@@ -1506,30 +1827,29 @@ var defaultBlockComponents = {
1506
1827
  "data-mdx-status": failureMessage ? "error" : "compiled",
1507
1828
  "data-mdx-mode": compileMode
1508
1829
  },
1509
- import_react5.default.createElement(
1830
+ import_react6.default.createElement(
1510
1831
  MdxRuntimeBoundary,
1511
1832
  { resetKey: retryKey, onError: handleRuntimeError },
1512
- import_react5.default.createElement(Comp, {})
1833
+ import_react6.default.createElement(Comp, {})
1513
1834
  )
1514
1835
  );
1515
1836
  }
1516
1837
  if (failureMessage) {
1517
- return import_react5.default.createElement(
1838
+ return import_react6.default.createElement(
1518
1839
  "div",
1519
1840
  {
1520
- className: "markdown-mdx",
1841
+ className: "markdown-mdx error",
1521
1842
  ref: containerRef,
1522
1843
  "data-mdx-ref": pendingId,
1523
1844
  "data-mdx-status": "error",
1524
1845
  "data-mdx-mode": compileMode
1525
1846
  },
1526
1847
  errorPanel,
1527
- rawFallback,
1528
1848
  retryButton
1529
1849
  );
1530
1850
  }
1531
1851
  if (!Comp) {
1532
- return import_react5.default.createElement(
1852
+ return import_react6.default.createElement(
1533
1853
  "div",
1534
1854
  {
1535
1855
  className: "markdown-mdx",
@@ -1544,28 +1864,37 @@ var defaultBlockComponents = {
1544
1864
  },
1545
1865
  // Footnotes block rendered at page end
1546
1866
  footnotes: ({ items }) => {
1547
- if (!items || items.length === 0) return import_react5.default.createElement(import_react5.default.Fragment, null);
1867
+ if (!items || items.length === 0) return import_react6.default.createElement(import_react6.default.Fragment, null);
1548
1868
  const listItems = items.map(
1549
- (item) => import_react5.default.createElement(
1869
+ (item) => import_react6.default.createElement(
1550
1870
  "li",
1551
1871
  { key: item.number, id: `fn:${item.number}` },
1552
1872
  renderInlineNodes(item.inlines, defaultInlineComponents),
1553
1873
  " ",
1554
- import_react5.default.createElement("a", { href: `#fnref:${item.number}`, className: "footnote-backref", "aria-label": "Back to content" }, "\u21A9")
1874
+ import_react6.default.createElement(
1875
+ "a",
1876
+ {
1877
+ href: `#fnref:${item.number}`,
1878
+ className: "footnote-backref",
1879
+ "aria-label": "Back to content",
1880
+ style: { color: "var(--foreground)", textDecoration: "underline" }
1881
+ },
1882
+ "\u21A9"
1883
+ )
1555
1884
  )
1556
1885
  );
1557
- return import_react5.default.createElement("section", { className: "footnotes" }, import_react5.default.createElement("hr", {}), import_react5.default.createElement("ol", {}, listItems));
1886
+ return import_react6.default.createElement("section", { className: "footnotes" }, import_react6.default.createElement("hr", {}), import_react6.default.createElement("ol", {}, listItems));
1558
1887
  },
1559
1888
  // Footnote definition placeholders (render nothing)
1560
- "footnote-def": () => import_react5.default.createElement(import_react5.default.Fragment, null),
1889
+ "footnote-def": () => import_react6.default.createElement(import_react6.default.Fragment, null),
1561
1890
  // Callouts block
1562
1891
  callout: ({ kind, inlines = [] }) => {
1563
1892
  const tone = (kind || "NOTE").toUpperCase();
1564
1893
  const title = tone.charAt(0) + tone.slice(1).toLowerCase();
1565
- return import_react5.default.createElement(
1894
+ return import_react6.default.createElement(
1566
1895
  "div",
1567
1896
  { className: `markdown-callout markdown-callout-${tone.toLowerCase()} border rounded p-3 my-3` },
1568
- import_react5.default.createElement("div", { className: "font-semibold mb-1" }, title),
1897
+ import_react6.default.createElement("div", { className: "font-semibold mb-1" }, title),
1569
1898
  inlines.length > 0 ? renderInlineNodes(inlines, defaultInlineComponents) : null
1570
1899
  );
1571
1900
  },
@@ -1580,7 +1909,7 @@ var defaultBlockComponents = {
1580
1909
  const renderCells = (cells, tag, rowIdx) => cells.map((cell, i) => {
1581
1910
  const columnAlign = align?.[i] ?? void 0;
1582
1911
  const cellStyle = columnAlign ? { textAlign: columnAlign } : void 0;
1583
- return import_react5.default.createElement(
1912
+ return import_react6.default.createElement(
1584
1913
  tag === "th" ? El.Th : El.Td,
1585
1914
  {
1586
1915
  key: `${rowIdx}-${i}`,
@@ -1591,14 +1920,14 @@ var defaultBlockComponents = {
1591
1920
  renderInlineNodes(cell, defaultInlineComponents)
1592
1921
  );
1593
1922
  });
1594
- return import_react5.default.createElement(
1923
+ return import_react6.default.createElement(
1595
1924
  El.Table,
1596
1925
  { className: "markdown-table" },
1597
- header && header.length > 0 ? import_react5.default.createElement(El.Thead, {}, import_react5.default.createElement(El.Tr, {}, renderCells(header, "th", -1))) : null,
1598
- import_react5.default.createElement(
1926
+ header && header.length > 0 ? import_react6.default.createElement(El.Thead, {}, import_react6.default.createElement(El.Tr, {}, renderCells(header, "th", -1))) : null,
1927
+ import_react6.default.createElement(
1599
1928
  El.Tbody,
1600
1929
  {},
1601
- rows.map((row, r) => import_react5.default.createElement(El.Tr, { key: r }, renderCells(row, "td", r)))
1930
+ rows.map((row, r) => import_react6.default.createElement(El.Tr, { key: r }, renderCells(row, "td", r)))
1602
1931
  )
1603
1932
  );
1604
1933
  }
@@ -1667,7 +1996,7 @@ var ComponentRegistry = class {
1667
1996
  renderBlock(block) {
1668
1997
  const Component = this.getBlockComponent(block.type);
1669
1998
  const props = this.getBlockProps(block);
1670
- return import_react5.default.createElement(Component, {
1999
+ return import_react6.default.createElement(Component, {
1671
2000
  key: block.id,
1672
2001
  ...props
1673
2002
  });
@@ -1796,42 +2125,42 @@ var ComponentRegistry = class {
1796
2125
  function getDefaultHtmlElements() {
1797
2126
  return {
1798
2127
  // Text semantics
1799
- p: (props) => import_react5.default.createElement("p", props),
1800
- strong: (props) => import_react5.default.createElement("strong", props),
1801
- em: (props) => import_react5.default.createElement("em", props),
1802
- code: (props) => import_react5.default.createElement("code", props),
1803
- pre: (props) => import_react5.default.createElement("pre", props),
1804
- span: (props) => import_react5.default.createElement("span", props),
1805
- br: (props) => import_react5.default.createElement("br", props),
1806
- hr: (props) => import_react5.default.createElement("hr", props),
2128
+ p: (props) => import_react6.default.createElement("p", props),
2129
+ strong: (props) => import_react6.default.createElement("strong", props),
2130
+ em: (props) => import_react6.default.createElement("em", props),
2131
+ code: (props) => import_react6.default.createElement("code", props),
2132
+ pre: (props) => import_react6.default.createElement("pre", props),
2133
+ span: (props) => import_react6.default.createElement("span", props),
2134
+ br: (props) => import_react6.default.createElement("br", props),
2135
+ hr: (props) => import_react6.default.createElement("hr", props),
1807
2136
  // Lists
1808
- ul: (props) => import_react5.default.createElement("ul", props),
1809
- ol: (props) => import_react5.default.createElement("ol", props),
1810
- li: (props) => import_react5.default.createElement("li", props),
2137
+ ul: (props) => import_react6.default.createElement("ul", props),
2138
+ ol: (props) => import_react6.default.createElement("ol", props),
2139
+ li: (props) => import_react6.default.createElement("li", props),
1811
2140
  // Links & media
1812
- a: (props) => import_react5.default.createElement("a", props),
1813
- img: (props) => import_react5.default.createElement("img", props),
2141
+ a: (props) => import_react6.default.createElement("a", props),
2142
+ img: (props) => import_react6.default.createElement("img", props),
1814
2143
  // Blockquotes
1815
- blockquote: (props) => import_react5.default.createElement("blockquote", props),
2144
+ blockquote: (props) => import_react6.default.createElement("blockquote", props),
1816
2145
  // Tables
1817
- table: (props) => import_react5.default.createElement("table", props),
1818
- thead: (props) => import_react5.default.createElement("thead", props),
1819
- tbody: (props) => import_react5.default.createElement("tbody", props),
1820
- tr: (props) => import_react5.default.createElement("tr", props),
1821
- th: (props) => import_react5.default.createElement("th", props),
1822
- td: (props) => import_react5.default.createElement("td", props),
2146
+ table: (props) => import_react6.default.createElement("table", props),
2147
+ thead: (props) => import_react6.default.createElement("thead", props),
2148
+ tbody: (props) => import_react6.default.createElement("tbody", props),
2149
+ tr: (props) => import_react6.default.createElement("tr", props),
2150
+ th: (props) => import_react6.default.createElement("th", props),
2151
+ td: (props) => import_react6.default.createElement("td", props),
1823
2152
  // Generic
1824
- div: (props) => import_react5.default.createElement("div", props)
2153
+ div: (props) => import_react6.default.createElement("div", props)
1825
2154
  };
1826
2155
  }
1827
2156
  function getDefaultTableElements(overrides) {
1828
2157
  const base = {
1829
- Table: (props) => import_react5.default.createElement("table", props),
1830
- Thead: (props) => import_react5.default.createElement("thead", props),
1831
- Tbody: (props) => import_react5.default.createElement("tbody", props),
1832
- Tr: (props) => import_react5.default.createElement("tr", props),
1833
- Th: (props) => import_react5.default.createElement("th", props),
1834
- Td: (props) => import_react5.default.createElement("td", props)
2158
+ Table: (props) => import_react6.default.createElement("table", props),
2159
+ Thead: (props) => import_react6.default.createElement("thead", props),
2160
+ Tbody: (props) => import_react6.default.createElement("tbody", props),
2161
+ Tr: (props) => import_react6.default.createElement("tr", props),
2162
+ Th: (props) => import_react6.default.createElement("th", props),
2163
+ Td: (props) => import_react6.default.createElement("td", props)
1835
2164
  };
1836
2165
  return { ...base, ...overrides || {} };
1837
2166
  }
@@ -1845,12 +2174,12 @@ function mapHtmlToReact(html, elements) {
1845
2174
  children.push(element);
1846
2175
  }
1847
2176
  });
1848
- return import_react5.default.createElement(import_react5.default.Fragment, {}, ...children);
2177
+ return import_react6.default.createElement(import_react6.default.Fragment, {}, ...children);
1849
2178
  }
1850
2179
  function toReact(node, elements, key) {
1851
2180
  if (node.nodeType === Node.TEXT_NODE) {
1852
2181
  const text = node.textContent ?? "";
1853
- return import_react5.default.createElement(import_react5.default.Fragment, { key }, text);
2182
+ return import_react6.default.createElement(import_react6.default.Fragment, { key }, text);
1854
2183
  }
1855
2184
  if (node.nodeType !== Node.ELEMENT_NODE) {
1856
2185
  return null;
@@ -1872,9 +2201,9 @@ function toReact(node, elements, key) {
1872
2201
  const component = elements[tag];
1873
2202
  const elementChildren = children.length > 0 ? children : void 0;
1874
2203
  if (component) {
1875
- return import_react5.default.createElement(component, { ...props, key }, elementChildren);
2204
+ return import_react6.default.createElement(component, { ...props, key }, elementChildren);
1876
2205
  }
1877
- return import_react5.default.createElement(tag, { ...props, key }, elementChildren);
2206
+ return import_react6.default.createElement(tag, { ...props, key }, elementChildren);
1878
2207
  }
1879
2208
  function attrsToProps(attrs) {
1880
2209
  if (!attrs) return {};
@@ -1919,12 +2248,12 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
1919
2248
  nodes.forEach((node, idx) => {
1920
2249
  if (node === null || node === void 0) return;
1921
2250
  const key = `${baseKey}-${idx}`;
1922
- if (import_react5.default.isValidElement(node)) {
1923
- target.push(node.key === key ? node : import_react5.default.cloneElement(node, { key }));
2251
+ if (import_react6.default.isValidElement(node)) {
2252
+ target.push(node.key === key ? node : import_react6.default.cloneElement(node, { key }));
1924
2253
  } else if (typeof node === "string" || typeof node === "number") {
1925
- target.push(import_react5.default.createElement(import_react5.default.Fragment, { key }, node));
2254
+ target.push(import_react6.default.createElement(import_react6.default.Fragment, { key }, node));
1926
2255
  } else {
1927
- target.push(import_react5.default.createElement(import_react5.default.Fragment, { key }, node));
2256
+ target.push(import_react6.default.createElement(import_react6.default.Fragment, { key }, node));
1928
2257
  }
1929
2258
  });
1930
2259
  };
@@ -1940,7 +2269,7 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
1940
2269
  }
1941
2270
  const key = `paragraph-inline-group-${inlineGroupIndex++}`;
1942
2271
  result.push(
1943
- import_react5.default.createElement(
2272
+ import_react6.default.createElement(
1944
2273
  "p",
1945
2274
  {
1946
2275
  key,
@@ -1958,7 +2287,7 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
1958
2287
  const inlineNodes = Array.isArray(segment.inline) ? segment.inline : [];
1959
2288
  if (inlineNodes.length === 0) {
1960
2289
  if (segment.value) {
1961
- inlineBuffer.push(import_react5.default.createElement(import_react5.default.Fragment, { key }, segment.value));
2290
+ inlineBuffer.push(import_react6.default.createElement(import_react6.default.Fragment, { key }, segment.value));
1962
2291
  }
1963
2292
  break;
1964
2293
  }
@@ -1986,14 +2315,14 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
1986
2315
  const status = segment.status ?? "pending";
1987
2316
  let element;
1988
2317
  if (status === "compiled") {
1989
- element = import_react5.default.createElement("span", { className: "markdown-mdx-inline", "data-mdx-status": "compiled" });
2318
+ element = import_react6.default.createElement("span", { className: "markdown-mdx-inline", "data-mdx-status": "compiled" });
1990
2319
  } else if (status === "error") {
1991
2320
  const message = segment.value || "MDX error";
1992
- element = import_react5.default.createElement("span", { className: "markdown-mdx-inline text-destructive", "data-mdx-status": "error" }, message);
2321
+ element = import_react6.default.createElement("span", { className: "markdown-mdx-inline text-destructive", "data-mdx-status": "error" }, message);
1993
2322
  } else {
1994
- element = import_react5.default.createElement("span", { className: "markdown-mdx-inline", "data-mdx-status": status }, segment.value);
2323
+ element = import_react6.default.createElement("span", { className: "markdown-mdx-inline", "data-mdx-status": status }, segment.value);
1995
2324
  }
1996
- inlineBuffer.push(import_react5.default.createElement(import_react5.default.Fragment, { key }, element));
2325
+ inlineBuffer.push(import_react6.default.createElement(import_react6.default.Fragment, { key }, element));
1997
2326
  break;
1998
2327
  }
1999
2328
  case "html": {
@@ -2009,7 +2338,7 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
2009
2338
  result.push(element);
2010
2339
  } else if (html) {
2011
2340
  result.push(
2012
- import_react5.default.createElement("div", {
2341
+ import_react6.default.createElement("div", {
2013
2342
  key,
2014
2343
  className: "markdown-inline-html-block",
2015
2344
  dangerouslySetInnerHTML: { __html: html }
@@ -2028,7 +2357,7 @@ function renderParagraphMixedSegments(segments, inlineComponents, inlineHtmlRend
2028
2357
  flushInline();
2029
2358
  if (result.length === 0) {
2030
2359
  return [
2031
- import_react5.default.createElement(
2360
+ import_react6.default.createElement(
2032
2361
  "p",
2033
2362
  {
2034
2363
  key: "paragraph-inline-group-0",
@@ -2090,20 +2419,21 @@ var BLOCK_LEVEL_TAGS = /* @__PURE__ */ new Set([
2090
2419
  init_mdx_client();
2091
2420
 
2092
2421
  // src/mdx-coordinator.ts
2093
- var import_react6 = require("react");
2422
+ var import_react7 = require("react");
2094
2423
  init_mdx_client();
2095
2424
  function useMdxCoordinator(blocks, compileEndpoint, options) {
2096
- const mdxClientRef = (0, import_react6.useRef)(getMDXClient(compileEndpoint));
2425
+ const mdxClientRef = (0, import_react7.useRef)(getMDXClient(compileEndpoint));
2097
2426
  const mode = options?.mode ?? "server";
2098
- const [compiledMap, setCompiledMap] = (0, import_react6.useState)(/* @__PURE__ */ new Map());
2099
- const blockSignatureRef = (0, import_react6.useRef)(/* @__PURE__ */ new Map());
2100
- const applyCompiledRef = (0, import_react6.useCallback)(
2427
+ const [compiledMap, setCompiledMap] = (0, import_react7.useState)(/* @__PURE__ */ new Map());
2428
+ const blockSignatureRef = (0, import_react7.useRef)(/* @__PURE__ */ new Map());
2429
+ const failedSignatureRef = (0, import_react7.useRef)(/* @__PURE__ */ new Map());
2430
+ const applyCompiledRef = (0, import_react7.useCallback)(
2101
2431
  (block, compiledId) => {
2102
2432
  if (mode === "worker") {
2103
2433
  return;
2104
2434
  }
2105
2435
  if (options?.workerClient) {
2106
- options.workerClient.setMdxCompiled(block.id, compiledId);
2436
+ options.workerClient.setMdxCompiled(block.id, compiledId, block.payload.raw ?? "");
2107
2437
  return;
2108
2438
  }
2109
2439
  const store = options?.store;
@@ -2114,6 +2444,9 @@ function useMdxCoordinator(blocks, compileEndpoint, options) {
2114
2444
  const index = currentBlocks.findIndex((candidate) => candidate.id === block.id);
2115
2445
  if (index === -1) return;
2116
2446
  const current = currentBlocks[index];
2447
+ if ((current.payload.raw ?? "") !== (block.payload.raw ?? "")) {
2448
+ return;
2449
+ }
2117
2450
  if (current.payload.compiledMdxRef?.id === compiledId) {
2118
2451
  return;
2119
2452
  }
@@ -2139,11 +2472,17 @@ function useMdxCoordinator(blocks, compileEndpoint, options) {
2139
2472
  },
2140
2473
  [options?.workerClient, options?.store, mode]
2141
2474
  );
2142
- (0, import_react6.useEffect)(() => {
2475
+ (0, import_react7.useEffect)(() => {
2143
2476
  if (mode === "worker") {
2144
2477
  return;
2145
2478
  }
2146
- const targets = blocks.filter((b) => b.type === "mdx" && b.isFinalized && !b.payload.compiledMdxRef && !compiledMap.has(b.id));
2479
+ const targets = blocks.filter((b) => {
2480
+ if (b.type !== "mdx" || !b.isFinalized || b.payload.compiledMdxRef || compiledMap.has(b.id)) {
2481
+ return false;
2482
+ }
2483
+ const raw = b.payload.raw ?? "";
2484
+ return failedSignatureRef.current.get(b.id) !== raw;
2485
+ });
2147
2486
  if (targets.length === 0) return;
2148
2487
  let cancelled = false;
2149
2488
  (async () => {
@@ -2162,22 +2501,29 @@ function useMdxCoordinator(blocks, compileEndpoint, options) {
2162
2501
  next.set(block.id, compiled.id);
2163
2502
  return next;
2164
2503
  });
2504
+ failedSignatureRef.current.delete(block.id);
2165
2505
  applyCompiledRef(block, compiled.id);
2166
2506
  } catch (e) {
2167
2507
  console.warn("MDX compile failed for block", block.id, e);
2508
+ failedSignatureRef.current.set(block.id, block.payload.raw ?? "");
2168
2509
  if (options?.workerClient) {
2169
- options.workerClient.setMdxError(block.id, e instanceof Error ? e.message : String(e));
2510
+ options.workerClient.setMdxError(block.id, e instanceof Error ? e.message : String(e), block.payload.raw ?? "");
2170
2511
  } else if (options?.store) {
2512
+ const currentBlocks = options.store.getBlocks();
2513
+ const current = currentBlocks.find((candidate) => candidate.id === block.id);
2514
+ if (!current || (current.payload.raw ?? "") !== (block.payload.raw ?? "")) {
2515
+ continue;
2516
+ }
2171
2517
  options.store.applyPatches([
2172
2518
  {
2173
2519
  op: "setProps",
2174
2520
  at: { blockId: block.id, nodeId: block.id },
2175
2521
  props: {
2176
2522
  block: {
2177
- ...block,
2523
+ ...current,
2178
2524
  payload: {
2179
- ...block.payload,
2180
- meta: { ...block.payload.meta ?? {}, mdxStatus: "error", mdxError: e instanceof Error ? e.message : String(e) }
2525
+ ...current.payload,
2526
+ meta: { ...current.payload.meta ?? {}, mdxStatus: "error", mdxError: e instanceof Error ? e.message : String(e) }
2181
2527
  }
2182
2528
  }
2183
2529
  }
@@ -2191,7 +2537,7 @@ function useMdxCoordinator(blocks, compileEndpoint, options) {
2191
2537
  cancelled = true;
2192
2538
  };
2193
2539
  }, [blocks, compiledMap, applyCompiledRef, options?.workerClient, options?.store, mode]);
2194
- (0, import_react6.useEffect)(() => {
2540
+ (0, import_react7.useEffect)(() => {
2195
2541
  if (mode === "worker") {
2196
2542
  return;
2197
2543
  }
@@ -2210,6 +2556,7 @@ function useMdxCoordinator(blocks, compileEndpoint, options) {
2210
2556
  const currentSignature = candidate.payload.raw ?? "";
2211
2557
  if (previousSignature !== void 0 && previousSignature !== currentSignature) {
2212
2558
  next.delete(blockId);
2559
+ failedSignatureRef.current.delete(blockId);
2213
2560
  mutated = true;
2214
2561
  }
2215
2562
  }
@@ -2219,11 +2566,14 @@ function useMdxCoordinator(blocks, compileEndpoint, options) {
2219
2566
  for (const block of blocks) {
2220
2567
  if (block.type === "mdx") {
2221
2568
  signatureMap.set(block.id, block.payload.raw ?? "");
2569
+ if (!block.isFinalized || block.payload.compiledMdxRef) {
2570
+ failedSignatureRef.current.delete(block.id);
2571
+ }
2222
2572
  }
2223
2573
  }
2224
2574
  blockSignatureRef.current = signatureMap;
2225
2575
  }, [blocks, mode]);
2226
- const derivedBlocks = (0, import_react6.useMemo)(() => {
2576
+ const derivedBlocks = (0, import_react7.useMemo)(() => {
2227
2577
  if (mode === "worker") {
2228
2578
  return blocks;
2229
2579
  }
@@ -2406,7 +2756,7 @@ async function prefetchMdxBundle(request) {
2406
2756
  }
2407
2757
 
2408
2758
  // src/math/display-wrapper.tsx
2409
- var import_jsx_runtime2 = require("react/jsx-runtime");
2759
+ var import_jsx_runtime3 = require("react/jsx-runtime");
2410
2760
  var BASE_CLASS = "katex-block-wrapper my-2";
2411
2761
  var SCROLL_ROOT_CLASS = "katex-scroll relative overflow-x-hidden w-full max-w-full";
2412
2762
  var VIEWPORT_CLASS = "katex-scroll-viewport h-full w-full rounded-[inherit]";
@@ -2421,27 +2771,30 @@ function combineClassNames(base, extra) {
2421
2771
  }
2422
2772
  function DisplayMathWrapper({ children, className = "" }) {
2423
2773
  const wrapperClass = combineClassNames(BASE_CLASS, className);
2424
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: wrapperClass, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { dir: "ltr", className: SCROLL_ROOT_CLASS, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: VIEWPORT_CLASS, style: VIEWPORT_STYLE, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: SHIM_STYLE, children }) }) }) });
2774
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: wrapperClass, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { dir: "ltr", className: SCROLL_ROOT_CLASS, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: VIEWPORT_CLASS, style: VIEWPORT_STYLE, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: SHIM_STYLE, children }) }) }) });
2425
2775
  }
2426
2776
  function renderDisplayMathWithHtml(html, className) {
2427
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DisplayMathWrapper, { className, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "katex-block", dangerouslySetInnerHTML: { __html: html } }) });
2777
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DisplayMathWrapper, { className, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "katex-block", dangerouslySetInnerHTML: { __html: html } }) });
2428
2778
  }
2429
2779
 
2430
2780
  // src/renderer.tsx
2431
- var import_react13 = __toESM(require("react"), 1);
2781
+ var import_react14 = __toESM(require("react"), 1);
2432
2782
  var import_worker = require("@stream-mdx/worker");
2433
2783
  init_mdx_client();
2434
2784
 
2435
2785
  // src/renderer/code-highlight-context.tsx
2436
- var import_react7 = __toESM(require("react"), 1);
2437
- var CodeHighlightRequestContext = import_react7.default.createContext(null);
2786
+ var import_react8 = __toESM(require("react"), 1);
2787
+ var CodeHighlightRequestContext = import_react8.default.createContext(null);
2438
2788
  function useCodeHighlightRequester() {
2439
- return import_react7.default.useContext(CodeHighlightRequestContext);
2789
+ return import_react8.default.useContext(CodeHighlightRequestContext);
2440
2790
  }
2441
2791
 
2442
2792
  // src/renderer/patch-batching.ts
2443
2793
  var import_patch_batching = require("@stream-mdx/core/perf/patch-batching");
2444
2794
 
2795
+ // src/renderer/patch-commit-scheduler.ts
2796
+ var import_patch_batching2 = require("@stream-mdx/core/perf/patch-batching");
2797
+
2445
2798
  // src/renderer/patch-coalescing.ts
2446
2799
  var import_core3 = require("@stream-mdx/core");
2447
2800
 
@@ -2452,6 +2805,9 @@ var COALESCING_DURATION_ACTIVATE_MS = 6;
2452
2805
  var COALESCING_DURATION_DEACTIVATE_MS = 4;
2453
2806
  var RETAIN_TOUCHED_IN_HISTORY = typeof process !== "undefined" && process.env ? process.env.NODE_ENV !== "production" : true;
2454
2807
  var EMPTY_TOUCHED_SET = /* @__PURE__ */ new Set();
2808
+ function shouldSkipCoalescing(patches) {
2809
+ return patches.length <= 1;
2810
+ }
2455
2811
  function getDefaultNow() {
2456
2812
  if (typeof performance !== "undefined" && typeof performance.now === "function") {
2457
2813
  return () => performance.now();
@@ -2478,8 +2834,9 @@ function getDefaultCancelRaf() {
2478
2834
  }
2479
2835
  var PatchCommitScheduler = class {
2480
2836
  constructor(params) {
2481
- this.highQueue = [];
2482
- this.lowQueue = [];
2837
+ this.semanticQueue = [];
2838
+ this.enrichmentHighQueue = [];
2839
+ this.enrichmentLowQueue = [];
2483
2840
  this.scheduled = false;
2484
2841
  this.flushing = false;
2485
2842
  this.scheduledHandle = null;
@@ -2491,6 +2848,7 @@ var PatchCommitScheduler = class {
2491
2848
  this.scheduleToken = 0;
2492
2849
  this.coalescingDurationSamples = [];
2493
2850
  this.adaptiveBudgetActive = false;
2851
+ this.flushCount = 0;
2494
2852
  this.store = params.store;
2495
2853
  this.onFlush = params.onFlush;
2496
2854
  this.frameBudgetMs = Math.max(1, params.options?.frameBudgetMs ?? 10);
@@ -2506,6 +2864,8 @@ var PatchCommitScheduler = class {
2506
2864
  this.maxLowPriorityBatchesPerFlush = params.options?.maxLowPriorityBatchesPerFlush ?? 2;
2507
2865
  this.urgentQueueThreshold = Math.max(1, params.options?.urgentQueueThreshold ?? 4);
2508
2866
  this.historyLimit = Math.max(1, params.options?.historyLimit ?? 200);
2867
+ this.startupMicrotaskFlushes = Math.max(0, Math.floor(params.options?.startupMicrotaskFlushes ?? 0));
2868
+ this.adaptiveBudgeting = params.options?.adaptiveBudgeting ?? true;
2509
2869
  const requestedBatch = params.options?.batch;
2510
2870
  if (requestedBatch === "microtask") {
2511
2871
  this.batchStrategy = "microtask";
@@ -2532,19 +2892,23 @@ var PatchCommitScheduler = class {
2532
2892
  patches: input.patches,
2533
2893
  meta: input.meta ?? {},
2534
2894
  receivedAt: input.meta?.receivedAt ?? this.now(),
2895
+ kind: input.meta?.kind === "semantic" || input.meta?.kind === "enrichment" ? input.meta.kind : input.patches.some((patch) => (0, import_patch_batching2.getPatchKind)(patch) === "semantic") ? "semantic" : "enrichment",
2535
2896
  priority: input.meta?.priority === "low" ? "low" : "high"
2536
2897
  };
2537
- if (batch.priority === "low") {
2538
- this.lowQueue.push(batch);
2898
+ if (batch.kind === "semantic") {
2899
+ batch.priority = "high";
2900
+ this.semanticQueue.push(batch);
2901
+ } else if (batch.priority === "low") {
2902
+ this.enrichmentLowQueue.push(batch);
2539
2903
  } else {
2540
- this.highQueue.push(batch);
2904
+ this.enrichmentHighQueue.push(batch);
2541
2905
  }
2542
2906
  if (!this.paused) {
2543
2907
  this.schedule();
2544
2908
  }
2545
2909
  }
2546
2910
  flushAll() {
2547
- if (this.highQueue.length === 0 && this.lowQueue.length === 0 && !this.flushing) {
2911
+ if (this.semanticQueue.length === 0 && this.enrichmentHighQueue.length === 0 && this.enrichmentLowQueue.length === 0 && !this.flushing) {
2548
2912
  return null;
2549
2913
  }
2550
2914
  this.cancelScheduled();
@@ -2554,9 +2918,11 @@ var PatchCommitScheduler = class {
2554
2918
  }
2555
2919
  clear() {
2556
2920
  this.cancelScheduled();
2557
- this.highQueue = [];
2558
- this.lowQueue = [];
2921
+ this.semanticQueue = [];
2922
+ this.enrichmentHighQueue = [];
2923
+ this.enrichmentLowQueue = [];
2559
2924
  this.flushing = false;
2925
+ this.flushCount = 0;
2560
2926
  this.coalescingDurationSamples = [];
2561
2927
  this.adaptiveBudgetActive = false;
2562
2928
  this.adaptiveHighBatchCap = void 0;
@@ -2564,10 +2930,10 @@ var PatchCommitScheduler = class {
2564
2930
  this.maybeResolveIdle();
2565
2931
  }
2566
2932
  getPendingCount() {
2567
- return this.highQueue.length + this.lowQueue.length;
2933
+ return this.semanticQueue.length + this.enrichmentHighQueue.length + this.enrichmentLowQueue.length;
2568
2934
  }
2569
2935
  isIdle() {
2570
- return !this.flushing && !this.scheduled && this.highQueue.length === 0 && this.lowQueue.length === 0;
2936
+ return !this.flushing && !this.scheduled && this.semanticQueue.length === 0 && this.enrichmentHighQueue.length === 0 && this.enrichmentLowQueue.length === 0;
2571
2937
  }
2572
2938
  awaitIdle() {
2573
2939
  if (this.isIdle()) {
@@ -2607,7 +2973,8 @@ var PatchCommitScheduler = class {
2607
2973
  this.runFlush(this.frameBudgetMs, false);
2608
2974
  this.maybeResolveIdle();
2609
2975
  };
2610
- if (this.batchStrategy === "microtask" && typeof queueMicrotask === "function") {
2976
+ const useStartupMicrotask = this.batchStrategy !== "microtask" && this.startupMicrotaskFlushes > 0 && this.flushCount < this.startupMicrotaskFlushes && typeof queueMicrotask === "function";
2977
+ if ((this.batchStrategy === "microtask" || useStartupMicrotask) && typeof queueMicrotask === "function") {
2611
2978
  this.scheduledViaRaf = false;
2612
2979
  this.scheduledHandle = token;
2613
2980
  queueMicrotask(execute);
@@ -2637,12 +3004,14 @@ var PatchCommitScheduler = class {
2637
3004
  if (this.paused && !manual) {
2638
3005
  return null;
2639
3006
  }
2640
- if (this.highQueue.length === 0 && this.lowQueue.length === 0) {
3007
+ if (this.semanticQueue.length === 0 && this.enrichmentHighQueue.length === 0 && this.enrichmentLowQueue.length === 0) {
2641
3008
  return null;
2642
3009
  }
2643
3010
  this.flushing = true;
2644
3011
  const startedAt = this.now();
2645
- const initialQueueSize = this.highQueue.length + this.lowQueue.length;
3012
+ const initialSemanticQueueSize = this.semanticQueue.length;
3013
+ const initialEnrichmentQueueSize = this.enrichmentHighQueue.length + this.enrichmentLowQueue.length;
3014
+ const initialQueueSize = initialSemanticQueueSize + initialEnrichmentQueueSize;
2646
3015
  const batches = [];
2647
3016
  let totalInputPatches = 0;
2648
3017
  let totalAppliedPatches = 0;
@@ -2657,7 +3026,15 @@ var PatchCommitScheduler = class {
2657
3026
  consumed += 1;
2658
3027
  const applyStart = this.now();
2659
3028
  const queueDelayMs = Math.max(0, applyStart - next.receivedAt);
2660
- const { patches: coalesced, metrics: coalescingMetrics } = (0, import_core3.coalescePatchesWithMetrics)(next.patches, import_core3.DEFAULT_COALESCE_CONFIG);
3029
+ let coalesced;
3030
+ let coalescingMetrics;
3031
+ if (shouldSkipCoalescing(next.patches)) {
3032
+ coalesced = next.patches;
3033
+ } else {
3034
+ const result = (0, import_core3.coalescePatchesWithMetrics)(next.patches, import_core3.DEFAULT_COALESCE_CONFIG);
3035
+ coalesced = result.patches;
3036
+ coalescingMetrics = result.metrics;
3037
+ }
2661
3038
  const touched = this.store.applyPatches(coalesced, {
2662
3039
  coalesced: true,
2663
3040
  metrics: coalescingMetrics
@@ -2677,6 +3054,7 @@ var PatchCommitScheduler = class {
2677
3054
  receivedAt: next.receivedAt,
2678
3055
  appliedAt: applyStart,
2679
3056
  priority: next.priority,
3057
+ kind: next.kind,
2680
3058
  coalescing: coalescingMetrics
2681
3059
  });
2682
3060
  if (maxBatches && batches.length - startingBatchCount >= maxBatches) {
@@ -2693,27 +3071,32 @@ var PatchCommitScheduler = class {
2693
3071
  queue.splice(0, consumed);
2694
3072
  }
2695
3073
  };
2696
- const initialHighQueueSize = this.highQueue.length;
3074
+ processQueue(this.semanticQueue, void 0, Number.POSITIVE_INFINITY);
3075
+ const initialHighQueueSize = this.enrichmentHighQueue.length;
2697
3076
  const configuredHighLimit = manual || !this.maxBatchesPerFlush ? void 0 : initialHighQueueSize > this.maxBatchesPerFlush ? void 0 : this.maxBatchesPerFlush;
2698
- const highBatchLimit = this.adaptiveHighBatchCap ?? configuredHighLimit;
2699
- processQueue(this.highQueue, highBatchLimit, budgetMs);
3077
+ const highBatchLimit = this.adaptiveBudgeting ? this.adaptiveHighBatchCap ?? configuredHighLimit : configuredHighLimit;
3078
+ processQueue(this.enrichmentHighQueue, highBatchLimit, budgetMs);
2700
3079
  if (manual) {
2701
- processQueue(this.lowQueue, void 0, Number.POSITIVE_INFINITY);
2702
- } else if (this.lowQueue.length > 0) {
3080
+ processQueue(this.enrichmentLowQueue, void 0, Number.POSITIVE_INFINITY);
3081
+ } else if (this.enrichmentLowQueue.length > 0) {
2703
3082
  elapsed = this.now() - startedAt;
2704
3083
  const budgetForLow = Math.max(0, this.lowPriorityFrameBudgetMs - elapsed);
2705
- if (budgetForLow > 0) {
2706
- const initialLowQueueSize = this.lowQueue.length;
3084
+ const processedHigherPriorityWork = batches.length > 0;
3085
+ if (budgetForLow > 0 || !processedHigherPriorityWork) {
3086
+ const initialLowQueueSize = this.enrichmentLowQueue.length;
2707
3087
  const configuredLowLimit = manual || !this.maxLowPriorityBatchesPerFlush ? void 0 : initialLowQueueSize > this.maxLowPriorityBatchesPerFlush ? void 0 : this.maxLowPriorityBatchesPerFlush;
2708
- const lowBatchLimit = this.adaptiveLowBatchCap ?? configuredLowLimit;
2709
- processQueue(this.lowQueue, lowBatchLimit, budgetForLow);
3088
+ const lowBatchLimit = this.adaptiveBudgeting ? this.adaptiveLowBatchCap ?? configuredLowLimit : configuredLowLimit;
3089
+ processQueue(this.enrichmentLowQueue, lowBatchLimit, budgetForLow);
2710
3090
  }
2711
3091
  }
2712
3092
  this.flushing = false;
2713
3093
  const completedAt = this.now();
2714
3094
  const totalDurationMs = completedAt - startedAt;
2715
- const remaining = this.highQueue.length + this.lowQueue.length;
3095
+ const remainingSemantic = this.semanticQueue.length;
3096
+ const remainingEnrichment = this.enrichmentHighQueue.length + this.enrichmentLowQueue.length;
3097
+ const remaining = remainingSemantic + remainingEnrichment;
2716
3098
  if (batches.length > 0) {
3099
+ this.flushCount += 1;
2717
3100
  try {
2718
3101
  this.onFlush({
2719
3102
  batches,
@@ -2721,7 +3104,11 @@ var PatchCommitScheduler = class {
2721
3104
  totalAppliedPatches,
2722
3105
  totalDurationMs,
2723
3106
  remainingQueueSize: remaining,
3107
+ remainingSemanticQueueSize: remainingSemantic,
3108
+ remainingEnrichmentQueueSize: remainingEnrichment,
2724
3109
  queueDepthBefore: initialQueueSize,
3110
+ semanticQueueDepthBefore: initialSemanticQueueSize,
3111
+ enrichmentQueueDepthBefore: initialEnrichmentQueueSize,
2725
3112
  flushStartedAt: startedAt,
2726
3113
  flushCompletedAt: completedAt
2727
3114
  });
@@ -2732,21 +3119,27 @@ var PatchCommitScheduler = class {
2732
3119
  if (remaining > 0 && !this.paused) {
2733
3120
  this.schedule();
2734
3121
  }
2735
- const coalescingStats = this.computeCoalescingDurationStats();
2736
- this.updateAdaptiveBudget(coalescingStats.p95);
2737
- const adaptiveState = this.snapshotAdaptiveBudget(coalescingStats.p95 ?? null);
3122
+ const coalescingStats = this.adaptiveBudgeting ? this.computeCoalescingDurationStats() : { sampleCount: this.coalescingDurationSamples.length, p95: null };
3123
+ if (this.adaptiveBudgeting) {
3124
+ this.updateAdaptiveBudget(coalescingStats.p95);
3125
+ }
3126
+ const adaptiveState = this.adaptiveBudgeting ? this.snapshotAdaptiveBudget(coalescingStats.p95 ?? null) : void 0;
2738
3127
  const flushResult = batches.length > 0 ? {
2739
3128
  batches,
2740
3129
  totalPatches: totalInputPatches,
2741
3130
  totalAppliedPatches,
2742
3131
  totalDurationMs,
2743
3132
  remainingQueueSize: remaining,
3133
+ remainingSemanticQueueSize: remainingSemantic,
3134
+ remainingEnrichmentQueueSize: remainingEnrichment,
2744
3135
  queueDepthBefore: initialQueueSize,
3136
+ semanticQueueDepthBefore: initialSemanticQueueSize,
3137
+ enrichmentQueueDepthBefore: initialEnrichmentQueueSize,
2745
3138
  flushStartedAt: startedAt,
2746
3139
  flushCompletedAt: completedAt,
2747
3140
  coalescingDurationP95: coalescingStats.p95 ?? void 0,
2748
3141
  coalescingDurationSampleCount: coalescingStats.sampleCount,
2749
- adaptiveBudgetActive: adaptiveState.active,
3142
+ adaptiveBudgetActive: adaptiveState?.active,
2750
3143
  adaptiveBudgetState: adaptiveState
2751
3144
  } : null;
2752
3145
  if (flushResult) {
@@ -2782,6 +3175,9 @@ var PatchCommitScheduler = class {
2782
3175
  };
2783
3176
  }
2784
3177
  updateAdaptiveBudget(p95) {
3178
+ if (!this.adaptiveBudgeting) {
3179
+ return;
3180
+ }
2785
3181
  if (p95 !== null && p95 > COALESCING_DURATION_ACTIVATE_MS) {
2786
3182
  if (!this.adaptiveBudgetActive) {
2787
3183
  this.adaptiveBudgetActive = true;
@@ -2855,11 +3251,13 @@ var PatchCommitScheduler = class {
2855
3251
  }
2856
3252
  restart() {
2857
3253
  this.cancelScheduled();
2858
- this.highQueue = [];
2859
- this.lowQueue = [];
3254
+ this.semanticQueue = [];
3255
+ this.enrichmentHighQueue = [];
3256
+ this.enrichmentLowQueue = [];
2860
3257
  this.flushing = false;
2861
3258
  this.sequence = 0;
2862
3259
  this.history = [];
3260
+ this.flushCount = 0;
2863
3261
  this.scheduleToken++;
2864
3262
  this.paused = false;
2865
3263
  this.coalescingDurationSamples = [];
@@ -2906,6 +3304,12 @@ var PatchCommitScheduler = class {
2906
3304
  if (typeof options.historyLimit !== "undefined") {
2907
3305
  this.setHistoryLimit(options.historyLimit);
2908
3306
  }
3307
+ if (typeof options.startupMicrotaskFlushes !== "undefined") {
3308
+ this.startupMicrotaskFlushes = Math.max(0, Math.floor(options.startupMicrotaskFlushes));
3309
+ }
3310
+ if (typeof options.adaptiveBudgeting !== "undefined") {
3311
+ this.adaptiveBudgeting = options.adaptiveBudgeting;
3312
+ }
2909
3313
  if (typeof options.batch !== "undefined") {
2910
3314
  const requestedBatch = options.batch;
2911
3315
  if (requestedBatch === "microtask") {
@@ -2932,6 +3336,7 @@ var PatchCommitScheduler = class {
2932
3336
 
2933
3337
  // src/renderer/store.ts
2934
3338
  var import_core4 = require("@stream-mdx/core");
3339
+ var import_patch_batching3 = require("@stream-mdx/core/perf/patch-batching");
2935
3340
 
2936
3341
  // src/renderer/list-utils.ts
2937
3342
  function updateNodeDepth(node, depth) {
@@ -3027,12 +3432,28 @@ function snapshotToBlock(node) {
3027
3432
  }
3028
3433
  return null;
3029
3434
  }
3030
- var nodeSnapshotCache = /* @__PURE__ */ new Map();
3031
- var childrenSnapshotCache = /* @__PURE__ */ new Map();
3435
+ var nodeSnapshotCacheByMap = /* @__PURE__ */ new WeakMap();
3436
+ var childrenSnapshotCacheByMap = /* @__PURE__ */ new WeakMap();
3032
3437
  var NODE_SNAPSHOT_CACHE_LIMIT = 5e4;
3033
3438
  var CHILDREN_SNAPSHOT_CACHE_LIMIT = 5e4;
3034
3439
  var NODE_SNAPSHOT_CACHE_BUFFER = Math.max(200, Math.floor(NODE_SNAPSHOT_CACHE_LIMIT * 0.1));
3035
3440
  var CHILDREN_SNAPSHOT_CACHE_BUFFER = Math.max(200, Math.floor(CHILDREN_SNAPSHOT_CACHE_LIMIT * 0.1));
3441
+ function getNodeSnapshotCacheForMap(map) {
3442
+ let cache = nodeSnapshotCacheByMap.get(map);
3443
+ if (!cache) {
3444
+ cache = /* @__PURE__ */ new Map();
3445
+ nodeSnapshotCacheByMap.set(map, cache);
3446
+ }
3447
+ return cache;
3448
+ }
3449
+ function getChildrenSnapshotCacheForMap(map) {
3450
+ let cache = childrenSnapshotCacheByMap.get(map);
3451
+ if (!cache) {
3452
+ cache = /* @__PURE__ */ new Map();
3453
+ childrenSnapshotCacheByMap.set(map, cache);
3454
+ }
3455
+ return cache;
3456
+ }
3036
3457
  function pruneCache(cache, max, buffer) {
3037
3458
  if (cache.size <= max + buffer) return;
3038
3459
  let remaining = cache.size - max;
@@ -3042,6 +3463,14 @@ function pruneCache(cache, max, buffer) {
3042
3463
  if (remaining <= 0) break;
3043
3464
  }
3044
3465
  }
3466
+ function deleteSnapshotCacheEntry(map, id) {
3467
+ getNodeSnapshotCacheForMap(map).delete(id);
3468
+ getChildrenSnapshotCacheForMap(map).delete(id);
3469
+ }
3470
+ function clearSnapshotCaches(map) {
3471
+ getNodeSnapshotCacheForMap(map).clear();
3472
+ getChildrenSnapshotCacheForMap(map).clear();
3473
+ }
3045
3474
  var EMPTY_CHILDREN = Object.freeze([]);
3046
3475
  var EMPTY_NODE_SNAPSHOT = Object.freeze({ version: -1, node: void 0 });
3047
3476
  var EMPTY_CHILDREN_SNAPSHOT = Object.freeze({
@@ -3209,9 +3638,57 @@ function createRootRecord() {
3209
3638
  parentId: null,
3210
3639
  children: [],
3211
3640
  props: {},
3212
- version: 0
3641
+ version: 0,
3642
+ blockEpoch: 0
3213
3643
  };
3214
3644
  }
3645
+ function readNumericEpoch(value) {
3646
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
3647
+ return void 0;
3648
+ }
3649
+ return value;
3650
+ }
3651
+ function readSnapshotBlockEpoch(snapshot) {
3652
+ return readNumericEpoch(snapshot.meta?.blockEpoch);
3653
+ }
3654
+ function readPatchBlockEpoch(patch) {
3655
+ if (patch.op === "setHTML") {
3656
+ return readNumericEpoch(patch.patchMeta?.blockEpoch);
3657
+ }
3658
+ return readNumericEpoch(patch.meta?.blockEpoch);
3659
+ }
3660
+ function readPatchParseEpoch(patch) {
3661
+ if (patch.op === "setHTML") {
3662
+ return readNumericEpoch(patch.patchMeta?.parseEpoch);
3663
+ }
3664
+ return readNumericEpoch(patch.meta?.parseEpoch);
3665
+ }
3666
+ function readPatchTx(patch) {
3667
+ if (patch.op === "setHTML") {
3668
+ return readNumericEpoch(patch.patchMeta?.tx);
3669
+ }
3670
+ return readNumericEpoch(patch.meta?.tx);
3671
+ }
3672
+ function assignSubtreeBlockEpoch(map, rootId, blockEpoch, touched) {
3673
+ const root = map.get(rootId);
3674
+ if (!root) return;
3675
+ const stack = [root];
3676
+ while (stack.length > 0) {
3677
+ const node = stack.pop();
3678
+ if (!node) continue;
3679
+ if (node.blockEpoch !== blockEpoch) {
3680
+ node.blockEpoch = blockEpoch;
3681
+ node.version += 1;
3682
+ touched?.add(node.id);
3683
+ }
3684
+ for (const childId of node.children) {
3685
+ const child = map.get(childId);
3686
+ if (child) {
3687
+ stack.push(child);
3688
+ }
3689
+ }
3690
+ }
3691
+ }
3215
3692
  function ensureArray(value) {
3216
3693
  return Array.isArray(value) ? value : [];
3217
3694
  }
@@ -3271,7 +3748,7 @@ function escapeHtml2(value) {
3271
3748
  }
3272
3749
  function stripOuterLineSpan(html) {
3273
3750
  if (!html) return null;
3274
- const openTagMatch = html.match(/<span[^>]*>/i);
3751
+ const openTagMatch = html.match(/<span[^>]*class="[^"]*\bline\b[^"]*"[^>]*>/i);
3275
3752
  if (!openTagMatch) {
3276
3753
  return null;
3277
3754
  }
@@ -3320,8 +3797,7 @@ function normalizeCodeBlockChildren(nodes, parent, touched) {
3320
3797
  if (node.type !== "code-line") {
3321
3798
  anomalies.push(`type-mismatch:${node.id}:${node.type}`);
3322
3799
  nodes.delete(node.id);
3323
- nodeSnapshotCache.delete(node.id);
3324
- childrenSnapshotCache.delete(node.id);
3800
+ deleteSnapshotCacheEntry(nodes, node.id);
3325
3801
  touched.add(node.id);
3326
3802
  continue;
3327
3803
  }
@@ -3365,16 +3841,14 @@ function normalizeCodeBlockChildren(nodes, parent, touched) {
3365
3841
  const existing = nodes.get(desiredId);
3366
3842
  if (existing && existing !== node) {
3367
3843
  nodes.delete(desiredId);
3368
- nodeSnapshotCache.delete(desiredId);
3369
- childrenSnapshotCache.delete(desiredId);
3844
+ deleteSnapshotCacheEntry(nodes, desiredId);
3370
3845
  touched.add(desiredId);
3371
3846
  mutated = true;
3372
3847
  }
3373
3848
  if (node.id !== desiredId) {
3374
3849
  const previousId = node.id;
3375
3850
  nodes.delete(node.id);
3376
- nodeSnapshotCache.delete(previousId);
3377
- childrenSnapshotCache.delete(previousId);
3851
+ deleteSnapshotCacheEntry(nodes, previousId);
3378
3852
  node.id = desiredId;
3379
3853
  nodes.set(desiredId, node);
3380
3854
  touched.add(desiredId);
@@ -3405,8 +3879,7 @@ function normalizeCodeBlockChildren(nodes, parent, touched) {
3405
3879
  for (const [id, record] of nodes) {
3406
3880
  if (record.parentId === parent.id && record.type === "code-line" && !allowed.has(id)) {
3407
3881
  nodes.delete(id);
3408
- nodeSnapshotCache.delete(id);
3409
- childrenSnapshotCache.delete(id);
3882
+ deleteSnapshotCacheEntry(nodes, id);
3410
3883
  touched.add(id);
3411
3884
  mutated = true;
3412
3885
  }
@@ -3490,8 +3963,10 @@ function normalizeCodeLineProps(incoming, previous) {
3490
3963
  }
3491
3964
  function createCodeLineProps(index, text, highlight, tokens) {
3492
3965
  const safeText = typeof text === "string" ? text : "";
3493
- const sanitized = sanitizeLineInnerHtml(highlight, safeText);
3494
- const html = sanitized && sanitized.length >= safeText.length ? sanitized : escapeHtml2(safeText);
3966
+ const hasIncomingHighlight = typeof highlight === "string" && highlight.trim().length > 0;
3967
+ const sanitized = hasIncomingHighlight ? sanitizeLineInnerHtml(highlight, safeText) : null;
3968
+ const hasRenderableTokens = tokens !== void 0 && tokens !== null;
3969
+ const html = sanitized && sanitized.length >= safeText.length ? sanitized : hasRenderableTokens ? null : escapeHtml2(safeText);
3495
3970
  const props = {
3496
3971
  index,
3497
3972
  text: safeText,
@@ -3602,6 +4077,18 @@ function validateCodeBlockChildren(nodes, parent) {
3602
4077
  issues.push({ kind: "dangling-node", id });
3603
4078
  }
3604
4079
  }
4080
+ if (parent.block?.isFinalized) {
4081
+ const snapshot = (0, import_core4.createBlockSnapshot)((0, import_core4.cloneBlock)(parent.block));
4082
+ const expectedChildren = ensureArray(snapshot.children).filter((child) => child.type === "code-line");
4083
+ if (expectedChildren.length !== parent.children.length) {
4084
+ issues.push({
4085
+ kind: "line-count-mismatch",
4086
+ id: parent.id,
4087
+ expected: expectedChildren.length,
4088
+ actual: parent.children.length
4089
+ });
4090
+ }
4091
+ }
3605
4092
  return { ok: issues.length === 0, issues };
3606
4093
  }
3607
4094
  function rebuildCodeBlockFromSnapshot(nodes, parent, touched, issues) {
@@ -3618,7 +4105,7 @@ function rebuildCodeBlockFromSnapshot(nodes, parent, touched, issues) {
3618
4105
  }
3619
4106
  const snapshot = (0, import_core4.createBlockSnapshot)((0, import_core4.cloneBlock)(parent.block));
3620
4107
  removeSubtree(nodes, parent.id, touched);
3621
- const inserted = insertSnapshotAt(nodes, ancestor, index, snapshot);
4108
+ const inserted = insertSnapshotAt(nodes, ancestor, index, snapshot, touched, parent.blockEpoch);
3622
4109
  if (!inserted) {
3623
4110
  return false;
3624
4111
  }
@@ -3641,7 +4128,55 @@ function arraysEqual(a, b) {
3641
4128
  }
3642
4129
  return true;
3643
4130
  }
3644
- function buildNodeFromSnapshot(map, snapshot, parentId) {
4131
+ function expectedCodeLineId(parentId, index) {
4132
+ return `${parentId}::line:${index}`;
4133
+ }
4134
+ function collectStoreInvariantViolations(nodes) {
4135
+ const violations = [];
4136
+ for (const [id, node] of nodes) {
4137
+ if (node.type === "__root__") continue;
4138
+ if (node.children.length > 1) {
4139
+ const seen = /* @__PURE__ */ new Set();
4140
+ for (const childId of node.children) {
4141
+ if (seen.has(childId)) {
4142
+ violations.push(`duplicate child id:${id}:${childId}`);
4143
+ } else {
4144
+ seen.add(childId);
4145
+ }
4146
+ }
4147
+ }
4148
+ if (node.type === "list") {
4149
+ const parent = node.parentId ? nodes.get(node.parentId) : void 0;
4150
+ if (parent?.type === "list-item" && node.children.length === 0) {
4151
+ violations.push(`empty nested list:${id}`);
4152
+ }
4153
+ }
4154
+ if (node.type === "code") {
4155
+ for (let index = 0; index < node.children.length; index += 1) {
4156
+ const childId = node.children[index];
4157
+ const child = nodes.get(childId);
4158
+ if (!child) {
4159
+ violations.push(`missing code-line node:${node.id}:${childId}`);
4160
+ continue;
4161
+ }
4162
+ if (child.type !== "code-line") {
4163
+ violations.push(`non-code child in code block:${node.id}:${child.id}:${child.type}`);
4164
+ continue;
4165
+ }
4166
+ const expectedId = expectedCodeLineId(node.id, index);
4167
+ if (child.id !== expectedId) {
4168
+ violations.push(`code-line id mismatch:${node.id}:${child.id}:${expectedId}`);
4169
+ }
4170
+ const indexProp = typeof child.props?.index === "number" ? child.props.index : null;
4171
+ if (indexProp !== index) {
4172
+ violations.push(`code-line index mismatch:${node.id}:${child.id}:${indexProp}:${index}`);
4173
+ }
4174
+ }
4175
+ }
4176
+ }
4177
+ return violations;
4178
+ }
4179
+ function buildNodeFromSnapshot(map, snapshot, parentId, blockEpoch) {
3645
4180
  const record = {
3646
4181
  id: snapshot.id,
3647
4182
  type: snapshot.type,
@@ -3651,6 +4186,7 @@ function buildNodeFromSnapshot(map, snapshot, parentId) {
3651
4186
  meta: snapshot.meta ? { ...snapshot.meta } : void 0,
3652
4187
  range: snapshot.range ? { ...snapshot.range } : void 0,
3653
4188
  version: 0,
4189
+ blockEpoch,
3654
4190
  block: snapshotToBlock(snapshot) ?? void 0
3655
4191
  };
3656
4192
  if (record.type === "code") {
@@ -3659,7 +4195,7 @@ function buildNodeFromSnapshot(map, snapshot, parentId) {
3659
4195
  map.set(record.id, record);
3660
4196
  const childSnapshots = ensureArray(snapshot.children);
3661
4197
  for (const child of childSnapshots) {
3662
- const childRecord = buildNodeFromSnapshot(map, child, record.id);
4198
+ const childRecord = buildNodeFromSnapshot(map, child, record.id, blockEpoch);
3663
4199
  record.children.push(childRecord.id);
3664
4200
  }
3665
4201
  return record;
@@ -3687,8 +4223,7 @@ function removeSubtree(map, id, touched) {
3687
4223
  }
3688
4224
  }
3689
4225
  map.delete(node.id);
3690
- nodeSnapshotCache.delete(node.id);
3691
- childrenSnapshotCache.delete(node.id);
4226
+ deleteSnapshotCacheEntry(map, node.id);
3692
4227
  touched.add(node.id);
3693
4228
  for (const childId of node.children) {
3694
4229
  const child = map.get(childId);
@@ -3720,13 +4255,13 @@ function resolveParent(map, path) {
3720
4255
  }
3721
4256
  return map.get(path.blockId);
3722
4257
  }
3723
- function insertSnapshotAt(map, parent, index, snapshot, touched) {
4258
+ function insertSnapshotAt(map, parent, index, snapshot, touched, blockEpoch) {
3724
4259
  if (!parent) return null;
3725
4260
  const existingIndex = parent.children.indexOf(snapshot.id);
3726
4261
  if (existingIndex !== -1) {
3727
4262
  removeSubtree(map, parent.children[existingIndex], touched ?? /* @__PURE__ */ new Set());
3728
4263
  }
3729
- const record = buildNodeFromSnapshot(map, snapshot, parent.id);
4264
+ const record = buildNodeFromSnapshot(map, snapshot, parent.id, blockEpoch ?? readSnapshotBlockEpoch(snapshot) ?? parent.blockEpoch);
3730
4265
  const insertedIds = [];
3731
4266
  const queue = [record];
3732
4267
  while (queue.length > 0) {
@@ -3744,13 +4279,13 @@ function insertSnapshotAt(map, parent, index, snapshot, touched) {
3744
4279
  ensureUniqueChildren(parent, touched);
3745
4280
  return { record, insertedIds };
3746
4281
  }
3747
- function replaceSnapshotAt(map, parent, index, snapshot, touched) {
4282
+ function replaceSnapshotAt(map, parent, index, snapshot, touched, blockEpoch) {
3748
4283
  if (!parent) return;
3749
4284
  if (index < 0 || index >= parent.children.length) return;
3750
4285
  const targetId = parent.children[index];
3751
4286
  parent.children.splice(index, 1);
3752
4287
  removeSubtree(map, targetId, touched);
3753
- const inserted = insertSnapshotAt(map, parent, index, snapshot, touched);
4288
+ const inserted = insertSnapshotAt(map, parent, index, snapshot, touched, blockEpoch);
3754
4289
  if (inserted) {
3755
4290
  for (const id of inserted.insertedIds) {
3756
4291
  touched.add(id);
@@ -3770,6 +4305,24 @@ function createRendererStore(initialBlocks = []) {
3770
4305
  const listeners = /* @__PURE__ */ new Set();
3771
4306
  let notifyScheduled = false;
3772
4307
  let lastCoalescingMetrics = null;
4308
+ let invariantViolations = [];
4309
+ let transientDiagnostics = [];
4310
+ let nextBlockEpoch = 1;
4311
+ const debugCounters = {
4312
+ appendLineGuardRejected: 0,
4313
+ staleEpochRejected: 0,
4314
+ storeInvariantViolationCount: 0
4315
+ };
4316
+ const allocateBlockEpoch = (preferred) => {
4317
+ const resolved = readNumericEpoch(preferred);
4318
+ if (resolved !== void 0) {
4319
+ nextBlockEpoch = Math.max(nextBlockEpoch, resolved + 1);
4320
+ return resolved;
4321
+ }
4322
+ const epoch = nextBlockEpoch;
4323
+ nextBlockEpoch += 1;
4324
+ return epoch;
4325
+ };
3773
4326
  const getRaf = () => {
3774
4327
  if (typeof globalThis !== "undefined" && typeof globalThis.requestAnimationFrame === "function") {
3775
4328
  return globalThis.requestAnimationFrame;
@@ -3801,9 +4354,12 @@ function createRendererStore(initialBlocks = []) {
3801
4354
  }
3802
4355
  }
3803
4356
  }
4357
+ function appendDiagnostic(message) {
4358
+ transientDiagnostics = [...transientDiagnostics, message];
4359
+ invariantViolations = [...invariantViolations, message];
4360
+ }
3804
4361
  function rebuildFromBlocks(blocks) {
3805
- nodeSnapshotCache.clear();
3806
- childrenSnapshotCache.clear();
4362
+ clearSnapshotCaches(nodes);
3807
4363
  nodes = /* @__PURE__ */ new Map();
3808
4364
  const root = createRootRecord();
3809
4365
  nodes.set(root.id, root);
@@ -3812,9 +4368,12 @@ function createRendererStore(initialBlocks = []) {
3812
4368
  for (let i = 0; i < blocks.length; i++) {
3813
4369
  const block = (0, import_core4.cloneBlock)(blocks[i]);
3814
4370
  const snapshot = (0, import_core4.createBlockSnapshot)(block);
3815
- insertSnapshotAt(nodes, root, root.children.length, snapshot);
4371
+ insertSnapshotAt(nodes, root, root.children.length, snapshot, void 0, allocateBlockEpoch(readSnapshotBlockEpoch(snapshot)));
3816
4372
  }
3817
4373
  normalizeAllListDepths(nodes, /* @__PURE__ */ new Set(), import_core4.PATCH_ROOT_ID);
4374
+ transientDiagnostics = [];
4375
+ invariantViolations = collectStoreInvariantViolations(nodes);
4376
+ debugCounters.storeInvariantViolationCount += invariantViolations.length;
3818
4377
  version++;
3819
4378
  blocksDirty = true;
3820
4379
  scheduleNotify();
@@ -3879,11 +4438,57 @@ function createRendererStore(initialBlocks = []) {
3879
4438
  listDepthDirty = true;
3880
4439
  }
3881
4440
  };
3882
- const applyPropsUpdate = (at, props) => {
4441
+ const semanticTxEpochs = /* @__PURE__ */ new Map();
4442
+ const resolveBlockEpochTarget = (patch, at) => {
4443
+ if ((patch.op === "insertChild" || patch.op === "replaceChild") && at.blockId === import_core4.PATCH_ROOT_ID) {
4444
+ const nodeId = patch.node?.id;
4445
+ return nodeId ? nodes.get(nodeId) : void 0;
4446
+ }
4447
+ return nodes.get(at.blockId) ?? (at.nodeId ? nodes.get(at.nodeId) : void 0);
4448
+ };
4449
+ const rejectStaleEpochPatch = (patch, at) => {
4450
+ const expectedBlockEpoch = readPatchBlockEpoch(patch);
4451
+ const patchTx = readPatchTx(patch);
4452
+ if (expectedBlockEpoch === void 0) {
4453
+ return false;
4454
+ }
4455
+ if ((0, import_patch_batching3.getPatchKind)(patch) !== "semantic" || !at) {
4456
+ return false;
4457
+ }
4458
+ const target = resolveBlockEpochTarget(patch, at);
4459
+ if (!target || target.blockEpoch === expectedBlockEpoch) {
4460
+ return false;
4461
+ }
4462
+ const txEpoch = at.blockId && patchTx !== void 0 ? semanticTxEpochs.get(at.blockId) : void 0;
4463
+ if (txEpoch && txEpoch.tx === patchTx && txEpoch.blockEpoch === target.blockEpoch) {
4464
+ return false;
4465
+ }
4466
+ debugCounters.staleEpochRejected += 1;
4467
+ appendDiagnostic(
4468
+ `stale epoch rejected:${patch.op}:${target.id}:expected=${expectedBlockEpoch}:actual=${target.blockEpoch}`
4469
+ );
4470
+ return true;
4471
+ };
4472
+ const advanceBlockEpoch = (blockId, touchedSet, preferredEpoch, tx) => {
4473
+ if (!blockId || blockId === import_core4.PATCH_ROOT_ID) {
4474
+ return null;
4475
+ }
4476
+ const blockRoot = nodes.get(blockId);
4477
+ if (!blockRoot) {
4478
+ return null;
4479
+ }
4480
+ const nextEpoch = allocateBlockEpoch(preferredEpoch);
4481
+ assignSubtreeBlockEpoch(nodes, blockRoot.id, nextEpoch, touchedSet);
4482
+ if (tx !== void 0) {
4483
+ semanticTxEpochs.set(blockRoot.id, { tx, blockEpoch: nextEpoch });
4484
+ }
4485
+ return nextEpoch;
4486
+ };
4487
+ const applyPropsUpdate = (at, props, preferredEpoch, tx, semanticUpdate = false) => {
3883
4488
  const perfStartLocal = perfEnabled ? getPerfNow() : 0;
3884
4489
  const targetId = at.nodeId ?? at.blockId;
3885
4490
  if (!targetId) return;
3886
- const target = nodes.get(targetId);
4491
+ let target = nodes.get(targetId);
3887
4492
  if (!target) return;
3888
4493
  const parentType = target.parentId ? nodes.get(target.parentId)?.type : void 0;
3889
4494
  if (debugListPatches && (isListRelated(target.type) || isListRelated(parentType))) {
@@ -3910,6 +4515,9 @@ function createRendererStore(initialBlocks = []) {
3910
4515
  propsChanged = true;
3911
4516
  }
3912
4517
  if (propsChanged) {
4518
+ if (semanticUpdate) {
4519
+ advanceBlockEpoch(at.blockId, touched, preferredEpoch, tx);
4520
+ }
3913
4521
  target.version++;
3914
4522
  touched.add(target.id);
3915
4523
  const parent = target.parentId ? nodes.get(target.parentId) : void 0;
@@ -3973,16 +4581,56 @@ function createRendererStore(initialBlocks = []) {
3973
4581
  }
3974
4582
  }
3975
4583
  let blockChanged = false;
4584
+ let typeChanged = false;
4585
+ let rebuiltFromFinalizedBlock = false;
4586
+ let blockEpochAdvanced = false;
3976
4587
  const incomingBlock = props?.block;
3977
4588
  if (incomingBlock && typeof incomingBlock === "object") {
3978
4589
  target.block = (0, import_core4.cloneBlock)(incomingBlock);
4590
+ const previousType = target.type;
4591
+ const incomingType = typeof target.block.type === "string" ? target.block.type : target.type;
4592
+ if (incomingType !== target.type) {
4593
+ target.type = incomingType;
4594
+ typeChanged = true;
4595
+ if (isListRelated(previousType) || isListRelated(target.type)) {
4596
+ markListDepthDirty(target.id);
4597
+ }
4598
+ }
3979
4599
  if (target.type === "code") {
3980
4600
  applyCodeBlockMetadata(target);
3981
4601
  }
4602
+ if (semanticUpdate) {
4603
+ advanceBlockEpoch(at.blockId, touched, preferredEpoch, tx);
4604
+ blockEpochAdvanced = true;
4605
+ }
4606
+ const shouldRebuildFinalizedTree = !at.nodeId && target.id === at.blockId && Boolean(target.block?.isFinalized) && target.type !== "code" && Boolean(target.parentId);
4607
+ if (shouldRebuildFinalizedTree) {
4608
+ const parent = target.parentId ? nodes.get(target.parentId) : void 0;
4609
+ const index = parent ? parent.children.indexOf(target.id) : -1;
4610
+ if (parent && index !== -1) {
4611
+ const snapshot = (0, import_core4.createBlockSnapshot)((0, import_core4.cloneBlock)(target.block));
4612
+ replaceSnapshotAt(nodes, parent, index, snapshot, touched, target.blockEpoch);
4613
+ mutatedBlocks = true;
4614
+ blockChanged = true;
4615
+ rebuiltFromFinalizedBlock = true;
4616
+ const rebuilt = nodes.get(target.id);
4617
+ if (isListRelated(previousType) || isListRelated(rebuilt?.type)) {
4618
+ markListDepthDirty(target.id);
4619
+ }
4620
+ target = rebuilt ?? target;
4621
+ }
4622
+ }
3982
4623
  mutatedBlocks = true;
3983
4624
  blockChanged = true;
3984
4625
  }
3985
- if (propsChanged || blockChanged) {
4626
+ if (rebuiltFromFinalizedBlock) {
4627
+ return;
4628
+ }
4629
+ if (propsChanged || blockChanged || typeChanged) {
4630
+ if (semanticUpdate && !blockEpochAdvanced) {
4631
+ advanceBlockEpoch(at.blockId, touched, preferredEpoch, tx);
4632
+ blockEpochAdvanced = true;
4633
+ }
3986
4634
  target.version++;
3987
4635
  touched.add(target.id);
3988
4636
  let parentForNormalization;
@@ -4025,13 +4673,22 @@ function createRendererStore(initialBlocks = []) {
4025
4673
  const applyPatch = (patch) => {
4026
4674
  switch (patch.op) {
4027
4675
  case "insertChild": {
4676
+ if (rejectStaleEpochPatch(patch, patch.at)) break;
4028
4677
  const parent = resolveParent(nodes, patch.at);
4029
- const inserted = insertSnapshotAt(nodes, parent, patch.index, patch.node, touched);
4678
+ const inserted = insertSnapshotAt(
4679
+ nodes,
4680
+ parent,
4681
+ patch.index,
4682
+ patch.node,
4683
+ touched,
4684
+ allocateBlockEpoch(readPatchParseEpoch(patch) ?? readSnapshotBlockEpoch(patch.node))
4685
+ );
4030
4686
  if (inserted) {
4031
4687
  for (const id of inserted.insertedIds) {
4032
4688
  touched.add(id);
4033
4689
  }
4034
4690
  mutatedBlocks = true;
4691
+ advanceBlockEpoch(patch.at.blockId, touched, readPatchParseEpoch(patch), readPatchTx(patch));
4035
4692
  if (isListRelated(inserted.record.type) || isListRelated(parent?.type)) {
4036
4693
  markListDepthDirty(inserted.record.id);
4037
4694
  if (parent) {
@@ -4051,6 +4708,7 @@ function createRendererStore(initialBlocks = []) {
4051
4708
  break;
4052
4709
  }
4053
4710
  case "deleteChild": {
4711
+ if (rejectStaleEpochPatch(patch, patch.at)) break;
4054
4712
  const parent = resolveParent(nodes, patch.at);
4055
4713
  if (!parent) break;
4056
4714
  if (patch.index < 0 || patch.index >= parent.children.length) break;
@@ -4062,6 +4720,7 @@ function createRendererStore(initialBlocks = []) {
4062
4720
  touched.add(parent.id);
4063
4721
  ensureUniqueChildren(parent, touched);
4064
4722
  mutatedBlocks = true;
4723
+ advanceBlockEpoch(patch.at.blockId, touched, readPatchParseEpoch(patch), readPatchTx(patch));
4065
4724
  if (isListRelated(parent.type) || isListRelated(removedNode?.type)) {
4066
4725
  markListDepthDirty(parent.id);
4067
4726
  }
@@ -4078,11 +4737,20 @@ function createRendererStore(initialBlocks = []) {
4078
4737
  break;
4079
4738
  }
4080
4739
  case "replaceChild": {
4740
+ if (rejectStaleEpochPatch(patch, patch.at)) break;
4081
4741
  const parent = resolveParent(nodes, patch.at);
4082
4742
  if (!parent) break;
4083
- replaceSnapshotAt(nodes, parent, patch.index, patch.node, touched);
4743
+ replaceSnapshotAt(
4744
+ nodes,
4745
+ parent,
4746
+ patch.index,
4747
+ patch.node,
4748
+ touched,
4749
+ allocateBlockEpoch(readPatchParseEpoch(patch) ?? readSnapshotBlockEpoch(patch.node))
4750
+ );
4084
4751
  touched.add(parent.id);
4085
4752
  mutatedBlocks = true;
4753
+ advanceBlockEpoch(patch.at.blockId, touched, readPatchParseEpoch(patch), readPatchTx(patch));
4086
4754
  if (isListRelated(parent.type)) {
4087
4755
  markListDepthDirty(parent.id);
4088
4756
  }
@@ -4096,18 +4764,33 @@ function createRendererStore(initialBlocks = []) {
4096
4764
  break;
4097
4765
  }
4098
4766
  case "setProps": {
4099
- applyPropsUpdate(patch.at, patch.props);
4767
+ if (rejectStaleEpochPatch(patch, patch.at)) break;
4768
+ applyPropsUpdate(patch.at, patch.props, readPatchParseEpoch(patch), readPatchTx(patch), (0, import_patch_batching3.getPatchKind)(patch) === "semantic");
4100
4769
  break;
4101
4770
  }
4102
4771
  case "setPropsBatch": {
4103
4772
  const entries2 = Array.isArray(patch.entries) ? patch.entries : [];
4104
4773
  for (const entry of entries2) {
4105
4774
  if (!entry || !entry.at) continue;
4106
- applyPropsUpdate(entry.at, entry.props);
4775
+ const entryPatch = {
4776
+ op: "setProps",
4777
+ at: entry.at,
4778
+ props: entry.props,
4779
+ meta: entry.meta ?? patch.meta
4780
+ };
4781
+ if (rejectStaleEpochPatch(entryPatch, entry.at)) continue;
4782
+ applyPropsUpdate(
4783
+ entry.at,
4784
+ entry.props,
4785
+ readPatchParseEpoch(entryPatch),
4786
+ readPatchTx(entryPatch),
4787
+ (0, import_patch_batching3.getPatchKind)(entryPatch) === "semantic"
4788
+ );
4107
4789
  }
4108
4790
  break;
4109
4791
  }
4110
4792
  case "finalize": {
4793
+ if (rejectStaleEpochPatch(patch, patch.at)) break;
4111
4794
  const target = nodes.get(patch.at.nodeId ?? patch.at.blockId);
4112
4795
  if (!target || !target.block) break;
4113
4796
  if (!target.block.isFinalized) {
@@ -4116,6 +4799,17 @@ function createRendererStore(initialBlocks = []) {
4116
4799
  target.version++;
4117
4800
  touched.add(target.id);
4118
4801
  mutatedBlocks = true;
4802
+ if (!patch.at.nodeId && target.id === patch.at.blockId && target.type !== "code" && target.parentId) {
4803
+ const parent = nodes.get(target.parentId);
4804
+ const index = parent ? parent.children.indexOf(target.id) : -1;
4805
+ if (parent && index !== -1) {
4806
+ const snapshot = (0, import_core4.createBlockSnapshot)((0, import_core4.cloneBlock)(target.block));
4807
+ replaceSnapshotAt(nodes, parent, index, snapshot, touched, target.blockEpoch);
4808
+ if (isListRelated(target.type) || isListRelated(snapshot.type)) {
4809
+ markListDepthDirty(target.id);
4810
+ }
4811
+ }
4812
+ }
4119
4813
  }
4120
4814
  if (isListRelated(target.type)) {
4121
4815
  markListDepthDirty(target.id);
@@ -4129,6 +4823,7 @@ function createRendererStore(initialBlocks = []) {
4129
4823
  break;
4130
4824
  }
4131
4825
  case "reorder": {
4826
+ if (rejectStaleEpochPatch(patch, patch.at)) break;
4132
4827
  const parent = resolveParent(nodes, patch.at);
4133
4828
  if (!parent) break;
4134
4829
  const length = parent.children.length;
@@ -4143,6 +4838,9 @@ function createRendererStore(initialBlocks = []) {
4143
4838
  parent.children.splice(to, 0, ...moved);
4144
4839
  parent.version++;
4145
4840
  touched.add(parent.id);
4841
+ if ((0, import_patch_batching3.getPatchKind)(patch) === "semantic") {
4842
+ advanceBlockEpoch(patch.at.blockId, touched, readPatchParseEpoch(patch), readPatchTx(patch));
4843
+ }
4146
4844
  if (isListRelated(parent.type)) {
4147
4845
  markListDepthDirty(parent.id);
4148
4846
  }
@@ -4158,15 +4856,31 @@ function createRendererStore(initialBlocks = []) {
4158
4856
  break;
4159
4857
  }
4160
4858
  case "appendLines": {
4859
+ if (rejectStaleEpochPatch(patch, patch.at)) break;
4161
4860
  const parent = resolveParent(nodes, patch.at);
4162
4861
  if (!parent) break;
4163
- const startIndex = Math.max(0, Math.min(patch.startIndex, parent.children.length));
4862
+ if (parent.type !== "code") {
4863
+ debugCounters.appendLineGuardRejected += 1;
4864
+ appendDiagnostic(`appendLines target not code:${parent.id}:${parent.type}`);
4865
+ break;
4866
+ }
4867
+ const requestedStartIndex = Math.max(0, patch.startIndex);
4868
+ const startIndex = Math.max(0, Math.min(requestedStartIndex, parent.children.length));
4164
4869
  const lineCount = patch.lines?.length ?? 0;
4165
4870
  if (lineCount === 0) break;
4871
+ const prefixMatches = parent.children.every((childId, index) => childId === expectedCodeLineId(parent.id, index));
4872
+ const isStrictTailAppend = requestedStartIndex === parent.children.length;
4873
+ if (!isStrictTailAppend || !prefixMatches) {
4874
+ debugCounters.appendLineGuardRejected += 1;
4875
+ appendDiagnostic(
4876
+ `appendLines guard rejected:${parent.id}:requestedStart=${requestedStartIndex}:childCount=${parent.children.length}:prefixMatches=${prefixMatches}`
4877
+ );
4878
+ break;
4879
+ }
4166
4880
  const originalChildren = parent.children.slice();
4167
4881
  const insertedIds = [];
4168
4882
  const insertedSet = /* @__PURE__ */ new Set();
4169
- const isTrailingAppend = startIndex >= originalChildren.length;
4883
+ const isTrailingAppend = true;
4170
4884
  let parentChildrenChanged = false;
4171
4885
  let codeLinesMutated = false;
4172
4886
  for (let offset = 0; offset < lineCount; offset++) {
@@ -4208,7 +4922,8 @@ function createRendererStore(initialBlocks = []) {
4208
4922
  parentId: parent.id,
4209
4923
  children: [],
4210
4924
  props: nextLineProps,
4211
- version: 0
4925
+ version: 0,
4926
+ blockEpoch: parent.blockEpoch
4212
4927
  };
4213
4928
  nodes.set(lineId, record);
4214
4929
  touched.add(lineId);
@@ -4258,6 +4973,7 @@ function createRendererStore(initialBlocks = []) {
4258
4973
  break;
4259
4974
  }
4260
4975
  case "setHTML": {
4976
+ if (rejectStaleEpochPatch(patch, patch.at)) break;
4261
4977
  const target = nodes.get(patch.at.nodeId ?? patch.at.blockId);
4262
4978
  if (!target) break;
4263
4979
  const sanitized = patch.sanitized ? patch.html : (0, import_core4.sanitizeHTML)(patch.html);
@@ -4300,6 +5016,30 @@ function createRendererStore(initialBlocks = []) {
4300
5016
  applyPatch(patch);
4301
5017
  }
4302
5018
  }
5019
+ const finalizedTableRoots = /* @__PURE__ */ new Set();
5020
+ for (const touchedId of touched) {
5021
+ let cursor = nodes.get(touchedId);
5022
+ while (cursor && cursor.id !== import_core4.PATCH_ROOT_ID) {
5023
+ if (cursor.type === "table" && cursor.block?.isFinalized && cursor.parentId) {
5024
+ finalizedTableRoots.add(cursor.id);
5025
+ break;
5026
+ }
5027
+ cursor = cursor.parentId ? nodes.get(cursor.parentId) : void 0;
5028
+ }
5029
+ }
5030
+ if (finalizedTableRoots.size > 0) {
5031
+ for (const tableId of finalizedTableRoots) {
5032
+ const tableNode = nodes.get(tableId);
5033
+ if (!tableNode || !tableNode.block || !tableNode.parentId) continue;
5034
+ const parent = nodes.get(tableNode.parentId);
5035
+ if (!parent) continue;
5036
+ const index = parent.children.indexOf(tableNode.id);
5037
+ if (index === -1) continue;
5038
+ const snapshot = (0, import_core4.createBlockSnapshot)((0, import_core4.cloneBlock)(tableNode.block));
5039
+ replaceSnapshotAt(nodes, parent, index, snapshot, touched, tableNode.blockEpoch);
5040
+ mutatedBlocks = true;
5041
+ }
5042
+ }
4303
5043
  if (mutatedBlocks) {
4304
5044
  blocksDirty = true;
4305
5045
  }
@@ -4320,6 +5060,8 @@ function createRendererStore(initialBlocks = []) {
4320
5060
  normalizeListDepthsForIds(nodes, touched, listDepthDirtyNodes, import_core4.PATCH_ROOT_ID);
4321
5061
  }
4322
5062
  }
5063
+ invariantViolations = [...collectStoreInvariantViolations(nodes), ...transientDiagnostics];
5064
+ debugCounters.storeInvariantViolationCount += invariantViolations.length;
4323
5065
  if (touched.size > 0 || mutatedBlocks) {
4324
5066
  version++;
4325
5067
  scheduleNotify();
@@ -4368,6 +5110,7 @@ function createRendererStore(initialBlocks = []) {
4368
5110
  if (!record) {
4369
5111
  return EMPTY_NODE_SNAPSHOT;
4370
5112
  }
5113
+ const nodeSnapshotCache = getNodeSnapshotCacheForMap(nodes);
4371
5114
  const cached = nodeSnapshotCache.get(id);
4372
5115
  if (cached && cached.version === record.version && cached.node === record) {
4373
5116
  return cached;
@@ -4387,6 +5130,7 @@ function createRendererStore(initialBlocks = []) {
4387
5130
  if (!record) {
4388
5131
  return EMPTY_CHILDREN_SNAPSHOT;
4389
5132
  }
5133
+ const childrenSnapshotCache = getChildrenSnapshotCacheForMap(nodes);
4390
5134
  const cached = childrenSnapshotCache.get(id);
4391
5135
  if (cached && cached.version === record.version) {
4392
5136
  return cached;
@@ -4396,6 +5140,12 @@ function createRendererStore(initialBlocks = []) {
4396
5140
  pruneCache(childrenSnapshotCache, CHILDREN_SNAPSHOT_CACHE_LIMIT, CHILDREN_SNAPSHOT_CACHE_BUFFER);
4397
5141
  return snapshot;
4398
5142
  },
5143
+ getInvariantViolations() {
5144
+ return invariantViolations.slice();
5145
+ },
5146
+ getDebugCounters() {
5147
+ return { ...debugCounters };
5148
+ },
4399
5149
  getLastCoalescingMetrics() {
4400
5150
  return lastCoalescingMetrics;
4401
5151
  },
@@ -4410,43 +5160,43 @@ function createRendererStore(initialBlocks = []) {
4410
5160
  }
4411
5161
 
4412
5162
  // src/renderer/blocks-renderer.tsx
4413
- var import_react12 = __toESM(require("react"), 1);
5163
+ var import_react13 = __toESM(require("react"), 1);
4414
5164
  var import_core6 = require("@stream-mdx/core");
4415
5165
 
4416
5166
  // src/renderer/hooks.ts
4417
- var import_react8 = require("react");
5167
+ var import_react9 = require("react");
4418
5168
  function useRendererBlocks(store) {
4419
- return (0, import_react8.useSyncExternalStore)(
5169
+ return (0, import_react9.useSyncExternalStore)(
4420
5170
  store.subscribe,
4421
5171
  () => store.getBlocks(),
4422
5172
  () => store.getBlocks()
4423
5173
  );
4424
5174
  }
4425
5175
  function useRendererNode(store, id) {
4426
- const selector = (0, import_react8.useMemo)(() => {
5176
+ const selector = (0, import_react9.useMemo)(() => {
4427
5177
  return () => store.getNodeWithVersion(id);
4428
5178
  }, [store, id]);
4429
- const snapshot = (0, import_react8.useSyncExternalStore)(store.subscribe, selector, selector);
5179
+ const snapshot = (0, import_react9.useSyncExternalStore)(store.subscribe, selector, selector);
4430
5180
  return snapshot.node;
4431
5181
  }
4432
5182
  function useRendererChildren(store, id) {
4433
- const selector = (0, import_react8.useMemo)(() => {
5183
+ const selector = (0, import_react9.useMemo)(() => {
4434
5184
  return () => store.getChildrenWithVersion(id);
4435
5185
  }, [store, id]);
4436
- const snapshot = (0, import_react8.useSyncExternalStore)(store.subscribe, selector, selector);
5186
+ const snapshot = (0, import_react9.useSyncExternalStore)(store.subscribe, selector, selector);
4437
5187
  return snapshot.children;
4438
5188
  }
4439
5189
 
4440
5190
  // src/renderer/node-views.tsx
4441
5191
  var import_core5 = require("@stream-mdx/core");
4442
- var import_react11 = __toESM(require("react"), 1);
5192
+ var import_react12 = __toESM(require("react"), 1);
4443
5193
 
4444
5194
  // src/renderer/deferred-render-context.tsx
4445
- var import_react9 = __toESM(require("react"), 1);
4446
- var DeferredRenderContext = import_react9.default.createContext(null);
5195
+ var import_react10 = __toESM(require("react"), 1);
5196
+ var DeferredRenderContext = import_react10.default.createContext(null);
4447
5197
 
4448
5198
  // src/renderer/virtualized-code.tsx
4449
- var import_react10 = require("react");
5199
+ var import_react11 = require("react");
4450
5200
  var DEFAULT_VIRTUALIZED_CODE_CONFIG = {
4451
5201
  enabled: true,
4452
5202
  windowSize: 100,
@@ -4486,11 +5236,11 @@ function calculateCodeWindow(lines, scrollTop, containerHeight, lineHeight, conf
4486
5236
  };
4487
5237
  }
4488
5238
  function useVirtualizedCode(lines, config = DEFAULT_VIRTUALIZED_CODE_CONFIG) {
4489
- const containerRef = (0, import_react10.useRef)(null);
4490
- const [scrollTop, setScrollTop] = (0, import_react10.useState)(0);
4491
- const [containerHeight, setContainerHeight] = (0, import_react10.useState)(0);
4492
- const lineHeightRef = (0, import_react10.useRef)(20);
4493
- (0, import_react10.useEffect)(() => {
5239
+ const containerRef = (0, import_react11.useRef)(null);
5240
+ const [scrollTop, setScrollTop] = (0, import_react11.useState)(0);
5241
+ const [containerHeight, setContainerHeight] = (0, import_react11.useState)(0);
5242
+ const lineHeightRef = (0, import_react11.useRef)(20);
5243
+ (0, import_react11.useEffect)(() => {
4494
5244
  if (!containerRef.current || lines.length === 0) return;
4495
5245
  const timeoutId = setTimeout(() => {
4496
5246
  if (!containerRef.current) return;
@@ -4504,12 +5254,12 @@ function useVirtualizedCode(lines, config = DEFAULT_VIRTUALIZED_CODE_CONFIG) {
4504
5254
  }, 0);
4505
5255
  return () => clearTimeout(timeoutId);
4506
5256
  }, [lines.length]);
4507
- const handleScroll = (0, import_react10.useCallback)((e) => {
5257
+ const handleScroll = (0, import_react11.useCallback)((e) => {
4508
5258
  const target = e.currentTarget;
4509
5259
  setScrollTop(target.scrollTop);
4510
5260
  setContainerHeight(target.clientHeight);
4511
5261
  }, []);
4512
- (0, import_react10.useEffect)(() => {
5262
+ (0, import_react11.useEffect)(() => {
4513
5263
  if (!containerRef.current) return;
4514
5264
  const resizeObserver = new ResizeObserver((entries2) => {
4515
5265
  for (const entry of entries2) {
@@ -4519,10 +5269,10 @@ function useVirtualizedCode(lines, config = DEFAULT_VIRTUALIZED_CODE_CONFIG) {
4519
5269
  resizeObserver.observe(containerRef.current);
4520
5270
  return () => resizeObserver.disconnect();
4521
5271
  }, []);
4522
- const window2 = (0, import_react10.useMemo)(() => {
5272
+ const window2 = (0, import_react11.useMemo)(() => {
4523
5273
  return calculateCodeWindow(lines, scrollTop, containerHeight, lineHeightRef.current, config);
4524
5274
  }, [lines, scrollTop, containerHeight, config]);
4525
- const scrollToLine = (0, import_react10.useCallback)((lineIndex) => {
5275
+ const scrollToLine = (0, import_react11.useCallback)((lineIndex) => {
4526
5276
  if (!containerRef.current) return;
4527
5277
  const targetScrollTop = lineIndex * lineHeightRef.current;
4528
5278
  containerRef.current.scrollTop = targetScrollTop;
@@ -4539,31 +5289,31 @@ function useVirtualizedCode(lines, config = DEFAULT_VIRTUALIZED_CODE_CONFIG) {
4539
5289
  }
4540
5290
 
4541
5291
  // src/renderer/node-views.tsx
4542
- var import_jsx_runtime3 = require("react/jsx-runtime");
5292
+ var import_jsx_runtime4 = require("react/jsx-runtime");
4543
5293
  var BlockNodeRenderer = ({ store, blockId, registry }) => {
4544
5294
  const node = useRendererNode(store, blockId);
4545
5295
  const block = node?.block;
4546
5296
  if (!node || !block) return null;
4547
5297
  switch (block.type) {
4548
5298
  case "paragraph":
4549
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ParagraphBlockView, { store, blockId: block.id, registry });
5299
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ParagraphBlockView, { store, blockId: block.id, registry });
4550
5300
  case "blockquote":
4551
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(BlockquoteBlockView, { store, blockId: block.id, registry });
5301
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(BlockquoteBlockView, { store, blockId: block.id, registry });
4552
5302
  case "list":
4553
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ListBlockView, { store, blockId: block.id, registry, depth: 0 });
5303
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ListBlockView, { store, blockId: block.id, registry, depth: 0 });
4554
5304
  case "table":
4555
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TableBlockView, { store, blockId: block.id, registry });
5305
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TableBlockView, { store, blockId: block.id, registry });
4556
5306
  case "code":
4557
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CodeBlockView, { store, blockId: block.id, registry });
5307
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CodeBlockView, { store, blockId: block.id, registry });
4558
5308
  case "html":
4559
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(HtmlBlockView, { store, blockId: block.id, registry });
5309
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HtmlBlockView, { store, blockId: block.id, registry });
4560
5310
  case "mdx":
4561
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MdxBlockView, { store, blockId: block.id, registry });
5311
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MdxBlockView, { store, blockId: block.id, registry });
4562
5312
  default:
4563
5313
  return registry.renderBlock(block);
4564
5314
  }
4565
5315
  };
4566
- var ParagraphBlockView = import_react11.default.memo(({ store, blockId, registry }) => {
5316
+ var ParagraphBlockView = import_react12.default.memo(({ store, blockId, registry }) => {
4567
5317
  const node = useRendererNode(store, blockId);
4568
5318
  const block = node?.block;
4569
5319
  const childIds = useRendererChildren(store, blockId);
@@ -4578,12 +5328,12 @@ var ParagraphBlockView = import_react11.default.memo(({ store, blockId, registry
4578
5328
  if (segments2.length > 0) {
4579
5329
  const allowMixedStreaming = Boolean(meta.allowMixedStreaming);
4580
5330
  if (!allowMixedStreaming) {
4581
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "markdown-paragraph streaming-partial", children: raw });
5331
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "markdown-paragraph streaming-partial", children: raw });
4582
5332
  }
4583
5333
  const structured = renderParagraphMixedSegments(segments2, inlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
4584
5334
  if (structured.length === 1) {
4585
5335
  const [single] = structured;
4586
- return import_react11.default.isValidElement(single) ? single : single;
5336
+ return import_react12.default.isValidElement(single) ? single : single;
4587
5337
  }
4588
5338
  return structured;
4589
5339
  }
@@ -4601,26 +5351,26 @@ var ParagraphBlockView = import_react11.default.memo(({ store, blockId, registry
4601
5351
  const structured = renderParagraphMixedSegments(derivedSegments, inlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
4602
5352
  if (structured.length === 1) {
4603
5353
  const [single] = structured;
4604
- return import_react11.default.isValidElement(single) ? single : single;
5354
+ return import_react12.default.isValidElement(single) ? single : single;
4605
5355
  }
4606
5356
  return structured;
4607
5357
  }
4608
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "markdown-paragraph streaming-partial", children: renderInlineNodes(inlineNodes2, inlineComponents) });
5358
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "markdown-paragraph streaming-partial", children: renderInlineNodes(inlineNodes2, inlineComponents) });
4609
5359
  }
4610
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "markdown-paragraph streaming-partial", children: raw });
5360
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "markdown-paragraph streaming-partial", children: raw });
4611
5361
  }
4612
5362
  const propsBlock = node.props?.block;
4613
5363
  const inlineStatus = propsBlock?.payload?.meta?.inlineStatus ?? block.payload.meta?.inlineStatus ?? node.props?.inlineStatus;
4614
5364
  if (inlineStatus && inlineStatus !== "complete") {
4615
5365
  const raw = typeof block.payload.raw === "string" ? block.payload.raw : "";
4616
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "markdown-paragraph", children: raw });
5366
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "markdown-paragraph", children: raw });
4617
5367
  }
4618
5368
  const segments = Array.isArray(block.payload.meta?.mixedSegments) ? block.payload.meta.mixedSegments : void 0;
4619
5369
  if (segments && segments.length > 0) {
4620
5370
  const structured = renderParagraphMixedSegments(segments, inlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
4621
5371
  if (structured.length === 1) {
4622
5372
  const [single] = structured;
4623
- return import_react11.default.isValidElement(single) ? single : single;
5373
+ return import_react12.default.isValidElement(single) ? single : single;
4624
5374
  }
4625
5375
  return structured;
4626
5376
  }
@@ -4637,31 +5387,31 @@ var ParagraphBlockView = import_react11.default.memo(({ store, blockId, registry
4637
5387
  const structured = renderParagraphMixedSegments(derivedSegments, inlineComponents, DEFAULT_INLINE_HTML_RENDERERS);
4638
5388
  if (structured.length === 1) {
4639
5389
  const [single] = structured;
4640
- return import_react11.default.isValidElement(single) ? single : single;
5390
+ return import_react12.default.isValidElement(single) ? single : single;
4641
5391
  }
4642
5392
  return structured;
4643
5393
  }
4644
5394
  const ParagraphComponent = registry.getBlockComponent("paragraph");
4645
- const baseElement = import_react11.default.createElement(ParagraphComponent, {
5395
+ const baseElement = import_react12.default.createElement(ParagraphComponent, {
4646
5396
  inlines: block.payload.inline ?? [],
4647
5397
  raw: block.payload.raw,
4648
5398
  meta: block.payload.meta
4649
5399
  });
4650
5400
  if (childIds.length > 0) {
4651
- const renderedChildren = childIds.map((childId) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MixedSegmentView, { store, nodeId: childId, inlineComponents }, childId));
4652
- if (import_react11.default.isValidElement(baseElement)) {
5401
+ const renderedChildren = childIds.map((childId) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MixedSegmentView, { store, nodeId: childId, inlineComponents }, childId));
5402
+ if (import_react12.default.isValidElement(baseElement)) {
4653
5403
  const { children: _ignored, className = "markdown-paragraph", inlines: _inlines, raw: _raw, meta: _meta, ...rest } = baseElement.props ?? {};
4654
- return import_react11.default.createElement("p", { ...rest, className }, renderedChildren);
5404
+ return import_react12.default.createElement("p", { ...rest, className }, renderedChildren);
4655
5405
  }
4656
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "markdown-paragraph", children: renderedChildren });
5406
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "markdown-paragraph", children: renderedChildren });
4657
5407
  }
4658
- if (import_react11.default.isValidElement(baseElement)) {
5408
+ if (import_react12.default.isValidElement(baseElement)) {
4659
5409
  return baseElement;
4660
5410
  }
4661
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "markdown-paragraph", children: renderInlineNodes(block.payload.inline ?? [], inlineComponents) });
5411
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "markdown-paragraph", children: renderInlineNodes(block.payload.inline ?? [], inlineComponents) });
4662
5412
  });
4663
5413
  ParagraphBlockView.displayName = "ParagraphBlockView";
4664
- var BlockquoteBlockView = import_react11.default.memo(({ store, blockId, registry }) => {
5414
+ var BlockquoteBlockView = import_react12.default.memo(({ store, blockId, registry }) => {
4665
5415
  const node = useRendererNode(store, blockId);
4666
5416
  const block = node?.block;
4667
5417
  const childIds = useRendererChildren(store, blockId);
@@ -4679,9 +5429,9 @@ var BlockquoteBlockView = import_react11.default.memo(({ store, blockId, registr
4679
5429
  return lines.map((line, idx) => {
4680
5430
  const key = `${keyPrefix}${offset}`;
4681
5431
  offset += line.length + 1;
4682
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "markdown-blockquote-line", children: [
5432
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "markdown-blockquote-line", children: [
4683
5433
  line,
4684
- idx < lastIndex ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("br", {}) : null
5434
+ idx < lastIndex ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("br", {}) : null
4685
5435
  ] }, key);
4686
5436
  });
4687
5437
  };
@@ -4707,7 +5457,7 @@ var BlockquoteBlockView = import_react11.default.memo(({ store, blockId, registr
4707
5457
  elements.push(htmlNode);
4708
5458
  } else {
4709
5459
  elements.push(
4710
- import_react11.default.createElement("span", {
5460
+ import_react12.default.createElement("span", {
4711
5461
  key: `blockquote-html-${block.id}-${segmentIndex}`,
4712
5462
  className: "markdown-inline-html",
4713
5463
  /* biome-ignore lint/security/noDangerouslySetInnerHtml: segment content is sanitized by the worker before streaming */
@@ -4719,16 +5469,16 @@ var BlockquoteBlockView = import_react11.default.memo(({ store, blockId, registr
4719
5469
  }
4720
5470
  case "mdx":
4721
5471
  elements.push(
4722
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { "data-mdx-status": segment.status ?? "pending", children: segment.value }, `blockquote-mdx-${block.id}-${segmentIndex}`)
5472
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "data-mdx-status": segment.status ?? "pending", children: segment.value }, `blockquote-mdx-${block.id}-${segmentIndex}`)
4723
5473
  );
4724
5474
  break;
4725
5475
  default: {
4726
5476
  const inline = renderInlineContent(segment.inline, `blockquote-text-inline-${block.id}-${segmentIndex}-`);
4727
5477
  if (inline) {
4728
- elements.push(/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react11.default.Fragment, { children: inline }, `blockquote-inline-${block.id}-${segmentIndex}`));
5478
+ elements.push(/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react12.default.Fragment, { children: inline }, `blockquote-inline-${block.id}-${segmentIndex}`));
4729
5479
  } else {
4730
5480
  elements.push(
4731
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react11.default.Fragment, { children: renderTextWithBreaks(segment.value, `blockquote-text-${block.id}-${segmentIndex}-`) }, `blockquote-text-${block.id}-${segmentIndex}`)
5481
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react12.default.Fragment, { children: renderTextWithBreaks(segment.value, `blockquote-text-${block.id}-${segmentIndex}-`) }, `blockquote-text-${block.id}-${segmentIndex}`)
4732
5482
  );
4733
5483
  }
4734
5484
  break;
@@ -4745,9 +5495,9 @@ var BlockquoteBlockView = import_react11.default.memo(({ store, blockId, registr
4745
5495
  const streamingContent = mixedSegmentElements.length ? mixedSegmentElements : inlineElements ? inlineElements : fallbackElements;
4746
5496
  const shouldShowStreaming = !block.isFinalized && (!streamingContent || Array.isArray(streamingContent) && streamingContent.length === 0);
4747
5497
  const className = shouldShowStreaming ? "markdown-blockquote streaming-partial" : "markdown-blockquote";
4748
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("blockquote", { className, children: streamingContent });
5498
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("blockquote", { className, children: streamingContent });
4749
5499
  }
4750
- const childContent = childIds.map((childId) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MixedSegmentView, { store, nodeId: childId, inlineComponents }, childId));
5500
+ const childContent = childIds.map((childId) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MixedSegmentView, { store, nodeId: childId, inlineComponents }, childId));
4751
5501
  const renderedContent = (() => {
4752
5502
  if (mixedSegmentElements.length > 0) {
4753
5503
  return mixedSegmentElements;
@@ -4767,7 +5517,7 @@ var BlockquoteBlockView = import_react11.default.memo(({ store, blockId, registr
4767
5517
  return null;
4768
5518
  })();
4769
5519
  const BlockquoteComponent = registry.getBlockComponent("blockquote");
4770
- const baseElement = import_react11.default.createElement(
5520
+ const baseElement = import_react12.default.createElement(
4771
5521
  BlockquoteComponent,
4772
5522
  {
4773
5523
  inlines: block.payload.inline ?? [],
@@ -4775,13 +5525,13 @@ var BlockquoteBlockView = import_react11.default.memo(({ store, blockId, registr
4775
5525
  },
4776
5526
  renderedContent
4777
5527
  );
4778
- if (import_react11.default.isValidElement(baseElement)) {
5528
+ if (import_react12.default.isValidElement(baseElement)) {
4779
5529
  return baseElement;
4780
5530
  }
4781
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("blockquote", { className: "markdown-blockquote", children: renderedContent });
5531
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("blockquote", { className: "markdown-blockquote", children: renderedContent });
4782
5532
  });
4783
5533
  BlockquoteBlockView.displayName = "BlockquoteBlockView";
4784
- var MixedSegmentView = import_react11.default.memo(({ store, nodeId, inlineComponents }) => {
5534
+ var MixedSegmentView = import_react12.default.memo(({ store, nodeId, inlineComponents }) => {
4785
5535
  const node = useRendererNode(store, nodeId);
4786
5536
  if (!node) return null;
4787
5537
  switch (node.type) {
@@ -4809,7 +5559,7 @@ var MixedSegmentView = import_react11.default.memo(({ store, nodeId, inlineCompo
4809
5559
  return rendered;
4810
5560
  }
4811
5561
  if (!html) return null;
4812
- return import_react11.default.createElement("span", {
5562
+ return import_react12.default.createElement("span", {
4813
5563
  className: "markdown-inline-html",
4814
5564
  /* biome-ignore lint/security/noDangerouslySetInnerHtml: html is sanitized upstream before reaching the renderer */
4815
5565
  dangerouslySetInnerHTML: { __html: html }
@@ -4821,32 +5571,32 @@ var MixedSegmentView = import_react11.default.memo(({ store, nodeId, inlineCompo
4821
5571
  const status = node.props?.status ?? "pending";
4822
5572
  const raw = typeof node.props?.raw === "string" ? node.props?.raw : "";
4823
5573
  if (status === "compiled") {
4824
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "markdown-mdx-inline", "data-mdx-status": "compiled" });
5574
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "markdown-mdx-inline", "data-mdx-status": "compiled" });
4825
5575
  }
4826
5576
  if (status === "error") {
4827
5577
  const message = raw || "MDX error";
4828
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "markdown-mdx-inline text-destructive", "data-mdx-status": "error", children: message });
5578
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "markdown-mdx-inline text-destructive", "data-mdx-status": "error", children: message });
4829
5579
  }
4830
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "markdown-mdx-inline", "data-mdx-status": status, children: status === "compiled" ? "" : raw });
5580
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "markdown-mdx-inline", "data-mdx-status": status, children: status === "compiled" ? "" : raw });
4831
5581
  }
4832
5582
  default:
4833
5583
  return null;
4834
5584
  }
4835
5585
  });
4836
5586
  MixedSegmentView.displayName = "MixedSegmentView";
4837
- var HtmlBlockView = import_react11.default.memo(({ store, blockId, registry }) => {
5587
+ var HtmlBlockView = import_react12.default.memo(({ store, blockId, registry }) => {
4838
5588
  const node = useRendererNode(store, blockId);
4839
5589
  if (!node || !node.block) return null;
4840
5590
  return registry.renderBlock(node.block);
4841
5591
  });
4842
5592
  HtmlBlockView.displayName = "HtmlBlockView";
4843
- var MdxBlockView = import_react11.default.memo(({ store, blockId, registry }) => {
5593
+ var MdxBlockView = import_react12.default.memo(({ store, blockId, registry }) => {
4844
5594
  const node = useRendererNode(store, blockId);
4845
5595
  if (!node || !node.block) return null;
4846
5596
  return registry.renderBlock(node.block);
4847
5597
  });
4848
5598
  MdxBlockView.displayName = "MdxBlockView";
4849
- var ListBlockView = import_react11.default.memo(
5599
+ var ListBlockView = import_react12.default.memo(
4850
5600
  ({ store, blockId, registry, depth = 0 }) => {
4851
5601
  const node = useRendererNode(store, blockId);
4852
5602
  const block = node?.block;
@@ -4855,7 +5605,7 @@ var ListBlockView = import_react11.default.memo(
4855
5605
  const ordered = Boolean(node?.props?.ordered ?? block?.payload.meta?.ordered);
4856
5606
  const Tag = ordered ? "ol" : "ul";
4857
5607
  const listDebugEnabled = isListPatchDebugEnabled();
4858
- const listItemIds = import_react11.default.useMemo(() => {
5608
+ const listItemIds = import_react12.default.useMemo(() => {
4859
5609
  const ids = [];
4860
5610
  for (const childId of childIds) {
4861
5611
  const childNode = store.getNode(childId);
@@ -4865,7 +5615,7 @@ var ListBlockView = import_react11.default.memo(
4865
5615
  }
4866
5616
  return ids;
4867
5617
  }, [childIds, store]);
4868
- import_react11.default.useEffect(() => {
5618
+ import_react12.default.useEffect(() => {
4869
5619
  if (!listDebugEnabled) return;
4870
5620
  const childTypes = childIds.map((childId) => store.getNode(childId)?.type ?? "missing");
4871
5621
  console.info("[stream-mdx:list-render]", {
@@ -4880,8 +5630,10 @@ var ListBlockView = import_react11.default.memo(
4880
5630
  isFinalized: block?.isFinalized ?? false
4881
5631
  });
4882
5632
  }, [listDebugEnabled, blockId, depth, ordered, childIds, listItemIds, store, block?.isFinalized]);
4883
- const listStyle = import_react11.default.useMemo(() => {
4884
- if (!ordered || listItemIds.length === 0) return void 0;
5633
+ const { listStyle, markerDigits } = import_react12.default.useMemo(() => {
5634
+ if (!ordered || listItemIds.length === 0) {
5635
+ return { listStyle: void 0, markerDigits: 1 };
5636
+ }
4885
5637
  let maxDigits = 1;
4886
5638
  listItemIds.forEach((childId, index) => {
4887
5639
  const childNode = store.getNode(childId);
@@ -4893,20 +5645,26 @@ var ListBlockView = import_react11.default.memo(
4893
5645
  const digits = digitMatch ? digitMatch.length : text.length;
4894
5646
  if (digits > maxDigits) maxDigits = digits;
4895
5647
  });
4896
- const baseIndent = depth === 0 ? "2.5rem" : depth === 1 ? "2rem" : "1.5rem";
5648
+ const baseIndent = depth === 0 ? "2rem" : depth === 1 ? "1.75rem" : "1.5rem";
5649
+ const extraDigits = Math.max(0, maxDigits - 1);
4897
5650
  return {
4898
- ["--list-indent"]: `calc(${baseIndent} + ${maxDigits}ch)`
5651
+ markerDigits: maxDigits,
5652
+ listStyle: {
5653
+ ["--list-indent"]: extraDigits > 0 ? `calc(${baseIndent} + ${extraDigits}ch)` : baseIndent,
5654
+ ["--list-marker-digits"]: String(maxDigits)
5655
+ }
4899
5656
  };
4900
5657
  }, [ordered, listItemIds, store, depth]);
4901
5658
  if (listItemIds.length === 0) return null;
4902
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
5659
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4903
5660
  Tag,
4904
5661
  {
4905
5662
  className: `markdown-list ${ordered ? "ordered" : "unordered"}`,
4906
5663
  "data-list-depth": depth,
5664
+ "data-marker-digits": ordered ? markerDigits : void 0,
4907
5665
  "data-list-id": listDebugEnabled ? blockId : void 0,
4908
5666
  style: listStyle,
4909
- children: listItemIds.map((childId, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
5667
+ children: listItemIds.map((childId, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
4910
5668
  ListItemView,
4911
5669
  {
4912
5670
  store,
@@ -4924,7 +5682,7 @@ var ListBlockView = import_react11.default.memo(
4924
5682
  }
4925
5683
  );
4926
5684
  ListBlockView.displayName = "ListBlockView";
4927
- var ListItemView = import_react11.default.memo(({ store, nodeId, inlineComponents, registry, ordered, index, depth }) => {
5685
+ var ListItemView = import_react12.default.memo(({ store, nodeId, inlineComponents, registry, ordered, index, depth }) => {
4928
5686
  const node = useRendererNode(store, nodeId);
4929
5687
  const childIds = useRendererChildren(store, nodeId);
4930
5688
  const inline = node?.props?.inline ?? [];
@@ -4939,7 +5697,7 @@ var ListItemView = import_react11.default.memo(({ store, nodeId, inlineComponent
4939
5697
  const counterText = !isTask ? isOrdered ? marker ? marker : `${inferredIndex + 1}.` : "\u2022" : void 0;
4940
5698
  const listDebugEnabled = isListPatchDebugEnabled();
4941
5699
  const inlineLength = inline.length;
4942
- const [segmentChildIds, contentChildIds] = import_react11.default.useMemo(() => {
5700
+ const [segmentChildIds, contentChildIds] = import_react12.default.useMemo(() => {
4943
5701
  const segments = [];
4944
5702
  const structural = [];
4945
5703
  for (const childId of childIds) {
@@ -4953,34 +5711,34 @@ var ListItemView = import_react11.default.memo(({ store, nodeId, inlineComponent
4953
5711
  }
4954
5712
  return [segments, structural];
4955
5713
  }, [childIds, store]);
4956
- const segmentElements = import_react11.default.useMemo(() => {
4957
- return segmentChildIds.map((childId) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MixedSegmentView, { store, nodeId: childId, inlineComponents }, childId));
5714
+ const segmentElements = import_react12.default.useMemo(() => {
5715
+ return segmentChildIds.map((childId) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MixedSegmentView, { store, nodeId: childId, inlineComponents }, childId));
4958
5716
  }, [segmentChildIds, store, inlineComponents]);
4959
- const primaryContent = import_react11.default.useMemo(() => {
5717
+ const primaryContent = import_react12.default.useMemo(() => {
4960
5718
  if (segmentChildIds.length > 0) {
4961
5719
  return segmentElements;
4962
5720
  }
4963
5721
  return renderInlineNodes(inline, inlineComponents);
4964
5722
  }, [segmentChildIds, segmentElements, inline, inlineComponents]);
4965
- const trailingChildren = import_react11.default.useMemo(() => {
5723
+ const trailingChildren = import_react12.default.useMemo(() => {
4966
5724
  return contentChildIds.map((childId) => {
4967
5725
  const childNode = store.getNode(childId);
4968
5726
  if (!childNode) return null;
4969
5727
  switch (childNode.type) {
4970
5728
  case "paragraph": {
4971
5729
  const childInline = childNode.props?.inline ?? [];
4972
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "markdown-list-item-paragraph", children: renderInlineNodes(childInline, inlineComponents) }, childId);
5730
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "markdown-list-item-paragraph", children: renderInlineNodes(childInline, inlineComponents) }, childId);
4973
5731
  }
4974
5732
  case "list":
4975
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ListBlockView, { store, blockId: childId, registry, depth: depth + 1 }, childId);
5733
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ListBlockView, { store, blockId: childId, registry, depth: depth + 1 }, childId);
4976
5734
  default:
4977
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(BlockNodeRenderer, { store, blockId: childId, registry }, childId);
5735
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(BlockNodeRenderer, { store, blockId: childId, registry }, childId);
4978
5736
  }
4979
5737
  });
4980
5738
  }, [contentChildIds, store, inlineComponents, registry, depth]);
4981
5739
  const filteredChildren = trailingChildren.filter((child) => Boolean(child));
4982
5740
  const hasChildren = filteredChildren.length > 0;
4983
- import_react11.default.useEffect(() => {
5741
+ import_react12.default.useEffect(() => {
4984
5742
  if (!listDebugEnabled) return;
4985
5743
  const childTypes = childIds.map((childId) => store.getNode(childId)?.type ?? "missing");
4986
5744
  console.info("[stream-mdx:list-item-render]", {
@@ -5016,7 +5774,7 @@ var ListItemView = import_react11.default.memo(({ store, nodeId, inlineComponent
5016
5774
  store,
5017
5775
  block?.isFinalized
5018
5776
  ]);
5019
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
5777
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
5020
5778
  "li",
5021
5779
  {
5022
5780
  className: `markdown-list-item${isTask ? " markdown-list-item-task" : ""}`,
@@ -5024,44 +5782,44 @@ var ListItemView = import_react11.default.memo(({ store, nodeId, inlineComponent
5024
5782
  "data-list-depth": depth,
5025
5783
  "data-list-item-id": listDebugEnabled ? nodeId : void 0,
5026
5784
  children: [
5027
- isTask ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "markdown-task", children: [
5028
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "checkbox", className: "markdown-task-checkbox", checked: isChecked, readOnly: true, disabled: true, tabIndex: -1, "aria-checked": isChecked }),
5029
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "markdown-task-content", children: primaryContent })
5785
+ isTask ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "markdown-task", children: [
5786
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "checkbox", className: "markdown-task-checkbox", checked: isChecked, readOnly: true, disabled: true, tabIndex: -1, "aria-checked": isChecked }),
5787
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "markdown-task-content", children: primaryContent })
5030
5788
  ] }) : primaryContent,
5031
- hasChildren ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "markdown-list-item-children", children: filteredChildren }) : null
5789
+ hasChildren ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "markdown-list-item-children", children: filteredChildren }) : null
5032
5790
  ]
5033
5791
  }
5034
5792
  );
5035
5793
  });
5036
5794
  ListItemView.displayName = "ListItemView";
5037
- var TableBlockView = import_react11.default.memo(({ store, blockId, registry }) => {
5795
+ var TableBlockView = import_react12.default.memo(({ store, blockId, registry }) => {
5038
5796
  const tableElements = registry.getTableElements();
5039
5797
  const childIds = useRendererChildren(store, blockId);
5040
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(tableElements.Table, { className: "markdown-table w-full caption-bottom text-base", children: childIds.map((sectionId) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TableSectionView, { store, nodeId: sectionId, registry }, sectionId)) });
5798
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(tableElements.Table, { className: "markdown-table w-full caption-bottom text-base", children: childIds.map((sectionId) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TableSectionView, { store, nodeId: sectionId, registry }, sectionId)) });
5041
5799
  });
5042
5800
  TableBlockView.displayName = "TableBlockView";
5043
- var TableSectionView = import_react11.default.memo(({ store, nodeId, registry }) => {
5801
+ var TableSectionView = import_react12.default.memo(({ store, nodeId, registry }) => {
5044
5802
  const node = useRendererNode(store, nodeId);
5045
5803
  if (!node) return null;
5046
5804
  const tableElements = registry.getTableElements();
5047
5805
  if (node.type === "table-header") {
5048
5806
  const childIds = useRendererChildren(store, nodeId);
5049
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(tableElements.Thead, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(tableElements.Tr, { children: childIds.map((cellId) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TableCellView, { store, nodeId: cellId, registry }, cellId)) }) });
5807
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(tableElements.Thead, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(tableElements.Tr, { children: childIds.map((cellId) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TableCellView, { store, nodeId: cellId, registry }, cellId)) }) });
5050
5808
  }
5051
5809
  if (node.type === "table-body") {
5052
5810
  const rowIds = useRendererChildren(store, nodeId);
5053
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(tableElements.Tbody, { children: rowIds.map((rowId) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TableRowView, { store, nodeId: rowId, registry }, rowId)) });
5811
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(tableElements.Tbody, { children: rowIds.map((rowId) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TableRowView, { store, nodeId: rowId, registry }, rowId)) });
5054
5812
  }
5055
5813
  return null;
5056
5814
  });
5057
5815
  TableSectionView.displayName = "TableSectionView";
5058
- var TableRowView = import_react11.default.memo(({ store, nodeId, registry }) => {
5816
+ var TableRowView = import_react12.default.memo(({ store, nodeId, registry }) => {
5059
5817
  const tableElements = registry.getTableElements();
5060
5818
  const cellIds = useRendererChildren(store, nodeId);
5061
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(tableElements.Tr, { children: cellIds.map((cellId) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TableCellView, { store, nodeId: cellId, registry }, cellId)) });
5819
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(tableElements.Tr, { children: cellIds.map((cellId) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TableCellView, { store, nodeId: cellId, registry }, cellId)) });
5062
5820
  });
5063
5821
  TableRowView.displayName = "TableRowView";
5064
- var TableCellView = import_react11.default.memo(({ store, nodeId, registry }) => {
5822
+ var TableCellView = import_react12.default.memo(({ store, nodeId, registry }) => {
5065
5823
  const node = useRendererNode(store, nodeId);
5066
5824
  const inlineComponents = registry.getInlineComponents();
5067
5825
  const tableElements = registry.getTableElements();
@@ -5071,22 +5829,23 @@ var TableCellView = import_react11.default.memo(({ store, nodeId, registry }) =>
5071
5829
  const align = node.props?.align;
5072
5830
  const content = renderInlineNodes(inline, inlineComponents);
5073
5831
  const alignProps = align ? { align } : void 0;
5074
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Tag, { ...alignProps, children: content });
5832
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Tag, { ...alignProps, children: content });
5075
5833
  });
5076
5834
  TableCellView.displayName = "TableCellView";
5077
- var CodeBlockView = import_react11.default.memo(({ store, blockId, registry }) => {
5835
+ var CodeBlockView = import_react12.default.memo(({ store, blockId, registry }) => {
5078
5836
  const node = useRendererNode(store, blockId);
5079
5837
  const childIds = useRendererChildren(store, blockId);
5080
5838
  const CodeComponent = registry.getBlockComponent("code");
5081
- const deferredConfig = import_react11.default.useContext(DeferredRenderContext);
5082
- const deferredRef = import_react11.default.useRef(null);
5839
+ const deferredConfig = import_react12.default.useContext(DeferredRenderContext);
5840
+ const deferredRef = import_react12.default.useRef(null);
5083
5841
  const shouldRenderDeferred = useDeferredRender(
5084
5842
  deferredRef,
5085
5843
  deferredConfig ? { ...deferredConfig, enabled: true } : { enabled: false }
5086
5844
  );
5087
5845
  if (!node || !node.block) return null;
5846
+ const blockIsFinalized = node.block.isFinalized;
5088
5847
  const nodeVersion = node.version;
5089
- const lines = import_react11.default.useMemo(() => {
5848
+ const lines = import_react12.default.useMemo(() => {
5090
5849
  const seenIds = /* @__PURE__ */ new Set();
5091
5850
  const seenIndices = /* @__PURE__ */ new Set();
5092
5851
  const deduped = [];
@@ -5115,17 +5874,29 @@ var CodeBlockView = import_react11.default.memo(({ store, blockId, registry }) =
5115
5874
  const lang = typeof node.props?.lang === "string" ? node.props?.lang : node.block.payload.meta?.lang;
5116
5875
  const preAttrs = node.props?.preAttrs ?? void 0;
5117
5876
  const codeAttrs = node.props?.codeAttrs ?? void 0;
5877
+ const blockMeta = node.block.payload.meta ?? void 0;
5878
+ const lazyEnabled = Boolean(blockMeta?.lazyTokenization);
5879
+ const lazyTokenizedUntil = typeof blockMeta?.lazyTokenizedUntil === "number" ? blockMeta.lazyTokenizedUntil : 0;
5880
+ const lazyHighlightedLines = Array.isArray(blockMeta?.highlightedLines) ? blockMeta.highlightedLines.length : 0;
5881
+ const lazyTokenLines = Array.isArray(blockMeta?.tokenLines) ? blockMeta.tokenLines.length : 0;
5882
+ const lazySourceTextLineCount = import_react12.default.useMemo(() => {
5883
+ const raw = typeof node.block?.payload.raw === "string" ? node.block.payload.raw : "";
5884
+ const metaCode = typeof blockMeta?.code === "string" ? blockMeta.code : null;
5885
+ const sourceText = resolveCodeSourceText(raw, metaCode);
5886
+ if (sourceText.length === 0) return 0;
5887
+ return sourceText.split("\n").length;
5888
+ }, [blockMeta, node.block?.payload.raw]);
5889
+ const totalLazyLineCount = Math.max(lines.length, lazyHighlightedLines, lazyTokenLines, lazySourceTextLineCount);
5118
5890
  const virtualizationConfig = DEFAULT_VIRTUALIZED_CODE_CONFIG;
5119
5891
  const virtualizationDisabled = typeof process !== "undefined" && typeof process.env === "object" && process.env.STREAM_MDX_DISABLE_VIRTUALIZED_CODE === "true";
5120
- const shouldVirtualize = !virtualizationDisabled && virtualizationConfig.enabled && lines.length >= virtualizationConfig.virtualizeThreshold;
5892
+ const canVirtualize = node.block.isFinalized && !lazyEnabled;
5893
+ const shouldVirtualize = canVirtualize && !virtualizationDisabled && virtualizationConfig.enabled && lines.length >= virtualizationConfig.virtualizeThreshold;
5121
5894
  const virtualization = useVirtualizedCode(lines, shouldVirtualize ? virtualizationConfig : { ...virtualizationConfig, enabled: false });
5122
5895
  const highlightRequester = useCodeHighlightRequester();
5123
- const lazyEnabled = Boolean(node.block.payload.meta?.lazyTokenization);
5124
- const lazyTokenizedUntil = typeof node.block.payload.meta?.lazyTokenizedUntil === "number" ? node.block.payload.meta.lazyTokenizedUntil : 0;
5125
- const lastRangeRef = import_react11.default.useRef(null);
5126
- const rafRef = import_react11.default.useRef(null);
5127
- const idleRef = import_react11.default.useRef(null);
5128
- import_react11.default.useEffect(() => {
5896
+ const lastRangeRef = import_react12.default.useRef(null);
5897
+ const rafRef = import_react12.default.useRef(null);
5898
+ const idleRef = import_react12.default.useRef(null);
5899
+ import_react12.default.useEffect(() => {
5129
5900
  if (!shouldVirtualize || !lazyEnabled || !highlightRequester) return;
5130
5901
  const { visibleStart, visibleEnd, startIndex, endIndex } = virtualization.window;
5131
5902
  if (endIndex <= lazyTokenizedUntil) return;
@@ -5202,30 +5973,112 @@ var CodeBlockView = import_react11.default.memo(({ store, blockId, registry }) =
5202
5973
  virtualization.window.startIndex,
5203
5974
  virtualization.window.endIndex
5204
5975
  ]);
5205
- const highlightedHtml = import_react11.default.useMemo(() => {
5206
- if (!shouldVirtualize && node.block?.payload.highlightedHtml) {
5207
- return node.block.payload.highlightedHtml;
5976
+ import_react12.default.useEffect(() => {
5977
+ if (shouldVirtualize || !blockIsFinalized || !lazyEnabled || !highlightRequester) return;
5978
+ if (totalLazyLineCount <= 0 || lazyTokenizedUntil >= totalLazyLineCount) return;
5979
+ const nextRange = {
5980
+ visibleStart: 0,
5981
+ visibleEnd: totalLazyLineCount,
5982
+ prefetchStart: 0,
5983
+ prefetchEnd: totalLazyLineCount,
5984
+ tokenizedUntil: lazyTokenizedUntil
5985
+ };
5986
+ const last = lastRangeRef.current;
5987
+ if (last && last.visibleStart === nextRange.visibleStart && last.visibleEnd === nextRange.visibleEnd && last.prefetchStart === nextRange.prefetchStart && last.prefetchEnd === nextRange.prefetchEnd && last.tokenizedUntil === nextRange.tokenizedUntil) {
5988
+ return;
5208
5989
  }
5990
+ lastRangeRef.current = nextRange;
5991
+ if (rafRef.current !== null && typeof cancelAnimationFrame === "function") {
5992
+ cancelAnimationFrame(rafRef.current);
5993
+ }
5994
+ const requestFullHighlight = () => {
5995
+ highlightRequester({
5996
+ blockId,
5997
+ startLine: 0,
5998
+ endLine: totalLazyLineCount,
5999
+ priority: "visible",
6000
+ reason: "finalize-full"
6001
+ });
6002
+ rafRef.current = null;
6003
+ };
6004
+ if (typeof requestAnimationFrame === "function") {
6005
+ rafRef.current = requestAnimationFrame(requestFullHighlight);
6006
+ } else {
6007
+ requestFullHighlight();
6008
+ }
6009
+ }, [blockId, blockIsFinalized, highlightRequester, lazyEnabled, lazyTokenizedUntil, shouldVirtualize, totalLazyLineCount]);
6010
+ const highlightedHtml = import_react12.default.useMemo(() => {
6011
+ const blockHtml = node.block?.payload.highlightedHtml ?? "";
6012
+ const raw = typeof node.block?.payload.raw === "string" ? node.block.payload.raw : "";
6013
+ const metaCode = typeof node.block?.payload.meta?.code === "string" ? (node.block?.payload.meta).code : null;
6014
+ const sourceText = resolveCodeSourceText(raw, metaCode);
6015
+ const sourceEndsWithNewline = sourceText.endsWith("\n");
6016
+ const sourceLines = sourceText.length > 0 ? sourceText.split("\n") : [];
6017
+ const rawFallbackLines = buildCodeFallbackLines(raw);
6018
+ const deterministicWrapperAttrs = (0, import_core5.getDefaultCodeWrapperAttributes)(lang);
6019
+ const composedPreAttrs = deterministicWrapperAttrs.preAttrs;
6020
+ const composedCodeAttrs = deterministicWrapperAttrs.codeAttrs;
6021
+ const shouldAppendTerminalNewline = (renderedLines) => {
6022
+ if (!sourceEndsWithNewline || renderedLines.length === 0 || lines.length === 0) {
6023
+ return false;
6024
+ }
6025
+ const lastRendered = renderedLines[renderedLines.length - 1];
6026
+ const lastKnown = lines[lines.length - 1];
6027
+ if (!lastRendered || !lastKnown || lastRendered.index !== lastKnown.index || lastRendered.text === "") {
6028
+ return false;
6029
+ }
6030
+ const expectedRenderedLineCount = Math.max(0, sourceLines.length - 1);
6031
+ const expectedLastRenderedLine = sourceLines.length >= 2 ? sourceLines[sourceLines.length - 2] ?? "" : "";
6032
+ return renderedLines.length === expectedRenderedLineCount && lastRendered.text === expectedLastRenderedLine;
6033
+ };
5209
6034
  if (lines.length > 0) {
5210
6035
  const hasLineHtml = lines.some((line) => typeof line.html === "string" && line.html.length > 0);
5211
- if (!hasLineHtml && node.block?.payload.highlightedHtml) {
5212
- return node.block.payload.highlightedHtml;
6036
+ if (!hasLineHtml && blockHtml) {
6037
+ return blockHtml;
5213
6038
  }
5214
6039
  if (shouldVirtualize) {
5215
- return composeHighlightedHtml(virtualization.window.visibleLines, preAttrs, codeAttrs);
6040
+ return composeHighlightedHtml(
6041
+ virtualization.window.visibleLines,
6042
+ composedPreAttrs,
6043
+ composedCodeAttrs,
6044
+ shouldAppendTerminalNewline(virtualization.window.visibleLines)
6045
+ );
5216
6046
  }
5217
- return composeHighlightedHtml(lines, preAttrs, codeAttrs);
6047
+ return composeHighlightedHtml(lines, composedPreAttrs, composedCodeAttrs, shouldAppendTerminalNewline(lines));
6048
+ }
6049
+ if (!shouldVirtualize && blockHtml) {
6050
+ const hasHighlightedLines = blockHtml.includes('class="line"');
6051
+ if (!hasHighlightedLines && rawFallbackLines.length > 0) {
6052
+ return composeHighlightedHtml(
6053
+ rawFallbackLines,
6054
+ composedPreAttrs,
6055
+ composedCodeAttrs,
6056
+ sourceEndsWithNewline && rawFallbackLines[rawFallbackLines.length - 1]?.text !== ""
6057
+ );
6058
+ }
6059
+ return blockHtml;
5218
6060
  }
5219
- const blockHtml = node.block?.payload.highlightedHtml ?? "";
5220
6061
  if (blockHtml?.trim().match(/^```[\w-]*\s*$/)) {
5221
- const raw = node.block?.payload.raw ?? "";
5222
- if (raw.trim().length > 0) {
5223
- return composeHighlightedHtml([{ index: 0, text: raw, html: null, id: "temp" }], preAttrs, codeAttrs);
6062
+ if (rawFallbackLines.length > 0) {
6063
+ return composeHighlightedHtml(
6064
+ rawFallbackLines,
6065
+ composedPreAttrs,
6066
+ composedCodeAttrs,
6067
+ sourceEndsWithNewline && rawFallbackLines[rawFallbackLines.length - 1]?.text !== ""
6068
+ );
5224
6069
  }
5225
6070
  }
6071
+ if (!blockHtml && rawFallbackLines.length > 0) {
6072
+ return composeHighlightedHtml(
6073
+ rawFallbackLines,
6074
+ composedPreAttrs,
6075
+ composedCodeAttrs,
6076
+ sourceEndsWithNewline && rawFallbackLines[rawFallbackLines.length - 1]?.text !== ""
6077
+ );
6078
+ }
5226
6079
  return blockHtml;
5227
- }, [shouldVirtualize, node.block?.payload.highlightedHtml, lines, preAttrs, codeAttrs, virtualization.window.visibleLines, node.block?.payload.raw]);
5228
- const rendered = /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
6080
+ }, [blockIsFinalized, shouldVirtualize, node.block?.payload.highlightedHtml, node.block?.payload.meta, lines, lang, virtualization.window.visibleLines, node.block?.payload.raw]);
6081
+ const rendered = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
5229
6082
  CodeComponent,
5230
6083
  {
5231
6084
  html: highlightedHtml,
@@ -5236,20 +6089,26 @@ var CodeBlockView = import_react11.default.memo(({ store, blockId, registry }) =
5236
6089
  codeAttrs
5237
6090
  }
5238
6091
  );
6092
+ const effectiveLineCount = import_react12.default.useMemo(() => {
6093
+ if (lines.length > 0) {
6094
+ return lines.length;
6095
+ }
6096
+ return 1;
6097
+ }, [lines.length]);
5239
6098
  const codeFrameClass = "not-prose flex flex-col rounded-lg border border-input pt-1 font-mono text-sm";
5240
6099
  const codeMetricsAttrs = {
5241
6100
  "data-code-block": "true",
5242
6101
  "data-block-id": blockId,
5243
6102
  "data-code-virtualized": shouldVirtualize ? "true" : "false",
5244
- "data-code-total-lines": String(lines.length),
5245
- "data-code-mounted-lines": String(shouldVirtualize ? virtualization.window.mountedLines : lines.length),
6103
+ "data-code-total-lines": String(effectiveLineCount),
6104
+ "data-code-mounted-lines": String(shouldVirtualize ? virtualization.window.mountedLines : effectiveLineCount),
5246
6105
  "data-code-window-size": String(virtualization.config.windowSize)
5247
6106
  };
5248
6107
  const codeView = shouldVirtualize ? (() => {
5249
6108
  const { containerRef, window: window2, handleScroll, lineHeight } = virtualization;
5250
6109
  const spacerTop = window2.startIndex * lineHeight;
5251
6110
  const spacerBottom = (window2.totalLines - window2.endIndex) * lineHeight;
5252
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("pre", { className: codeFrameClass, ...codeMetricsAttrs, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
6111
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("pre", { className: codeFrameClass, ...codeMetricsAttrs, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
5253
6112
  "div",
5254
6113
  {
5255
6114
  ref: containerRef,
@@ -5257,13 +6116,13 @@ var CodeBlockView = import_react11.default.memo(({ store, blockId, registry }) =
5257
6116
  style: { overflowY: "auto", overflowX: "hidden", maxHeight: "600px" },
5258
6117
  onScroll: handleScroll,
5259
6118
  children: [
5260
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { height: spacerTop }, "aria-hidden": "true" }),
6119
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { height: spacerTop }, "aria-hidden": "true" }),
5261
6120
  rendered,
5262
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { height: spacerBottom }, "aria-hidden": "true" })
6121
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { height: spacerBottom }, "aria-hidden": "true" })
5263
6122
  ]
5264
6123
  }
5265
6124
  ) });
5266
- })() : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("pre", { className: codeFrameClass, ...codeMetricsAttrs, children: rendered });
6125
+ })() : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("pre", { className: codeFrameClass, ...codeMetricsAttrs, children: rendered });
5267
6126
  const blockComponentMap = registry.getBlockComponentMap();
5268
6127
  const MermaidComponent = Object.prototype.hasOwnProperty.call(blockComponentMap, "mermaid") ? blockComponentMap.mermaid : null;
5269
6128
  if ((lang ?? "").toLowerCase() === "mermaid" && MermaidComponent) {
@@ -5271,14 +6130,14 @@ var CodeBlockView = import_react11.default.memo(({ store, blockId, registry }) =
5271
6130
  const fenced = (0, import_core5.stripCodeFence)(raw);
5272
6131
  const code = fenced.hadFence ? fenced.code : raw;
5273
6132
  if (deferredConfig) {
5274
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: deferredRef, children: shouldRenderDeferred ? import_react11.default.createElement(MermaidComponent, {
6133
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ref: deferredRef, children: shouldRenderDeferred ? import_react12.default.createElement(MermaidComponent, {
5275
6134
  code,
5276
6135
  renderCode: codeView,
5277
6136
  meta: node.block.payload.meta,
5278
6137
  isFinalized: node.block.isFinalized
5279
6138
  }) : codeView });
5280
6139
  }
5281
- return import_react11.default.createElement(MermaidComponent, {
6140
+ return import_react12.default.createElement(MermaidComponent, {
5282
6141
  code,
5283
6142
  renderCode: codeView,
5284
6143
  meta: node.block.payload.meta,
@@ -5288,21 +6147,152 @@ var CodeBlockView = import_react11.default.memo(({ store, blockId, registry }) =
5288
6147
  return codeView;
5289
6148
  });
5290
6149
  CodeBlockView.displayName = "CodeBlockView";
5291
- function composeHighlightedHtml(lines, preAttrs, codeAttrs) {
6150
+ function composeHighlightedHtml(lines, preAttrs, codeAttrs, appendTerminalNewline = false) {
5292
6151
  const lineMarkup = lines.map((line) => {
5293
- const content = line.html ?? escapeHtml3(line.text);
6152
+ const content = line.html ?? renderTokenLineHtml(line.tokens) ?? escapeHtml3(line.text);
5294
6153
  const dataLine = Number.isFinite(line.index) ? ` data-line="${line.index + 1}"` : "";
5295
6154
  return `<span class="line"${dataLine}>${content}</span>`;
5296
6155
  }).join("\n");
5297
6156
  const preAttr = attrsToString(preAttrs);
5298
6157
  const codeAttr = attrsToString(codeAttrs);
5299
- return `<pre${preAttr}><code${codeAttr}>${lineMarkup}
5300
- </code></pre>`;
6158
+ return `<pre${preAttr}><code${codeAttr}>${lineMarkup}${appendTerminalNewline ? "\n" : ""}</code></pre>`;
6159
+ }
6160
+ var TOKEN_FONT_STYLE_ITALIC = 1;
6161
+ var TOKEN_FONT_STYLE_BOLD = 2;
6162
+ var TOKEN_FONT_STYLE_UNDERLINE = 4;
6163
+ var TOKEN_FONT_STYLE_STRIKETHROUGH = 8;
6164
+ function renderTokenLineHtml(tokens) {
6165
+ if (!tokens || !Array.isArray(tokens.spans)) {
6166
+ return null;
6167
+ }
6168
+ return mergeRenderableTokenSpans(tokens.spans).map((span) => renderTokenSpanHtml(span)).join("");
6169
+ }
6170
+ function renderTokenSpanHtml(span) {
6171
+ const dark = span.v?.dark;
6172
+ const light = span.v?.light;
6173
+ const single = span.s;
6174
+ const styles = [];
6175
+ if (dark?.fg) {
6176
+ styles.push(`--shiki-dark:${dark.fg}`);
6177
+ }
6178
+ if (light?.fg) {
6179
+ styles.push(`--shiki-light:${light.fg}`);
6180
+ }
6181
+ if (!light?.fg && !dark?.fg && single?.fg) {
6182
+ styles.push(`color:${single.fg}`);
6183
+ }
6184
+ const fontStyle = light?.fs ?? dark?.fs ?? single?.fs;
6185
+ if (typeof fontStyle === "number" && fontStyle > 0) {
6186
+ if (fontStyle & TOKEN_FONT_STYLE_ITALIC) {
6187
+ styles.push("font-style: italic");
6188
+ }
6189
+ if (fontStyle & TOKEN_FONT_STYLE_BOLD) {
6190
+ styles.push("font-weight: bold");
6191
+ }
6192
+ const decorations = [];
6193
+ if (fontStyle & TOKEN_FONT_STYLE_UNDERLINE) {
6194
+ decorations.push("underline");
6195
+ }
6196
+ if (fontStyle & TOKEN_FONT_STYLE_STRIKETHROUGH) {
6197
+ decorations.push("line-through");
6198
+ }
6199
+ if (decorations.length > 0) {
6200
+ styles.push(`text-decoration: ${decorations.join(" ")}`);
6201
+ }
6202
+ }
6203
+ const content = escapeHtml3(span.t ?? "");
6204
+ if (styles.length === 0) {
6205
+ return content;
6206
+ }
6207
+ return `<span style="${styles.join(";")}">${content}</span>`;
6208
+ }
6209
+ function mergeRenderableTokenSpans(spans) {
6210
+ if (spans.length <= 1) {
6211
+ return spans.slice();
6212
+ }
6213
+ const merged = [];
6214
+ let pendingWhitespace = "";
6215
+ for (const span of spans) {
6216
+ const text = typeof span.t === "string" ? span.t : "";
6217
+ if (/^[\t ]+$/.test(text)) {
6218
+ pendingWhitespace += text;
6219
+ continue;
6220
+ }
6221
+ const nextSpan = pendingWhitespace ? { ...span, t: `${pendingWhitespace}${text}` } : span;
6222
+ pendingWhitespace = "";
6223
+ const previous = merged[merged.length - 1];
6224
+ if (previous && sameTokenSpanStyle(previous, nextSpan)) {
6225
+ previous.t += nextSpan.t;
6226
+ } else {
6227
+ merged.push({ ...nextSpan });
6228
+ }
6229
+ }
6230
+ if (pendingWhitespace) {
6231
+ const previous = merged[merged.length - 1];
6232
+ if (previous) {
6233
+ previous.t += pendingWhitespace;
6234
+ } else {
6235
+ merged.push({ t: pendingWhitespace });
6236
+ }
6237
+ }
6238
+ return merged;
6239
+ }
6240
+ function sameTokenSpanStyle(a, b) {
6241
+ const variantKeys = /* @__PURE__ */ new Set([
6242
+ ...Object.keys(a.v ?? {}),
6243
+ ...Object.keys(b.v ?? {})
6244
+ ]);
6245
+ for (const key of variantKeys) {
6246
+ const aStyle = a.v?.[key];
6247
+ const bStyle = b.v?.[key];
6248
+ if ((aStyle?.fg ?? null) !== (bStyle?.fg ?? null)) return false;
6249
+ if ((aStyle?.bg ?? null) !== (bStyle?.bg ?? null)) return false;
6250
+ if ((aStyle?.fs ?? null) !== (bStyle?.fs ?? null)) return false;
6251
+ }
6252
+ if ((a.s?.fg ?? null) !== (b.s?.fg ?? null)) return false;
6253
+ if ((a.s?.bg ?? null) !== (b.s?.bg ?? null)) return false;
6254
+ if ((a.s?.fs ?? null) !== (b.s?.fs ?? null)) return false;
6255
+ return true;
6256
+ }
6257
+ function resolveCodeSourceText(raw, metaCode) {
6258
+ if (metaCode !== null) {
6259
+ return metaCode.replace(/\r\n?/g, "\n");
6260
+ }
6261
+ if (!raw) return "";
6262
+ const normalized = raw.replace(/\r\n?/g, "\n");
6263
+ const fenced = (0, import_core5.stripCodeFence)(normalized);
6264
+ return fenced.hadFence ? fenced.code : normalized;
5301
6265
  }
5302
6266
  function attrsToString(attrs) {
5303
6267
  if (!attrs) return "";
5304
6268
  return Object.entries(attrs).map(([key, value]) => ` ${key}="${escapeAttribute(value)}"`).join("");
5305
6269
  }
6270
+ function buildCodeFallbackLines(raw) {
6271
+ const normalized = normalizeCodeFallbackRaw(raw);
6272
+ if (normalized.length === 0) {
6273
+ if (/^\s*```[^\n]*\n?\s*$/.test(raw)) {
6274
+ return [{ id: "temp-0", index: 0, text: "", html: null }];
6275
+ }
6276
+ return [];
6277
+ }
6278
+ return normalized.split("\n").map((line, index) => ({
6279
+ id: `temp-${index}`,
6280
+ index,
6281
+ text: line,
6282
+ html: null
6283
+ }));
6284
+ }
6285
+ function normalizeCodeFallbackRaw(raw) {
6286
+ if (!raw) return "";
6287
+ const normalized = raw.replace(/\r\n?/g, "\n");
6288
+ const fenced = (0, import_core5.stripCodeFence)(normalized);
6289
+ if (!fenced.hadFence) {
6290
+ return normalized.replace(/\n+$/, "");
6291
+ }
6292
+ let code = fenced.code;
6293
+ code = code.replace(/\n+$/, "");
6294
+ return code;
6295
+ }
5306
6296
  function escapeHtml3(value) {
5307
6297
  return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
5308
6298
  }
@@ -5311,22 +6301,22 @@ function escapeAttribute(value) {
5311
6301
  }
5312
6302
 
5313
6303
  // src/renderer/blocks-renderer.tsx
5314
- var MarkdownBlocksRenderer = import_react12.default.memo(({ blocks, componentRegistry, className = "markdown-renderer", style, store }) => {
6304
+ var MarkdownBlocksRenderer = import_react13.default.memo(({ blocks, componentRegistry, className = "markdown-renderer", style, store }) => {
5315
6305
  if (store) {
5316
- return import_react12.default.createElement(
6306
+ return import_react13.default.createElement(
5317
6307
  "div",
5318
6308
  {
5319
6309
  className,
5320
6310
  style: { contain: "content", ...style ?? {} }
5321
6311
  // CSS containment for performance
5322
6312
  },
5323
- import_react12.default.createElement(StoreBackedBlocks, { store, componentRegistry })
6313
+ import_react13.default.createElement(StoreBackedBlocks, { store, componentRegistry })
5324
6314
  );
5325
6315
  }
5326
- const renderedBlocks = (0, import_react12.useMemo)(() => {
6316
+ const renderedBlocks = (0, import_react13.useMemo)(() => {
5327
6317
  return blocks.map((block) => {
5328
6318
  const key = (0, import_core6.getBlockKey)(block);
5329
- return import_react12.default.createElement(BlockRenderer, {
6319
+ return import_react13.default.createElement(BlockRenderer, {
5330
6320
  key,
5331
6321
  block,
5332
6322
  componentRegistry,
@@ -5334,7 +6324,7 @@ var MarkdownBlocksRenderer = import_react12.default.memo(({ blocks, componentReg
5334
6324
  });
5335
6325
  });
5336
6326
  }, [blocks, componentRegistry]);
5337
- return import_react12.default.createElement(
6327
+ return import_react13.default.createElement(
5338
6328
  "div",
5339
6329
  {
5340
6330
  className,
@@ -5344,23 +6334,23 @@ var MarkdownBlocksRenderer = import_react12.default.memo(({ blocks, componentReg
5344
6334
  renderedBlocks
5345
6335
  );
5346
6336
  });
5347
- var StoreBackedBlocks = import_react12.default.memo(
6337
+ var StoreBackedBlocks = import_react13.default.memo(
5348
6338
  ({ store, componentRegistry }) => {
5349
6339
  const blockIds = useRendererChildren(store, import_core6.PATCH_ROOT_ID);
5350
- return import_react12.default.createElement(
5351
- import_react12.default.Fragment,
6340
+ return import_react13.default.createElement(
6341
+ import_react13.default.Fragment,
5352
6342
  null,
5353
- blockIds.map((blockId) => import_react12.default.createElement(BlockNodeRenderer, { key: blockId, store, blockId, registry: componentRegistry }))
6343
+ blockIds.map((blockId) => import_react13.default.createElement(BlockNodeRenderer, { key: blockId, store, blockId, registry: componentRegistry }))
5354
6344
  );
5355
6345
  }
5356
6346
  );
5357
6347
  StoreBackedBlocks.displayName = "StoreBackedBlocks";
5358
- var BlockRenderer = import_react12.default.memo(({ block, componentRegistry, isFinalized }) => {
5359
- const element = (0, import_react12.useMemo)(() => {
6348
+ var BlockRenderer = import_react13.default.memo(({ block, componentRegistry, isFinalized }) => {
6349
+ const element = (0, import_react13.useMemo)(() => {
5360
6350
  return componentRegistry.renderBlock(block);
5361
6351
  }, [block, componentRegistry]);
5362
6352
  const className = `markdown-block markdown-block-${block.type} ${isFinalized ? "finalized" : "dirty"}`;
5363
- return import_react12.default.cloneElement(element, {
6353
+ return import_react13.default.cloneElement(element, {
5364
6354
  className: `${element.props.className || ""} ${className}`.trim(),
5365
6355
  "data-block-id": block.id,
5366
6356
  "data-finalized": isFinalized
@@ -5426,7 +6416,9 @@ var MarkdownRenderer = class {
5426
6416
  lowPriorityFrameBudgetMs: this.config.performance?.lowPriorityFrameBudgetMs,
5427
6417
  urgentQueueThreshold: this.config.performance?.urgentQueueThreshold,
5428
6418
  batch: this.config.performance?.batch,
5429
- historyLimit: this.config.performance?.historyLimit
6419
+ historyLimit: this.config.performance?.historyLimit,
6420
+ startupMicrotaskFlushes: this.config.performance?.startupMicrotaskFlushes,
6421
+ adaptiveBudgeting: this.config.performance?.adaptiveBudgeting
5430
6422
  }
5431
6423
  });
5432
6424
  }
@@ -5620,18 +6612,8 @@ var MarkdownRenderer = class {
5620
6612
  const receivedAt = typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
5621
6613
  const batches = (0, import_patch_batching.splitPatchBatch)(message.patches);
5622
6614
  batches.forEach((batch, index) => {
5623
- const hasStructural = batch.some((patch) => {
5624
- switch (patch.op) {
5625
- case "insertChild":
5626
- case "replaceChild":
5627
- case "deleteChild":
5628
- case "reorder":
5629
- return true;
5630
- default:
5631
- return false;
5632
- }
5633
- });
5634
- const priority = hasStructural ? "high" : batch.some(import_patch_batching.isHeavyPatch) ? "low" : "high";
6615
+ const hasSemantic = batch.some((patch) => (0, import_patch_batching.getPatchKind)(patch) === "semantic");
6616
+ const priority = hasSemantic ? "high" : batch.some(import_patch_batching.isHeavyPatch) ? "low" : "high";
5635
6617
  this.patchScheduler.enqueue({
5636
6618
  patches: batch,
5637
6619
  meta: {
@@ -5768,10 +6750,10 @@ var MarkdownRenderer = class {
5768
6750
  }
5769
6751
  };
5770
6752
  function useMarkdownRenderer(config = {}) {
5771
- const [renderer] = (0, import_react13.useState)(() => new MarkdownRenderer(config));
5772
- const [blocks, setBlocks] = (0, import_react13.useState)([]);
5773
- const workerRef = (0, import_react13.useRef)(null);
5774
- (0, import_react13.useEffect)(() => {
6753
+ const [renderer] = (0, import_react14.useState)(() => new MarkdownRenderer(config));
6754
+ const [blocks, setBlocks] = (0, import_react14.useState)([]);
6755
+ const workerRef = (0, import_react14.useRef)(null);
6756
+ (0, import_react14.useEffect)(() => {
5775
6757
  if (!workerRef.current) {
5776
6758
  const fallbackFactory = () => new Worker("/workers/markdown-worker.js", { type: "module", name: "markdown-v2" });
5777
6759
  const worker = (0, import_worker.createDefaultWorker)() ?? fallbackFactory();
@@ -5786,41 +6768,41 @@ function useMarkdownRenderer(config = {}) {
5786
6768
  }
5787
6769
  };
5788
6770
  }, [renderer]);
5789
- (0, import_react13.useEffect)(() => {
6771
+ (0, import_react14.useEffect)(() => {
5790
6772
  const unsubscribe = renderer.onUpdate(setBlocks);
5791
6773
  return unsubscribe;
5792
6774
  }, [renderer]);
5793
6775
  const mdxComponents = config.mdx?.components;
5794
- (0, import_react13.useEffect)(() => {
6776
+ (0, import_react14.useEffect)(() => {
5795
6777
  if (mdxComponents && Object.keys(mdxComponents).length > 0) {
5796
6778
  renderer.setMdxComponents(mdxComponents);
5797
6779
  }
5798
6780
  }, [renderer, mdxComponents]);
5799
- const append = (0, import_react13.useCallback)(
6781
+ const append = (0, import_react14.useCallback)(
5800
6782
  (text) => {
5801
6783
  renderer.append(text);
5802
6784
  },
5803
6785
  [renderer]
5804
6786
  );
5805
- const renderStatic = (0, import_react13.useCallback)(
6787
+ const renderStatic = (0, import_react14.useCallback)(
5806
6788
  (text) => {
5807
6789
  return renderer.renderStatic(text);
5808
6790
  },
5809
6791
  [renderer]
5810
6792
  );
5811
- const setBlockComponents = (0, import_react13.useCallback)(
6793
+ const setBlockComponents = (0, import_react14.useCallback)(
5812
6794
  (components) => {
5813
6795
  renderer.setBlockComponents(components);
5814
6796
  },
5815
6797
  [renderer]
5816
6798
  );
5817
- const setInlineComponents = (0, import_react13.useCallback)(
6799
+ const setInlineComponents = (0, import_react14.useCallback)(
5818
6800
  (components) => {
5819
6801
  renderer.setInlineComponents(components);
5820
6802
  },
5821
6803
  [renderer]
5822
6804
  );
5823
- const setMdxComponents = (0, import_react13.useCallback)(
6805
+ const setMdxComponents = (0, import_react14.useCallback)(
5824
6806
  (components) => {
5825
6807
  renderer.setMdxComponents(components);
5826
6808
  },
@@ -5839,24 +6821,24 @@ function useMarkdownRenderer(config = {}) {
5839
6821
  }
5840
6822
  var MarkdownRenderer2 = ({ config, className, onBlocksChange, children }) => {
5841
6823
  const api = useMarkdownRenderer(config);
5842
- const highlightRequester = (0, import_react13.useCallback)(
6824
+ const highlightRequester = (0, import_react14.useCallback)(
5843
6825
  (request) => {
5844
6826
  api.renderer.requestCodeHighlightRange(request);
5845
6827
  },
5846
6828
  [api.renderer]
5847
6829
  );
5848
- (0, import_react13.useEffect)(() => {
6830
+ (0, import_react14.useEffect)(() => {
5849
6831
  if (onBlocksChange) {
5850
6832
  onBlocksChange(api.blocks);
5851
6833
  }
5852
6834
  }, [api.blocks, onBlocksChange]);
5853
6835
  if (children) {
5854
- return import_react13.default.createElement(import_react13.default.Fragment, {}, children(api));
6836
+ return import_react14.default.createElement(import_react14.default.Fragment, {}, children(api));
5855
6837
  }
5856
- return import_react13.default.createElement(
6838
+ return import_react14.default.createElement(
5857
6839
  CodeHighlightRequestContext.Provider,
5858
6840
  { value: highlightRequester },
5859
- import_react13.default.createElement(MarkdownBlocksRenderer, {
6841
+ import_react14.default.createElement(MarkdownBlocksRenderer, {
5860
6842
  blocks: api.blocks,
5861
6843
  componentRegistry: api.renderer.getComponentRegistry(),
5862
6844
  className,
@@ -5869,9 +6851,9 @@ function createMarkdownRenderer(config = {}) {
5869
6851
  }
5870
6852
 
5871
6853
  // src/streaming-markdown.tsx
5872
- var import_react14 = __toESM(require("react"), 1);
6854
+ var import_react15 = __toESM(require("react"), 1);
5873
6855
  var import_worker2 = require("@stream-mdx/worker");
5874
- var import_jsx_runtime4 = require("react/jsx-runtime");
6856
+ var import_jsx_runtime5 = require("react/jsx-runtime");
5875
6857
  var EMPTY_BLOCKS = [];
5876
6858
  function createConfigSignature(input) {
5877
6859
  return JSON.stringify(input);
@@ -5883,13 +6865,13 @@ var MdxCoordinatorBridge = ({ store, mode }) => {
5883
6865
  };
5884
6866
  var MdxPrefetchBridge = ({ store }) => {
5885
6867
  const blocks = useRendererBlocks(store);
5886
- const prefetchedRuntimeRef = (0, import_react14.useRef)(false);
5887
- const trackedIdsRef = (0, import_react14.useRef)(/* @__PURE__ */ new Set());
5888
- const queueRef = (0, import_react14.useRef)(null);
6868
+ const prefetchedRuntimeRef = (0, import_react15.useRef)(false);
6869
+ const trackedIdsRef = (0, import_react15.useRef)(/* @__PURE__ */ new Set());
6870
+ const queueRef = (0, import_react15.useRef)(null);
5889
6871
  if (!queueRef.current) {
5890
6872
  queueRef.current = new MdxPrefetchQueue();
5891
6873
  }
5892
- (0, import_react14.useEffect)(() => {
6874
+ (0, import_react15.useEffect)(() => {
5893
6875
  const queue = queueRef.current;
5894
6876
  if (!queue) return;
5895
6877
  const nextIds = /* @__PURE__ */ new Map();
@@ -5927,7 +6909,7 @@ var MdxPrefetchBridge = ({ store }) => {
5927
6909
  }
5928
6910
  trackedIdsRef.current = new Set(nextIds.keys());
5929
6911
  }, [blocks]);
5930
- (0, import_react14.useEffect)(() => {
6912
+ (0, import_react15.useEffect)(() => {
5931
6913
  return () => {
5932
6914
  queueRef.current?.cancelAll();
5933
6915
  };
@@ -6001,7 +6983,7 @@ function StreamingMarkdownComponent({
6001
6983
  const effectiveScheduling = scheduling ?? DEFAULT_SCHEDULING;
6002
6984
  const adaptiveSwitchEnabled = effectiveScheduling.batch === "microtask" && (scheduling?.adaptiveSwitch ?? true);
6003
6985
  const adaptiveQueueThreshold = scheduling?.adaptiveQueueThreshold ?? (typeof effectiveScheduling.maxBatchesPerFlush === "number" ? effectiveScheduling.maxBatchesPerFlush : DEFAULT_ADAPTIVE_QUEUE_THRESHOLD);
6004
- const configSignature = (0, import_react14.useMemo)(
6986
+ const configSignature = (0, import_react15.useMemo)(
6005
6987
  () => createConfigSignature({
6006
6988
  features,
6007
6989
  prewarm: prewarmLangs,
@@ -6012,16 +6994,16 @@ function StreamingMarkdownComponent({
6012
6994
  }),
6013
6995
  [features, prewarmLangs, effectiveScheduling, mdxCompileMode, mdxComponents, mdxHydration]
6014
6996
  );
6015
- const mdxHydrationController = (0, import_react14.useMemo)(() => createMdxHydrationController(mdxHydration), [mdxHydration]);
6016
- const mdxHydrationContextValue = (0, import_react14.useMemo)(
6997
+ const mdxHydrationController = (0, import_react15.useMemo)(() => createMdxHydrationController(mdxHydration), [mdxHydration]);
6998
+ const mdxHydrationContextValue = (0, import_react15.useMemo)(
6017
6999
  () => ({
6018
7000
  controller: mdxHydrationController,
6019
7001
  options: mdxHydration
6020
7002
  }),
6021
7003
  [mdxHydrationController, mdxHydration]
6022
7004
  );
6023
- const rendererRef = (0, import_react14.useRef)();
6024
- const [session, setSession] = (0, import_react14.useState)(0);
7005
+ const rendererRef = (0, import_react15.useRef)();
7006
+ const [session, setSession] = (0, import_react15.useState)(0);
6025
7007
  const rendererKey = `${configSignature}:${session}`;
6026
7008
  const historyLimit = effectiveScheduling.historyLimit ?? DEFAULT_HISTORY_LIMIT;
6027
7009
  if (!rendererRef.current || rendererRef.current.signature !== rendererKey) {
@@ -6040,7 +7022,9 @@ function StreamingMarkdownComponent({
6040
7022
  lowPriorityFrameBudgetMs: effectiveScheduling.lowPriorityFrameBudgetMs,
6041
7023
  urgentQueueThreshold: effectiveScheduling.urgentQueueThreshold,
6042
7024
  batch: effectiveScheduling.batch,
6043
- historyLimit
7025
+ historyLimit,
7026
+ startupMicrotaskFlushes: effectiveScheduling.startupMicrotaskFlushes,
7027
+ adaptiveBudgeting: effectiveScheduling.adaptiveBudgeting
6044
7028
  },
6045
7029
  mdx: mdxConfig
6046
7030
  };
@@ -6050,7 +7034,7 @@ function StreamingMarkdownComponent({
6050
7034
  };
6051
7035
  }
6052
7036
  const renderer = rendererRef.current.renderer;
6053
- const highlightRequester = (0, import_react14.useCallback)(
7037
+ const highlightRequester = (0, import_react15.useCallback)(
6054
7038
  (request) => {
6055
7039
  renderer.requestCodeHighlightRange(request);
6056
7040
  },
@@ -6058,15 +7042,15 @@ function StreamingMarkdownComponent({
6058
7042
  );
6059
7043
  const store = renderer.getStore();
6060
7044
  const blocks = useRendererBlocks(store);
6061
- const adaptiveSwitchedRef = (0, import_react14.useRef)(false);
6062
- const adaptiveFirstFlushRef = (0, import_react14.useRef)(false);
7045
+ const adaptiveSwitchedRef = (0, import_react15.useRef)(false);
7046
+ const adaptiveFirstFlushRef = (0, import_react15.useRef)(false);
6063
7047
  const mdxMode = mdxCompileMode ?? "server";
6064
- const [workerReady, setWorkerReady] = (0, import_react14.useState)(false);
6065
- const workerReadyRef = (0, import_react14.useRef)(false);
6066
- const [streamStatus, setStreamStatus] = (0, import_react14.useState)("idle");
6067
- const lastMetricsRef = (0, import_react14.useRef)(null);
6068
- const patchHistoryRef = (0, import_react14.useRef)([]);
6069
- (0, import_react14.useEffect)(() => {
7048
+ const [workerReady, setWorkerReady] = (0, import_react15.useState)(false);
7049
+ const workerReadyRef = (0, import_react15.useRef)(false);
7050
+ const [streamStatus, setStreamStatus] = (0, import_react15.useState)("idle");
7051
+ const lastMetricsRef = (0, import_react15.useRef)(null);
7052
+ const patchHistoryRef = (0, import_react15.useRef)([]);
7053
+ (0, import_react15.useEffect)(() => {
6070
7054
  if (typeof window === "undefined" || typeof PerformanceObserver === "undefined") {
6071
7055
  return void 0;
6072
7056
  }
@@ -6090,27 +7074,27 @@ function StreamingMarkdownComponent({
6090
7074
  observer?.disconnect();
6091
7075
  };
6092
7076
  }, []);
6093
- const previousTextRef = (0, import_react14.useRef)();
6094
- (0, import_react14.useEffect)(() => {
7077
+ const previousTextRef = (0, import_react15.useRef)();
7078
+ (0, import_react15.useEffect)(() => {
6095
7079
  if (text !== void 0 && text !== previousTextRef.current) {
6096
7080
  previousTextRef.current = text;
6097
7081
  setSession((prev) => prev + 1);
6098
7082
  }
6099
7083
  }, [text]);
6100
- const previousStreamRef = (0, import_react14.useRef)();
6101
- (0, import_react14.useEffect)(() => {
7084
+ const previousStreamRef = (0, import_react15.useRef)();
7085
+ (0, import_react15.useEffect)(() => {
6102
7086
  if (stream && stream !== previousStreamRef.current) {
6103
7087
  previousStreamRef.current = stream;
6104
7088
  setSession((prev) => prev + 1);
6105
7089
  }
6106
7090
  }, [stream]);
6107
7091
  const linkSafetyEnabled = Boolean(linkSafety?.enabled);
6108
- const [linkModalState, setLinkModalState] = (0, import_react14.useState)({
7092
+ const [linkModalState, setLinkModalState] = (0, import_react15.useState)({
6109
7093
  url: "",
6110
7094
  isOpen: false,
6111
7095
  isChecking: false
6112
7096
  });
6113
- const openLink = (0, import_react14.useMemo)(() => {
7097
+ const openLink = (0, import_react15.useMemo)(() => {
6114
7098
  return (url) => {
6115
7099
  if (typeof window === "undefined") return;
6116
7100
  if (url.startsWith("http://") || url.startsWith("https://")) {
@@ -6120,7 +7104,7 @@ function StreamingMarkdownComponent({
6120
7104
  }
6121
7105
  };
6122
7106
  }, []);
6123
- const handleLinkClick = (0, import_react14.useMemo)(() => {
7107
+ const handleLinkClick = (0, import_react15.useMemo)(() => {
6124
7108
  return async (url) => {
6125
7109
  if (!linkSafetyEnabled) {
6126
7110
  openLink(url);
@@ -6142,10 +7126,10 @@ function StreamingMarkdownComponent({
6142
7126
  setLinkModalState({ url, isOpen: true, isChecking: false });
6143
7127
  };
6144
7128
  }, [linkSafety, linkSafetyEnabled, openLink]);
6145
- const handleLinkClose = (0, import_react14.useMemo)(() => {
7129
+ const handleLinkClose = (0, import_react15.useMemo)(() => {
6146
7130
  return () => setLinkModalState((prev) => ({ ...prev, isOpen: false }));
6147
7131
  }, []);
6148
- const handleLinkConfirm = (0, import_react14.useMemo)(() => {
7132
+ const handleLinkConfirm = (0, import_react15.useMemo)(() => {
6149
7133
  return () => {
6150
7134
  const url = linkModalState.url;
6151
7135
  setLinkModalState((prev) => ({ ...prev, isOpen: false }));
@@ -6154,7 +7138,7 @@ function StreamingMarkdownComponent({
6154
7138
  }
6155
7139
  };
6156
7140
  }, [linkModalState.url, openLink]);
6157
- const handleLinkCopy = (0, import_react14.useMemo)(() => {
7141
+ const handleLinkCopy = (0, import_react15.useMemo)(() => {
6158
7142
  return () => {
6159
7143
  const url = linkModalState.url;
6160
7144
  if (!url || typeof navigator === "undefined") return;
@@ -6175,7 +7159,7 @@ function StreamingMarkdownComponent({
6175
7159
  }
6176
7160
  };
6177
7161
  }, [linkModalState.url]);
6178
- const resolvedInlineComponents = (0, import_react14.useMemo)(() => {
7162
+ const resolvedInlineComponents = (0, import_react15.useMemo)(() => {
6179
7163
  if (!linkSafetyEnabled) {
6180
7164
  return inlineComponents;
6181
7165
  }
@@ -6183,9 +7167,9 @@ function StreamingMarkdownComponent({
6183
7167
  const url = typeof href === "string" ? href : "";
6184
7168
  const isIncomplete = url.startsWith("streamdown:incomplete-link") || url.startsWith("stream-mdx:incomplete-link");
6185
7169
  if (!url || isIncomplete) {
6186
- return import_react14.default.createElement("span", { className: "markdown-link", title }, children);
7170
+ return import_react15.default.createElement("span", { className: "markdown-link", title }, children);
6187
7171
  }
6188
- return import_react14.default.createElement(
7172
+ return import_react15.default.createElement(
6189
7173
  "button",
6190
7174
  {
6191
7175
  type: "button",
@@ -6202,14 +7186,14 @@ function StreamingMarkdownComponent({
6202
7186
  };
6203
7187
  return { ...inlineComponents ?? {}, link: LinkComponent };
6204
7188
  }, [handleLinkClick, inlineComponents, linkSafetyEnabled]);
6205
- (0, import_react14.useEffect)(() => {
7189
+ (0, import_react15.useEffect)(() => {
6206
7190
  setStreamStatus("idle");
6207
7191
  }, [session]);
6208
- (0, import_react14.useEffect)(() => {
7192
+ (0, import_react15.useEffect)(() => {
6209
7193
  adaptiveSwitchedRef.current = false;
6210
7194
  adaptiveFirstFlushRef.current = false;
6211
7195
  }, [renderer]);
6212
- (0, import_react14.useEffect)(() => {
7196
+ (0, import_react15.useEffect)(() => {
6213
7197
  if (!adaptiveSwitchEnabled) return void 0;
6214
7198
  const unsubscribe = renderer.addFlushListener((result) => {
6215
7199
  if (adaptiveSwitchedRef.current) return;
@@ -6231,12 +7215,12 @@ function StreamingMarkdownComponent({
6231
7215
  });
6232
7216
  return unsubscribe;
6233
7217
  }, [renderer, adaptiveSwitchEnabled, adaptiveQueueThreshold]);
6234
- (0, import_react14.useEffect)(() => {
7218
+ (0, import_react15.useEffect)(() => {
6235
7219
  lastMetricsRef.current = null;
6236
7220
  patchHistoryRef.current = [];
6237
7221
  void renderer;
6238
7222
  }, [renderer]);
6239
- (0, import_react14.useEffect)(() => {
7223
+ (0, import_react15.useEffect)(() => {
6240
7224
  if (components) {
6241
7225
  renderer.setBlockComponents(components);
6242
7226
  }
@@ -6255,7 +7239,7 @@ function StreamingMarkdownComponent({
6255
7239
  renderer.getComponentRegistry().setHtmlElements(htmlElements);
6256
7240
  }
6257
7241
  }, [renderer, components, mdxComponents, inlineComponents, resolvedInlineComponents, tableElements, htmlElements]);
6258
- (0, import_react14.useEffect)(() => {
7242
+ (0, import_react15.useEffect)(() => {
6259
7243
  const removeListener = renderer.addFlushListener((result) => {
6260
7244
  const metrics = summarizeFlush(result);
6261
7245
  lastMetricsRef.current = metrics;
@@ -6273,12 +7257,12 @@ function StreamingMarkdownComponent({
6273
7257
  });
6274
7258
  return removeListener;
6275
7259
  }, [renderer, historyLimit, onMetrics]);
6276
- (0, import_react14.useEffect)(() => {
7260
+ (0, import_react15.useEffect)(() => {
6277
7261
  if (patchHistoryRef.current.length > historyLimit) {
6278
7262
  patchHistoryRef.current.splice(0, patchHistoryRef.current.length - historyLimit);
6279
7263
  }
6280
7264
  }, [historyLimit]);
6281
- (0, import_react14.useEffect)(() => {
7265
+ (0, import_react15.useEffect)(() => {
6282
7266
  const restartToken = session;
6283
7267
  void restartToken;
6284
7268
  if (process.env.NODE_ENV !== "production" && DEBUG_WORKER) {
@@ -6334,7 +7318,7 @@ function StreamingMarkdownComponent({
6334
7318
  }
6335
7319
  };
6336
7320
  }, [renderer, workerSource, session, onError, managedWorker]);
6337
- (0, import_react14.useEffect)(() => {
7321
+ (0, import_react15.useEffect)(() => {
6338
7322
  const restartToken = session;
6339
7323
  void restartToken;
6340
7324
  let cancelled = false;
@@ -6397,7 +7381,7 @@ function StreamingMarkdownComponent({
6397
7381
  cancelled = true;
6398
7382
  };
6399
7383
  }, [renderer, text, stream, workerReady, session, onError, managedWorker]);
6400
- (0, import_react14.useImperativeHandle)(
7384
+ (0, import_react15.useImperativeHandle)(
6401
7385
  ref,
6402
7386
  () => ({
6403
7387
  pause() {
@@ -6451,8 +7435,8 @@ function StreamingMarkdownComponent({
6451
7435
  }),
6452
7436
  [renderer, store]
6453
7437
  );
6454
- const hasActiveBlocks = (0, import_react14.useMemo)(() => blocks.some((block) => !block.isFinalized), [blocks]);
6455
- const caretValue = (0, import_react14.useMemo)(() => {
7438
+ const hasActiveBlocks = (0, import_react15.useMemo)(() => blocks.some((block) => !block.isFinalized), [blocks]);
7439
+ const caretValue = (0, import_react15.useMemo)(() => {
6456
7440
  if (!caret) {
6457
7441
  return null;
6458
7442
  }
@@ -6473,7 +7457,7 @@ function StreamingMarkdownComponent({
6473
7457
  ...style ?? {},
6474
7458
  ["--stream-mdx-caret"]: JSON.stringify(caretValue)
6475
7459
  } : style;
6476
- const deferredConfig = (0, import_react14.useMemo)(() => {
7460
+ const deferredConfig = (0, import_react15.useMemo)(() => {
6477
7461
  if (!deferHeavyBlocks) {
6478
7462
  return null;
6479
7463
  }
@@ -6490,10 +7474,10 @@ function StreamingMarkdownComponent({
6490
7474
  onConfirm: handleLinkConfirm,
6491
7475
  onCopy: handleLinkCopy
6492
7476
  }) : null;
6493
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MdxHydrationContext.Provider, { value: mdxHydrationContextValue, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(DeferredRenderContext.Provider, { value: deferredConfig, children: [
6494
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MdxPrefetchBridge, { store }),
6495
- mdxMode === "server" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MdxCoordinatorBridge, { store, mode: mdxMode }) : null,
6496
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CodeHighlightRequestContext.Provider, { value: highlightRequester, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
7477
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MdxHydrationContext.Provider, { value: mdxHydrationContextValue, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(DeferredRenderContext.Provider, { value: deferredConfig, children: [
7478
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MdxPrefetchBridge, { store }),
7479
+ mdxMode === "server" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MdxCoordinatorBridge, { store, mode: mdxMode }) : null,
7480
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CodeHighlightRequestContext.Provider, { value: highlightRequester, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
6497
7481
  MarkdownBlocksRenderer,
6498
7482
  {
6499
7483
  blocks: EMPTY_BLOCKS,
@@ -6506,7 +7490,7 @@ function StreamingMarkdownComponent({
6506
7490
  linkModal
6507
7491
  ] }) });
6508
7492
  }
6509
- var StreamingMarkdownWithRef = (0, import_react14.forwardRef)(StreamingMarkdownComponent);
7493
+ var StreamingMarkdownWithRef = (0, import_react15.forwardRef)(StreamingMarkdownComponent);
6510
7494
  StreamingMarkdownWithRef.displayName = "StreamingMarkdown";
6511
7495
  var StreamingMarkdown = StreamingMarkdownWithRef;
6512
7496
  function instantiateWorker(source) {
@@ -6613,6 +7597,7 @@ function percentile2(values, ratio) {
6613
7597
  }
6614
7598
  // Annotate the CommonJS export names for ESM import in node:
6615
7599
  0 && (module.exports = {
7600
+ BottomStickScrollArea,
6616
7601
  ComponentRegistry,
6617
7602
  DEFAULT_COALESCE_CONFIG,
6618
7603
  DEFAULT_VIRTUALIZED_CODE_CONFIG,
@@ -6638,6 +7623,7 @@ function percentile2(values, ratio) {
6638
7623
  defaultInlineComponents,
6639
7624
  getMDXClient,
6640
7625
  getMDXComponentFactory,
7626
+ getPatchKind,
6641
7627
  isHeavyPatch,
6642
7628
  isListPatchDebugEnabled,
6643
7629
  mapHtmlToReact,