reachat 2.2.0 → 3.1.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 (46) hide show
  1. package/dist/{CSVFileRenderer-BOdL4Jte.js → CSVFileRenderer-C2E4Xnkz.js} +2 -2
  2. package/dist/{CSVFileRenderer-BOdL4Jte.js.map → CSVFileRenderer-C2E4Xnkz.js.map} +1 -1
  3. package/dist/Chat.d.ts +12 -0
  4. package/dist/{Markdown/charts/ChartError.d.ts → ComponentCatalog/ComponentError.d.ts} +2 -2
  5. package/dist/ComponentCatalog/ComponentPre.d.ts +18 -0
  6. package/dist/ComponentCatalog/ComponentRenderer.d.ts +17 -0
  7. package/dist/ComponentCatalog/chartComponentDef.d.ts +36 -0
  8. package/dist/ComponentCatalog/componentCatalog.d.ts +44 -0
  9. package/dist/ComponentCatalog/componentCatalog.spec.d.ts +1 -0
  10. package/dist/ComponentCatalog/generatePrompt.d.ts +9 -0
  11. package/dist/ComponentCatalog/generatePrompt.spec.d.ts +1 -0
  12. package/dist/ComponentCatalog/index.d.ts +9 -0
  13. package/dist/ComponentCatalog/types.d.ts +108 -0
  14. package/dist/ComponentCatalog/validateSpec.d.ts +17 -0
  15. package/dist/ComponentCatalog/validateSpec.spec.d.ts +1 -0
  16. package/dist/{DefaultFileRenderer-C2MsQ9wz.js → DefaultFileRenderer-Day12qYs.js} +2 -2
  17. package/dist/{DefaultFileRenderer-C2MsQ9wz.js.map → DefaultFileRenderer-Day12qYs.js.map} +1 -1
  18. package/dist/Markdown/charts/ChartRenderer.d.ts +1 -1
  19. package/dist/Markdown/charts/ComponentError.d.ts +1 -0
  20. package/dist/Markdown/charts/index.d.ts +2 -6
  21. package/dist/Markdown/charts/types.d.ts +21 -0
  22. package/dist/Markdown/plugins/index.d.ts +1 -1
  23. package/dist/Markdown/plugins/remarkComponent.d.ts +27 -0
  24. package/dist/docs.json +275 -93
  25. package/dist/{index-DdRyk11n.js → index-CZSBRZbI.js} +524 -230
  26. package/dist/index-CZSBRZbI.js.map +1 -0
  27. package/dist/index.css +101 -1077
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.js +22 -22
  30. package/dist/index.umd.cjs +509 -215
  31. package/dist/index.umd.cjs.map +1 -1
  32. package/dist/stories/Changelog.mdx +1 -1
  33. package/dist/stories/Charts.stories.tsx +118 -130
  34. package/dist/stories/ComponentCatalog.stories.tsx +509 -0
  35. package/dist/stories/{ChartError.stories.tsx → ComponentError.stories.tsx} +14 -11
  36. package/dist/stories/Intro.mdx +1 -1
  37. package/dist/theme.d.ts +3 -0
  38. package/dist/utils/getChildText.d.ts +10 -0
  39. package/dist/utils/getChildText.spec.d.ts +1 -0
  40. package/package.json +27 -30
  41. package/dist/Markdown/charts/ChartPre.d.ts +0 -6
  42. package/dist/Markdown/charts/chartHelpers.d.ts +0 -40
  43. package/dist/Markdown/plugins/remarkChart.d.ts +0 -59
  44. package/dist/index-DdRyk11n.js.map +0 -1
  45. package/dist/stories/Integration.stories.tsx +0 -312
  46. /package/dist/{Markdown/charts/chartHelpers.spec.d.ts → ComponentCatalog/chartComponentDef.spec.d.ts} +0 -0
@@ -11,8 +11,8 @@
11
11
  }
12
12
  })();
13
13
  (function(global, factory) {
14
- typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react/jsx-runtime"), require("reablocks"), require("react"), require("motion/react"), require("@tiptap/react"), require("@floating-ui/dom"), require("@tiptap/extension-document"), require("@tiptap/extension-paragraph"), require("@tiptap/extension-text"), require("@tiptap/extension-hard-break"), require("@tiptap/extension-placeholder"), require("@tiptap/extension-mention"), require("@radix-ui/react-slot"), require("react-markdown"), require("react-syntax-highlighter"), require("rehype-katex"), require("rehype-raw"), require("reaviz"), require("mdast-util-find-and-replace"), require("unist-util-visit"), require("lodash/debounce.js"), require("reakeys"), require("remark-gfm"), require("remark-youtube"), require("remark-math"), require("date-fns"), require("@floating-ui/react")) : typeof define === "function" && define.amd ? define(["exports", "react/jsx-runtime", "reablocks", "react", "motion/react", "@tiptap/react", "@floating-ui/dom", "@tiptap/extension-document", "@tiptap/extension-paragraph", "@tiptap/extension-text", "@tiptap/extension-hard-break", "@tiptap/extension-placeholder", "@tiptap/extension-mention", "@radix-ui/react-slot", "react-markdown", "react-syntax-highlighter", "rehype-katex", "rehype-raw", "reaviz", "mdast-util-find-and-replace", "unist-util-visit", "lodash/debounce.js", "reakeys", "remark-gfm", "remark-youtube", "remark-math", "date-fns", "@floating-ui/react"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.reachat = {}, global.jsxRuntime, global.reablocks, global.React, global.react$1, global.react, global.dom, global.Document, global.Paragraph, global.Text, global.HardBreak, global.Placeholder, global.Mention, global.reactSlot, global.ReactMarkdown, global.reactSyntaxHighlighter, global.rehypeKatex, global.rehypeRaw, global.reaviz, global.mdastUtilFindAndReplace, global.unistUtilVisit, global.debounce, global.reakeys, global.remarkGfm, global.remarkYoutube, global.remarkMath, global.dateFns, global.react$2));
15
- })(this, function(exports2, jsxRuntime, reablocks, React, react$1, react, dom, Document, Paragraph, Text, HardBreak, Placeholder, Mention, reactSlot, ReactMarkdown, reactSyntaxHighlighter, rehypeKatex, rehypeRaw, reaviz, mdastUtilFindAndReplace, unistUtilVisit, debounce, reakeys, remarkGfm, remarkYoutube, remarkMath, dateFns, react$2) {
14
+ typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react/jsx-runtime"), require("reablocks"), require("react"), require("motion/react"), require("@tiptap/react"), require("@floating-ui/dom"), require("@tiptap/extension-document"), require("@tiptap/extension-paragraph"), require("@tiptap/extension-text"), require("@tiptap/extension-hard-break"), require("@tiptap/extension-placeholder"), require("@tiptap/extension-mention"), require("@radix-ui/react-slot"), require("react-markdown"), require("react-syntax-highlighter"), require("rehype-katex"), require("rehype-raw"), require("reaviz"), require("mdast-util-find-and-replace"), require("lodash/debounce.js"), require("reakeys"), require("remark-gfm"), require("remark-youtube"), require("remark-math"), require("date-fns"), require("@floating-ui/react"), require("zod")) : typeof define === "function" && define.amd ? define(["exports", "react/jsx-runtime", "reablocks", "react", "motion/react", "@tiptap/react", "@floating-ui/dom", "@tiptap/extension-document", "@tiptap/extension-paragraph", "@tiptap/extension-text", "@tiptap/extension-hard-break", "@tiptap/extension-placeholder", "@tiptap/extension-mention", "@radix-ui/react-slot", "react-markdown", "react-syntax-highlighter", "rehype-katex", "rehype-raw", "reaviz", "mdast-util-find-and-replace", "lodash/debounce.js", "reakeys", "remark-gfm", "remark-youtube", "remark-math", "date-fns", "@floating-ui/react", "zod"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.reachat = {}, global.jsxRuntime, global.reablocks, global.React, global.react$1, global.react, global.dom, global.Document, global.Paragraph, global.Text, global.HardBreak, global.Placeholder, global.Mention, global.reactSlot, global.ReactMarkdown, global.reactSyntaxHighlighter, global.rehypeKatex, global.rehypeRaw, global.reaviz, global.mdastUtilFindAndReplace, global.debounce, global.reakeys, global.remarkGfm, global.remarkYoutube, global.remarkMath, global.dateFns, global.react$2, global.zod));
15
+ })(this, (function(exports2, jsxRuntime, reablocks, React, react$1, react, dom, Document, Paragraph, Text, HardBreak, Placeholder, Mention, reactSlot, ReactMarkdown, reactSyntaxHighlighter, rehypeKatex, rehypeRaw, reaviz, mdastUtilFindAndReplace, debounce, reakeys, remarkGfm, remarkYoutube, remarkMath, dateFns, react$2, zod) {
16
16
  "use strict";
17
17
  function _interopNamespaceDefault(e) {
18
18
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
@@ -70,10 +70,7 @@
70
70
  variant: "text",
71
71
  disabled: isLoading || disabled,
72
72
  className: reablocks.cn(theme.input.upload),
73
- onClick: () => {
74
- var _a;
75
- return (_a = fileInputRef.current) == null ? void 0 : _a.click();
76
- },
73
+ onClick: () => fileInputRef.current?.click(),
77
74
  children: attachIcon
78
75
  }
79
76
  )
@@ -320,23 +317,24 @@
320
317
  ].join(" "),
321
318
  title: "text-yellow-600 dark:text-yellow-400 text-sm font-medium mb-2"
322
319
  }
320
+ },
321
+ component: {
322
+ base: "my-4"
323
323
  }
324
324
  };
325
325
  const POPUP_STYLE = { zIndex: 9999 };
326
326
  const MentionList = React.forwardRef(
327
327
  ({ items, command, triggerChar, config, query }, ref) => {
328
- var _a;
329
328
  const [selectedIndex, setSelectedIndex] = React.useState(0);
330
329
  const itemRefs = React.useRef([]);
331
330
  const { theme } = React.useContext(ChatContext);
332
- const popupTheme = ((_a = theme == null ? void 0 : theme.input) == null ? void 0 : _a.popup) || chatTheme.input.popup;
331
+ const popupTheme = theme?.input?.popup || chatTheme.input.popup;
333
332
  React.useEffect(() => {
334
333
  setSelectedIndex(0);
335
334
  }, [items]);
336
335
  React.useEffect(() => {
337
- var _a2;
338
336
  if (itemRefs.current[selectedIndex]) {
339
- (_a2 = itemRefs.current[selectedIndex]) == null ? void 0 : _a2.scrollIntoView({
337
+ itemRefs.current[selectedIndex]?.scrollIntoView({
340
338
  block: "nearest",
341
339
  behavior: "smooth"
342
340
  });
@@ -467,10 +465,7 @@
467
465
  if (!query) return config.items.slice(0, config.maxResults || 10);
468
466
  const lowerQuery = query.toLowerCase();
469
467
  return config.items.filter(
470
- (item) => {
471
- var _a;
472
- return item.label.toLowerCase().includes(lowerQuery) || ((_a = item.description) == null ? void 0 : _a.toLowerCase().includes(lowerQuery));
473
- }
468
+ (item) => item.label.toLowerCase().includes(lowerQuery) || item.description?.toLowerCase().includes(lowerQuery)
474
469
  ).slice(0, config.maxResults || 10);
475
470
  },
476
471
  // Render callbacks for managing the popup lifecycle
@@ -497,7 +492,7 @@
497
492
  },
498
493
  // Called when query or items change
499
494
  onUpdate: (props) => {
500
- component == null ? void 0 : component.updateProps({
495
+ component?.updateProps({
501
496
  ...props,
502
497
  triggerChar,
503
498
  config
@@ -505,25 +500,23 @@
505
500
  if (!props.clientRect) {
506
501
  return;
507
502
  }
508
- if (component == null ? void 0 : component.element) {
503
+ if (component?.element) {
509
504
  updatePopupPosition(props.editor, component.element);
510
505
  }
511
506
  },
512
507
  // Handle keyboard navigation (Escape closes popup)
513
508
  onKeyDown: (props) => {
514
- var _a;
515
509
  if (props.event.key === "Escape") {
516
- component == null ? void 0 : component.destroy();
510
+ component?.destroy();
517
511
  return true;
518
512
  }
519
- return ((_a = component == null ? void 0 : component.ref) == null ? void 0 : _a.onKeyDown(props)) ?? false;
513
+ return component?.ref?.onKeyDown(props) ?? false;
520
514
  },
521
515
  // Cleanup when suggestion is dismissed
522
516
  onExit: () => {
523
- var _a;
524
517
  suggestionActiveRef.current = false;
525
- (_a = component == null ? void 0 : component.element) == null ? void 0 : _a.remove();
526
- component == null ? void 0 : component.destroy();
518
+ component?.element?.remove();
519
+ component?.destroy();
527
520
  }
528
521
  };
529
522
  }
@@ -543,12 +536,10 @@
543
536
  onSubmit,
544
537
  onChange
545
538
  }, ref) => {
546
- var _a, _b, _c, _d;
547
539
  const { theme } = React.useContext(ChatContext);
548
540
  const containerRef = React.useRef(null);
549
541
  const suggestionActiveRef = React.useRef(false);
550
542
  const extensions = React.useMemo(() => {
551
- var _a2, _b2, _c2, _d2, _e, _f, _g, _h;
552
543
  const exts = [
553
544
  Document,
554
545
  Paragraph.configure({
@@ -567,7 +558,7 @@
567
558
  exts.push(
568
559
  Mention.configure({
569
560
  HTMLAttributes: {
570
- class: reablocks.cn((_b2 = (_a2 = theme == null ? void 0 : theme.input) == null ? void 0 : _a2.tag) == null ? void 0 : _b2.base, (_d2 = (_c2 = theme == null ? void 0 : theme.input) == null ? void 0 : _c2.tag) == null ? void 0 : _d2.mention)
561
+ class: reablocks.cn(theme?.input?.tag?.base, theme?.input?.tag?.mention)
571
562
  },
572
563
  suggestion: createSuggestionConfig(
573
564
  mentions,
@@ -583,7 +574,7 @@
583
574
  exts.push(
584
575
  Mention.configure({
585
576
  HTMLAttributes: {
586
- class: reablocks.cn((_f = (_e = theme == null ? void 0 : theme.input) == null ? void 0 : _e.tag) == null ? void 0 : _f.base, (_h = (_g = theme == null ? void 0 : theme.input) == null ? void 0 : _g.tag) == null ? void 0 : _h.command)
577
+ class: reablocks.cn(theme?.input?.tag?.base, theme?.input?.tag?.command)
587
578
  },
588
579
  suggestion: createSuggestionConfig(
589
580
  commands,
@@ -604,13 +595,13 @@
604
595
  immediatelyRender: false,
605
596
  onUpdate: ({ editor: editor2 }) => {
606
597
  const text = editor2.getText();
607
- onChange == null ? void 0 : onChange(text);
598
+ onChange?.(text);
608
599
  },
609
600
  editorProps: {
610
601
  attributes: {
611
602
  class: reablocks.cn(
612
- (_b = (_a = theme == null ? void 0 : theme.input) == null ? void 0 : _a.editor) == null ? void 0 : _b.base,
613
- (_d = (_c = theme == null ? void 0 : theme.input) == null ? void 0 : _c.editor) == null ? void 0 : _d.placeholder
603
+ theme?.input?.editor?.base,
604
+ theme?.input?.editor?.placeholder
614
605
  ),
615
606
  style: `min-height: ${minHeight}px; max-height: ${maxHeight}px;`,
616
607
  role: "textbox",
@@ -628,7 +619,7 @@
628
619
  if (text.trim() && onSubmit) {
629
620
  event.preventDefault();
630
621
  onSubmit(text);
631
- editor == null ? void 0 : editor.commands.clearContent();
622
+ editor?.commands.clearContent();
632
623
  return true;
633
624
  }
634
625
  }
@@ -645,16 +636,16 @@
645
636
  }, [editor, autoFocus]);
646
637
  React.useImperativeHandle(ref, () => ({
647
638
  focus: () => {
648
- editor == null ? void 0 : editor.commands.focus();
639
+ editor?.commands.focus();
649
640
  },
650
641
  getValue: () => {
651
- return (editor == null ? void 0 : editor.getText()) || "";
642
+ return editor?.getText() || "";
652
643
  },
653
644
  setValue: (newValue) => {
654
- editor == null ? void 0 : editor.commands.setContent(newValue ? `<p>${newValue}</p>` : "");
645
+ editor?.commands.setContent(newValue ? `<p>${newValue}</p>` : "");
655
646
  },
656
647
  insertText: (text) => {
657
- editor == null ? void 0 : editor.commands.insertContent(text);
648
+ editor?.commands.insertContent(text);
658
649
  }
659
650
  }));
660
651
  return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, className: reablocks.cn("relative w-full", className), children: /* @__PURE__ */ jsxRuntime.jsx(react.EditorContent, { editor }) });
@@ -688,43 +679,37 @@
688
679
  const inputRef = React.useRef(null);
689
680
  const containerRef = React.useRef(null);
690
681
  React.useEffect(() => {
691
- var _a;
692
682
  if (autoFocus) {
693
- (_a = inputRef.current) == null ? void 0 : _a.focus();
683
+ inputRef.current?.focus();
694
684
  }
695
685
  }, [activeSessionId, autoFocus]);
696
686
  React.useImperativeHandle(ref, () => ({
697
687
  focus: () => {
698
- var _a;
699
- (_a = inputRef.current) == null ? void 0 : _a.focus();
688
+ inputRef.current?.focus();
700
689
  },
701
690
  getValue: () => {
702
- var _a;
703
- return ((_a = inputRef.current) == null ? void 0 : _a.getValue()) || "";
691
+ return inputRef.current?.getValue() || "";
704
692
  },
705
693
  setValue: (value) => {
706
- var _a;
707
694
  setMessage(value);
708
- (_a = inputRef.current) == null ? void 0 : _a.setValue(value);
695
+ inputRef.current?.setValue(value);
709
696
  },
710
697
  insertText: (text) => {
711
- var _a;
712
- (_a = inputRef.current) == null ? void 0 : _a.insertText(text);
698
+ inputRef.current?.insertText(text);
713
699
  }
714
700
  }));
715
701
  const handleSendMessage = React.useCallback(() => {
716
- var _a, _b;
717
- const currentMessage = (_a = inputRef.current) == null ? void 0 : _a.getValue();
702
+ const currentMessage = inputRef.current?.getValue();
718
703
  if (currentMessage.trim()) {
719
- sendMessage == null ? void 0 : sendMessage(currentMessage);
704
+ sendMessage?.(currentMessage);
720
705
  setMessage("");
721
- (_b = inputRef.current) == null ? void 0 : _b.setValue("");
706
+ inputRef.current?.setValue("");
722
707
  }
723
708
  }, [sendMessage]);
724
709
  const handleSubmit = React.useCallback(
725
710
  (value) => {
726
711
  if (value.trim()) {
727
- sendMessage == null ? void 0 : sendMessage(value);
712
+ sendMessage?.(value);
728
713
  setMessage("");
729
714
  }
730
715
  },
@@ -735,8 +720,7 @@
735
720
  }, []);
736
721
  const handleFileUpload = React.useCallback(
737
722
  (event) => {
738
- var _a;
739
- const file = (_a = event.target.files) == null ? void 0 : _a[0];
723
+ const file = event.target.files?.[0];
740
724
  if (file && fileUpload) {
741
725
  fileUpload(file);
742
726
  }
@@ -770,7 +754,7 @@
770
754
  }
771
755
  ),
772
756
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: reablocks.cn(theme.input.actions.base), children: [
773
- (allowedFiles == null ? void 0 : allowedFiles.length) > 0 && /* @__PURE__ */ jsxRuntime.jsx(
757
+ allowedFiles?.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
774
758
  FileInput,
775
759
  {
776
760
  allowedFiles,
@@ -1880,7 +1864,7 @@
1880
1864
  toolbarClassName,
1881
1865
  theme = dark
1882
1866
  }) => {
1883
- const match = language == null ? void 0 : language.match(/language-(\w+)/);
1867
+ const match = language?.match(/language-(\w+)/);
1884
1868
  const lang = match ? match[1] : "text";
1885
1869
  const handleCopy = (text) => {
1886
1870
  navigator.clipboard.writeText(text).then(() => {
@@ -1963,14 +1947,16 @@
1963
1947
  li: (props) => /* @__PURE__ */ jsxRuntime.jsx("li", { ...props, className: reablocks.cn(theme.messages.message.markdown.li) }),
1964
1948
  ul: (props) => /* @__PURE__ */ jsxRuntime.jsx("ul", { ...props, className: reablocks.cn(theme.messages.message.markdown.ul) }),
1965
1949
  ol: (props) => /* @__PURE__ */ jsxRuntime.jsx("ol", { ...props, className: reablocks.cn(theme.messages.message.markdown.ol) }),
1966
- redact: (props) => /* @__PURE__ */ jsxRuntime.jsx(
1950
+ // 'redact' is a custom element created by remarkRedact, not a standard
1951
+ // HTML tag, so it falls outside react-markdown's Components type.
1952
+ redact: ((props) => /* @__PURE__ */ jsxRuntime.jsx(
1967
1953
  reablocks.Redact,
1968
1954
  {
1969
1955
  value: props["data-redact-value"] || props.children,
1970
1956
  allowToggle: true,
1971
1957
  tooltipText: `${props["data-redact-name"] || "Sensitive"} information - Click to toggle`
1972
1958
  }
1973
- )
1959
+ ))
1974
1960
  };
1975
1961
  return {
1976
1962
  ...defaultComponents,
@@ -1988,7 +1974,7 @@
1988
1974
  }
1989
1975
  );
1990
1976
  };
1991
- const ChartError = ({
1977
+ const ComponentError = ({
1992
1978
  variant = "error",
1993
1979
  title,
1994
1980
  message,
@@ -2016,12 +2002,12 @@
2016
2002
  data: d.data
2017
2003
  }));
2018
2004
  if (!chartData || chartData.length === 0) {
2019
- return /* @__PURE__ */ jsxRuntime.jsx(ChartError, { variant: "warning", message: "No chart data available" });
2005
+ return /* @__PURE__ */ jsxRuntime.jsx(ComponentError, { variant: "warning", message: "No chart data available" });
2020
2006
  }
2021
2007
  for (const point of chartData) {
2022
2008
  if (typeof point.data !== "number" || isNaN(point.data)) {
2023
2009
  return /* @__PURE__ */ jsxRuntime.jsx(
2024
- ChartError,
2010
+ ComponentError,
2025
2011
  {
2026
2012
  message: `Invalid data point: ${JSON.stringify(point)}`
2027
2013
  }
@@ -2090,10 +2076,10 @@
2090
2076
  case "sparkline":
2091
2077
  return /* @__PURE__ */ jsxRuntime.jsx(reaviz.SparklineChart, { width, height, data: chartData });
2092
2078
  default:
2093
- return /* @__PURE__ */ jsxRuntime.jsx(ChartError, { message: `Unknown chart type: ${type}` });
2079
+ return /* @__PURE__ */ jsxRuntime.jsx(ComponentError, { message: `Unknown chart type: ${type}` });
2094
2080
  }
2095
2081
  } catch (error) {
2096
- return /* @__PURE__ */ jsxRuntime.jsx(ChartError, { message: `Chart render error: ${String(error)}` });
2082
+ return /* @__PURE__ */ jsxRuntime.jsx(ComponentError, { message: `Chart render error: ${String(error)}` });
2097
2083
  }
2098
2084
  }, [type, data, width, height]);
2099
2085
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: reablocks.cn(theme.chart.base, className), children: [
@@ -2101,93 +2087,6 @@
2101
2087
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: theme.chart.content, children: chartElement })
2102
2088
  ] });
2103
2089
  };
2104
- function validateChartData(data) {
2105
- if (!Array.isArray(data)) {
2106
- return null;
2107
- }
2108
- const validData = [];
2109
- for (const item of data) {
2110
- if (item && typeof item === "object" && "key" in item && "data" in item && typeof item.data === "number") {
2111
- validData.push({
2112
- key: String(item.key),
2113
- data: item.data
2114
- });
2115
- } else {
2116
- return null;
2117
- }
2118
- }
2119
- return validData.length > 0 ? validData : null;
2120
- }
2121
- function parseChartConfig(value) {
2122
- try {
2123
- const config = JSON.parse(value);
2124
- if (!config || !config.type || !config.data) {
2125
- return null;
2126
- }
2127
- const validData = validateChartData(config.data);
2128
- if (!validData) {
2129
- console.warn("parseChartConfig: Invalid chart data format");
2130
- return null;
2131
- }
2132
- return {
2133
- ...config,
2134
- data: validData
2135
- };
2136
- } catch (error) {
2137
- console.warn("parseChartConfig: Failed to parse JSON", error);
2138
- return null;
2139
- }
2140
- }
2141
- function isChartClassName(className) {
2142
- return className === "language-chart";
2143
- }
2144
- function getChildText(children) {
2145
- if (children === null || children === void 0) {
2146
- return "";
2147
- }
2148
- if (typeof children === "string") {
2149
- return children;
2150
- }
2151
- if (typeof children === "number") {
2152
- return String(children);
2153
- }
2154
- if (Array.isArray(children)) {
2155
- return children.map(getChildText).join("");
2156
- }
2157
- if (typeof children === "object") {
2158
- if ("props" in children && children.props) {
2159
- const element = children;
2160
- return getChildText(element.props.children);
2161
- }
2162
- }
2163
- return "";
2164
- }
2165
- const ChartPre = ({ children, ...props }) => {
2166
- var _a, _b;
2167
- if (children && typeof children === "object" && "props" in children) {
2168
- const codeElement = children;
2169
- if (isChartClassName((_a = codeElement.props) == null ? void 0 : _a.className)) {
2170
- const codeContent = getChildText((_b = codeElement.props) == null ? void 0 : _b.children);
2171
- if (codeContent) {
2172
- const chartConfig = parseChartConfig(codeContent);
2173
- if (chartConfig) {
2174
- return /* @__PURE__ */ jsxRuntime.jsx(ChartRenderer, { config: chartConfig });
2175
- }
2176
- }
2177
- return /* @__PURE__ */ jsxRuntime.jsx(
2178
- ChartError,
2179
- {
2180
- title: "Failed to parse chart configuration",
2181
- code: codeContent || "No content"
2182
- }
2183
- );
2184
- }
2185
- }
2186
- return /* @__PURE__ */ jsxRuntime.jsx("pre", { ...props, children });
2187
- };
2188
- const chartComponents = {
2189
- pre: ChartPre
2190
- };
2191
2090
  const CVE_REGEX = /(CVE-(19|20)\d{2}-\d{4,7})/gi;
2192
2091
  function remarkCve() {
2193
2092
  return (tree, _file) => {
@@ -2208,31 +2107,8 @@
2208
2107
  ];
2209
2108
  }
2210
2109
  }
2211
- const remarkChart = (options = {}) => {
2212
- const { defaultWidth = 400, defaultHeight = 300 } = options;
2213
- return (tree) => {
2214
- unistUtilVisit.visit(tree, "code", (node) => {
2215
- if (node.lang !== "chart") {
2216
- return;
2217
- }
2218
- try {
2219
- const config = JSON.parse(node.value);
2220
- if (!config.type || !config.data) {
2221
- console.warn(
2222
- "remarkChart: Invalid chart config - missing type or data"
2223
- );
2224
- return;
2225
- }
2226
- const chartConfig = {
2227
- ...config,
2228
- width: config.width ?? defaultWidth,
2229
- height: config.height ?? defaultHeight
2230
- };
2231
- node.value = JSON.stringify(chartConfig);
2232
- } catch (error) {
2233
- console.warn("remarkChart: Failed to parse chart config:", error);
2234
- }
2235
- });
2110
+ const remarkComponent = (_options = {}) => {
2111
+ return () => {
2236
2112
  };
2237
2113
  };
2238
2114
  function remarkRedact(matchers) {
@@ -2307,7 +2183,7 @@
2307
2183
  }) => {
2308
2184
  const { theme } = React.useContext(ChatContext);
2309
2185
  const FileRenderer = React.useMemo(() => {
2310
- const Renderer = Object.keys(FILE_TYPE_RENDERER_MAP).find((key) => type == null ? void 0 : type.startsWith(key)) ?? "default";
2186
+ const Renderer = Object.keys(FILE_TYPE_RENDERER_MAP).find((key) => type?.startsWith(key)) ?? "default";
2311
2187
  return FILE_TYPE_RENDERER_MAP[Renderer] || DefaultFileRenderer$2;
2312
2188
  }, [type]);
2313
2189
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -2491,8 +2367,7 @@
2491
2367
  }
2492
2368
  return files.reduce(
2493
2369
  (acc, file) => {
2494
- var _a;
2495
- if ((_a = file.type) == null ? void 0 : _a.startsWith("image/")) {
2370
+ if (file.type?.startsWith("image/")) {
2496
2371
  acc.imageFiles.push(file);
2497
2372
  } else {
2498
2373
  acc.otherFiles.push(file);
@@ -2794,7 +2669,6 @@ ${response}` : ""}`);
2794
2669
  showMoreText = "Show more",
2795
2670
  showScrollBottomButton = false
2796
2671
  }) => {
2797
- var _a, _b, _c, _d, _e, _f;
2798
2672
  const { activeSession, theme } = React.useContext(ChatContext);
2799
2673
  const contentRef = React.useRef(null);
2800
2674
  const messagesRef = React.useRef(null);
@@ -2835,7 +2709,7 @@ ${response}` : ""}`);
2835
2709
  }
2836
2710
  };
2837
2711
  const reversedConvos = React.useMemo(
2838
- () => [...(activeSession == null ? void 0 : activeSession.conversations) ?? []].reverse(),
2712
+ () => [...activeSession?.conversations ?? []].reverse(),
2839
2713
  [activeSession]
2840
2714
  );
2841
2715
  const { data, hasMore, showNext } = reablocks.useInfinityList({
@@ -2843,7 +2717,7 @@ ${response}` : ""}`);
2843
2717
  size: limit
2844
2718
  });
2845
2719
  const reReversedConvo = React.useMemo(() => [...data].reverse(), [data]);
2846
- const convosToRender = limit ? reReversedConvo : activeSession == null ? void 0 : activeSession.conversations;
2720
+ const convosToRender = limit ? reReversedConvo : activeSession?.conversations;
2847
2721
  if (!activeSession) {
2848
2722
  return /* @__PURE__ */ jsxRuntime.jsx(SessionEmpty, { children: newSessionContent });
2849
2723
  }
@@ -2853,7 +2727,7 @@ ${response}` : ""}`);
2853
2727
  {
2854
2728
  className: reablocks.cn(theme.messages.content, "h-full"),
2855
2729
  ref: contentRef,
2856
- id: activeSession == null ? void 0 : activeSession.id,
2730
+ id: activeSession?.id,
2857
2731
  children: [
2858
2732
  hasMore && /* @__PURE__ */ jsxRuntime.jsx(
2859
2733
  reablocks.Button,
@@ -2887,7 +2761,7 @@ ${response}` : ""}`);
2887
2761
  conversation.id
2888
2762
  ))
2889
2763
  },
2890
- activeSession == null ? void 0 : activeSession.id
2764
+ activeSession?.id
2891
2765
  ) })
2892
2766
  ]
2893
2767
  }
@@ -2899,12 +2773,12 @@ ${response}` : ""}`);
2899
2773
  animate: { y: 0, opacity: 1 },
2900
2774
  exit: { y: 100, opacity: 0 },
2901
2775
  transition: { duration: 0.3, ease: "easeOut" },
2902
- className: (_c = (_b = (_a = theme.messages) == null ? void 0 : _a.message) == null ? void 0 : _b.scrollToBottom) == null ? void 0 : _c.container,
2776
+ className: theme.messages?.message?.scrollToBottom?.container,
2903
2777
  children: /* @__PURE__ */ jsxRuntime.jsx(
2904
2778
  reablocks.IconButton,
2905
2779
  {
2906
2780
  onClick: handleScrollToBottom,
2907
- className: (_f = (_e = (_d = theme.messages) == null ? void 0 : _d.message) == null ? void 0 : _e.scrollToBottom) == null ? void 0 : _f.button,
2781
+ className: theme.messages?.message?.scrollToBottom?.button,
2908
2782
  size: "sm",
2909
2783
  children: /* @__PURE__ */ jsxRuntime.jsx(SvgArrowDown, {})
2910
2784
  }
@@ -2960,6 +2834,7 @@ ${response}` : ""}`);
2960
2834
  onNewSession,
2961
2835
  remarkPlugins = defaultRemarkPlugins,
2962
2836
  markdownComponents,
2837
+ components: componentCatalog2,
2963
2838
  disabled,
2964
2839
  style,
2965
2840
  className
@@ -2974,20 +2849,20 @@ ${response}` : ""}`);
2974
2849
  const handleSelectSession = React.useCallback(
2975
2850
  (sessionId) => {
2976
2851
  setInternalActiveSessionID(sessionId);
2977
- onSelectSession == null ? void 0 : onSelectSession(sessionId);
2852
+ onSelectSession?.(sessionId);
2978
2853
  },
2979
2854
  [onSelectSession]
2980
2855
  );
2981
2856
  const handleDeleteSession = React.useCallback(
2982
2857
  (sessionId) => {
2983
2858
  setInternalActiveSessionID(void 0);
2984
- onDeleteSession == null ? void 0 : onDeleteSession(sessionId);
2859
+ onDeleteSession?.(sessionId);
2985
2860
  },
2986
2861
  [onDeleteSession]
2987
2862
  );
2988
2863
  const handleCreateNewSession = React.useCallback(() => {
2989
2864
  setInternalActiveSessionID(void 0);
2990
- onNewSession == null ? void 0 : onNewSession();
2865
+ onNewSession?.();
2991
2866
  }, [onNewSession]);
2992
2867
  reakeys.useHotkeys([
2993
2868
  {
@@ -3004,12 +2879,23 @@ ${response}` : ""}`);
3004
2879
  () => sessions.find((session) => session.id === internalActiveSessionID),
3005
2880
  [sessions, internalActiveSessionID]
3006
2881
  );
2882
+ const mergedRemarkPlugins = React.useMemo(() => {
2883
+ if (!componentCatalog2) return remarkPlugins;
2884
+ return [...remarkPlugins, componentCatalog2.remarkPlugin];
2885
+ }, [remarkPlugins, componentCatalog2]);
2886
+ const mergedMarkdownComponents = React.useMemo(() => {
2887
+ if (!componentCatalog2) return markdownComponents;
2888
+ return {
2889
+ ...componentCatalog2.components,
2890
+ ...markdownComponents
2891
+ };
2892
+ }, [markdownComponents, componentCatalog2]);
3007
2893
  const contextValue = React.useMemo(
3008
2894
  () => ({
3009
2895
  sessions,
3010
2896
  activeSession,
3011
- remarkPlugins,
3012
- markdownComponents,
2897
+ remarkPlugins: mergedRemarkPlugins,
2898
+ markdownComponents: mergedMarkdownComponents,
3013
2899
  theme,
3014
2900
  disabled,
3015
2901
  isLoading,
@@ -3029,8 +2915,8 @@ ${response}` : ""}`);
3029
2915
  viewType,
3030
2916
  disabled,
3031
2917
  theme,
3032
- remarkPlugins,
3033
- markdownComponents,
2918
+ mergedRemarkPlugins,
2919
+ mergedMarkdownComponents,
3034
2920
  sessions,
3035
2921
  activeSession,
3036
2922
  internalActiveSessionID,
@@ -3069,7 +2955,7 @@ ${response}` : ""}`);
3069
2955
  const { activeSessionId, selectSession, deleteSession, theme } = React.useContext(ChatContext);
3070
2956
  const Comp = children ? reactSlot.Slot : reablocks.ListItem;
3071
2957
  const handleSelect = React.useCallback(() => {
3072
- selectSession == null ? void 0 : selectSession(session.id);
2958
+ selectSession?.(session.id);
3073
2959
  }, [selectSession, session.id]);
3074
2960
  const handleDelete = React.useCallback(
3075
2961
  (e) => {
@@ -3131,7 +3017,7 @@ ${response}` : ""}`);
3131
3017
  }),
3132
3018
  children: [
3133
3019
  /* @__PURE__ */ jsxRuntime.jsx(reablocks.List, { children }),
3134
- templates && !activeSessionId && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4", children: templates.map((template) => /* @__PURE__ */ jsxRuntime.jsx("div", { onClick: () => createSession == null ? void 0 : createSession(), children: /* @__PURE__ */ jsxRuntime.jsx(
3020
+ templates && !activeSessionId && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4", children: templates.map((template) => /* @__PURE__ */ jsxRuntime.jsx("div", { onClick: () => createSession?.(), children: /* @__PURE__ */ jsxRuntime.jsx(
3135
3021
  SessionListItem,
3136
3022
  {
3137
3023
  session: {
@@ -3160,7 +3046,7 @@ ${response}` : ""}`);
3160
3046
  fullWidth: true,
3161
3047
  disableMargins: true,
3162
3048
  color: "primary",
3163
- startAdornment: /* @__PURE__ */ jsxRuntime.jsx(SvgPlus, {}),
3049
+ start: /* @__PURE__ */ jsxRuntime.jsx(SvgPlus, {}),
3164
3050
  className: reablocks.cn(theme.sessions.create),
3165
3051
  disabled,
3166
3052
  onClick: createSession,
@@ -3296,7 +3182,7 @@ ${response}` : ""}`);
3296
3182
  const { theme, disabled, isLoading } = React.useContext(ChatContext);
3297
3183
  const handleClick = () => {
3298
3184
  if (disabled || isLoading) return;
3299
- onClick == null ? void 0 : onClick(content);
3185
+ onClick?.(content);
3300
3186
  };
3301
3187
  return /* @__PURE__ */ jsxRuntime.jsx(
3302
3188
  reablocks.Button,
@@ -3549,8 +3435,7 @@ ${response}` : ""}`);
3549
3435
  return null;
3550
3436
  }
3551
3437
  async function* parseSSE(response, signal) {
3552
- var _a;
3553
- const reader = (_a = response.body) == null ? void 0 : _a.getReader();
3438
+ const reader = response.body?.getReader();
3554
3439
  if (!reader) {
3555
3440
  throw new Error("Response body is not readable");
3556
3441
  }
@@ -3602,8 +3487,7 @@ ${response}` : ""}`);
3602
3487
  onEventRef.current = onEvent;
3603
3488
  React.useEffect(() => {
3604
3489
  return () => {
3605
- var _a;
3606
- (_a = abortRef.current) == null ? void 0 : _a.abort();
3490
+ abortRef.current?.abort();
3607
3491
  };
3608
3492
  }, []);
3609
3493
  const selectSession = React.useCallback((sessionId) => {
@@ -3631,15 +3515,13 @@ ${response}` : ""}`);
3631
3515
  setActiveSessionId(id);
3632
3516
  }, []);
3633
3517
  const stopMessage = React.useCallback(() => {
3634
- var _a;
3635
- (_a = abortRef.current) == null ? void 0 : _a.abort();
3518
+ abortRef.current?.abort();
3636
3519
  abortRef.current = null;
3637
3520
  setIsLoading(false);
3638
3521
  }, []);
3639
3522
  const sendMessage = React.useCallback(
3640
3523
  async (message) => {
3641
- var _a, _b, _c, _d, _e, _f;
3642
- (_a = abortRef.current) == null ? void 0 : _a.abort();
3524
+ abortRef.current?.abort();
3643
3525
  const abortController = new AbortController();
3644
3526
  abortRef.current = abortController;
3645
3527
  let sessionId = activeSessionId;
@@ -3666,7 +3548,7 @@ ${response}` : ""}`);
3666
3548
  );
3667
3549
  setIsLoading(true);
3668
3550
  const currentSession = [
3669
- ...((_b = sessions.find((s) => s.id === sessionId)) == null ? void 0 : _b.conversations) ?? []
3551
+ ...sessions.find((s) => s.id === sessionId)?.conversations ?? []
3670
3552
  ];
3671
3553
  const historyMessages = sessionsToAgUiMessages({
3672
3554
  conversations: currentSession
@@ -3714,11 +3596,11 @@ ${response}` : ""}`);
3714
3596
  abortController.signal
3715
3597
  )) {
3716
3598
  if (eventOrError instanceof Error) {
3717
- (_c = onErrorRef.current) == null ? void 0 : _c.call(onErrorRef, eventOrError);
3599
+ onErrorRef.current?.(eventOrError);
3718
3600
  continue;
3719
3601
  }
3720
3602
  const event = eventOrError;
3721
- (_d = onEventRef.current) == null ? void 0 : _d.call(onEventRef, event);
3603
+ onEventRef.current?.(event);
3722
3604
  switch (event.type) {
3723
3605
  case AgUiEventType.TEXT_MESSAGE_CONTENT: {
3724
3606
  responseText += event.delta;
@@ -3763,7 +3645,7 @@ ${response}` : ""}`);
3763
3645
  }
3764
3646
  case AgUiEventType.RUN_ERROR: {
3765
3647
  const err = new Error(event.message);
3766
- (_e = onErrorRef.current) == null ? void 0 : _e.call(onErrorRef, err);
3648
+ onErrorRef.current?.(err);
3767
3649
  break;
3768
3650
  }
3769
3651
  case AgUiEventType.RUN_FINISHED: {
@@ -3776,7 +3658,7 @@ ${response}` : ""}`);
3776
3658
  return;
3777
3659
  }
3778
3660
  const error = err instanceof Error ? err : new Error(String(err));
3779
- (_f = onErrorRef.current) == null ? void 0 : _f.call(onErrorRef, error);
3661
+ onErrorRef.current?.(error);
3780
3662
  } finally {
3781
3663
  if (abortRef.current === abortController) {
3782
3664
  abortRef.current = null;
@@ -3797,10 +3679,420 @@ ${response}` : ""}`);
3797
3679
  stopMessage
3798
3680
  };
3799
3681
  }
3682
+ function validateSpec(raw, definitions) {
3683
+ let parsed;
3684
+ try {
3685
+ parsed = JSON.parse(raw);
3686
+ } catch {
3687
+ return {
3688
+ ok: false,
3689
+ error: {
3690
+ type: "invalid_json",
3691
+ message: "Failed to parse component JSON",
3692
+ raw
3693
+ }
3694
+ };
3695
+ }
3696
+ const specArray = Array.isArray(parsed) ? parsed : [parsed];
3697
+ const validated = [];
3698
+ for (const item of specArray) {
3699
+ const result = validateSingleSpec(item, raw, definitions);
3700
+ if (!result.ok) {
3701
+ return { ok: false, error: result.error };
3702
+ }
3703
+ validated.push(result.spec);
3704
+ }
3705
+ return { ok: true, specs: validated };
3706
+ }
3707
+ function validateSingleSpec(item, raw, definitions) {
3708
+ if (!item || typeof item !== "object" || !("type" in item)) {
3709
+ return {
3710
+ ok: false,
3711
+ error: {
3712
+ type: "invalid_json",
3713
+ message: 'Component spec must be an object with a "type" field',
3714
+ raw
3715
+ }
3716
+ };
3717
+ }
3718
+ const spec = item;
3719
+ if (typeof spec.type !== "string") {
3720
+ return {
3721
+ ok: false,
3722
+ error: {
3723
+ type: "invalid_json",
3724
+ message: '"type" must be a string',
3725
+ raw
3726
+ }
3727
+ };
3728
+ }
3729
+ const componentType = spec.type;
3730
+ const definition = definitions[componentType];
3731
+ if (!definition) {
3732
+ return {
3733
+ ok: false,
3734
+ error: {
3735
+ type: "unknown_component",
3736
+ message: `Unknown component "${componentType}". Available: ${Object.keys(definitions).join(", ")}`,
3737
+ raw,
3738
+ componentType
3739
+ }
3740
+ };
3741
+ }
3742
+ const props = spec.props && typeof spec.props === "object" && !Array.isArray(spec.props) ? spec.props : {};
3743
+ const parseResult = definition.props.safeParse(props);
3744
+ if (!parseResult.success) {
3745
+ return {
3746
+ ok: false,
3747
+ error: {
3748
+ type: "invalid_props",
3749
+ message: `Invalid props for "${componentType}": ${parseResult.error.issues.map((i) => i.message).join(", ")}`,
3750
+ raw,
3751
+ componentType,
3752
+ issues: parseResult.error.issues.map((i) => ({
3753
+ message: i.message,
3754
+ path: i.path
3755
+ }))
3756
+ }
3757
+ };
3758
+ }
3759
+ let validatedChildren;
3760
+ if (spec.children) {
3761
+ if (!Array.isArray(spec.children)) {
3762
+ return {
3763
+ ok: false,
3764
+ error: {
3765
+ type: "invalid_json",
3766
+ message: '"children" must be an array',
3767
+ raw,
3768
+ componentType
3769
+ }
3770
+ };
3771
+ }
3772
+ validatedChildren = [];
3773
+ for (const child of spec.children) {
3774
+ const childResult = validateSingleSpec(child, raw, definitions);
3775
+ if (!childResult.ok) {
3776
+ return childResult;
3777
+ }
3778
+ validatedChildren.push(childResult.spec);
3779
+ }
3780
+ }
3781
+ return {
3782
+ ok: true,
3783
+ spec: {
3784
+ type: componentType,
3785
+ props: parseResult.data,
3786
+ ...validatedChildren ? { children: validatedChildren } : {}
3787
+ }
3788
+ };
3789
+ }
3790
+ const ComponentRenderer = ({
3791
+ raw,
3792
+ definitions,
3793
+ options
3794
+ }) => {
3795
+ const { theme, sendMessage } = React.useContext(ChatContext);
3796
+ const result = React.useMemo(
3797
+ () => validateSpec(raw, definitions),
3798
+ [raw, definitions]
3799
+ );
3800
+ if (!result.ok) {
3801
+ const error = result.error;
3802
+ const custom = options?.onError?.(error);
3803
+ if (custom !== void 0) {
3804
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: custom });
3805
+ }
3806
+ return /* @__PURE__ */ jsxRuntime.jsx(
3807
+ ComponentError,
3808
+ {
3809
+ title: errorTitle(error.type),
3810
+ message: error.message,
3811
+ code: error.raw
3812
+ }
3813
+ );
3814
+ }
3815
+ const specs = result.specs;
3816
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: theme.component?.base, children: specs.map((spec, index) => /* @__PURE__ */ jsxRuntime.jsx(
3817
+ SpecRenderer,
3818
+ {
3819
+ spec,
3820
+ definitions,
3821
+ options,
3822
+ sendMessage
3823
+ },
3824
+ `${spec.type}-${index}-${stableKey(spec)}`
3825
+ )) });
3826
+ };
3827
+ const SpecRenderer = ({
3828
+ spec,
3829
+ definitions,
3830
+ options,
3831
+ sendMessage
3832
+ }) => {
3833
+ const definition = definitions[spec.type];
3834
+ if (!definition) {
3835
+ const error = {
3836
+ type: "unknown_component",
3837
+ message: `Unknown component "${spec.type}"`,
3838
+ raw: JSON.stringify(spec),
3839
+ componentType: spec.type
3840
+ };
3841
+ const custom = options?.onError?.(error);
3842
+ if (custom !== void 0) {
3843
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: custom });
3844
+ }
3845
+ return /* @__PURE__ */ jsxRuntime.jsx(ComponentError, { title: errorTitle(error.type), message: error.message });
3846
+ }
3847
+ const RenderedComponent = definition.component;
3848
+ const children = spec.children?.map((child, index) => /* @__PURE__ */ jsxRuntime.jsx(
3849
+ SpecRenderer,
3850
+ {
3851
+ spec: child,
3852
+ definitions,
3853
+ options,
3854
+ sendMessage
3855
+ },
3856
+ `${child.type}-${index}-${stableKey(child)}`
3857
+ ));
3858
+ return /* @__PURE__ */ jsxRuntime.jsx(SpecErrorBoundary, { spec, options, children: /* @__PURE__ */ jsxRuntime.jsx(RenderedComponent, { ...spec.props, sendMessage, children }) });
3859
+ };
3860
+ class SpecErrorBoundary extends React.Component {
3861
+ constructor() {
3862
+ super(...arguments);
3863
+ this.state = { error: null };
3864
+ }
3865
+ static getDerivedStateFromError(error) {
3866
+ return { error };
3867
+ }
3868
+ render() {
3869
+ if (this.state.error) {
3870
+ const { spec, options } = this.props;
3871
+ const catalogError = {
3872
+ type: "render_error",
3873
+ message: `Error rendering "${spec.type}": ${this.state.error.message}`,
3874
+ raw: JSON.stringify(spec),
3875
+ componentType: spec.type
3876
+ };
3877
+ const custom = options?.onError?.(catalogError);
3878
+ if (custom !== void 0) {
3879
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: custom });
3880
+ }
3881
+ return /* @__PURE__ */ jsxRuntime.jsx(
3882
+ ComponentError,
3883
+ {
3884
+ title: errorTitle(catalogError.type),
3885
+ message: catalogError.message
3886
+ }
3887
+ );
3888
+ }
3889
+ return this.props.children;
3890
+ }
3891
+ }
3892
+ function stableKey(spec) {
3893
+ const str = JSON.stringify({
3894
+ t: spec.type,
3895
+ p: spec.props,
3896
+ c: spec.children
3897
+ });
3898
+ let h = 0;
3899
+ for (let i = 0; i < str.length; i++) {
3900
+ h = h * 31 + str.charCodeAt(i) | 0;
3901
+ }
3902
+ return (h >>> 0).toString(36);
3903
+ }
3904
+ function errorTitle(type) {
3905
+ switch (type) {
3906
+ case "unknown_component":
3907
+ return "Unknown Component";
3908
+ case "invalid_props":
3909
+ return "Invalid Props";
3910
+ case "render_error":
3911
+ return "Render Error";
3912
+ default:
3913
+ return "Invalid Component";
3914
+ }
3915
+ }
3916
+ function getChildText(children) {
3917
+ if (children === null || children === void 0) {
3918
+ return "";
3919
+ }
3920
+ if (typeof children === "string") {
3921
+ return children;
3922
+ }
3923
+ if (typeof children === "number") {
3924
+ return String(children);
3925
+ }
3926
+ if (Array.isArray(children)) {
3927
+ return children.map(getChildText).join("");
3928
+ }
3929
+ if (typeof children === "object") {
3930
+ if ("props" in children && children.props) {
3931
+ const element = children;
3932
+ return getChildText(element.props.children);
3933
+ }
3934
+ }
3935
+ return "";
3936
+ }
3937
+ function createComponentPre(definitions, options) {
3938
+ const language = options?.language ?? "component";
3939
+ const className = `language-${language}`;
3940
+ const ComponentPre = ({ children, ...props }) => {
3941
+ if (children && typeof children === "object" && "props" in children) {
3942
+ const codeElement = children;
3943
+ if (codeElement.props?.className === className) {
3944
+ const codeContent = getChildText(codeElement.props?.children);
3945
+ if (codeContent) {
3946
+ return /* @__PURE__ */ jsxRuntime.jsx(
3947
+ ComponentRenderer,
3948
+ {
3949
+ raw: codeContent,
3950
+ definitions,
3951
+ options
3952
+ }
3953
+ );
3954
+ }
3955
+ }
3956
+ }
3957
+ return /* @__PURE__ */ jsxRuntime.jsx("pre", { ...props, children });
3958
+ };
3959
+ ComponentPre.displayName = "ComponentPre";
3960
+ return ComponentPre;
3961
+ }
3962
+ function describeJsonSchemaProperty(prop, indent = "") {
3963
+ const description = prop.description ? ` // ${prop.description}` : "";
3964
+ if (prop.anyOf) {
3965
+ const nonNull = prop.anyOf.filter((s) => !(s.type === "null"));
3966
+ const hasNull = prop.anyOf.some((s) => s.type === "null");
3967
+ if (nonNull.length === 1 && hasNull) {
3968
+ return `${describeJsonSchemaProperty(nonNull[0], indent)} | null${description}`;
3969
+ }
3970
+ const parts = prop.anyOf.map(
3971
+ (s) => describeJsonSchemaProperty(s, indent)
3972
+ );
3973
+ return `${parts.join(" | ")}${description}`;
3974
+ }
3975
+ if (prop.enum) {
3976
+ return `${prop.enum.map((v) => `"${v}"`).join(" | ")}${description}`;
3977
+ }
3978
+ if (prop.type === "array") {
3979
+ const items = prop.items ? describeJsonSchemaProperty(prop.items, indent) : "any";
3980
+ return `${items}[]${description}`;
3981
+ }
3982
+ if (prop.type === "object" && prop.properties) {
3983
+ const required = new Set(prop.required ?? []);
3984
+ const fields = [];
3985
+ for (const [key, value] of Object.entries(prop.properties)) {
3986
+ const opt = required.has(key) ? "" : "?";
3987
+ fields.push(
3988
+ `${indent} ${key}: ${describeJsonSchemaProperty(value, indent + " ")}${opt}`
3989
+ );
3990
+ }
3991
+ return `{
3992
+ ${fields.join(",\n")}
3993
+ ${indent}}${description}`;
3994
+ }
3995
+ if (prop.type === "string") return `string${description}`;
3996
+ if (prop.type === "number" || prop.type === "integer")
3997
+ return `number${description}`;
3998
+ if (prop.type === "boolean") return `boolean${description}`;
3999
+ if (prop.type === "null") return `null${description}`;
4000
+ return `any${description}`;
4001
+ }
4002
+ function describeProps(schema) {
4003
+ try {
4004
+ const jsonSchema = zod.z.toJSONSchema(schema);
4005
+ if (jsonSchema.type === "object" && jsonSchema.properties) {
4006
+ return describeJsonSchemaProperty(jsonSchema);
4007
+ }
4008
+ return "Record<string, any>";
4009
+ } catch {
4010
+ return "Record<string, any>";
4011
+ }
4012
+ }
4013
+ function generatePrompt(definitions, language = "component") {
4014
+ const names = Object.keys(definitions);
4015
+ if (names.length === 0) {
4016
+ return "";
4017
+ }
4018
+ const componentDocs = names.map((name) => {
4019
+ const def = definitions[name];
4020
+ const propsDesc = describeProps(def.props);
4021
+ return `- **${name}**: ${def.description}
4022
+ Props: ${propsDesc}`;
4023
+ }).join("\n\n");
4024
+ return `When you need to render a dynamic UI component in your response, use a fenced code block with language \`${language}\` containing a JSON object:
4025
+
4026
+ \`\`\`${language}
4027
+ { "type": "ComponentName", "props": { ... } }
4028
+ \`\`\`
4029
+
4030
+ For multiple components, use a JSON array:
4031
+
4032
+ \`\`\`${language}
4033
+ [
4034
+ { "type": "ComponentA", "props": { ... } },
4035
+ { "type": "ComponentB", "props": { ... } }
4036
+ ]
4037
+ \`\`\`
4038
+
4039
+ For nested/composed layouts, use the "children" field:
4040
+
4041
+ \`\`\`${language}
4042
+ {
4043
+ "type": "Parent",
4044
+ "props": { ... },
4045
+ "children": [
4046
+ { "type": "Child", "props": { ... } }
4047
+ ]
4048
+ }
4049
+ \`\`\`
4050
+
4051
+ Available components:
4052
+
4053
+ ${componentDocs}`;
4054
+ }
4055
+ function componentCatalog(definitions, options) {
4056
+ const language = options?.language ?? "component";
4057
+ const plugin = remarkComponent.bind(void 0, {
4058
+ language
4059
+ });
4060
+ const Pre = createComponentPre(definitions, options);
4061
+ return {
4062
+ remarkPlugin: plugin,
4063
+ components: { pre: Pre },
4064
+ systemPrompt: () => generatePrompt(definitions, language),
4065
+ definitions
4066
+ };
4067
+ }
4068
+ function createChartComponentDef() {
4069
+ const chartPropsSchema = zod.z.object({
4070
+ type: zod.z.enum([
4071
+ "bar",
4072
+ "line",
4073
+ "area",
4074
+ "pie",
4075
+ "radialBar",
4076
+ "radialArea",
4077
+ "sparkline"
4078
+ ]).describe("Chart type"),
4079
+ data: zod.z.array(zod.z.object({ key: zod.z.string(), data: zod.z.number() })).describe("Array of { key, data } data points"),
4080
+ width: zod.z.number().describe("Chart width in px").optional(),
4081
+ height: zod.z.number().describe("Chart height in px").optional(),
4082
+ title: zod.z.string().describe("Chart title").optional()
4083
+ });
4084
+ return {
4085
+ description: "Renders a chart. Supported types: bar, line, area, pie, radialBar, radialArea, sparkline",
4086
+ props: chartPropsSchema,
4087
+ component: ({
4088
+ children: _children,
4089
+ sendMessage: _sendMessage,
4090
+ ...config
4091
+ }) => /* @__PURE__ */ jsxRuntime.jsx(ChartRenderer, { config })
4092
+ };
4093
+ }
3800
4094
  exports2.AgUiEventType = AgUiEventType;
3801
4095
  exports2.AppBar = AppBar;
3802
- exports2.ChartError = ChartError;
3803
- exports2.ChartPre = ChartPre;
3804
4096
  exports2.ChartRenderer = ChartRenderer;
3805
4097
  exports2.Chat = Chat;
3806
4098
  exports2.ChatBubble = ChatBubble;
@@ -3809,6 +4101,8 @@ ${response}` : ""}`);
3809
4101
  exports2.ChatSuggestion = ChatSuggestion;
3810
4102
  exports2.ChatSuggestions = ChatSuggestions;
3811
4103
  exports2.CodeHighlighter = CodeHighlighter;
4104
+ exports2.ComponentError = ComponentError;
4105
+ exports2.ComponentRenderer = ComponentRenderer;
3812
4106
  exports2.FileInput = FileInput;
3813
4107
  exports2.Markdown = Markdown;
3814
4108
  exports2.MentionList = MentionList;
@@ -3837,21 +4131,21 @@ ${response}` : ""}`);
3837
4131
  exports2.TableDataCell = TableDataCell;
3838
4132
  exports2.TableHeaderCell = TableHeaderCell;
3839
4133
  exports2.bitcoinMatcher = bitcoinMatcher;
3840
- exports2.chartComponents = chartComponents;
3841
4134
  exports2.chatTheme = chatTheme;
3842
4135
  exports2.commonRedactMatchers = commonRedactMatchers;
4136
+ exports2.componentCatalog = componentCatalog;
4137
+ exports2.createChartComponentDef = createChartComponentDef;
4138
+ exports2.createComponentPre = createComponentPre;
3843
4139
  exports2.creditCardMatcher = creditCardMatcher;
3844
4140
  exports2.dark = dark;
3845
- exports2.getChildText = getChildText;
3846
- exports2.isChartClassName = isChartClassName;
4141
+ exports2.generatePrompt = generatePrompt;
3847
4142
  exports2.light = light;
3848
- exports2.parseChartConfig = parseChartConfig;
3849
- exports2.remarkChart = remarkChart;
4143
+ exports2.remarkComponent = remarkComponent;
3850
4144
  exports2.remarkCve = remarkCve;
3851
4145
  exports2.remarkRedact = remarkRedact;
3852
4146
  exports2.ssnMatcher = ssnMatcher;
3853
4147
  exports2.useAgUi = useAgUi;
3854
- exports2.validateChartData = validateChartData;
4148
+ exports2.validateSpec = validateSpec;
3855
4149
  Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
3856
- });
4150
+ }));
3857
4151
  //# sourceMappingURL=index.umd.cjs.map