@schandlergarcia/sf-web-components 1.8.0 → 1.9.1
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/components/library/cards/SemanticTableCard.d.ts +1 -1
- package/dist/components/library/chat/ChatBar.d.ts +14 -11
- package/dist/components/library/chat/ChatBar.js +2 -3
- package/dist/components/library/chat/ChatBar.js.map +1 -1
- package/dist/components/library/chat/ChatInput.d.ts +9 -8
- package/dist/components/library/chat/ChatInput.js.map +1 -1
- package/dist/components/library/chat/ChatMessage.d.ts +18 -4
- package/dist/components/library/chat/ChatMessage.js.map +1 -1
- package/dist/components/library/chat/ChatMessageList.d.ts +11 -8
- package/dist/components/library/chat/ChatMessageList.js.map +1 -1
- package/dist/components/library/chat/ChatPanel.d.ts +16 -12
- package/dist/components/library/chat/ChatPanel.js +8 -9
- package/dist/components/library/chat/ChatPanel.js.map +1 -1
- package/dist/components/library/chat/ChatSuggestions.d.ts +5 -4
- package/dist/components/library/chat/ChatSuggestions.js +2 -3
- package/dist/components/library/chat/ChatSuggestions.js.map +1 -1
- package/dist/components/library/chat/ChatToolCall.d.ts +11 -3
- package/dist/components/library/chat/ChatToolCall.js.map +1 -1
- package/dist/components/library/chat/ChatTypingIndicator.d.ts +4 -3
- package/dist/components/library/chat/ChatTypingIndicator.js +2 -3
- package/dist/components/library/chat/ChatTypingIndicator.js.map +1 -1
- package/dist/components/library/chat/ChatWelcome.d.ts +9 -7
- package/dist/components/library/chat/ChatWelcome.js +6 -7
- package/dist/components/library/chat/ChatWelcome.js.map +1 -1
- package/dist/components/library/chat/index.d.ts +10 -0
- package/dist/components/library/chat/useChatState.d.ts +37 -11
- package/dist/components/library/chat/useChatState.js +63 -46
- package/dist/components/library/chat/useChatState.js.map +1 -1
- package/dist/components/library/data/DataModeProvider.d.ts +15 -11
- package/dist/components/library/data/DataModeProvider.js +1 -1
- package/dist/components/library/data/DataModeProvider.js.map +1 -1
- package/dist/components/library/data/DataModeToggle.d.ts +4 -3
- package/dist/components/library/data/DataModeToggle.js +4 -5
- package/dist/components/library/data/DataModeToggle.js.map +1 -1
- package/dist/components/library/data/chartDataProvider.d.ts +41 -3
- package/dist/components/library/data/filterUtils.d.ts +38 -9
- package/dist/components/library/data/filterUtils.js.map +1 -1
- package/dist/components/library/data/useDataSource.d.ts +6 -4
- package/dist/components/library/data/useDataSource.js.map +1 -1
- package/dist/components/library/data/usePageFilters.d.ts +31 -5
- package/dist/components/library/data/usePageFilters.js +6 -2
- package/dist/components/library/data/usePageFilters.js.map +1 -1
- package/dist/components/library/index.d.ts +92 -73
- package/dist/components/library/index.js +25 -25
- package/dist/components/library/index.js.map +1 -1
- package/dist/components/library/skeletons/CardSkeleton.d.ts +5 -4
- package/dist/components/library/skeletons/CardSkeleton.js +2 -3
- package/dist/components/library/skeletons/CardSkeleton.js.map +1 -1
- package/dist/components/library/theme/AppThemeProvider.d.ts +13 -50
- package/dist/components/library/theme/AppThemeProvider.js.map +1 -1
- package/dist/components/library/theme/tokens.d.ts +45 -44
- package/dist/components/library/theme/tokens.js.map +1 -1
- package/dist/components/workspace/ComponentRegistry.d.ts +116 -140
- package/dist/components/workspace/ComponentRegistry.js +43 -43
- package/dist/components/workspace/ComponentRegistry.js.map +1 -1
- package/package.json +2 -2
- package/src/components/library/cards/SemanticMetricCard.tsx +1 -1
- package/src/components/library/cards/SemanticTableCard.tsx +3 -3
- package/src/components/library/chat/{ChatBar.jsx → ChatBar.tsx} +19 -8
- package/src/components/library/chat/{ChatInput.jsx → ChatInput.tsx} +13 -11
- package/src/components/library/chat/{ChatMessage.jsx → ChatMessage.tsx} +23 -10
- package/src/components/library/chat/{ChatMessageList.jsx → ChatMessageList.tsx} +13 -11
- package/src/components/library/chat/{ChatPanel.jsx → ChatPanel.tsx} +16 -13
- package/src/components/library/chat/{ChatSuggestions.jsx → ChatSuggestions.tsx} +6 -5
- package/src/components/library/chat/{ChatToolCall.jsx → ChatToolCall.tsx} +14 -4
- package/src/components/library/chat/{ChatTypingIndicator.jsx → ChatTypingIndicator.tsx} +5 -2
- package/src/components/library/chat/{ChatWelcome.jsx → ChatWelcome.tsx} +9 -7
- package/src/components/library/chat/index.tsx +26 -0
- package/src/components/library/chat/useChatState.tsx +182 -0
- package/src/components/library/data/{DataModeProvider.jsx → DataModeProvider.tsx} +25 -8
- package/src/components/library/data/{DataModeToggle.jsx → DataModeToggle.tsx} +5 -2
- package/src/components/library/data/{chartDataProvider.jsx → chartDataProvider.tsx} +49 -5
- package/src/components/library/data/{filterUtils.jsx → filterUtils.tsx} +58 -12
- package/src/components/library/data/{useDataSource.jsx → useDataSource.tsx} +9 -2
- package/src/components/library/data/{usePageFilters.jsx → usePageFilters.tsx} +49 -9
- package/src/components/library/{index.jsx → index.ts} +14 -14
- package/src/components/library/skeletons/{CardSkeleton.jsx → CardSkeleton.tsx} +5 -4
- package/src/components/library/theme/{AppThemeProvider.jsx → AppThemeProvider.tsx} +20 -7
- package/src/components/library/theme/{tokens.jsx → tokens.tsx} +37 -3
- package/src/components/workspace/{ComponentRegistry.jsx → ComponentRegistry.tsx} +137 -32
- package/src/components/library/chat/index.jsx +0 -10
- package/src/components/library/chat/useChatState.jsx +0 -130
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs as i, jsx as e } from "react/jsx-runtime";
|
|
2
|
-
import b from "react";
|
|
2
|
+
import * as b from "react";
|
|
3
3
|
import "../library/theme/AppThemeProvider.js";
|
|
4
4
|
import u from "../library/ui/UIButton.js";
|
|
5
5
|
import p from "../library/ui/Chip.js";
|
|
@@ -18,14 +18,14 @@ import "react-dom";
|
|
|
18
18
|
import "../library/data/DataModeProvider.js";
|
|
19
19
|
import "@heroicons/react/24/solid";
|
|
20
20
|
const y = {
|
|
21
|
-
NarrativeSummary({ summary:
|
|
21
|
+
NarrativeSummary({ summary: r, title: a }) {
|
|
22
22
|
return /* @__PURE__ */ i("div", { className: "text-sm text-slate-600 dark:text-slate-300", children: [
|
|
23
23
|
a && /* @__PURE__ */ e("div", { className: "mb-1 font-medium text-slate-900 dark:text-slate-50", children: a }),
|
|
24
|
-
|
|
24
|
+
r
|
|
25
25
|
] });
|
|
26
26
|
},
|
|
27
|
-
MetricsStrip({ metrics:
|
|
28
|
-
const [o, s] = b.useState(l), n =
|
|
27
|
+
MetricsStrip({ metrics: r = [], title: a, collapsible: d = !1, collapsed: l = !1 }) {
|
|
28
|
+
const [o, s] = b.useState(l), n = r.length ? r : [
|
|
29
29
|
{ label: "Metric A", value: "—", trend: null },
|
|
30
30
|
{ label: "Metric B", value: "—", trend: null },
|
|
31
31
|
{ label: "Metric C", value: "—", trend: null }
|
|
@@ -40,7 +40,7 @@ const y = {
|
|
|
40
40
|
/* @__PURE__ */ i("span", { children: [
|
|
41
41
|
a ?? "Metrics",
|
|
42
42
|
": ",
|
|
43
|
-
n.map((
|
|
43
|
+
n.map((t) => `${t.label} ${t.value}`).join(" · ")
|
|
44
44
|
] }),
|
|
45
45
|
/* @__PURE__ */ e("span", { children: "▸" })
|
|
46
46
|
]
|
|
@@ -58,26 +58,26 @@ const y = {
|
|
|
58
58
|
}
|
|
59
59
|
)
|
|
60
60
|
] }),
|
|
61
|
-
/* @__PURE__ */ e("div", { className: "flex flex-wrap gap-4", children: n.map((
|
|
62
|
-
/* @__PURE__ */ e("div", { className: "text-xs text-slate-400 dark:text-slate-500", children:
|
|
61
|
+
/* @__PURE__ */ e("div", { className: "flex flex-wrap gap-4", children: n.map((t) => /* @__PURE__ */ i("div", { className: "min-w-[80px]", children: [
|
|
62
|
+
/* @__PURE__ */ e("div", { className: "text-xs text-slate-400 dark:text-slate-500", children: t.label }),
|
|
63
63
|
/* @__PURE__ */ i("div", { className: "flex items-baseline gap-1.5", children: [
|
|
64
|
-
/* @__PURE__ */ e("span", { className: "text-sm font-semibold text-slate-700 dark:text-slate-200", children:
|
|
65
|
-
|
|
64
|
+
/* @__PURE__ */ e("span", { className: "text-sm font-semibold text-slate-700 dark:text-slate-200", children: t.value }),
|
|
65
|
+
t.trend && /* @__PURE__ */ e("span", { className: `text-xs ${String(t.trend).startsWith?.("+") || typeof t.trend == "number" && t.trend > 0 ? "text-red-500" : "text-emerald-500"}`, children: typeof t.trend == "number" && t.trend > 0 ? `+${t.trend}` : t.trend })
|
|
66
66
|
] })
|
|
67
|
-
] },
|
|
67
|
+
] }, t.label)) })
|
|
68
68
|
] });
|
|
69
69
|
},
|
|
70
|
-
ItemList({ items:
|
|
70
|
+
ItemList({ items: r = [], title: a, onItemClick: d }) {
|
|
71
71
|
const [l, o] = b.useState(null);
|
|
72
|
-
return
|
|
72
|
+
return r.length ? /* @__PURE__ */ i("div", { className: "space-y-2", children: [
|
|
73
73
|
a && /* @__PURE__ */ i("div", { className: "flex items-center justify-between", children: [
|
|
74
74
|
/* @__PURE__ */ e("span", { className: "text-sm font-medium text-slate-900 dark:text-slate-50", children: a }),
|
|
75
75
|
/* @__PURE__ */ i("span", { className: "text-xs text-slate-400 dark:text-slate-500", children: [
|
|
76
|
-
|
|
76
|
+
r.length,
|
|
77
77
|
" items"
|
|
78
78
|
] })
|
|
79
79
|
] }),
|
|
80
|
-
/* @__PURE__ */ e("div", { className: "space-y-1.5", children:
|
|
80
|
+
/* @__PURE__ */ e("div", { className: "space-y-1.5", children: r.map((s, n) => /* @__PURE__ */ i("div", { className: "rounded-xl border border-slate-200 bg-white dark:border-slate-800 dark:bg-slate-900", children: [
|
|
81
81
|
/* @__PURE__ */ e(
|
|
82
82
|
"button",
|
|
83
83
|
{
|
|
@@ -95,19 +95,19 @@ const y = {
|
|
|
95
95
|
] })
|
|
96
96
|
}
|
|
97
97
|
),
|
|
98
|
-
l === (s.id ?? n) && s.actions && /* @__PURE__ */ e("div", { className: "border-t border-slate-100 px-3 py-2 dark:border-slate-800", children: /* @__PURE__ */ e("div", { className: "flex flex-wrap gap-1.5", children: s.actions.map((
|
|
98
|
+
l === (s.id ?? n) && s.actions && /* @__PURE__ */ e("div", { className: "border-t border-slate-100 px-3 py-2 dark:border-slate-800", children: /* @__PURE__ */ e("div", { className: "flex flex-wrap gap-1.5", children: s.actions.map((t, m) => /* @__PURE__ */ e(
|
|
99
99
|
"button",
|
|
100
100
|
{
|
|
101
101
|
type: "button",
|
|
102
102
|
className: `rounded-md px-2.5 py-1 text-xs font-medium transition-colors ${m === 0 ? "bg-slate-900 text-white hover:bg-slate-800 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-200" : "bg-slate-100 text-slate-700 hover:bg-slate-200 dark:bg-slate-800 dark:text-slate-300 dark:hover:bg-slate-700"}`,
|
|
103
|
-
children: typeof
|
|
103
|
+
children: typeof t == "string" ? t : t.label
|
|
104
104
|
},
|
|
105
|
-
typeof
|
|
105
|
+
typeof t == "string" ? t : t.label
|
|
106
106
|
)) }) })
|
|
107
107
|
] }, s.id ?? n)) })
|
|
108
108
|
] }) : /* @__PURE__ */ e("div", { className: "text-sm text-slate-500 dark:text-slate-400", children: "No items." });
|
|
109
109
|
},
|
|
110
|
-
DataTable({ title:
|
|
110
|
+
DataTable({ title: r, subtitle: a, columns: d = [], data: l = [], rows: o, searchable: s = !0, sortable: n = !0, paginated: t = !0, pageSize: m = 5 }) {
|
|
111
111
|
const c = l.length ? l : o ?? [], x = d.length ? d : [
|
|
112
112
|
{ key: "name", label: "Name" },
|
|
113
113
|
{ key: "status", label: "Status" },
|
|
@@ -116,23 +116,23 @@ const y = {
|
|
|
116
116
|
return /* @__PURE__ */ e(
|
|
117
117
|
k,
|
|
118
118
|
{
|
|
119
|
-
title:
|
|
119
|
+
title: r ?? "Data",
|
|
120
120
|
subtitle: a,
|
|
121
121
|
columns: x,
|
|
122
122
|
data: c,
|
|
123
123
|
searchable: s,
|
|
124
124
|
sortable: n,
|
|
125
|
-
paginated:
|
|
125
|
+
paginated: t,
|
|
126
126
|
pageSize: m
|
|
127
127
|
}
|
|
128
128
|
);
|
|
129
129
|
},
|
|
130
|
-
DataChart({ title:
|
|
131
|
-
const s = l.length ? l : Array.from({ length: 12 }, (n,
|
|
130
|
+
DataChart({ title: r, subtitle: a, chartType: d = "line", data: l = [], height: o = 200 }) {
|
|
131
|
+
const s = l.length ? l : Array.from({ length: 12 }, (n, t) => ({ x: t, y: Math.random() * 100 }));
|
|
132
132
|
return /* @__PURE__ */ e(
|
|
133
133
|
h,
|
|
134
134
|
{
|
|
135
|
-
title:
|
|
135
|
+
title: r ?? "Trend",
|
|
136
136
|
subtitle: a ?? "Data visualization",
|
|
137
137
|
chartType: d,
|
|
138
138
|
height: o,
|
|
@@ -142,34 +142,34 @@ const y = {
|
|
|
142
142
|
data: s,
|
|
143
143
|
responsive: !0,
|
|
144
144
|
height: o,
|
|
145
|
-
ariaLabel:
|
|
146
|
-
renderChart: (n,
|
|
145
|
+
ariaLabel: r,
|
|
146
|
+
renderChart: (n, t, m, c) => N.lineChart(n, t, m, c),
|
|
147
147
|
options: { xKey: "x", yKey: "y", showGrid: !0, showAxes: !0 }
|
|
148
148
|
}
|
|
149
149
|
)
|
|
150
150
|
}
|
|
151
151
|
);
|
|
152
152
|
},
|
|
153
|
-
MetricCard({ title:
|
|
153
|
+
MetricCard({ title: r, label: a, value: d, trend: l, change: o, changeType: s, color: n, icon: t, description: m }) {
|
|
154
154
|
return /* @__PURE__ */ e(
|
|
155
155
|
g,
|
|
156
156
|
{
|
|
157
|
-
title:
|
|
157
|
+
title: r ?? a,
|
|
158
158
|
value: d ?? "—",
|
|
159
159
|
trend: l,
|
|
160
160
|
change: o,
|
|
161
161
|
changeType: s,
|
|
162
162
|
color: n,
|
|
163
|
-
icon:
|
|
164
|
-
|
|
163
|
+
icon: t,
|
|
164
|
+
subtitle: m
|
|
165
165
|
}
|
|
166
166
|
);
|
|
167
167
|
},
|
|
168
|
-
StatusCard({ title:
|
|
168
|
+
StatusCard({ title: r, subtitle: a, status: d, items: l, layout: o, showProgress: s, showTimestamp: n }) {
|
|
169
169
|
return /* @__PURE__ */ e(
|
|
170
170
|
f,
|
|
171
171
|
{
|
|
172
|
-
title:
|
|
172
|
+
title: r,
|
|
173
173
|
subtitle: a,
|
|
174
174
|
status: d,
|
|
175
175
|
items: l,
|
|
@@ -179,10 +179,10 @@ const y = {
|
|
|
179
179
|
}
|
|
180
180
|
);
|
|
181
181
|
},
|
|
182
|
-
ActionList({ actions:
|
|
182
|
+
ActionList({ actions: r = [], title: a, onAction: d }) {
|
|
183
183
|
return /* @__PURE__ */ i("div", { className: "rounded-2xl border border-slate-200 bg-white p-4 dark:border-slate-800 dark:bg-slate-900", children: [
|
|
184
184
|
a && /* @__PURE__ */ e("div", { className: "mb-3 text-sm font-medium text-slate-900 dark:text-slate-50", children: a }),
|
|
185
|
-
/* @__PURE__ */ e("div", { className: "flex flex-wrap gap-2", children:
|
|
185
|
+
/* @__PURE__ */ e("div", { className: "flex flex-wrap gap-2", children: r.map((l, o) => /* @__PURE__ */ e(
|
|
186
186
|
u,
|
|
187
187
|
{
|
|
188
188
|
size: "sm",
|
|
@@ -194,7 +194,7 @@ const y = {
|
|
|
194
194
|
)) })
|
|
195
195
|
] });
|
|
196
196
|
},
|
|
197
|
-
CalloutCard({ title:
|
|
197
|
+
CalloutCard({ title: r, message: a, tone: d = "neutral" }) {
|
|
198
198
|
const l = {
|
|
199
199
|
neutral: "border-slate-200 bg-slate-50 text-slate-700 dark:border-slate-800 dark:bg-slate-950/30 dark:text-slate-200",
|
|
200
200
|
success: "border-emerald-200 bg-emerald-50 text-emerald-800 dark:border-emerald-900/40 dark:bg-emerald-950/20 dark:text-emerald-200",
|
|
@@ -202,31 +202,31 @@ const y = {
|
|
|
202
202
|
danger: "border-rose-200 bg-rose-50 text-rose-800 dark:border-rose-900/40 dark:bg-rose-950/20 dark:text-rose-200"
|
|
203
203
|
};
|
|
204
204
|
return /* @__PURE__ */ i("div", { className: `rounded-xl border p-4 ${l[d] ?? l.neutral}`, children: [
|
|
205
|
-
|
|
205
|
+
r && /* @__PURE__ */ e("div", { className: "mb-1 text-sm font-semibold", children: r }),
|
|
206
206
|
/* @__PURE__ */ e("div", { className: "text-sm", children: a })
|
|
207
207
|
] });
|
|
208
208
|
},
|
|
209
209
|
Divider() {
|
|
210
210
|
return /* @__PURE__ */ e("div", { className: "h-px bg-slate-200 dark:bg-slate-800" });
|
|
211
211
|
},
|
|
212
|
-
Spacer({ size:
|
|
212
|
+
Spacer({ size: r = "md" }) {
|
|
213
213
|
const a = { sm: "h-2", md: "h-4", lg: "h-6" };
|
|
214
|
-
return /* @__PURE__ */ e("div", { className: a[
|
|
214
|
+
return /* @__PURE__ */ e("div", { className: a[r] ?? a.md });
|
|
215
215
|
}
|
|
216
216
|
};
|
|
217
217
|
let C = { ...y };
|
|
218
218
|
function w() {
|
|
219
219
|
return C;
|
|
220
220
|
}
|
|
221
|
-
function
|
|
222
|
-
const l = w()[
|
|
223
|
-
return l ? /* @__PURE__ */ e(l, { ...
|
|
221
|
+
function P(r, a) {
|
|
222
|
+
const l = w()[r.type];
|
|
223
|
+
return l ? /* @__PURE__ */ e(l, { ...r.props ?? {} }, r.id ?? a) : /* @__PURE__ */ i("div", { className: "rounded-lg border border-dashed border-slate-300 p-3 text-xs text-slate-500 dark:border-slate-700", children: [
|
|
224
224
|
"Unknown component: ",
|
|
225
|
-
|
|
225
|
+
r.type
|
|
226
226
|
] }, a);
|
|
227
227
|
}
|
|
228
228
|
export {
|
|
229
229
|
w as getComponentRegistry,
|
|
230
|
-
|
|
230
|
+
P as renderSchemaComponent
|
|
231
231
|
};
|
|
232
232
|
//# sourceMappingURL=ComponentRegistry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComponentRegistry.js","sources":["../../../src/components/workspace/ComponentRegistry.jsx"],"sourcesContent":["import React from \"react\";\nimport {\n BaseCard,\n MetricCard,\n TableCard,\n ChartCard,\n D3Chart,\n D3ChartTemplates,\n StatusCard,\n ListCard,\n UIButton,\n UIChip,\n UIText\n} from \"@/components/library\";\n\nconst BUILTIN_COMPONENTS = {\n NarrativeSummary({ summary, title }) {\n return (\n <div className=\"text-sm text-slate-600 dark:text-slate-300\">\n {title && <div className=\"mb-1 font-medium text-slate-900 dark:text-slate-50\">{title}</div>}\n {summary}\n </div>\n );\n },\n\n MetricsStrip({ metrics = [], title, collapsible = false, collapsed: initialCollapsed = false }) {\n const [collapsed, setCollapsed] = React.useState(initialCollapsed);\n\n const items = metrics.length ? metrics : [\n { label: \"Metric A\", value: \"—\", trend: null },\n { label: \"Metric B\", value: \"—\", trend: null },\n { label: \"Metric C\", value: \"—\", trend: null }\n ];\n\n if (collapsible && collapsed) {\n return (\n <button\n type=\"button\"\n onClick={() => setCollapsed(false)}\n className=\"flex w-full items-center justify-between rounded-lg border border-slate-200 bg-white px-3 py-2 text-left text-xs text-slate-500 hover:bg-slate-50 dark:border-slate-800 dark:bg-slate-900 dark:text-slate-400 dark:hover:bg-slate-800\"\n >\n <span>{title ?? \"Metrics\"}: {items.map(m => `${m.label} ${m.value}`).join(\" · \")}</span>\n <span>▸</span>\n </button>\n );\n }\n\n return (\n <div className=\"rounded-xl border border-slate-200 bg-white p-3 dark:border-slate-800 dark:bg-slate-900\">\n {(title || collapsible) && (\n <div className=\"mb-2 flex items-center justify-between\">\n <span className=\"text-xs font-medium text-slate-500 dark:text-slate-400\">{title ?? \"Metrics\"}</span>\n {collapsible && (\n <button\n type=\"button\"\n onClick={() => setCollapsed(true)}\n className=\"text-xs text-slate-400 hover:text-slate-600 dark:text-slate-500 dark:hover:text-slate-300\"\n >\n Collapse\n </button>\n )}\n </div>\n )}\n <div className=\"flex flex-wrap gap-4\">\n {items.map((m) => (\n <div key={m.label} className=\"min-w-[80px]\">\n <div className=\"text-xs text-slate-400 dark:text-slate-500\">{m.label}</div>\n <div className=\"flex items-baseline gap-1.5\">\n <span className=\"text-sm font-semibold text-slate-700 dark:text-slate-200\">{m.value}</span>\n {m.trend && (\n <span className={`text-xs ${String(m.trend).startsWith?.(\"+\") || m.trend > 0 ? \"text-red-500\" : \"text-emerald-500\"}`}>\n {typeof m.trend === \"number\" ? (m.trend > 0 ? `+${m.trend}` : m.trend) : m.trend}\n </span>\n )}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n },\n\n ItemList({ items = [], title, onItemClick }) {\n const [expanded, setExpanded] = React.useState(null);\n if (!items.length) {\n return <div className=\"text-sm text-slate-500 dark:text-slate-400\">No items.</div>;\n }\n return (\n <div className=\"space-y-2\">\n {title && (\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium text-slate-900 dark:text-slate-50\">{title}</span>\n <span className=\"text-xs text-slate-400 dark:text-slate-500\">{items.length} items</span>\n </div>\n )}\n <div className=\"space-y-1.5\">\n {items.map((item, idx) => (\n <div key={item.id ?? idx} className=\"rounded-xl border border-slate-200 bg-white dark:border-slate-800 dark:bg-slate-900\">\n <button\n type=\"button\"\n onClick={() => {\n setExpanded(expanded === (item.id ?? idx) ? null : (item.id ?? idx));\n onItemClick?.(item);\n }}\n className=\"flex w-full items-start justify-between gap-3 p-3 text-left\"\n >\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"text-sm font-medium text-slate-900 dark:text-slate-50\">\n {item.title ?? item.name ?? `Item ${idx + 1}`}\n </div>\n {item.status && (\n <UIChip tone={item.status === \"critical\" ? \"danger\" : item.status === \"warning\" ? \"warning\" : \"neutral\"} className=\"shrink-0\">\n {item.status}\n </UIChip>\n )}\n </div>\n {item.description && (\n <div className=\"mt-1 text-xs text-slate-500 dark:text-slate-400\">{item.description}</div>\n )}\n </div>\n </button>\n {expanded === (item.id ?? idx) && item.actions && (\n <div className=\"border-t border-slate-100 px-3 py-2 dark:border-slate-800\">\n <div className=\"flex flex-wrap gap-1.5\">\n {item.actions.map((action, i) => (\n <button\n key={typeof action === \"string\" ? action : action.label}\n type=\"button\"\n className={`rounded-md px-2.5 py-1 text-xs font-medium transition-colors ${\n i === 0\n ? \"bg-slate-900 text-white hover:bg-slate-800 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-200\"\n : \"bg-slate-100 text-slate-700 hover:bg-slate-200 dark:bg-slate-800 dark:text-slate-300 dark:hover:bg-slate-700\"\n }`}\n >\n {typeof action === \"string\" ? action : action.label}\n </button>\n ))}\n </div>\n </div>\n )}\n </div>\n ))}\n </div>\n </div>\n );\n },\n\n DataTable({ title, subtitle, columns = [], data = [], rows, searchable = true, sortable = true, paginated = true, pageSize = 5 }) {\n const tableData = data.length ? data : (rows ?? []);\n const cols = columns.length ? columns : [\n { key: \"name\", label: \"Name\" },\n { key: \"status\", label: \"Status\" },\n { key: \"value\", label: \"Value\" }\n ];\n return (\n <TableCard\n title={title ?? \"Data\"}\n subtitle={subtitle}\n columns={cols}\n data={tableData}\n searchable={searchable}\n sortable={sortable}\n paginated={paginated}\n pageSize={pageSize}\n />\n );\n },\n\n DataChart({ title, subtitle, chartType = \"line\", data = [], height = 200 }) {\n const series = data.length ? data : Array.from({ length: 12 }, (_, i) => ({ x: i, y: Math.random() * 100 }));\n return (\n <ChartCard\n title={title ?? \"Trend\"}\n subtitle={subtitle ?? \"Data visualization\"}\n chartType={chartType}\n height={height}\n chart={\n <D3Chart\n data={series}\n responsive\n height={height}\n ariaLabel={title}\n renderChart={(svg, d, dims, opts) => D3ChartTemplates.lineChart(svg, d, dims, opts)}\n options={{ xKey: \"x\", yKey: \"y\", showGrid: true, showAxes: true }}\n />\n }\n />\n );\n },\n\n MetricCard({ title, label, value, trend, change, changeType, color, icon, description }) {\n return (\n <MetricCard\n title={title ?? label}\n value={value ?? \"—\"}\n trend={trend}\n change={change}\n changeType={changeType}\n color={color}\n icon={icon}\n description={description}\n />\n );\n },\n\n StatusCard({ title, subtitle, status, items, layout, showProgress, showTimestamp }) {\n return (\n <StatusCard\n title={title}\n subtitle={subtitle}\n status={status}\n items={items}\n layout={layout}\n showProgress={showProgress}\n showTimestamp={showTimestamp}\n />\n );\n },\n\n ActionList({ actions = [], title, onAction }) {\n return (\n <div className=\"rounded-2xl border border-slate-200 bg-white p-4 dark:border-slate-800 dark:bg-slate-900\">\n {title && <div className=\"mb-3 text-sm font-medium text-slate-900 dark:text-slate-50\">{title}</div>}\n <div className=\"flex flex-wrap gap-2\">\n {actions.map((action, i) => (\n <UIButton\n key={i}\n size=\"sm\"\n variant={i === 0 ? \"primary\" : \"outline\"}\n onClick={() => onAction?.(action)}\n >\n {typeof action === \"string\" ? action : action.label}\n </UIButton>\n ))}\n </div>\n </div>\n );\n },\n\n CalloutCard({ title, message, tone = \"neutral\" }) {\n const toneClasses = {\n neutral: \"border-slate-200 bg-slate-50 text-slate-700 dark:border-slate-800 dark:bg-slate-950/30 dark:text-slate-200\",\n success: \"border-emerald-200 bg-emerald-50 text-emerald-800 dark:border-emerald-900/40 dark:bg-emerald-950/20 dark:text-emerald-200\",\n warning: \"border-amber-200 bg-amber-50 text-amber-800 dark:border-amber-900/40 dark:bg-amber-950/20 dark:text-amber-200\",\n danger: \"border-rose-200 bg-rose-50 text-rose-800 dark:border-rose-900/40 dark:bg-rose-950/20 dark:text-rose-200\"\n };\n return (\n <div className={`rounded-xl border p-4 ${toneClasses[tone] ?? toneClasses.neutral}`}>\n {title && <div className=\"mb-1 text-sm font-semibold\">{title}</div>}\n <div className=\"text-sm\">{message}</div>\n </div>\n );\n },\n\n Divider() {\n return <div className=\"h-px bg-slate-200 dark:bg-slate-800\" />;\n },\n\n Spacer({ size = \"md\" }) {\n const heights = { sm: \"h-2\", md: \"h-4\", lg: \"h-6\" };\n return <div className={heights[size] ?? heights.md} />;\n }\n};\n\nlet _registry = { ...BUILTIN_COMPONENTS };\n\nexport function getComponentRegistry() {\n return _registry;\n}\n\nexport function registerComponent(type, Component) {\n _registry = { ..._registry, [type]: Component };\n}\n\nexport function registerComponents(map) {\n _registry = { ..._registry, ...map };\n}\n\nexport function renderSchemaComponent(component, index) {\n const registry = getComponentRegistry();\n const Component = registry[component.type];\n if (!Component) {\n return (\n <div key={index} className=\"rounded-lg border border-dashed border-slate-300 p-3 text-xs text-slate-500 dark:border-slate-700\">\n Unknown component: {component.type}\n </div>\n );\n }\n return <Component key={component.id ?? index} {...(component.props ?? {})} />;\n}\n\nexport function renderSchema(components = []) {\n return components.map((c, i) => renderSchemaComponent(c, i));\n}\n\nexport default BUILTIN_COMPONENTS;\n"],"names":["BUILTIN_COMPONENTS","summary","title","jsxs","jsx","metrics","collapsible","initialCollapsed","collapsed","setCollapsed","React","items","m","onItemClick","expanded","setExpanded","item","idx","UIChip","action","i","subtitle","columns","data","rows","searchable","sortable","paginated","pageSize","tableData","cols","TableCard","chartType","height","series","_","ChartCard","D3Chart","svg","d","dims","opts","D3ChartTemplates","label","value","trend","change","changeType","color","icon","description","MetricCard","status","layout","showProgress","showTimestamp","StatusCard","actions","onAction","UIButton","message","tone","toneClasses","size","heights","_registry","getComponentRegistry","renderSchemaComponent","component","index","Component"],"mappings":";;;;;;;;;;;;;;;;;;;AAeA,MAAMA,IAAqB;AAAA,EACzB,iBAAiB,EAAE,SAAAC,GAAS,OAAAC,KAAS;AACnC,WACE,gBAAAC,EAAC,OAAA,EAAI,WAAU,8CACZ,UAAA;AAAA,MAAAD,KAAS,gBAAAE,EAAC,OAAA,EAAI,WAAU,sDAAsD,UAAAF,GAAM;AAAA,MACpFD;AAAA,IAAA,GACH;AAAA,EAEJ;AAAA,EAEA,aAAa,EAAE,SAAAI,IAAU,CAAA,GAAI,OAAAH,GAAO,aAAAI,IAAc,IAAO,WAAWC,IAAmB,MAAS;AAC9F,UAAM,CAACC,GAAWC,CAAY,IAAIC,EAAM,SAASH,CAAgB,GAE3DI,IAAQN,EAAQ,SAASA,IAAU;AAAA,MACvC,EAAE,OAAO,YAAY,OAAO,KAAK,OAAO,KAAA;AAAA,MACxC,EAAE,OAAO,YAAY,OAAO,KAAK,OAAO,KAAA;AAAA,MACxC,EAAE,OAAO,YAAY,OAAO,KAAK,OAAO,KAAA;AAAA,IAAK;AAG/C,WAAIC,KAAeE,IAEf,gBAAAL;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAMM,EAAa,EAAK;AAAA,QACjC,WAAU;AAAA,QAEV,UAAA;AAAA,UAAA,gBAAAN,EAAC,QAAA,EAAM,UAAA;AAAA,YAAAD,KAAS;AAAA,YAAU;AAAA,YAAGS,EAAM,IAAI,CAAAC,MAAK,GAAGA,EAAE,KAAK,IAAIA,EAAE,KAAK,EAAE,EAAE,KAAK,KAAK;AAAA,UAAA,GAAE;AAAA,UACjF,gBAAAR,EAAC,UAAK,UAAA,IAAA,CAAC;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA,IAMX,gBAAAD,EAAC,OAAA,EAAI,WAAU,2FACX,UAAA;AAAA,OAAAD,KAASI,MACT,gBAAAH,EAAC,OAAA,EAAI,WAAU,0CACb,UAAA;AAAA,QAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,0DAA0D,UAAAF,KAAS,WAAU;AAAA,QAC5FI,KACC,gBAAAF;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS,MAAMK,EAAa,EAAI;AAAA,YAChC,WAAU;AAAA,YACX,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAED,GAEJ;AAAA,MAEF,gBAAAL,EAAC,OAAA,EAAI,WAAU,wBACZ,UAAAO,EAAM,IAAI,CAACC,MACV,gBAAAT,EAAC,OAAA,EAAkB,WAAU,gBAC3B,UAAA;AAAA,QAAA,gBAAAC,EAAC,OAAA,EAAI,WAAU,8CAA8C,UAAAQ,EAAE,OAAM;AAAA,QACrE,gBAAAT,EAAC,OAAA,EAAI,WAAU,+BACb,UAAA;AAAA,UAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,4DAA4D,UAAAQ,EAAE,OAAM;AAAA,UACnFA,EAAE,SACD,gBAAAR,EAAC,QAAA,EAAK,WAAW,WAAW,OAAOQ,EAAE,KAAK,EAAE,aAAa,GAAG,KAAKA,EAAE,QAAQ,IAAI,iBAAiB,kBAAkB,IAC/G,UAAA,OAAOA,EAAE,SAAU,YAAYA,EAAE,QAAQ,IAAI,IAAIA,EAAE,KAAK,KAAgBA,EAAE,MAAA,CAC7E;AAAA,QAAA,EAAA,CAEJ;AAAA,MAAA,KATQA,EAAE,KAUZ,CACD,EAAA,CACH;AAAA,IAAA,GACF;AAAA,EAEJ;AAAA,EAEA,SAAS,EAAE,OAAAD,IAAQ,CAAA,GAAI,OAAAT,GAAO,aAAAW,KAAe;AAC3C,UAAM,CAACC,GAAUC,CAAW,IAAIL,EAAM,SAAS,IAAI;AACnD,WAAKC,EAAM,SAIT,gBAAAR,EAAC,OAAA,EAAI,WAAU,aACZ,UAAA;AAAA,MAAAD,KACC,gBAAAC,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,QAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,yDAAyD,UAAAF,GAAM;AAAA,QAC/E,gBAAAC,EAAC,QAAA,EAAK,WAAU,8CAA8C,UAAA;AAAA,UAAAQ,EAAM;AAAA,UAAO;AAAA,QAAA,EAAA,CAAM;AAAA,MAAA,GACnF;AAAA,MAEF,gBAAAP,EAAC,OAAA,EAAI,WAAU,eACZ,UAAAO,EAAM,IAAI,CAACK,GAAMC,MAChB,gBAAAd,EAAC,OAAA,EAAyB,WAAU,uFAClC,UAAA;AAAA,QAAA,gBAAAC;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS,MAAM;AACb,cAAAW,EAAYD,OAAcE,EAAK,MAAMC,KAAO,OAAQD,EAAK,MAAMC,CAAI,GACnEJ,IAAcG,CAAI;AAAA,YACpB;AAAA,YACA,WAAU;AAAA,YAEV,UAAA,gBAAAb,EAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,cAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,0CACb,UAAA;AAAA,gBAAA,gBAAAC,EAAC,OAAA,EAAI,WAAU,yDACZ,UAAAY,EAAK,SAASA,EAAK,QAAQ,QAAQC,IAAM,CAAC,GAAA,CAC7C;AAAA,gBACCD,EAAK,UACJ,gBAAAZ,EAACc,GAAA,EAAO,MAAMF,EAAK,WAAW,aAAa,WAAWA,EAAK,WAAW,YAAY,YAAY,WAAW,WAAU,YAChH,YAAK,OAAA,CACR;AAAA,cAAA,GAEJ;AAAA,cACCA,EAAK,eACJ,gBAAAZ,EAAC,SAAI,WAAU,mDAAmD,YAAK,YAAA,CAAY;AAAA,YAAA,EAAA,CAEvF;AAAA,UAAA;AAAA,QAAA;AAAA,QAEDU,OAAcE,EAAK,MAAMC,MAAQD,EAAK,6BACpC,OAAA,EAAI,WAAU,6DACb,UAAA,gBAAAZ,EAAC,OAAA,EAAI,WAAU,0BACZ,UAAAY,EAAK,QAAQ,IAAI,CAACG,GAAQC,MACzB,gBAAAhB;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC,MAAK;AAAA,YACL,WAAW,gEACTgB,MAAM,IACF,4GACA,8GACN;AAAA,YAEC,UAAA,OAAOD,KAAW,WAAWA,IAASA,EAAO;AAAA,UAAA;AAAA,UARzC,OAAOA,KAAW,WAAWA,IAASA,EAAO;AAAA,QAAA,CAUrD,GACH,EAAA,CACF;AAAA,MAAA,EAAA,GA1CMH,EAAK,MAAMC,CA4CrB,CACD,EAAA,CACH;AAAA,IAAA,GACF,IA3DO,gBAAAb,EAAC,OAAA,EAAI,WAAU,8CAA6C,UAAA,aAAS;AAAA,EA6DhF;AAAA,EAEA,UAAU,EAAE,OAAAF,GAAO,UAAAmB,GAAU,SAAAC,IAAU,CAAA,GAAI,MAAAC,IAAO,IAAI,MAAAC,GAAM,YAAAC,IAAa,IAAM,UAAAC,IAAW,IAAM,WAAAC,IAAY,IAAM,UAAAC,IAAW,KAAK;AAChI,UAAMC,IAAYN,EAAK,SAASA,IAAQC,KAAQ,CAAA,GAC1CM,IAAOR,EAAQ,SAASA,IAAU;AAAA,MACtC,EAAE,KAAK,QAAQ,OAAO,OAAA;AAAA,MACtB,EAAE,KAAK,UAAU,OAAO,SAAA;AAAA,MACxB,EAAE,KAAK,SAAS,OAAO,QAAA;AAAA,IAAQ;AAEjC,WACE,gBAAAlB;AAAA,MAAC2B;AAAA,MAAA;AAAA,QACC,OAAO7B,KAAS;AAAA,QAChB,UAAAmB;AAAA,QACA,SAASS;AAAA,QACT,MAAMD;AAAA,QACN,YAAAJ;AAAA,QACA,UAAAC;AAAA,QACA,WAAAC;AAAA,QACA,UAAAC;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AAAA,EAEA,UAAU,EAAE,OAAA1B,GAAO,UAAAmB,GAAU,WAAAW,IAAY,QAAQ,MAAAT,IAAO,CAAA,GAAI,QAAAU,IAAS,OAAO;AAC1E,UAAMC,IAASX,EAAK,SAASA,IAAO,MAAM,KAAK,EAAE,QAAQ,GAAA,GAAM,CAACY,GAAGf,OAAO,EAAE,GAAGA,GAAG,GAAG,KAAK,OAAA,IAAW,IAAA,EAAM;AAC3G,WACE,gBAAAhB;AAAA,MAACgC;AAAA,MAAA;AAAA,QACC,OAAOlC,KAAS;AAAA,QAChB,UAAUmB,KAAY;AAAA,QACtB,WAAAW;AAAA,QACA,QAAAC;AAAA,QACA,OACE,gBAAA7B;AAAA,UAACiC;AAAA,UAAA;AAAA,YACC,MAAMH;AAAA,YACN,YAAU;AAAA,YACV,QAAAD;AAAA,YACA,WAAW/B;AAAA,YACX,aAAa,CAACoC,GAAKC,GAAGC,GAAMC,MAASC,EAAiB,UAAUJ,GAAKC,GAAGC,GAAMC,CAAI;AAAA,YAClF,SAAS,EAAE,MAAM,KAAK,MAAM,KAAK,UAAU,IAAM,UAAU,GAAA;AAAA,UAAK;AAAA,QAAA;AAAA,MAClE;AAAA,IAAA;AAAA,EAIR;AAAA,EAEA,WAAW,EAAE,OAAAvC,GAAO,OAAAyC,GAAO,OAAAC,GAAO,OAAAC,GAAO,QAAAC,GAAQ,YAAAC,GAAY,OAAAC,GAAO,MAAAC,GAAM,aAAAC,EAAA,GAAe;AACvF,WACE,gBAAA9C;AAAA,MAAC+C;AAAA,MAAA;AAAA,QACC,OAAOjD,KAASyC;AAAA,QAChB,OAAOC,KAAS;AAAA,QAChB,OAAAC;AAAA,QACA,QAAAC;AAAA,QACA,YAAAC;AAAA,QACA,OAAAC;AAAA,QACA,MAAAC;AAAA,QACA,aAAAC;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AAAA,EAEA,WAAW,EAAE,OAAAhD,GAAO,UAAAmB,GAAU,QAAA+B,GAAQ,OAAAzC,GAAO,QAAA0C,GAAQ,cAAAC,GAAc,eAAAC,KAAiB;AAClF,WACE,gBAAAnD;AAAA,MAACoD;AAAA,MAAA;AAAA,QACC,OAAAtD;AAAA,QACA,UAAAmB;AAAA,QACA,QAAA+B;AAAA,QACA,OAAAzC;AAAA,QACA,QAAA0C;AAAA,QACA,cAAAC;AAAA,QACA,eAAAC;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AAAA,EAEA,WAAW,EAAE,SAAAE,IAAU,CAAA,GAAI,OAAAvD,GAAO,UAAAwD,KAAY;AAC5C,WACE,gBAAAvD,EAAC,OAAA,EAAI,WAAU,4FACZ,UAAA;AAAA,MAAAD,KAAS,gBAAAE,EAAC,OAAA,EAAI,WAAU,8DAA8D,UAAAF,GAAM;AAAA,MAC7F,gBAAAE,EAAC,SAAI,WAAU,wBACZ,YAAQ,IAAI,CAACe,GAAQC,MACpB,gBAAAhB;AAAA,QAACuD;AAAA,QAAA;AAAA,UAEC,MAAK;AAAA,UACL,SAASvC,MAAM,IAAI,YAAY;AAAA,UAC/B,SAAS,MAAMsC,IAAWvC,CAAM;AAAA,UAE/B,UAAA,OAAOA,KAAW,WAAWA,IAASA,EAAO;AAAA,QAAA;AAAA,QALzCC;AAAA,MAAA,CAOR,EAAA,CACH;AAAA,IAAA,GACF;AAAA,EAEJ;AAAA,EAEA,YAAY,EAAE,OAAAlB,GAAO,SAAA0D,GAAS,MAAAC,IAAO,aAAa;AAChD,UAAMC,IAAc;AAAA,MAClB,SAAS;AAAA,MACT,SAAS;AAAA,MACT,SAAS;AAAA,MACT,QAAQ;AAAA,IAAA;AAEV,WACE,gBAAA3D,EAAC,SAAI,WAAW,yBAAyB2D,EAAYD,CAAI,KAAKC,EAAY,OAAO,IAC9E,UAAA;AAAA,MAAA5D,KAAS,gBAAAE,EAAC,OAAA,EAAI,WAAU,8BAA8B,UAAAF,GAAM;AAAA,MAC7D,gBAAAE,EAAC,OAAA,EAAI,WAAU,WAAW,UAAAwD,EAAA,CAAQ;AAAA,IAAA,GACpC;AAAA,EAEJ;AAAA,EAEA,UAAU;AACR,WAAO,gBAAAxD,EAAC,OAAA,EAAI,WAAU,sCAAA,CAAsC;AAAA,EAC9D;AAAA,EAEA,OAAO,EAAE,MAAA2D,IAAO,QAAQ;AACtB,UAAMC,IAAU,EAAE,IAAI,OAAO,IAAI,OAAO,IAAI,MAAA;AAC5C,6BAAQ,OAAA,EAAI,WAAWA,EAAQD,CAAI,KAAKC,EAAQ,IAAI;AAAA,EACtD;AACF;AAEA,IAAIC,IAAY,EAAE,GAAGjE,EAAA;AAEd,SAASkE,IAAuB;AACrC,SAAOD;AACT;AAUO,SAASE,EAAsBC,GAAWC,GAAO;AAEtD,QAAMC,IADWJ,EAAA,EACUE,EAAU,IAAI;AACzC,SAAKE,IAOE,gBAAAlE,EAACkE,KAAuC,GAAIF,EAAU,SAAS,CAAA,KAA/CA,EAAU,MAAMC,CAAoC,IALvE,gBAAAlE,EAAC,OAAA,EAAgB,WAAU,qGAAoG,UAAA;AAAA,IAAA;AAAA,IACzGiE,EAAU;AAAA,EAAA,EAAA,GADtBC,CAEV;AAIN;"}
|
|
1
|
+
{"version":3,"file":"ComponentRegistry.js","sources":["../../../src/components/workspace/ComponentRegistry.tsx"],"sourcesContent":["import * as React from \"react\";\nimport {\n MetricCard,\n TableCard,\n ChartCard,\n D3Chart,\n D3ChartTemplates,\n StatusCard,\n UIButton,\n UIChip\n} from \"@/components/library\";\n\nexport interface Metric {\n label: string;\n value: string | number;\n trend?: string | number | null;\n}\n\nexport interface MetricsStripProps {\n metrics?: Metric[];\n title?: string;\n collapsible?: boolean;\n collapsed?: boolean;\n}\n\nexport interface ListItem {\n id?: string;\n title?: string;\n name?: string;\n description?: string;\n status?: \"critical\" | \"warning\" | string;\n actions?: Array<string | { label: string }>;\n}\n\nexport interface ItemListProps {\n items?: ListItem[];\n title?: string;\n onItemClick?: (item: ListItem) => void;\n}\n\nexport interface TableColumn {\n key: string;\n label: string;\n}\n\nexport interface DataTableProps {\n title?: string;\n subtitle?: string;\n columns?: TableColumn[];\n data?: any[];\n rows?: any[];\n searchable?: boolean;\n sortable?: boolean;\n paginated?: boolean;\n pageSize?: number;\n}\n\nexport interface DataPoint {\n x: number;\n y: number;\n [key: string]: any;\n}\n\nexport interface DataChartProps {\n title?: string;\n subtitle?: string;\n chartType?: string;\n data?: DataPoint[];\n height?: number;\n}\n\nexport interface MetricCardComponentProps {\n title?: string;\n label?: string;\n value?: string | number;\n trend?: string | number;\n change?: string | number;\n changeType?: string;\n color?: string;\n icon?: React.ReactNode;\n description?: string;\n}\n\nexport interface StatusCardComponentProps {\n title?: string;\n subtitle?: string;\n status?: string;\n items?: any[];\n layout?: string;\n showProgress?: boolean;\n showTimestamp?: boolean;\n}\n\nexport interface ActionListProps {\n actions?: Array<string | { label: string }>;\n title?: string;\n onAction?: (action: string | { label: string }) => void;\n}\n\nexport interface CalloutCardProps {\n title?: string;\n message?: string;\n tone?: \"neutral\" | \"success\" | \"warning\" | \"danger\";\n}\n\nexport interface SpacerProps {\n size?: \"sm\" | \"md\" | \"lg\";\n}\n\nexport interface NarrativeSummaryProps {\n summary?: string;\n title?: string;\n}\n\nexport interface SchemaComponent {\n id?: string;\n type: string;\n props?: Record<string, any>;\n}\n\nconst BUILTIN_COMPONENTS = {\n NarrativeSummary({ summary, title }: NarrativeSummaryProps) {\n return (\n <div className=\"text-sm text-slate-600 dark:text-slate-300\">\n {title && <div className=\"mb-1 font-medium text-slate-900 dark:text-slate-50\">{title}</div>}\n {summary}\n </div>\n );\n },\n\n MetricsStrip({ metrics = [], title, collapsible = false, collapsed: initialCollapsed = false }: MetricsStripProps) {\n const [collapsed, setCollapsed] = React.useState(initialCollapsed);\n\n const items = metrics.length ? metrics : [\n { label: \"Metric A\", value: \"—\", trend: null },\n { label: \"Metric B\", value: \"—\", trend: null },\n { label: \"Metric C\", value: \"—\", trend: null }\n ];\n\n if (collapsible && collapsed) {\n return (\n <button\n type=\"button\"\n onClick={() => setCollapsed(false)}\n className=\"flex w-full items-center justify-between rounded-lg border border-slate-200 bg-white px-3 py-2 text-left text-xs text-slate-500 hover:bg-slate-50 dark:border-slate-800 dark:bg-slate-900 dark:text-slate-400 dark:hover:bg-slate-800\"\n >\n <span>{title ?? \"Metrics\"}: {items.map(m => `${m.label} ${m.value}`).join(\" · \")}</span>\n <span>▸</span>\n </button>\n );\n }\n\n return (\n <div className=\"rounded-xl border border-slate-200 bg-white p-3 dark:border-slate-800 dark:bg-slate-900\">\n {(title || collapsible) && (\n <div className=\"mb-2 flex items-center justify-between\">\n <span className=\"text-xs font-medium text-slate-500 dark:text-slate-400\">{title ?? \"Metrics\"}</span>\n {collapsible && (\n <button\n type=\"button\"\n onClick={() => setCollapsed(true)}\n className=\"text-xs text-slate-400 hover:text-slate-600 dark:text-slate-500 dark:hover:text-slate-300\"\n >\n Collapse\n </button>\n )}\n </div>\n )}\n <div className=\"flex flex-wrap gap-4\">\n {items.map((m) => (\n <div key={m.label} className=\"min-w-[80px]\">\n <div className=\"text-xs text-slate-400 dark:text-slate-500\">{m.label}</div>\n <div className=\"flex items-baseline gap-1.5\">\n <span className=\"text-sm font-semibold text-slate-700 dark:text-slate-200\">{m.value}</span>\n {m.trend && (\n <span className={`text-xs ${String(m.trend).startsWith?.(\"+\") || (typeof m.trend === \"number\" && m.trend > 0) ? \"text-red-500\" : \"text-emerald-500\"}`}>\n {typeof m.trend === \"number\" ? (m.trend > 0 ? `+${m.trend}` : m.trend) : m.trend}\n </span>\n )}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n },\n\n ItemList({ items = [], title, onItemClick }: ItemListProps) {\n const [expanded, setExpanded] = React.useState<string | number | null>(null);\n if (!items.length) {\n return <div className=\"text-sm text-slate-500 dark:text-slate-400\">No items.</div>;\n }\n return (\n <div className=\"space-y-2\">\n {title && (\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium text-slate-900 dark:text-slate-50\">{title}</span>\n <span className=\"text-xs text-slate-400 dark:text-slate-500\">{items.length} items</span>\n </div>\n )}\n <div className=\"space-y-1.5\">\n {items.map((item, idx) => (\n <div key={item.id ?? idx} className=\"rounded-xl border border-slate-200 bg-white dark:border-slate-800 dark:bg-slate-900\">\n <button\n type=\"button\"\n onClick={() => {\n setExpanded(expanded === (item.id ?? idx) ? null : (item.id ?? idx));\n onItemClick?.(item);\n }}\n className=\"flex w-full items-start justify-between gap-3 p-3 text-left\"\n >\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"text-sm font-medium text-slate-900 dark:text-slate-50\">\n {item.title ?? item.name ?? `Item ${idx + 1}`}\n </div>\n {item.status && (\n <UIChip tone={item.status === \"critical\" ? \"danger\" : item.status === \"warning\" ? \"warning\" : \"neutral\"} className=\"shrink-0\">\n {item.status}\n </UIChip>\n )}\n </div>\n {item.description && (\n <div className=\"mt-1 text-xs text-slate-500 dark:text-slate-400\">{item.description}</div>\n )}\n </div>\n </button>\n {expanded === (item.id ?? idx) && item.actions && (\n <div className=\"border-t border-slate-100 px-3 py-2 dark:border-slate-800\">\n <div className=\"flex flex-wrap gap-1.5\">\n {item.actions.map((action, i) => (\n <button\n key={typeof action === \"string\" ? action : action.label}\n type=\"button\"\n className={`rounded-md px-2.5 py-1 text-xs font-medium transition-colors ${\n i === 0\n ? \"bg-slate-900 text-white hover:bg-slate-800 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-200\"\n : \"bg-slate-100 text-slate-700 hover:bg-slate-200 dark:bg-slate-800 dark:text-slate-300 dark:hover:bg-slate-700\"\n }`}\n >\n {typeof action === \"string\" ? action : action.label}\n </button>\n ))}\n </div>\n </div>\n )}\n </div>\n ))}\n </div>\n </div>\n );\n },\n\n DataTable({ title, subtitle, columns = [], data = [], rows, searchable = true, sortable = true, paginated = true, pageSize = 5 }: DataTableProps) {\n const tableData = data.length ? data : (rows ?? []);\n const cols = columns.length ? columns : [\n { key: \"name\", label: \"Name\" },\n { key: \"status\", label: \"Status\" },\n { key: \"value\", label: \"Value\" }\n ];\n return (\n <TableCard\n title={title ?? \"Data\"}\n subtitle={subtitle}\n columns={cols}\n data={tableData}\n searchable={searchable}\n sortable={sortable}\n paginated={paginated}\n pageSize={pageSize}\n />\n );\n },\n\n DataChart({ title, subtitle, chartType = \"line\", data = [], height = 200 }: DataChartProps) {\n const series = data.length ? data : Array.from({ length: 12 }, (_, i) => ({ x: i, y: Math.random() * 100 }));\n return (\n <ChartCard\n title={title ?? \"Trend\"}\n subtitle={subtitle ?? \"Data visualization\"}\n chartType={chartType}\n height={height}\n chart={\n <D3Chart\n data={series as any}\n responsive\n height={height}\n ariaLabel={title}\n renderChart={(svg, d, dims, opts) => D3ChartTemplates.lineChart(svg, d as any, dims, opts)}\n options={{ xKey: \"x\", yKey: \"y\", showGrid: true, showAxes: true }}\n />\n }\n />\n );\n },\n\n MetricCard({ title, label, value, trend, change, changeType, color, icon, description }: MetricCardComponentProps) {\n return (\n <MetricCard\n title={(title ?? label) as any}\n value={value ?? \"—\"}\n trend={trend as any}\n change={change as any}\n changeType={changeType as any}\n color={color as any}\n icon={icon}\n subtitle={description}\n />\n );\n },\n\n StatusCard({ title, subtitle, status, items, layout, showProgress, showTimestamp }: StatusCardComponentProps) {\n return (\n <StatusCard\n title={title}\n subtitle={subtitle}\n status={status}\n items={items}\n layout={layout as any}\n showProgress={showProgress}\n showTimestamp={showTimestamp}\n />\n );\n },\n\n ActionList({ actions = [], title, onAction }: ActionListProps) {\n return (\n <div className=\"rounded-2xl border border-slate-200 bg-white p-4 dark:border-slate-800 dark:bg-slate-900\">\n {title && <div className=\"mb-3 text-sm font-medium text-slate-900 dark:text-slate-50\">{title}</div>}\n <div className=\"flex flex-wrap gap-2\">\n {actions.map((action, i) => (\n <UIButton\n key={i}\n size=\"sm\"\n variant={i === 0 ? \"primary\" : \"outline\"}\n onClick={() => onAction?.(action)}\n >\n {typeof action === \"string\" ? action : action.label}\n </UIButton>\n ))}\n </div>\n </div>\n );\n },\n\n CalloutCard({ title, message, tone = \"neutral\" }: CalloutCardProps) {\n const toneClasses = {\n neutral: \"border-slate-200 bg-slate-50 text-slate-700 dark:border-slate-800 dark:bg-slate-950/30 dark:text-slate-200\",\n success: \"border-emerald-200 bg-emerald-50 text-emerald-800 dark:border-emerald-900/40 dark:bg-emerald-950/20 dark:text-emerald-200\",\n warning: \"border-amber-200 bg-amber-50 text-amber-800 dark:border-amber-900/40 dark:bg-amber-950/20 dark:text-amber-200\",\n danger: \"border-rose-200 bg-rose-50 text-rose-800 dark:border-rose-900/40 dark:bg-rose-950/20 dark:text-rose-200\"\n };\n return (\n <div className={`rounded-xl border p-4 ${toneClasses[tone] ?? toneClasses.neutral}`}>\n {title && <div className=\"mb-1 text-sm font-semibold\">{title}</div>}\n <div className=\"text-sm\">{message}</div>\n </div>\n );\n },\n\n Divider() {\n return <div className=\"h-px bg-slate-200 dark:bg-slate-800\" />;\n },\n\n Spacer({ size = \"md\" }: SpacerProps) {\n const heights = { sm: \"h-2\", md: \"h-4\", lg: \"h-6\" };\n return <div className={heights[size] ?? heights.md} />;\n }\n};\n\nlet _registry: Record<string, React.ComponentType<any>> = { ...BUILTIN_COMPONENTS };\n\nexport function getComponentRegistry(): Record<string, React.ComponentType<any>> {\n return _registry;\n}\n\nexport function registerComponent(type: string, Component: React.ComponentType<any>): void {\n _registry = { ..._registry, [type]: Component };\n}\n\nexport function registerComponents(map: Record<string, React.ComponentType<any>>): void {\n _registry = { ..._registry, ...map };\n}\n\nexport function renderSchemaComponent(component: SchemaComponent, index: number): React.ReactElement {\n const registry = getComponentRegistry();\n const Component = registry[component.type];\n if (!Component) {\n return (\n <div key={index} className=\"rounded-lg border border-dashed border-slate-300 p-3 text-xs text-slate-500 dark:border-slate-700\">\n Unknown component: {component.type}\n </div>\n );\n }\n return <Component key={component.id ?? index} {...(component.props ?? {})} />;\n}\n\nexport function renderSchema(components: SchemaComponent[] = []): React.ReactElement[] {\n return components.map((c, i) => renderSchemaComponent(c, i));\n}\n\nexport default BUILTIN_COMPONENTS;\n"],"names":["BUILTIN_COMPONENTS","summary","title","jsxs","jsx","metrics","collapsible","initialCollapsed","collapsed","setCollapsed","React","items","m","onItemClick","expanded","setExpanded","item","idx","UIChip","action","i","subtitle","columns","data","rows","searchable","sortable","paginated","pageSize","tableData","cols","TableCard","chartType","height","series","_","ChartCard","D3Chart","svg","d","dims","opts","D3ChartTemplates","label","value","trend","change","changeType","color","icon","description","MetricCard","status","layout","showProgress","showTimestamp","StatusCard","actions","onAction","UIButton","message","tone","toneClasses","size","heights","_registry","getComponentRegistry","renderSchemaComponent","component","index","Component"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@schandlergarcia/sf-web-components",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.1",
|
|
4
4
|
"description": "Reusable Salesforce web components library with Tailwind CSS v4 and shadcn/ui",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"world-atlas": "^2.0.0"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@schandlergarcia/sf-web-components": "^1.
|
|
67
|
+
"@schandlergarcia/sf-web-components": "^1.9.0",
|
|
68
68
|
"class-variance-authority": "^0.7.1",
|
|
69
69
|
"clsx": "^2.1.1",
|
|
70
70
|
"glob": "^11.0.0",
|
|
@@ -36,7 +36,7 @@ export default function SemanticMetricCard({
|
|
|
36
36
|
loading = false,
|
|
37
37
|
...rest
|
|
38
38
|
}: SemanticMetricCardProps) {
|
|
39
|
-
const metric = React.useMemo(() => getSemanticMetric(semanticId, metricId), [semanticId, metricId]);
|
|
39
|
+
const metric = React.useMemo(() => getSemanticMetric(semanticId, metricId ?? ""), [semanticId, metricId]);
|
|
40
40
|
|
|
41
41
|
const resolvedTitle = title ?? metric?.title ?? metricId ?? "Metric";
|
|
42
42
|
const resolvedSubtitle = subtitle ?? metric?.subtitle;
|
|
@@ -4,7 +4,7 @@ import { getSemanticDataset } from "../data/chartDataProvider";
|
|
|
4
4
|
|
|
5
5
|
export interface SemanticTableCardProps extends Omit<TableCardProps, "data" | "columns"> {
|
|
6
6
|
semanticId: string;
|
|
7
|
-
dataOverride?: unknown[];
|
|
7
|
+
dataOverride?: Record<string, unknown>[];
|
|
8
8
|
columnsOverride?: TableColumn[];
|
|
9
9
|
compact?: boolean;
|
|
10
10
|
striped?: boolean;
|
|
@@ -35,8 +35,8 @@ export default function SemanticTableCard({
|
|
|
35
35
|
const ds = React.useMemo(() => getSemanticDataset(semanticId), [semanticId]);
|
|
36
36
|
const table = ds?.table;
|
|
37
37
|
|
|
38
|
-
const resolvedColumns = columnsOverride ?? table?.columns ?? [];
|
|
39
|
-
const resolvedData = dataOverride ?? table?.rows ?? [];
|
|
38
|
+
const resolvedColumns = (columnsOverride ?? table?.columns ?? []) as TableColumn[];
|
|
39
|
+
const resolvedData = (dataOverride ?? table?.rows ?? []) as Record<string, unknown>[];
|
|
40
40
|
const resolvedTitle = title ?? table?.title ?? ds?.title ?? "Table";
|
|
41
41
|
const resolvedSubtitle = subtitle ?? table?.subtitle;
|
|
42
42
|
|
|
@@ -9,7 +9,8 @@ import {
|
|
|
9
9
|
} from "@heroicons/react/24/outline";
|
|
10
10
|
import ChatMessageList from "./ChatMessageList";
|
|
11
11
|
import ChatInput from "./ChatInput";
|
|
12
|
-
import useChatState from "./useChatState";
|
|
12
|
+
import useChatState, { UseChatStateOptions, ChatMessage } from "./useChatState";
|
|
13
|
+
import { ChatMessageData } from "./ChatMessage";
|
|
13
14
|
|
|
14
15
|
const BACKDROP_VARIANTS = {
|
|
15
16
|
hidden: { opacity: 0 },
|
|
@@ -23,11 +24,22 @@ const PANEL_VARIANTS = {
|
|
|
23
24
|
opacity: 1,
|
|
24
25
|
y: 0,
|
|
25
26
|
scale: 1,
|
|
26
|
-
transition: { type: "spring", damping: 28, stiffness: 380 },
|
|
27
|
+
transition: { type: "spring" as const, damping: 28, stiffness: 380 },
|
|
27
28
|
},
|
|
28
29
|
exit: { opacity: 0, y: 10, scale: 0.97, transition: { duration: 0.12 } },
|
|
29
30
|
};
|
|
30
31
|
|
|
32
|
+
export interface ChatBarProps {
|
|
33
|
+
onSend?: UseChatStateOptions["onSend"];
|
|
34
|
+
suggestions?: string[];
|
|
35
|
+
placeholder?: string;
|
|
36
|
+
title?: string;
|
|
37
|
+
initialMessages?: UseChatStateOptions["initialMessages"];
|
|
38
|
+
className?: string;
|
|
39
|
+
renderAvatar?: (message: ChatMessageData) => React.ReactNode;
|
|
40
|
+
onOpenInTab?: (messages: ChatMessage[]) => void;
|
|
41
|
+
}
|
|
42
|
+
|
|
31
43
|
/**
|
|
32
44
|
* Command-palette style AI chat bar.
|
|
33
45
|
*
|
|
@@ -41,17 +53,16 @@ const PANEL_VARIANTS = {
|
|
|
41
53
|
export default function ChatBar({
|
|
42
54
|
onSend,
|
|
43
55
|
suggestions = [],
|
|
44
|
-
placeholder = "Ask a question
|
|
56
|
+
placeholder = "Ask a question…",
|
|
45
57
|
title = "AI Assistant",
|
|
46
58
|
initialMessages = [],
|
|
47
59
|
className = "",
|
|
48
|
-
panelHeight,
|
|
49
60
|
renderAvatar,
|
|
50
61
|
onOpenInTab,
|
|
51
|
-
}) {
|
|
62
|
+
}: ChatBarProps) {
|
|
52
63
|
const [open, setOpen] = useState(false);
|
|
53
64
|
const [portalVisible, setPortalVisible] = useState(false);
|
|
54
|
-
const panelRef = useRef(null);
|
|
65
|
+
const panelRef = useRef<HTMLDivElement>(null);
|
|
55
66
|
const chat = useChatState({ initialMessages, onSend });
|
|
56
67
|
const isEmpty = chat.messages.length === 0;
|
|
57
68
|
|
|
@@ -62,7 +73,7 @@ export default function ChatBar({
|
|
|
62
73
|
}, [open]);
|
|
63
74
|
|
|
64
75
|
useEffect(() => {
|
|
65
|
-
function onKey(e) {
|
|
76
|
+
function onKey(e: KeyboardEvent) {
|
|
66
77
|
if ((e.metaKey || e.ctrlKey) && e.key === "k") {
|
|
67
78
|
e.preventDefault();
|
|
68
79
|
setOpen((prev) => !prev);
|
|
@@ -79,7 +90,7 @@ export default function ChatBar({
|
|
|
79
90
|
return () => { document.body.style.overflow = ""; };
|
|
80
91
|
}, [open]);
|
|
81
92
|
|
|
82
|
-
function handleSend(content) {
|
|
93
|
+
function handleSend(content: string) {
|
|
83
94
|
if (!open) setOpen(true);
|
|
84
95
|
chat.sendMessage(content);
|
|
85
96
|
}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useState, useRef, useEffect } from "react";
|
|
2
2
|
import { PaperAirplaneIcon, StopCircleIcon } from "@heroicons/react/24/solid";
|
|
3
3
|
|
|
4
|
+
export interface ChatInputProps {
|
|
5
|
+
onSend?: (content: string) => void;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
isLoading?: boolean;
|
|
8
|
+
onStop?: () => void;
|
|
9
|
+
placeholder?: string;
|
|
10
|
+
maxRows?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
4
13
|
/**
|
|
5
14
|
* Chat input with auto-resize textarea, Send button, and keyboard shortcuts.
|
|
6
15
|
* Enter sends, Shift+Enter inserts newline.
|
|
7
|
-
*
|
|
8
|
-
* @param {Function} onSend — (content: string) => void
|
|
9
|
-
* @param {boolean} disabled — disable input while agent is processing
|
|
10
|
-
* @param {boolean} isLoading — show stop button instead of send
|
|
11
|
-
* @param {Function} onStop — optional: called when stop is clicked
|
|
12
|
-
* @param {string} placeholder
|
|
13
|
-
* @param {number} maxRows — max visible rows before scroll (default 6)
|
|
14
16
|
*/
|
|
15
17
|
export default function ChatInput({
|
|
16
18
|
onSend,
|
|
@@ -19,9 +21,9 @@ export default function ChatInput({
|
|
|
19
21
|
onStop,
|
|
20
22
|
placeholder = "Type a message…",
|
|
21
23
|
maxRows = 6,
|
|
22
|
-
}) {
|
|
24
|
+
}: ChatInputProps) {
|
|
23
25
|
const [value, setValue] = useState("");
|
|
24
|
-
const textareaRef = useRef(null);
|
|
26
|
+
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
|
25
27
|
|
|
26
28
|
useEffect(() => {
|
|
27
29
|
const ta = textareaRef.current;
|
|
@@ -41,7 +43,7 @@ export default function ChatInput({
|
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
function handleKeyDown(e) {
|
|
46
|
+
function handleKeyDown(e: React.KeyboardEvent<HTMLTextAreaElement>) {
|
|
45
47
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
46
48
|
e.preventDefault();
|
|
47
49
|
handleSend();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { renderSchemaComponent } from "@/components/workspace/ComponentRegistry";
|
|
3
|
-
import ChatToolCall from "./ChatToolCall";
|
|
2
|
+
import { renderSchemaComponent, type SchemaComponent } from "@/components/workspace/ComponentRegistry";
|
|
3
|
+
import ChatToolCall, { ToolCall } from "./ChatToolCall";
|
|
4
4
|
import { UserCircleIcon, CpuChipIcon } from "@heroicons/react/24/solid";
|
|
5
5
|
|
|
6
|
-
function cx(...classes) {
|
|
6
|
+
function cx(...classes: (string | boolean | undefined)[]): string {
|
|
7
7
|
return classes.filter(Boolean).join(" ");
|
|
8
8
|
}
|
|
9
9
|
|
|
@@ -11,9 +11,9 @@ function cx(...classes) {
|
|
|
11
11
|
* Lightweight inline formatter for assistant messages.
|
|
12
12
|
* Handles code blocks, inline code, bold, italic, and line breaks.
|
|
13
13
|
*/
|
|
14
|
-
function formatContent(text) {
|
|
14
|
+
function formatContent(text: string): React.ReactNode {
|
|
15
15
|
if (!text) return null;
|
|
16
|
-
const parts = [];
|
|
16
|
+
const parts: React.ReactNode[] = [];
|
|
17
17
|
let key = 0;
|
|
18
18
|
|
|
19
19
|
const codeBlockRegex = /```(\w*)\n?([\s\S]*?)```/g;
|
|
@@ -46,7 +46,7 @@ function formatContent(text) {
|
|
|
46
46
|
return parts;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
function formatInline(text) {
|
|
49
|
+
function formatInline(text: string): React.ReactNode {
|
|
50
50
|
const tokens = text.split(/(`[^`]+`|\*\*[^*]+\*\*|\*[^*]+\*)/g);
|
|
51
51
|
return tokens.map((token, i) => {
|
|
52
52
|
if (token.startsWith("**") && token.endsWith("**")) {
|
|
@@ -74,13 +74,26 @@ function formatInline(text) {
|
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
export interface ChatMessageData {
|
|
78
|
+
id: string;
|
|
79
|
+
role: "user" | "assistant" | "system";
|
|
80
|
+
content?: string;
|
|
81
|
+
components?: SchemaComponent[];
|
|
82
|
+
toolCalls?: ToolCall[];
|
|
83
|
+
isError?: boolean;
|
|
84
|
+
isStreaming?: boolean;
|
|
85
|
+
timestamp?: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface ChatMessageProps {
|
|
89
|
+
message: ChatMessageData;
|
|
90
|
+
avatar?: React.ReactNode;
|
|
91
|
+
}
|
|
92
|
+
|
|
77
93
|
/**
|
|
78
94
|
* Renders a single chat message.
|
|
79
|
-
*
|
|
80
|
-
* @param {Object} message — { id, role, content, components?, toolCalls?, isError?, isStreaming?, timestamp? }
|
|
81
|
-
* @param {React.ReactNode} avatar — custom avatar override
|
|
82
95
|
*/
|
|
83
|
-
export default function ChatMessage({ message, avatar }) {
|
|
96
|
+
export default function ChatMessage({ message, avatar }: ChatMessageProps) {
|
|
84
97
|
const isUser = message.role === "user";
|
|
85
98
|
const isSystem = message.role === "system";
|
|
86
99
|
const isAssistant = message.role === "assistant";
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import React, { useRef, useEffect } from "react";
|
|
2
|
-
import ChatMessage from "./ChatMessage";
|
|
2
|
+
import ChatMessage, { ChatMessageData } from "./ChatMessage";
|
|
3
3
|
import ChatTypingIndicator from "./ChatTypingIndicator";
|
|
4
4
|
import ChatSuggestions from "./ChatSuggestions";
|
|
5
5
|
|
|
6
|
+
export interface ChatMessageListProps {
|
|
7
|
+
messages?: ChatMessageData[];
|
|
8
|
+
isLoading?: boolean;
|
|
9
|
+
isStreaming?: boolean;
|
|
10
|
+
suggestions?: string[];
|
|
11
|
+
onSuggestion?: (text: string) => void;
|
|
12
|
+
renderAvatar?: (message: ChatMessageData) => React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
|
|
6
15
|
/**
|
|
7
16
|
* Scrollable message area with auto-scroll to latest message.
|
|
8
|
-
*
|
|
9
|
-
* @param {Array} messages — array of message objects
|
|
10
|
-
* @param {boolean} isLoading — show typing indicator
|
|
11
|
-
* @param {boolean} isStreaming — agent is streaming (show different indicator text)
|
|
12
|
-
* @param {string[]} suggestions — follow-up suggestions shown after last assistant message
|
|
13
|
-
* @param {Function} onSuggestion — (text) => void
|
|
14
|
-
* @param {Function} renderAvatar — (message) => ReactNode, optional per-message avatar
|
|
15
17
|
*/
|
|
16
18
|
export default function ChatMessageList({
|
|
17
19
|
messages = [],
|
|
@@ -20,9 +22,9 @@ export default function ChatMessageList({
|
|
|
20
22
|
suggestions = [],
|
|
21
23
|
onSuggestion,
|
|
22
24
|
renderAvatar,
|
|
23
|
-
}) {
|
|
24
|
-
const bottomRef = useRef(null);
|
|
25
|
-
const containerRef = useRef(null);
|
|
25
|
+
}: ChatMessageListProps) {
|
|
26
|
+
const bottomRef = useRef<HTMLDivElement>(null);
|
|
27
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
26
28
|
|
|
27
29
|
useEffect(() => {
|
|
28
30
|
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|