@ai-react-markdown/mantine 2.12.0 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -24,8 +24,14 @@ var MantineAIMDefaultExtraStyles = ({ children }) => {
24
24
  var DefaultExtraStyles_default = MantineAIMDefaultExtraStyles;
25
25
 
26
26
  // src/components/customized/PreCode.tsx
27
- import { memo as memo3, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
28
- import { CodeHighlight, CodeHighlightTabs as CodeHighlightTabs2, CodeHighlightControl as CodeHighlightControl2 } from "@mantine/code-highlight";
27
+ import { createContext, memo as memo3, useContext, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2, useState as useState3 } from "react";
28
+ import {
29
+ CodeHighlight,
30
+ CodeHighlightTabs as CodeHighlightTabs2,
31
+ CodeHighlightControl as CodeHighlightControl2,
32
+ CodeHighlightAdapterProvider,
33
+ useHighlight
34
+ } from "@mantine/code-highlight";
29
35
  import { useAIMarkdownState as useAIMarkdownState2, useAIMarkdownTheme as useAIMarkdownTheme2 } from "@ai-react-markdown/core";
30
36
 
31
37
  // src/hooks/useMantineCodeBlockOptions.ts
@@ -37,7 +43,8 @@ var defaultMantineCodeBlockOptions = Object.freeze({
37
43
  defaultExpanded: true,
38
44
  autoDetectUnknownLanguage: false,
39
45
  formatJson: true,
40
- expandNestedJson: true
46
+ expandNestedJson: true,
47
+ highlightIntervalMs: 50
41
48
  });
42
49
 
43
50
  // src/hooks/useMantineCodeBlockOptions.ts
@@ -50,6 +57,9 @@ function useMantineCodeBlockOptions() {
50
57
  const value = group?.[key];
51
58
  if (value !== void 0) resolved[key] = value;
52
59
  }
60
+ if (!Number.isFinite(resolved.highlightIntervalMs) || resolved.highlightIntervalMs < 0) {
61
+ resolved.highlightIntervalMs = defaultMantineCodeBlockOptions.highlightIntervalMs;
62
+ }
53
63
  return resolved;
54
64
  }, [group]);
55
65
  }
@@ -483,6 +493,51 @@ function createJsonCompletenessScanner() {
483
493
  };
484
494
  }
485
495
 
496
+ // src/components/customized/useCodeFrame.ts
497
+ import { useEffect as useEffect2, useState as useState2 } from "react";
498
+
499
+ // src/components/customized/codeFrame.ts
500
+ function createCodeFrame(initial, publish) {
501
+ let shown = initial;
502
+ let latest = initial;
503
+ let delay = 0;
504
+ let timer;
505
+ const cancel = () => {
506
+ if (timer !== void 0) clearTimeout(timer);
507
+ timer = void 0;
508
+ };
509
+ const flush = () => {
510
+ cancel();
511
+ if (shown.code === latest.code && shown.language === latest.language) return;
512
+ shown = latest;
513
+ publish(shown);
514
+ };
515
+ return {
516
+ update(next, streaming, interval) {
517
+ const replaced = next.language !== latest.language || !next.code.startsWith(latest.code);
518
+ latest = next;
519
+ if (delay !== interval) cancel();
520
+ delay = interval;
521
+ if (!streaming || interval === 0 || replaced) return flush();
522
+ if (shown.code === next.code && shown.language === next.language) return cancel();
523
+ timer ??= setTimeout(flush, interval);
524
+ },
525
+ // Cancellation is reversible: Strict Mode replays the update effect.
526
+ dispose: cancel
527
+ };
528
+ }
529
+
530
+ // src/components/customized/useCodeFrame.ts
531
+ function useCodeFrame(code, language, streaming, interval) {
532
+ const [frame, setFrame] = useState2(() => ({ code, language }));
533
+ const [controller] = useState2(() => createCodeFrame({ code, language }, setFrame));
534
+ useEffect2(() => {
535
+ controller.update({ code, language }, streaming, interval);
536
+ }, [controller, code, language, streaming, interval]);
537
+ useEffect2(() => () => controller.dispose(), [controller]);
538
+ return !streaming || interval === 0 || language !== frame.language || !code.startsWith(frame.code) ? code : frame.code;
539
+ }
540
+
486
541
  // src/components/customized/PreCode.tsx
487
542
  import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
488
543
  var hljsAutoPromise = null;
@@ -500,13 +555,13 @@ var AUTODETECT_MIN_CHARS = 32;
500
555
  var HLJS_LOAD_RETRIES = 3;
501
556
  var HLJS_LOAD_RETRY_MS = 1500;
502
557
  function useAutoDetectedLanguage(codeText, enabled, streaming) {
503
- const [detected, setDetected] = useState2(
558
+ const [detected, setDetected] = useState3(
504
559
  null
505
560
  );
506
- const [loadAttempt, setLoadAttempt] = useState2(0);
561
+ const [loadAttempt, setLoadAttempt] = useState3(0);
507
562
  const loadFailuresRef = useRef2(0);
508
563
  const previousTextRef = useRef2(codeText);
509
- useEffect2(() => {
564
+ useEffect3(() => {
510
565
  const appended = codeText.startsWith(previousTextRef.current);
511
566
  previousTextRef.current = codeText;
512
567
  if (!enabled) {
@@ -552,7 +607,9 @@ function preloadMantineCodeAssets() {
552
607
  () => void 0
553
608
  );
554
609
  }
555
- function RawCodeCopy({ code }) {
610
+ var RawCodeContext = createContext("");
611
+ function RawCodeCopy() {
612
+ const code = useContext(RawCodeContext);
556
613
  return /* @__PURE__ */ jsx4(CopyButton2, { value: code, children: ({ copied, copy }) => /* @__PURE__ */ jsx4(
557
614
  CodeHighlightControl2,
558
615
  {
@@ -578,6 +635,64 @@ function RawCodeCopy({ code }) {
578
635
  }
579
636
  ) });
580
637
  }
638
+ function createCachedHighlightAdapter(highlight) {
639
+ let previous;
640
+ let result;
641
+ return {
642
+ getHighlighter: () => (input) => {
643
+ if (!previous || input.code !== previous.code || input.language !== previous.language || input.colorScheme !== previous.colorScheme) {
644
+ result = highlight(input);
645
+ previous = input;
646
+ }
647
+ return result;
648
+ }
649
+ };
650
+ }
651
+ var OrdinaryCodeHighlight = memo3(function OrdinaryCodeHighlight2({
652
+ code,
653
+ language,
654
+ fileName,
655
+ fontSize,
656
+ defaultExpanded
657
+ }) {
658
+ const highlight = useHighlight();
659
+ const adapter = useMemo2(() => createCachedHighlightAdapter(highlight), [highlight]);
660
+ return /* @__PURE__ */ jsx4(CodeHighlightAdapterProvider, { adapter, children: fileName === "unknown" ? /* @__PURE__ */ jsx4(
661
+ CodeHighlight,
662
+ {
663
+ mb: 15,
664
+ fz: fontSize,
665
+ w: "100%",
666
+ code,
667
+ withBorder: true,
668
+ withExpandButton: true,
669
+ defaultExpanded,
670
+ maxCollapsedHeight: "320px",
671
+ withCopyButton: false,
672
+ controls: [/* @__PURE__ */ jsx4(RawCodeCopy, {}, "copy")]
673
+ }
674
+ ) : /* @__PURE__ */ jsx4(
675
+ CodeHighlightTabs2,
676
+ {
677
+ mb: 15,
678
+ fz: fontSize,
679
+ w: "100%",
680
+ code: [
681
+ {
682
+ fileName,
683
+ code,
684
+ language
685
+ }
686
+ ],
687
+ withBorder: true,
688
+ withExpandButton: true,
689
+ defaultExpanded,
690
+ maxCollapsedHeight: "320px",
691
+ withCopyButton: false,
692
+ controls: [/* @__PURE__ */ jsx4(RawCodeCopy, {}, "copy")]
693
+ }
694
+ ) });
695
+ });
581
696
  var SpecialCodeLanguage = /* @__PURE__ */ ((SpecialCodeLanguage2) => {
582
697
  SpecialCodeLanguage2["Mermaid"] = "mermaid";
583
698
  return SpecialCodeLanguage2;
@@ -587,7 +702,7 @@ var MantineAIMPreCode = memo3(
587
702
  (props) => {
588
703
  const { fontSize } = useAIMarkdownTheme2();
589
704
  const { streaming } = useAIMarkdownState2();
590
- const { autoDetectUnknownLanguage, defaultExpanded, formatJson, expandNestedJson } = useMantineCodeBlockOptions();
705
+ const { autoDetectUnknownLanguage, defaultExpanded, formatJson, expandNestedJson, highlightIntervalMs } = useMantineCodeBlockOptions();
591
706
  const detectedLanguage = useAutoDetectedLanguage(
592
707
  props.codeText,
593
708
  autoDetectUnknownLanguage && !props.existLanguage,
@@ -599,7 +714,7 @@ var MantineAIMPreCode = memo3(
599
714
  [codeLanguage]
600
715
  );
601
716
  const isSpecialCodeBlock = SPECIAL_LANGUAGES.has(codeLanguage);
602
- const [scanJson] = useState2(createJsonCompletenessScanner);
717
+ const [scanJson] = useState3(createJsonCompletenessScanner);
603
718
  const jsonComplete = useMemo2(
604
719
  () => usedCodeLanguage === "json" && formatJson && streaming ? scanJson(props.codeText) : false,
605
720
  [usedCodeLanguage, formatJson, streaming, scanJson, props.codeText]
@@ -610,53 +725,14 @@ var MantineAIMPreCode = memo3(
610
725
  if (formatJson && usedCodeStr && usedCodeLanguage === "json" && (!streaming || jsonComplete)) {
611
726
  usedCodeStr = prettyPrintJson(usedCodeStr, expandNestedJson);
612
727
  }
613
- return usedFileName === "unknown" ? /* @__PURE__ */ jsx4(
614
- CodeHighlight,
615
- {
616
- mb: 15,
617
- fz: fontSize,
618
- w: "100%",
619
- code: usedCodeStr,
620
- withBorder: true,
621
- withExpandButton: true,
622
- defaultExpanded,
623
- maxCollapsedHeight: "320px",
624
- withCopyButton: false,
625
- controls: [/* @__PURE__ */ jsx4(RawCodeCopy, { code: props.codeText }, "copy")]
626
- }
627
- ) : /* @__PURE__ */ jsx4(
628
- CodeHighlightTabs2,
629
- {
630
- mb: 15,
631
- fz: fontSize,
632
- w: "100%",
633
- code: [
634
- {
635
- fileName: usedFileName,
636
- code: usedCodeStr,
637
- language: usedCodeLanguage
638
- }
639
- ],
640
- withBorder: true,
641
- withExpandButton: true,
642
- defaultExpanded,
643
- maxCollapsedHeight: "320px",
644
- withCopyButton: false,
645
- controls: [/* @__PURE__ */ jsx4(RawCodeCopy, { code: props.codeText }, "copy")]
646
- }
647
- );
648
- }, [
649
- isSpecialCodeBlock,
650
- props.codeText,
728
+ return usedCodeStr;
729
+ }, [isSpecialCodeBlock, props.codeText, usedCodeLanguage, streaming, formatJson, expandNestedJson, jsonComplete]);
730
+ const displayedCode = useCodeFrame(
731
+ normalCodeBlockContent ?? "",
651
732
  usedCodeLanguage,
652
- usedFileName,
653
- fontSize,
654
- defaultExpanded,
655
- streaming,
656
- formatJson,
657
- expandNestedJson,
658
- jsonComplete
659
- ]);
733
+ streaming && !isSpecialCodeBlock,
734
+ highlightIntervalMs
735
+ );
660
736
  const specialCodeBlockContent = useMemo2(() => {
661
737
  switch (codeLanguage) {
662
738
  case "mermaid" /* Mermaid */:
@@ -665,7 +741,16 @@ var MantineAIMPreCode = memo3(
665
741
  return null;
666
742
  }
667
743
  }, [codeLanguage, props.codeText]);
668
- return isSpecialCodeBlock ? specialCodeBlockContent : normalCodeBlockContent;
744
+ return isSpecialCodeBlock ? specialCodeBlockContent : /* @__PURE__ */ jsx4(RawCodeContext.Provider, { value: props.codeText, children: /* @__PURE__ */ jsx4(
745
+ OrdinaryCodeHighlight,
746
+ {
747
+ code: displayedCode,
748
+ language: usedCodeLanguage,
749
+ fileName: usedFileName,
750
+ fontSize,
751
+ defaultExpanded
752
+ }
753
+ ) });
669
754
  }
670
755
  );
671
756
  MantineAIMPreCode.displayName = "MantineAIMPreCode";