reachat 2.2.0 → 3.0.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 (44) hide show
  1. package/dist/{CSVFileRenderer-BOdL4Jte.js → CSVFileRenderer-C2tuexJf.js} +2 -2
  2. package/dist/{CSVFileRenderer-BOdL4Jte.js.map → CSVFileRenderer-C2tuexJf.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-CJ3jwiQa.js} +2 -2
  17. package/dist/{DefaultFileRenderer-C2MsQ9wz.js.map → DefaultFileRenderer-CJ3jwiQa.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 +259 -77
  25. package/dist/{index-DdRyk11n.js → index-8tlsyFe-.js} +470 -147
  26. package/dist/index-8tlsyFe-.js.map +1 -0
  27. package/dist/index.css +26 -0
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.js +22 -22
  30. package/dist/index.umd.cjs +454 -131
  31. package/dist/index.umd.cjs.map +1 -1
  32. package/dist/stories/Charts.stories.tsx +118 -130
  33. package/dist/stories/ComponentCatalog.stories.tsx +509 -0
  34. package/dist/stories/{ChartError.stories.tsx → ComponentError.stories.tsx} +14 -11
  35. package/dist/theme.d.ts +3 -0
  36. package/dist/utils/getChildText.d.ts +10 -0
  37. package/dist/utils/getChildText.spec.d.ts +1 -0
  38. package/package.json +4 -6
  39. package/dist/Markdown/charts/ChartPre.d.ts +0 -6
  40. package/dist/Markdown/charts/chartHelpers.d.ts +0 -40
  41. package/dist/Markdown/plugins/remarkChart.d.ts +0 -59
  42. package/dist/index-DdRyk11n.js.map +0 -1
  43. package/dist/stories/Integration.stories.tsx +0 -312
  44. /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" } });
@@ -320,6 +320,9 @@
320
320
  ].join(" "),
321
321
  title: "text-yellow-600 dark:text-yellow-400 text-sm font-medium mb-2"
322
322
  }
323
+ },
324
+ component: {
325
+ base: "my-4"
323
326
  }
324
327
  };
325
328
  const POPUP_STYLE = { zIndex: 9999 };
@@ -1963,6 +1966,8 @@
1963
1966
  li: (props) => /* @__PURE__ */ jsxRuntime.jsx("li", { ...props, className: reablocks.cn(theme.messages.message.markdown.li) }),
1964
1967
  ul: (props) => /* @__PURE__ */ jsxRuntime.jsx("ul", { ...props, className: reablocks.cn(theme.messages.message.markdown.ul) }),
1965
1968
  ol: (props) => /* @__PURE__ */ jsxRuntime.jsx("ol", { ...props, className: reablocks.cn(theme.messages.message.markdown.ol) }),
1969
+ // 'redact' is a custom element created by remarkRedact, not a standard
1970
+ // HTML tag, so it falls outside react-markdown's Components type.
1966
1971
  redact: (props) => /* @__PURE__ */ jsxRuntime.jsx(
1967
1972
  reablocks.Redact,
1968
1973
  {
@@ -1988,7 +1993,7 @@
1988
1993
  }
1989
1994
  );
1990
1995
  };
1991
- const ChartError = ({
1996
+ const ComponentError = ({
1992
1997
  variant = "error",
1993
1998
  title,
1994
1999
  message,
@@ -2016,12 +2021,12 @@
2016
2021
  data: d.data
2017
2022
  }));
2018
2023
  if (!chartData || chartData.length === 0) {
2019
- return /* @__PURE__ */ jsxRuntime.jsx(ChartError, { variant: "warning", message: "No chart data available" });
2024
+ return /* @__PURE__ */ jsxRuntime.jsx(ComponentError, { variant: "warning", message: "No chart data available" });
2020
2025
  }
2021
2026
  for (const point of chartData) {
2022
2027
  if (typeof point.data !== "number" || isNaN(point.data)) {
2023
2028
  return /* @__PURE__ */ jsxRuntime.jsx(
2024
- ChartError,
2029
+ ComponentError,
2025
2030
  {
2026
2031
  message: `Invalid data point: ${JSON.stringify(point)}`
2027
2032
  }
@@ -2090,10 +2095,10 @@
2090
2095
  case "sparkline":
2091
2096
  return /* @__PURE__ */ jsxRuntime.jsx(reaviz.SparklineChart, { width, height, data: chartData });
2092
2097
  default:
2093
- return /* @__PURE__ */ jsxRuntime.jsx(ChartError, { message: `Unknown chart type: ${type}` });
2098
+ return /* @__PURE__ */ jsxRuntime.jsx(ComponentError, { message: `Unknown chart type: ${type}` });
2094
2099
  }
2095
2100
  } catch (error) {
2096
- return /* @__PURE__ */ jsxRuntime.jsx(ChartError, { message: `Chart render error: ${String(error)}` });
2101
+ return /* @__PURE__ */ jsxRuntime.jsx(ComponentError, { message: `Chart render error: ${String(error)}` });
2097
2102
  }
2098
2103
  }, [type, data, width, height]);
2099
2104
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: reablocks.cn(theme.chart.base, className), children: [
@@ -2101,93 +2106,6 @@
2101
2106
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: theme.chart.content, children: chartElement })
2102
2107
  ] });
2103
2108
  };
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
2109
  const CVE_REGEX = /(CVE-(19|20)\d{2}-\d{4,7})/gi;
2192
2110
  function remarkCve() {
2193
2111
  return (tree, _file) => {
@@ -2208,31 +2126,8 @@
2208
2126
  ];
2209
2127
  }
2210
2128
  }
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
- });
2129
+ const remarkComponent = (_options = {}) => {
2130
+ return () => {
2236
2131
  };
2237
2132
  };
2238
2133
  function remarkRedact(matchers) {
@@ -2960,6 +2855,7 @@ ${response}` : ""}`);
2960
2855
  onNewSession,
2961
2856
  remarkPlugins = defaultRemarkPlugins,
2962
2857
  markdownComponents,
2858
+ components: componentCatalog2,
2963
2859
  disabled,
2964
2860
  style,
2965
2861
  className
@@ -3004,12 +2900,23 @@ ${response}` : ""}`);
3004
2900
  () => sessions.find((session) => session.id === internalActiveSessionID),
3005
2901
  [sessions, internalActiveSessionID]
3006
2902
  );
2903
+ const mergedRemarkPlugins = React.useMemo(() => {
2904
+ if (!componentCatalog2) return remarkPlugins;
2905
+ return [...remarkPlugins, componentCatalog2.remarkPlugin];
2906
+ }, [remarkPlugins, componentCatalog2]);
2907
+ const mergedMarkdownComponents = React.useMemo(() => {
2908
+ if (!componentCatalog2) return markdownComponents;
2909
+ return {
2910
+ ...componentCatalog2.components,
2911
+ ...markdownComponents
2912
+ };
2913
+ }, [markdownComponents, componentCatalog2]);
3007
2914
  const contextValue = React.useMemo(
3008
2915
  () => ({
3009
2916
  sessions,
3010
2917
  activeSession,
3011
- remarkPlugins,
3012
- markdownComponents,
2918
+ remarkPlugins: mergedRemarkPlugins,
2919
+ markdownComponents: mergedMarkdownComponents,
3013
2920
  theme,
3014
2921
  disabled,
3015
2922
  isLoading,
@@ -3029,8 +2936,8 @@ ${response}` : ""}`);
3029
2936
  viewType,
3030
2937
  disabled,
3031
2938
  theme,
3032
- remarkPlugins,
3033
- markdownComponents,
2939
+ mergedRemarkPlugins,
2940
+ mergedMarkdownComponents,
3034
2941
  sessions,
3035
2942
  activeSession,
3036
2943
  internalActiveSessionID,
@@ -3797,10 +3704,424 @@ ${response}` : ""}`);
3797
3704
  stopMessage
3798
3705
  };
3799
3706
  }
3707
+ function validateSpec(raw, definitions) {
3708
+ let parsed;
3709
+ try {
3710
+ parsed = JSON.parse(raw);
3711
+ } catch {
3712
+ return {
3713
+ ok: false,
3714
+ error: {
3715
+ type: "invalid_json",
3716
+ message: "Failed to parse component JSON",
3717
+ raw
3718
+ }
3719
+ };
3720
+ }
3721
+ const specArray = Array.isArray(parsed) ? parsed : [parsed];
3722
+ const validated = [];
3723
+ for (const item of specArray) {
3724
+ const result = validateSingleSpec(item, raw, definitions);
3725
+ if (!result.ok) {
3726
+ return { ok: false, error: result.error };
3727
+ }
3728
+ validated.push(result.spec);
3729
+ }
3730
+ return { ok: true, specs: validated };
3731
+ }
3732
+ function validateSingleSpec(item, raw, definitions) {
3733
+ if (!item || typeof item !== "object" || !("type" in item)) {
3734
+ return {
3735
+ ok: false,
3736
+ error: {
3737
+ type: "invalid_json",
3738
+ message: 'Component spec must be an object with a "type" field',
3739
+ raw
3740
+ }
3741
+ };
3742
+ }
3743
+ const spec = item;
3744
+ if (typeof spec.type !== "string") {
3745
+ return {
3746
+ ok: false,
3747
+ error: {
3748
+ type: "invalid_json",
3749
+ message: '"type" must be a string',
3750
+ raw
3751
+ }
3752
+ };
3753
+ }
3754
+ const componentType = spec.type;
3755
+ const definition = definitions[componentType];
3756
+ if (!definition) {
3757
+ return {
3758
+ ok: false,
3759
+ error: {
3760
+ type: "unknown_component",
3761
+ message: `Unknown component "${componentType}". Available: ${Object.keys(definitions).join(", ")}`,
3762
+ raw,
3763
+ componentType
3764
+ }
3765
+ };
3766
+ }
3767
+ const props = spec.props && typeof spec.props === "object" && !Array.isArray(spec.props) ? spec.props : {};
3768
+ const parseResult = definition.props.safeParse(props);
3769
+ if (!parseResult.success) {
3770
+ return {
3771
+ ok: false,
3772
+ error: {
3773
+ type: "invalid_props",
3774
+ message: `Invalid props for "${componentType}": ${parseResult.error.issues.map((i) => i.message).join(", ")}`,
3775
+ raw,
3776
+ componentType,
3777
+ issues: parseResult.error.issues.map((i) => ({
3778
+ message: i.message,
3779
+ path: i.path
3780
+ }))
3781
+ }
3782
+ };
3783
+ }
3784
+ let validatedChildren;
3785
+ if (spec.children) {
3786
+ if (!Array.isArray(spec.children)) {
3787
+ return {
3788
+ ok: false,
3789
+ error: {
3790
+ type: "invalid_json",
3791
+ message: '"children" must be an array',
3792
+ raw,
3793
+ componentType
3794
+ }
3795
+ };
3796
+ }
3797
+ validatedChildren = [];
3798
+ for (const child of spec.children) {
3799
+ const childResult = validateSingleSpec(child, raw, definitions);
3800
+ if (!childResult.ok) {
3801
+ return childResult;
3802
+ }
3803
+ validatedChildren.push(childResult.spec);
3804
+ }
3805
+ }
3806
+ return {
3807
+ ok: true,
3808
+ spec: {
3809
+ type: componentType,
3810
+ props: parseResult.data,
3811
+ ...validatedChildren ? { children: validatedChildren } : {}
3812
+ }
3813
+ };
3814
+ }
3815
+ const ComponentRenderer = ({
3816
+ raw,
3817
+ definitions,
3818
+ options
3819
+ }) => {
3820
+ var _a, _b;
3821
+ const { theme, sendMessage } = React.useContext(ChatContext);
3822
+ const result = React.useMemo(
3823
+ () => validateSpec(raw, definitions),
3824
+ [raw, definitions]
3825
+ );
3826
+ if (!result.ok) {
3827
+ const error = result.error;
3828
+ const custom = (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, error);
3829
+ if (custom !== void 0) {
3830
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: custom });
3831
+ }
3832
+ return /* @__PURE__ */ jsxRuntime.jsx(
3833
+ ComponentError,
3834
+ {
3835
+ title: errorTitle(error.type),
3836
+ message: error.message,
3837
+ code: error.raw
3838
+ }
3839
+ );
3840
+ }
3841
+ const specs = result.specs;
3842
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: (_b = theme.component) == null ? void 0 : _b.base, children: specs.map((spec, index) => /* @__PURE__ */ jsxRuntime.jsx(
3843
+ SpecRenderer,
3844
+ {
3845
+ spec,
3846
+ definitions,
3847
+ options,
3848
+ sendMessage
3849
+ },
3850
+ `${spec.type}-${index}-${stableKey(spec)}`
3851
+ )) });
3852
+ };
3853
+ const SpecRenderer = ({
3854
+ spec,
3855
+ definitions,
3856
+ options,
3857
+ sendMessage
3858
+ }) => {
3859
+ var _a, _b;
3860
+ const definition = definitions[spec.type];
3861
+ if (!definition) {
3862
+ const error = {
3863
+ type: "unknown_component",
3864
+ message: `Unknown component "${spec.type}"`,
3865
+ raw: JSON.stringify(spec),
3866
+ componentType: spec.type
3867
+ };
3868
+ const custom = (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, error);
3869
+ if (custom !== void 0) {
3870
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: custom });
3871
+ }
3872
+ return /* @__PURE__ */ jsxRuntime.jsx(ComponentError, { title: errorTitle(error.type), message: error.message });
3873
+ }
3874
+ const RenderedComponent = definition.component;
3875
+ const children = (_b = spec.children) == null ? void 0 : _b.map((child, index) => /* @__PURE__ */ jsxRuntime.jsx(
3876
+ SpecRenderer,
3877
+ {
3878
+ spec: child,
3879
+ definitions,
3880
+ options,
3881
+ sendMessage
3882
+ },
3883
+ `${child.type}-${index}-${stableKey(child)}`
3884
+ ));
3885
+ return /* @__PURE__ */ jsxRuntime.jsx(SpecErrorBoundary, { spec, options, children: /* @__PURE__ */ jsxRuntime.jsx(RenderedComponent, { ...spec.props, sendMessage, children }) });
3886
+ };
3887
+ class SpecErrorBoundary extends React.Component {
3888
+ constructor() {
3889
+ super(...arguments);
3890
+ this.state = { error: null };
3891
+ }
3892
+ static getDerivedStateFromError(error) {
3893
+ return { error };
3894
+ }
3895
+ render() {
3896
+ var _a;
3897
+ if (this.state.error) {
3898
+ const { spec, options } = this.props;
3899
+ const catalogError = {
3900
+ type: "render_error",
3901
+ message: `Error rendering "${spec.type}": ${this.state.error.message}`,
3902
+ raw: JSON.stringify(spec),
3903
+ componentType: spec.type
3904
+ };
3905
+ const custom = (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, catalogError);
3906
+ if (custom !== void 0) {
3907
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: custom });
3908
+ }
3909
+ return /* @__PURE__ */ jsxRuntime.jsx(
3910
+ ComponentError,
3911
+ {
3912
+ title: errorTitle(catalogError.type),
3913
+ message: catalogError.message
3914
+ }
3915
+ );
3916
+ }
3917
+ return this.props.children;
3918
+ }
3919
+ }
3920
+ function stableKey(spec) {
3921
+ const str = JSON.stringify({
3922
+ t: spec.type,
3923
+ p: spec.props,
3924
+ c: spec.children
3925
+ });
3926
+ let h = 0;
3927
+ for (let i = 0; i < str.length; i++) {
3928
+ h = h * 31 + str.charCodeAt(i) | 0;
3929
+ }
3930
+ return (h >>> 0).toString(36);
3931
+ }
3932
+ function errorTitle(type) {
3933
+ switch (type) {
3934
+ case "unknown_component":
3935
+ return "Unknown Component";
3936
+ case "invalid_props":
3937
+ return "Invalid Props";
3938
+ case "render_error":
3939
+ return "Render Error";
3940
+ default:
3941
+ return "Invalid Component";
3942
+ }
3943
+ }
3944
+ function getChildText(children) {
3945
+ if (children === null || children === void 0) {
3946
+ return "";
3947
+ }
3948
+ if (typeof children === "string") {
3949
+ return children;
3950
+ }
3951
+ if (typeof children === "number") {
3952
+ return String(children);
3953
+ }
3954
+ if (Array.isArray(children)) {
3955
+ return children.map(getChildText).join("");
3956
+ }
3957
+ if (typeof children === "object") {
3958
+ if ("props" in children && children.props) {
3959
+ const element = children;
3960
+ return getChildText(element.props.children);
3961
+ }
3962
+ }
3963
+ return "";
3964
+ }
3965
+ function createComponentPre(definitions, options) {
3966
+ const language = (options == null ? void 0 : options.language) ?? "component";
3967
+ const className = `language-${language}`;
3968
+ const ComponentPre = ({ children, ...props }) => {
3969
+ var _a, _b;
3970
+ if (children && typeof children === "object" && "props" in children) {
3971
+ const codeElement = children;
3972
+ if (((_a = codeElement.props) == null ? void 0 : _a.className) === className) {
3973
+ const codeContent = getChildText((_b = codeElement.props) == null ? void 0 : _b.children);
3974
+ if (codeContent) {
3975
+ return /* @__PURE__ */ jsxRuntime.jsx(
3976
+ ComponentRenderer,
3977
+ {
3978
+ raw: codeContent,
3979
+ definitions,
3980
+ options
3981
+ }
3982
+ );
3983
+ }
3984
+ }
3985
+ }
3986
+ return /* @__PURE__ */ jsxRuntime.jsx("pre", { ...props, children });
3987
+ };
3988
+ ComponentPre.displayName = "ComponentPre";
3989
+ return ComponentPre;
3990
+ }
3991
+ function describeJsonSchemaProperty(prop, indent = "") {
3992
+ const description = prop.description ? ` // ${prop.description}` : "";
3993
+ if (prop.anyOf) {
3994
+ const nonNull = prop.anyOf.filter((s) => !(s.type === "null"));
3995
+ const hasNull = prop.anyOf.some((s) => s.type === "null");
3996
+ if (nonNull.length === 1 && hasNull) {
3997
+ return `${describeJsonSchemaProperty(nonNull[0], indent)} | null${description}`;
3998
+ }
3999
+ const parts = prop.anyOf.map(
4000
+ (s) => describeJsonSchemaProperty(s, indent)
4001
+ );
4002
+ return `${parts.join(" | ")}${description}`;
4003
+ }
4004
+ if (prop.enum) {
4005
+ return `${prop.enum.map((v) => `"${v}"`).join(" | ")}${description}`;
4006
+ }
4007
+ if (prop.type === "array") {
4008
+ const items = prop.items ? describeJsonSchemaProperty(prop.items, indent) : "any";
4009
+ return `${items}[]${description}`;
4010
+ }
4011
+ if (prop.type === "object" && prop.properties) {
4012
+ const required = new Set(prop.required ?? []);
4013
+ const fields = [];
4014
+ for (const [key, value] of Object.entries(prop.properties)) {
4015
+ const opt = required.has(key) ? "" : "?";
4016
+ fields.push(
4017
+ `${indent} ${key}: ${describeJsonSchemaProperty(value, indent + " ")}${opt}`
4018
+ );
4019
+ }
4020
+ return `{
4021
+ ${fields.join(",\n")}
4022
+ ${indent}}${description}`;
4023
+ }
4024
+ if (prop.type === "string") return `string${description}`;
4025
+ if (prop.type === "number" || prop.type === "integer")
4026
+ return `number${description}`;
4027
+ if (prop.type === "boolean") return `boolean${description}`;
4028
+ if (prop.type === "null") return `null${description}`;
4029
+ return `any${description}`;
4030
+ }
4031
+ function describeProps(schema) {
4032
+ try {
4033
+ const jsonSchema = zod.z.toJSONSchema(schema);
4034
+ if (jsonSchema.type === "object" && jsonSchema.properties) {
4035
+ return describeJsonSchemaProperty(jsonSchema);
4036
+ }
4037
+ return "Record<string, any>";
4038
+ } catch {
4039
+ return "Record<string, any>";
4040
+ }
4041
+ }
4042
+ function generatePrompt(definitions, language = "component") {
4043
+ const names = Object.keys(definitions);
4044
+ if (names.length === 0) {
4045
+ return "";
4046
+ }
4047
+ const componentDocs = names.map((name) => {
4048
+ const def = definitions[name];
4049
+ const propsDesc = describeProps(def.props);
4050
+ return `- **${name}**: ${def.description}
4051
+ Props: ${propsDesc}`;
4052
+ }).join("\n\n");
4053
+ 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:
4054
+
4055
+ \`\`\`${language}
4056
+ { "type": "ComponentName", "props": { ... } }
4057
+ \`\`\`
4058
+
4059
+ For multiple components, use a JSON array:
4060
+
4061
+ \`\`\`${language}
4062
+ [
4063
+ { "type": "ComponentA", "props": { ... } },
4064
+ { "type": "ComponentB", "props": { ... } }
4065
+ ]
4066
+ \`\`\`
4067
+
4068
+ For nested/composed layouts, use the "children" field:
4069
+
4070
+ \`\`\`${language}
4071
+ {
4072
+ "type": "Parent",
4073
+ "props": { ... },
4074
+ "children": [
4075
+ { "type": "Child", "props": { ... } }
4076
+ ]
4077
+ }
4078
+ \`\`\`
4079
+
4080
+ Available components:
4081
+
4082
+ ${componentDocs}`;
4083
+ }
4084
+ function componentCatalog(definitions, options) {
4085
+ const language = (options == null ? void 0 : options.language) ?? "component";
4086
+ const plugin = remarkComponent.bind(void 0, {
4087
+ language
4088
+ });
4089
+ const Pre = createComponentPre(definitions, options);
4090
+ return {
4091
+ remarkPlugin: plugin,
4092
+ components: { pre: Pre },
4093
+ systemPrompt: () => generatePrompt(definitions, language),
4094
+ definitions
4095
+ };
4096
+ }
4097
+ function createChartComponentDef() {
4098
+ const chartPropsSchema = zod.z.object({
4099
+ type: zod.z.enum([
4100
+ "bar",
4101
+ "line",
4102
+ "area",
4103
+ "pie",
4104
+ "radialBar",
4105
+ "radialArea",
4106
+ "sparkline"
4107
+ ]).describe("Chart type"),
4108
+ data: zod.z.array(zod.z.object({ key: zod.z.string(), data: zod.z.number() })).describe("Array of { key, data } data points"),
4109
+ width: zod.z.number().describe("Chart width in px").optional(),
4110
+ height: zod.z.number().describe("Chart height in px").optional(),
4111
+ title: zod.z.string().describe("Chart title").optional()
4112
+ });
4113
+ return {
4114
+ description: "Renders a chart. Supported types: bar, line, area, pie, radialBar, radialArea, sparkline",
4115
+ props: chartPropsSchema,
4116
+ component: ({
4117
+ children: _children,
4118
+ sendMessage: _sendMessage,
4119
+ ...config
4120
+ }) => /* @__PURE__ */ jsxRuntime.jsx(ChartRenderer, { config })
4121
+ };
4122
+ }
3800
4123
  exports2.AgUiEventType = AgUiEventType;
3801
4124
  exports2.AppBar = AppBar;
3802
- exports2.ChartError = ChartError;
3803
- exports2.ChartPre = ChartPre;
3804
4125
  exports2.ChartRenderer = ChartRenderer;
3805
4126
  exports2.Chat = Chat;
3806
4127
  exports2.ChatBubble = ChatBubble;
@@ -3809,6 +4130,8 @@ ${response}` : ""}`);
3809
4130
  exports2.ChatSuggestion = ChatSuggestion;
3810
4131
  exports2.ChatSuggestions = ChatSuggestions;
3811
4132
  exports2.CodeHighlighter = CodeHighlighter;
4133
+ exports2.ComponentError = ComponentError;
4134
+ exports2.ComponentRenderer = ComponentRenderer;
3812
4135
  exports2.FileInput = FileInput;
3813
4136
  exports2.Markdown = Markdown;
3814
4137
  exports2.MentionList = MentionList;
@@ -3837,21 +4160,21 @@ ${response}` : ""}`);
3837
4160
  exports2.TableDataCell = TableDataCell;
3838
4161
  exports2.TableHeaderCell = TableHeaderCell;
3839
4162
  exports2.bitcoinMatcher = bitcoinMatcher;
3840
- exports2.chartComponents = chartComponents;
3841
4163
  exports2.chatTheme = chatTheme;
3842
4164
  exports2.commonRedactMatchers = commonRedactMatchers;
4165
+ exports2.componentCatalog = componentCatalog;
4166
+ exports2.createChartComponentDef = createChartComponentDef;
4167
+ exports2.createComponentPre = createComponentPre;
3843
4168
  exports2.creditCardMatcher = creditCardMatcher;
3844
4169
  exports2.dark = dark;
3845
- exports2.getChildText = getChildText;
3846
- exports2.isChartClassName = isChartClassName;
4170
+ exports2.generatePrompt = generatePrompt;
3847
4171
  exports2.light = light;
3848
- exports2.parseChartConfig = parseChartConfig;
3849
- exports2.remarkChart = remarkChart;
4172
+ exports2.remarkComponent = remarkComponent;
3850
4173
  exports2.remarkCve = remarkCve;
3851
4174
  exports2.remarkRedact = remarkRedact;
3852
4175
  exports2.ssnMatcher = ssnMatcher;
3853
4176
  exports2.useAgUi = useAgUi;
3854
- exports2.validateChartData = validateChartData;
4177
+ exports2.validateSpec = validateSpec;
3855
4178
  Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
3856
4179
  });
3857
4180
  //# sourceMappingURL=index.umd.cjs.map