@timbal-ai/timbal-react 0.6.1 → 0.7.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/README.md +35 -5
  3. package/dist/app.cjs +2291 -741
  4. package/dist/app.d.cts +5 -2
  5. package/dist/app.d.ts +5 -2
  6. package/dist/app.esm.js +58 -5
  7. package/dist/button-CIKzUrJI.d.cts +18 -0
  8. package/dist/button-CIKzUrJI.d.ts +18 -0
  9. package/dist/chart-artifact-C2m891nx.d.cts +756 -0
  10. package/dist/chart-artifact-CqqhdSR9.d.ts +756 -0
  11. package/dist/{chat-CWtQWDtJ.d.cts → chat-Bed4FQSl.d.cts} +10 -0
  12. package/dist/{chat-CWtQWDtJ.d.ts → chat-Bed4FQSl.d.ts} +10 -0
  13. package/dist/chat.cjs +876 -562
  14. package/dist/chat.d.cts +3 -3
  15. package/dist/chat.d.ts +3 -3
  16. package/dist/chat.esm.js +3 -3
  17. package/dist/{chunk-4TCJQSIX.esm.js → chunk-2XZ3S4OP.esm.js} +14 -3
  18. package/dist/{chunk-WLTW56MC.esm.js → chunk-3WCG6ZRL.esm.js} +2 -2
  19. package/dist/chunk-7U2N6XZA.esm.js +2296 -0
  20. package/dist/{chunk-OVHR7J3J.esm.js → chunk-EQC5JEDZ.esm.js} +38 -11
  21. package/dist/{chunk-YJQLLFKP.esm.js → chunk-RY3LB3JN.esm.js} +817 -507
  22. package/dist/{chunk-IYENDIRY.esm.js → chunk-TDIJHV4I.esm.js} +1 -1
  23. package/dist/{chunk-OFHLFNJH.esm.js → chunk-Z27GBSOT.esm.js} +3 -1
  24. package/dist/index.cjs +2596 -1019
  25. package/dist/index.d.cts +8 -7
  26. package/dist/index.d.ts +8 -7
  27. package/dist/index.esm.js +57 -7
  28. package/dist/{layout-CQWngNQ7.d.ts → layout-BTJyU8wd.d.ts} +1 -1
  29. package/dist/{layout-B9VayJhZ.d.cts → layout-C2G-FcER.d.cts} +1 -1
  30. package/dist/studio.cjs +1131 -788
  31. package/dist/studio.d.cts +2 -2
  32. package/dist/studio.d.ts +2 -2
  33. package/dist/studio.esm.js +6 -6
  34. package/dist/styles.css +8 -4
  35. package/dist/{timbal-v2-button-F4-z7m33.d.ts → timbal-v2-button-CNfdwGq4.d.cts} +1 -1
  36. package/dist/{timbal-v2-button-F4-z7m33.d.cts → timbal-v2-button-CNfdwGq4.d.ts} +1 -1
  37. package/dist/ui.cjs +12 -3
  38. package/dist/ui.d.cts +5 -16
  39. package/dist/ui.d.ts +5 -16
  40. package/dist/ui.esm.js +2 -2
  41. package/dist/{welcome--80i_O0p.d.cts → welcome-COOb05a5.d.cts} +5 -4
  42. package/dist/{welcome-BOizSp5h.d.ts → welcome-DE08m9ca.d.ts} +5 -4
  43. package/package.json +2 -1
  44. package/vite/local-dev.mjs +45 -3
  45. package/dist/chart-artifact-C71dk4xI.d.ts +0 -329
  46. package/dist/chart-artifact-CPEpOmtV.d.cts +0 -329
  47. package/dist/chunk-M4V6Q6XO.esm.js +0 -1082
package/dist/app.cjs CHANGED
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/app.ts
31
31
  var app_exports = {};
32
32
  __export(app_exports, {
33
+ APP_KIT_AGENT_INSTRUCTIONS: () => APP_KIT_AGENT_INSTRUCTIONS,
33
34
  AppChatPanel: () => AppChatPanel,
34
35
  AppConfirmDialog: () => AppConfirmDialog,
35
36
  AppCopilotProvider: () => AppCopilotProvider,
@@ -37,23 +38,47 @@ __export(app_exports, {
37
38
  AppShellChatTrigger: () => AppShellChatTrigger,
38
39
  AppShellTopbar: () => AppShellTopbar,
39
40
  Breadcrumbs: () => Breadcrumbs,
41
+ Button: () => Button,
42
+ CHART_PALETTE: () => CHART_PALETTE,
40
43
  ChartArtifactView: () => ChartArtifactView,
41
44
  ChartPanel: () => ChartPanel,
45
+ ConnectionRow: () => ConnectionRow,
46
+ ConnectionRowList: () => ConnectionRowList,
47
+ DangerZone: () => DangerZone,
48
+ DangerZoneAction: () => DangerZoneAction,
42
49
  DataTable: () => DataTable,
43
- EmptyState: () => EmptyState2,
50
+ DescriptionList: () => DescriptionList,
51
+ EmptyState: () => EmptyState,
52
+ ExpandableSection: () => ExpandableSection,
44
53
  Field: () => Field,
45
54
  FieldInput: () => FieldInput,
55
+ FieldRow: () => FieldRow,
46
56
  FieldSelect: () => FieldSelect,
47
57
  FieldSwitch: () => FieldSwitch,
48
58
  FieldTextarea: () => FieldTextarea,
49
59
  FilterBar: () => FilterBar,
60
+ FloatingUnsavedChangesBar: () => FloatingUnsavedChangesBar,
50
61
  FormSection: () => FormSection,
62
+ INTEGRATION_CATALOG_CARD_HEIGHT_CLASS: () => INTEGRATION_CATALOG_CARD_HEIGHT_CLASS,
63
+ InfoCard: () => InfoCard,
64
+ IntegrationCard: () => IntegrationCard,
65
+ IntegrationsEmptyState: () => IntegrationsEmptyState,
66
+ LineAreaChart: () => LineAreaChart,
67
+ MetricChartCard: () => MetricChartCard,
68
+ MetricRow: () => MetricRow,
69
+ MetricTile: () => MetricTile,
51
70
  Page: () => Page,
52
71
  PageHeader: () => PageHeader,
72
+ PlanBadge: () => PlanBadge,
73
+ ResourceCard: () => ResourceCard,
53
74
  SearchInput: () => SearchInput,
54
75
  Section: () => Section,
76
+ SettingsSection: () => SettingsSection,
77
+ SettingsSectionHeader: () => SettingsSectionHeader,
78
+ Sparkline: () => Sparkline,
55
79
  StatTile: () => StatTile,
56
80
  StatusBadge: () => StatusBadge,
81
+ StatusDot: () => StatusDot,
57
82
  SubNav: () => SubNav,
58
83
  SurfaceCard: () => SurfaceCard,
59
84
  TimbalChat: () => TimbalChat,
@@ -64,11 +89,197 @@ __export(app_exports, {
64
89
  appShellTopbarInsetClass: () => appShellTopbarInsetClass,
65
90
  appStatTileClass: () => appStatTileClass,
66
91
  appSurfaceCardClass: () => appSurfaceCardClass,
92
+ connectionRowListClass: () => connectionRowListClass,
67
93
  useAppCopilotContext: () => useAppCopilotContext,
68
94
  useAppShellChat: () => useAppShellChat
69
95
  });
70
96
  module.exports = __toCommonJS(app_exports);
71
97
 
98
+ // src/app/agent-instructions.ts
99
+ var APP_KIT_AGENT_INSTRUCTIONS = `
100
+ ## App kit (@timbal-ai/timbal-react/app)
101
+
102
+ Build **dashboard and operations UIs** with React components. Import from \`@timbal-ai/timbal-react/app\` (or the main package entry if your app already uses it).
103
+
104
+ ### Creative freedom (read this first)
105
+
106
+ You are **not** required to copy any example layout, page title, section order, or visual theme.
107
+
108
+ - **Do** invent layouts that fit the user's domain (CRM, inventory, billing, internal tools, etc.).
109
+ - **Do** pick only the components you need; skip shell, sidebar, or copilot when the task does not need them.
110
+ - **Do** vary density, grid columns, navigation patterns, and copy \u2014 as long as you follow the **design guidelines** below.
111
+ - **Do not** treat \`examples/app-kit/reference/\` as a template to clone (no default "Operations" dashboard with sidebar + three KPI tiles + SubNav + table unless the user asked for that).
112
+ - **Do** use \`examples/app-kit/recipes/\` as **short grammar examples** (one concern per file), not as a full app blueprint.
113
+
114
+ When in doubt: compose from the **component menu** + **guidelines**, then adapt creatively to the request.
115
+
116
+ ### Module layout (source folders)
117
+
118
+ Presentational groups \u2014 import from the package root, not from these paths:
119
+
120
+ | Folder | Components |
121
+ |--------|------------|
122
+ | \`data/\` | \`MetricRow\`, \`MetricChartCard\`, \`MetricTile\`, \`DataTable\`, \`FilterBar\`, \`ChartPanel\` |
123
+ | \`integrations/\` | \`IntegrationCard\`, \`ConnectionRow\`, \`ConnectionRowList\`, \`IntegrationsEmptyState\`, \`PlanBadge\` |
124
+ | \`settings/\` | \`SettingsSection\`, \`FieldRow\`, \`DangerZone\`, \`FloatingUnsavedChangesBar\` |
125
+ | \`surfaces/\` | \`StatTile\`, \`InfoCard\`, \`ResourceCard\`, \`DescriptionList\`, \`ExpandableSection\`, \`StatusDot\`, \`StatusBadge\`, \`EmptyState\` |
126
+ | \`layout/\` | \`AppShell\`, \`Page\`, \`Section\` |
127
+ | \`charts\` (re-exported) | \`LineAreaChart\`, \`Sparkline\`, \`CHART_PALETTE\` |
128
+
129
+ Also re-exported: \`Button\`, \`TimbalChat\`, \`ChartArtifactView\`, \`APP_KIT_AGENT_INSTRUCTIONS\`.
130
+
131
+ ### Design guidelines (required)
132
+
133
+ | Area | Rule |
134
+ |------|------|
135
+ | **Copilot** | Use \`AppCopilotProvider\` for page context (\`useAppCopilotContext\`). Copilot is a **floating overlay** via \`AppShell\` \`chat={<AppChatPanel />}\` \u2014 not a sidebar column that shrinks main content. |
136
+ | **Chat panel** | \`AppChatPanel\` only; \`Thread\` uses \`variant="panel"\` internally. Dismiss with **X**; trigger is a **text-only** pill (e.g. "Assistant") \u2014 **no** MessageSquare or chat icons on the shell trigger. |
137
+ | **Context** | Do not show raw JSON context in the panel header; keep context in \`AppCopilotProvider\` only. |
138
+ | **Theming** | Use semantic Tailwind tokens (\`bg-background\`, \`text-foreground\`, \`border-border\`, \`bg-elevated-from\`, etc.) from the host app's \`styles.css\`. Optional: \`import "@timbal-ai/timbal-react/styles.css"\`. |
139
+ | **Layout chrome** | \`Page\` \u2192 \`Section\` for main content hierarchy. \`AppShellTopbar\` for global actions (auth, theme). |
140
+ | **Data** | Prefer \`DataTable\` with typed \`columns\` / \`rows\` / \`getRowKey\`; use \`ChartPanel\` with \`ChartArtifact\` for charts. |
141
+ | **Modals** | Use \`AppConfirmDialog\` for destructive/export confirmations. |
142
+ | **Metrics** | Overview KPIs \u2192 \`MetricRow\` or \`MetricChartCard\` (not four separate heavy cards). Values use **normal** font weight, not bold. |
143
+ | **Integrations** | Catalog \u2192 \`IntegrationCard\` grid; connected list \u2192 \`ConnectionRow\` inside \`ConnectionRowList\`. Footer CTAs: \`Button variant="secondary"\`. |
144
+ | **Anti-slop** | No loud green/red trend pills on every tile; no \`bg-card\` flat grids when platform chrome exists; avoid recycling demo names ("Operations", mock workforce lists). |
145
+
146
+ ### Accessibility (required)
147
+
148
+ | Area | Rule |
149
+ |------|------|
150
+ | **Headings** | Use \`Page\` / \`Section\` titles for hierarchy. Card titles inside premade components are already \`h3\`/\`h4\`. |
151
+ | **Selectable metrics** | \`MetricChartCard\` / \`MetricRow\` tiles are buttons with \`aria-pressed\`. Pass \`metricsAriaLabel\` when the default "Metrics" is too vague. |
152
+ | **Charts** | \`LineAreaChart\` exposes \`role="img"\` + \`aria-label\`; \`MetricChartCard\` updates the chart label when the active metric changes (\`aria-live\` on the plot region). |
153
+ | **Integration cards** | Whole-card click \u2192 \`onClick\` only (no nested footer button). With footer \`action\`, render a static \`article\` \u2014 do not wrap the CTA in a card button. Pass \`ariaLabel\` when \`name\` is not plain text. |
154
+ | **Lists** | Wrap \`ConnectionRow\` in \`ConnectionRowList\` (\`role="list"\`); rows expose \`role="listitem"\`. |
155
+ | **Status** | Pair \`StatusDot\` / \`StatusBadge\` with visible text \u2014 do not rely on color alone. |
156
+ | **Forms** | Use \`Field*\` components; errors use \`role="alert"\`. |
157
+ | **Custom labels** | \`ariaLabel\` props exist on \`MetricTile\`, \`IntegrationCard\`, \`ConnectionRow\`, \`ResourceCard\` when slots are icons or rich nodes. |
158
+
159
+ ### Component menu
160
+
161
+ | Component | Use for |
162
+ |-----------|---------|
163
+ | \`AppShell\` | Shell: optional \`sidebar\`, \`topbar\`, main \`children\`, optional floating \`chat\`. Props: \`chatTriggerLabel\`, \`chatCollapsible\`, \`chatWidth\`, \`chatHeight\`, controlled \`chatOpen\`. |
164
+ | \`AppShellTopbar\` | Full-width top bar: \`start\`, \`actions\` slots. |
165
+ | \`AppCopilotProvider\` | React context for copilot-aware tools (page, filters, selection, etc.). |
166
+ | \`AppChatPanel\` | Floating thread: \`workforceId\`, \`welcome\`, \`debug\`. |
167
+ | \`useAppShellChat\` | Custom open/close trigger when \`hideChatTrigger\` on shell. |
168
+ | \`Page\` | Page title, description, \`breadcrumbs\`, \`actions\`, children. |
169
+ | \`Section\` | Titled block inside a page. |
170
+ | \`SubNav\` | In-page tabs: \`items\`, \`activeId\`, \`onChange\`. |
171
+ | \`Breadcrumbs\` | Trail: \`items: [{ label, href? }]\`. |
172
+ | \`Button\` | Actions \u2014 \`variant="secondary"\` for catalog/secondary CTAs; \`variant="default"\` for primary. |
173
+ | \`StatTile\` | Single KPI in its own card (grid of scattered stats). Prefer \`MetricRow\` for a unified overview strip. |
174
+ | \`StatusBadge\` | Status pill: \`tone\` (\`success\`, \`warn\`, \u2026), children. |
175
+ | \`FilterBar\` | Horizontal filter row (wraps \`SearchInput\`, buttons, etc.). |
176
+ | \`SearchInput\` | Filter field with consistent app styling. |
177
+ | \`DataTable\` | Sortable table: \`columns\`, \`rows\`, \`getRowKey\`, optional \`sort\` / \`onSortChange\`, \`emptyTitle\`, \`showRowCount\`, \`caption\` for screen readers. |
178
+ | \`ChartPanel\` | Same shell as \`MetricChartCard\`: title row (\`px-4 pt-4\`), flush plot (\`pt-2\` only). Pass \`title\` + \`artifact\` (omit \`artifact.title\` to avoid duplicates) or \`children\`. |
179
+ | \`FieldInput\`, \`FieldTextarea\`, \`FieldSelect\`, \`FieldSwitch\` | Settings-style forms with labels and hints. |
180
+ | \`FormSection\` | Grouped form block. |
181
+ | \`AppConfirmDialog\` | Confirm/cancel modal: \`open\`, \`onOpenChange\`, \`title\`, \`description\`, \`onConfirm\`. |
182
+ | \`SurfaceCard\`, \`EmptyState\` | Generic surfaces when needed. |
183
+ | \`TimbalChat\` | Re-export if you need chat outside \`AppChatPanel\`. |
184
+
185
+ #### Charts & metrics
186
+
187
+ | Component | Use for |
188
+ |-----------|---------|
189
+ | \`LineAreaChart\` | Chart engine. Props: \`data\`, \`xKey\`, \`series\`, \`variant\` (\`"area"\`), \`layout\` (\`"flush"\`), \`height\`, \`ariaLabel\`, \`formatX\`, \`formatValue\`. |
190
+ | \`Sparkline\` | Tiny inline trend (table cells): \`data\`, \`color\`, \`area\`. |
191
+ | \`MetricTile\` | Low-level KPI cell \u2014 prefer \`MetricRow\` / \`MetricChartCard\` instead of hand-wiring tiles. |
192
+ | \`MetricRow\` | KPI strip in one elevated card (no chart). Props: \`metrics: [{ id, label, value, unit?, trend? }]\`, optional \`onMetricChange\`, \`metricsAriaLabel\`. |
193
+ | \`MetricChartCard\` | KPI strip + flush chart; tile click swaps series. Same metrics shape + \`data\` per metric. Default chart height 300. |
194
+
195
+ #### Settings
196
+
197
+ | Component | Use for |
198
+ |-----------|---------|
199
+ | \`SettingsSection\` | Two-column settings block: \`title\` + \`description\` rail on the left, controls on the right. |
200
+ | \`FieldRow\` | Labeled control row: \`label\`, \`description\`, \`inline\` (right-aligned control for switches). |
201
+ | \`DangerZone\` + \`DangerZoneAction\` | Destructive-actions container with destructive border. |
202
+ | \`FloatingUnsavedChangesBar\` | Portaled discard/save pill: \`visible\`, \`onDiscard\`, \`onSave\`, \`isSaving\`. |
203
+
204
+ #### Integrations & resources
205
+
206
+ | Component | Use for |
207
+ |-----------|---------|
208
+ | \`IntegrationCard\` | Catalog tile: \`logo\`, \`name\`, \`description\`, \`badge\`, \`status\`, footer \`action\` **or** whole-card \`onClick\` (never both). |
209
+ | \`ConnectionRow\` | One connected provider row: \`logo\`, \`name\`, \`meta\`, \`badge\`, \`action\`. |
210
+ | \`ConnectionRowList\` | Wrapper for rows (\`role="list"\`) \u2014 use instead of raw class strings. |
211
+ | \`IntegrationsEmptyState\` | Empty catalog hero: \`icon\`, \`title\`, \`description\`, \`action\`. |
212
+ | \`PlanBadge\` | Neutral tier chip on catalog cards. |
213
+ | \`ResourceCard\` | Project/agent/dataset card on elevated surface + logo tile: \`media\`, \`title\`, \`subtitle\`, optional \`badge\`, \`footer\` (\`StatusDot\`), \`action\` (\`Sparkline\`). |
214
+
215
+ #### Surfaces & details
216
+
217
+ | Component | Use for |
218
+ |-----------|---------|
219
+ | \`InfoCard\` | Soft callout: \`icon\`, \`title\`, body, \`action\`, \`tone\` (\`info\`/\`success\`/\`warn\`/\`danger\`). |
220
+ | \`DescriptionList\` | Read-only key/value metadata: \`items: [{ label, value }]\`, optional \`stacked\`. |
221
+ | \`ExpandableSection\` | Collapsible block: \`title\`, \`icon\`, \`count\`, animated body (\`aria-expanded\` + \`aria-controls\`). |
222
+ | \`StatusDot\` | Status indicator dot: \`tone\`, \`label\`, \`pulse\`. |
223
+
224
+ Studio chrome (\`StudioSidebar\`, \`ModeToggle\`, \u2026) lives in \`@timbal-ai/timbal-react/studio\` \u2014 optional, not required for every dashboard.
225
+
226
+ ### Recipe index (\`examples/app-kit/recipes/\`)
227
+
228
+ | Recipe file | Components to study |
229
+ |-------------|---------------------|
230
+ | \`metrics-row.tsx\` | \`Page\`, \`MetricRow\` |
231
+ | \`analytics-card.tsx\` | \`MetricChartCard\`, \`Button\` |
232
+ | \`integrations-grid.tsx\` | \`IntegrationCard\`, \`ConnectionRowList\`, \`PlanBadge\` |
233
+ | \`table-with-filters.tsx\` | \`FilterBar\`, \`DataTable\` |
234
+ | \`settings-page.tsx\` | \`SettingsSection\`, \`DangerZone\`, \`FloatingUnsavedChangesBar\` |
235
+ | \`resource-gallery.tsx\` | \`ResourceCard\`, \`StatusDot\`, \`Sparkline\` |
236
+ | \`charts-panel.tsx\` | \`ChartPanel\`, \`ChartArtifact\` |
237
+ | \`copilot-overlay.tsx\` | \`AppShell\`, \`AppChatPanel\` |
238
+
239
+ ### Typical compositions
240
+
241
+ - **Metrics overview** \u2014 \`MetricRow\` or \`MetricChartCard\` (not four isolated stat cards with bold numbers).
242
+ - **Analytics** \u2014 \`MetricChartCard\`; header action: \`Button variant="secondary" size="sm"\`.
243
+ - **Table workspace** \u2014 \`Page\` + \`FilterBar\` + \`DataTable\` (+ \`StatusBadge\` / \`StatusDot\` in cells).
244
+ - **Settings** \u2014 \`Page\` + \`SettingsSection\`s + \`DangerZone\` + \`FloatingUnsavedChangesBar\`.
245
+ - **Integrations** \u2014 grid of \`IntegrationCard\`; \`ConnectionRowList\` for connected providers; \`IntegrationsEmptyState\` when empty.
246
+ - **Resource gallery** \u2014 grid of \`ResourceCard\`.
247
+ - **Copilot-assisted app** \u2014 \`AppCopilotProvider\` + \`AppShell\` with \`chat={<AppChatPanel workforceId="\u2026" />}\`.
248
+
249
+ ### Example imports
250
+
251
+ \`\`\`tsx
252
+ import {
253
+ AppShell,
254
+ AppCopilotProvider,
255
+ AppChatPanel,
256
+ Page,
257
+ Section,
258
+ MetricRow,
259
+ MetricChartCard,
260
+ IntegrationCard,
261
+ ConnectionRow,
262
+ ConnectionRowList,
263
+ Button,
264
+ DataTable,
265
+ FilterBar,
266
+ } from "@timbal-ai/timbal-react/app";
267
+ \`\`\`
268
+
269
+ ### Examples in this repo (for humans/tools)
270
+
271
+ | Path | Purpose |
272
+ |------|---------|
273
+ | \`examples/app-kit/recipes/*\` | **Recipes** \u2014 one pattern each (~20\u201380 lines). Use for capability, not layout. |
274
+ | \`examples/app-kit/reference/operations-dashboard.tsx\` | **Reference only** \u2014 full wired app; do not treat as the default generated layout. |
275
+
276
+ ### Rules
277
+
278
+ - Prefer stable props documented above; avoid undocumented \`design/*\` class exports (\`connectionRowListClass\` is exported but \`ConnectionRowList\` is preferred).
279
+ - Match the user's domain language in titles and labels.
280
+ - For rich in-chat widgets, use **artifacts** (\`ARTIFACT_AGENT_INSTRUCTIONS\`) \u2014 app kit is for the **host application shell**.
281
+ `.trim();
282
+
72
283
  // src/app/layout/AppShell.tsx
73
284
  var import_react3 = require("motion/react");
74
285
  var import_react4 = require("react");
@@ -174,6 +385,10 @@ var TIMBAL_V2_SWITCH_THUMB = cn(
174
385
  TIMBAL_V2_ELEVATED_GRADIENT,
175
386
  "border border-border/80 shadow-sm"
176
387
  );
388
+ var TIMBAL_V2_ELEVATED_SURFACE = cn(
389
+ TIMBAL_V2_ELEVATED_GRADIENT,
390
+ "border border-border shadow-card"
391
+ );
177
392
  var TIMBAL_V2_SECONDARY_CHROME = [
178
393
  TIMBAL_V2_ELEVATED_GRADIENT,
179
394
  "border border-border shadow-card",
@@ -181,6 +396,11 @@ var TIMBAL_V2_SECONDARY_CHROME = [
181
396
  "hover:from-secondary-fill-hover-from hover:to-secondary-fill-hover-to",
182
397
  "active:from-secondary-fill-active-from active:to-secondary-fill-active-to"
183
398
  ].join(" ");
399
+ var TIMBAL_V2_LOGO_TILE = cn(
400
+ "bg-gradient-to-b from-white to-neutral-100",
401
+ "border border-neutral-200",
402
+ "shadow-[0_1px_2px_-0.5px_rgba(0,0,0,0.08)]"
403
+ );
184
404
 
185
405
  // src/design/classes.ts
186
406
  var studioTopbarPillHeightClass = "h-[var(--studio-chrome-pill-height)] min-h-[var(--studio-chrome-pill-height)]";
@@ -312,10 +532,10 @@ var appSurfaceCardClass = cn(
312
532
  );
313
533
  var appStatTileClass = cn(
314
534
  appSurfaceCardClass,
315
- "flex flex-col gap-1"
535
+ "flex flex-col gap-1 px-4 py-3 shadow-none"
316
536
  );
317
- var appStatValueClass = "text-2xl font-semibold tracking-tight text-foreground";
318
- var appStatLabelClass = "text-sm text-muted-foreground";
537
+ var appStatValueClass = "text-2xl font-normal tracking-tight text-foreground tabular-nums";
538
+ var appStatLabelClass = "text-xs font-normal text-muted-foreground";
319
539
  var appFilterBarClass = cn(
320
540
  "flex flex-wrap items-center gap-2",
321
541
  studioTopbarPillHeightClass
@@ -339,7 +559,6 @@ var appEmptyStateClass = cn(
339
559
  var appEmptyStateTitleClass = "text-base font-medium text-foreground";
340
560
  var appEmptyStateDescriptionClass = "max-w-sm text-sm text-muted-foreground";
341
561
  var appChartPanelClass = cn(appSurfaceCardClass, "flex flex-col gap-3");
342
- var appChartPanelTitleClass = "text-sm font-medium text-foreground";
343
562
 
344
563
  // src/design/sidebar-motion.ts
345
564
  var STUDIO_SIDEBAR_EASE_ENTER = [0, 0, 0.2, 1];
@@ -636,7 +855,7 @@ var TimbalV2Button = React.forwardRef(function TimbalV2Button2({
636
855
  isIconOnly = false,
637
856
  isLoading = false,
638
857
  fullWidth = false,
639
- shape = "pill",
858
+ shape: _shape = "pill",
640
859
  asChild = false,
641
860
  className,
642
861
  disabled,
@@ -646,7 +865,7 @@ var TimbalV2Button = React.forwardRef(function TimbalV2Button2({
646
865
  }, ref) {
647
866
  const isDisabled = disabled || isLoading;
648
867
  const sizeClass = isIconOnly ? TIMBAL_V2_SIZE_ICON[size] : TIMBAL_V2_SIZE_HEIGHT[size];
649
- const radiusClass = variant === "link" || variant === "ghost" ? "rounded-md" : shape === "rect" ? "rounded-md" : "rounded-full";
868
+ const radiusClass = "rounded-full";
650
869
  const sharedRootClass = cn(
651
870
  "relative box-border inline-flex items-center justify-center gap-2 whitespace-nowrap border-0 text-sm font-normal shadow-none transition duration-200 ease-in-out",
652
871
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/60 focus-visible:ring-offset-1 focus-visible:ring-offset-background",
@@ -811,10 +1030,10 @@ function useAppCopilotContext() {
811
1030
  var import_lucide_react9 = require("lucide-react");
812
1031
 
813
1032
  // src/chat/thread.tsx
814
- var import_react32 = require("react");
815
- var import_react33 = require("@assistant-ui/react");
1033
+ var import_react34 = require("react");
1034
+ var import_react35 = require("@assistant-ui/react");
816
1035
  var import_lucide_react8 = require("lucide-react");
817
- var import_react34 = require("motion/react");
1036
+ var import_react36 = require("motion/react");
818
1037
 
819
1038
  // src/chat/attachment.tsx
820
1039
  var import_react7 = require("react");
@@ -1187,292 +1406,476 @@ var import_react_markdown = require("@assistant-ui/react-markdown");
1187
1406
  var import_remark_gfm = __toESM(require("remark-gfm"), 1);
1188
1407
  var import_remark_math = __toESM(require("remark-math"), 1);
1189
1408
  var import_rehype_katex = __toESM(require("rehype-katex"), 1);
1190
- var import_react19 = require("react");
1409
+ var import_react21 = require("react");
1191
1410
  var import_lucide_react4 = require("lucide-react");
1192
1411
 
1193
1412
  // src/chat/syntax-highlighter.tsx
1194
- var import_react18 = require("react");
1413
+ var import_react20 = require("react");
1195
1414
  var import_core = require("shiki/core");
1196
1415
  var import_javascript = require("shiki/engine/javascript");
1197
1416
 
1198
1417
  // src/artifacts/registry.tsx
1199
- var import_react17 = require("react");
1418
+ var import_react19 = require("react");
1200
1419
 
1201
1420
  // src/artifacts/chart-artifact.tsx
1421
+ var import_react11 = require("react");
1422
+
1423
+ // src/charts/line-area-chart.tsx
1424
+ var import_react10 = require("react");
1425
+
1426
+ // src/charts/use-chart-width.ts
1202
1427
  var import_react9 = require("react");
1428
+ function useChartWidth(initial = 640) {
1429
+ const ref = (0, import_react9.useRef)(null);
1430
+ const [width, setWidth] = (0, import_react9.useState)(initial);
1431
+ (0, import_react9.useEffect)(() => {
1432
+ const el = ref.current;
1433
+ if (!el || typeof ResizeObserver === "undefined") return;
1434
+ const ro = new ResizeObserver((entries) => {
1435
+ const w = entries[0]?.contentRect.width;
1436
+ if (w && w > 0) setWidth(w);
1437
+ });
1438
+ ro.observe(el);
1439
+ return () => ro.disconnect();
1440
+ }, []);
1441
+ return { ref, width };
1442
+ }
1203
1443
 
1204
- // src/artifacts/artifact-card.tsx
1205
- var import_jsx_runtime14 = require("react/jsx-runtime");
1206
- var ArtifactCard = ({ title, kind, className, bodyClassName, toolbar, children }) => {
1207
- const hasHeader = Boolean(title || toolbar);
1208
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1209
- "div",
1210
- {
1211
- className: cn(
1212
- "aui-artifact-root my-3 overflow-hidden rounded-xl border border-border/60 bg-background shadow-sm",
1213
- className
1214
- ),
1215
- "data-artifact-kind": kind,
1216
- children: [
1217
- hasHeader && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "aui-artifact-header flex items-center gap-2 border-b border-border/40 bg-muted/30 px-3 py-1.5", children: [
1218
- title && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "aui-artifact-title flex-1 truncate text-xs font-semibold text-foreground/80", children: title }),
1219
- !title && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "flex-1" }),
1220
- toolbar
1221
- ] }),
1222
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: cn("aui-artifact-body", bodyClassName), children })
1223
- ]
1444
+ // src/charts/geometry.ts
1445
+ function toNum(value) {
1446
+ const n = typeof value === "number" ? value : Number(value);
1447
+ return Number.isFinite(n) ? n : 0;
1448
+ }
1449
+ function monotoneLinePath(points) {
1450
+ const n = points.length;
1451
+ if (n === 0) return "";
1452
+ if (n === 1) return `M ${points[0].x},${points[0].y}`;
1453
+ if (n === 2) {
1454
+ return `M ${points[0].x},${points[0].y} L ${points[1].x},${points[1].y}`;
1455
+ }
1456
+ const tangents = monotoneTangents(points);
1457
+ let d = `M ${points[0].x},${points[0].y}`;
1458
+ for (let i = 0; i < n - 1; i++) {
1459
+ const p0 = points[i];
1460
+ const p1 = points[i + 1];
1461
+ const dx = (p1.x - p0.x) / 3;
1462
+ const c1x = p0.x + dx;
1463
+ const c1y = p0.y + dx * tangents[i];
1464
+ const c2x = p1.x - dx;
1465
+ const c2y = p1.y - dx * tangents[i + 1];
1466
+ d += ` C ${c1x},${c1y} ${c2x},${c2y} ${p1.x},${p1.y}`;
1467
+ }
1468
+ return d;
1469
+ }
1470
+ function monotoneAreaPath(points, baseY) {
1471
+ if (points.length === 0) return "";
1472
+ const line = monotoneLinePath(points);
1473
+ const last = points[points.length - 1];
1474
+ const first = points[0];
1475
+ return `${line} L ${last.x},${baseY} L ${first.x},${baseY} Z`;
1476
+ }
1477
+ function monotoneTangents(points) {
1478
+ const n = points.length;
1479
+ const slopes = new Array(n - 1);
1480
+ for (let i = 0; i < n - 1; i++) {
1481
+ const dx = points[i + 1].x - points[i].x || 1;
1482
+ slopes[i] = (points[i + 1].y - points[i].y) / dx;
1483
+ }
1484
+ const tangents = new Array(n);
1485
+ tangents[0] = slopes[0];
1486
+ tangents[n - 1] = slopes[n - 2];
1487
+ for (let i = 1; i < n - 1; i++) {
1488
+ const s0 = slopes[i - 1];
1489
+ const s1 = slopes[i];
1490
+ if (s0 * s1 <= 0) {
1491
+ tangents[i] = 0;
1492
+ } else {
1493
+ tangents[i] = (s0 + s1) / 2;
1224
1494
  }
1225
- );
1226
- };
1495
+ }
1496
+ for (let i = 0; i < n - 1; i++) {
1497
+ const s = slopes[i];
1498
+ if (s === 0) {
1499
+ tangents[i] = 0;
1500
+ tangents[i + 1] = 0;
1501
+ continue;
1502
+ }
1503
+ const a = tangents[i] / s;
1504
+ const b = tangents[i + 1] / s;
1505
+ const h = Math.hypot(a, b);
1506
+ if (h > 3) {
1507
+ const t = 3 / h;
1508
+ tangents[i] = t * a * s;
1509
+ tangents[i + 1] = t * b * s;
1510
+ }
1511
+ }
1512
+ return tangents;
1513
+ }
1514
+ function niceTicks(min, max, count = 4) {
1515
+ if (!Number.isFinite(min) || !Number.isFinite(max) || max === min) {
1516
+ return [min || 0];
1517
+ }
1518
+ const step = niceStep((max - min) / count);
1519
+ const start = Math.floor(min / step) * step;
1520
+ const out = [];
1521
+ for (let v = start; v <= max + step / 2; v += step) {
1522
+ out.push(round(v));
1523
+ }
1524
+ return out;
1525
+ }
1526
+ function niceStep(raw) {
1527
+ const exp = Math.floor(Math.log10(Math.abs(raw) || 1));
1528
+ const base = Math.pow(10, exp);
1529
+ const norm = raw / base;
1530
+ let nice = 1;
1531
+ if (norm >= 5) nice = 5;
1532
+ else if (norm >= 2) nice = 2;
1533
+ return nice * base;
1534
+ }
1535
+ function round(v) {
1536
+ return Math.round(v * 1e6) / 1e6;
1537
+ }
1538
+ function formatCompact(value, unit) {
1539
+ const abs = Math.abs(value);
1540
+ let s;
1541
+ if (abs >= 1e6) s = `${round(value / 1e6)}M`;
1542
+ else if (abs >= 1e3) s = `${round(value / 1e3)}k`;
1543
+ else s = String(round(value));
1544
+ return unit ? `${s}${unit}` : s;
1545
+ }
1227
1546
 
1228
- // src/artifacts/chart-artifact.tsx
1229
- var import_jsx_runtime15 = require("react/jsx-runtime");
1230
- var ChartArtifactView = ({
1231
- artifact
1232
- }) => {
1233
- const { type: _t, chartType = "bar", data = [] } = artifact;
1234
- const xKey = artifact.xKey ?? inferXKey(data);
1235
- const dataKeys = (0, import_react9.useMemo)(() => {
1236
- if (Array.isArray(artifact.dataKey)) return artifact.dataKey;
1237
- if (typeof artifact.dataKey === "string") return [artifact.dataKey];
1238
- return inferDataKeys(data, xKey);
1239
- }, [artifact.dataKey, data, xKey]);
1240
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ArtifactCard, { title: artifact.title, kind: "chart", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "aui-artifact-chart p-3", children: [
1241
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1242
- ChartSvg,
1243
- {
1244
- chartType,
1245
- data,
1246
- xKey,
1247
- dataKeys,
1248
- unit: artifact.unit
1249
- }
1250
- ),
1251
- dataKeys.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Legend, { dataKeys })
1252
- ] }) });
1253
- };
1254
- var COLORS = [
1547
+ // src/charts/line-area-chart.tsx
1548
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1549
+ var CHART_PALETTE = [
1255
1550
  "var(--primary, #6366f1)",
1256
- "#22c55e",
1551
+ "#10b981",
1257
1552
  "#f59e0b",
1258
- "#ef4444",
1259
1553
  "#06b6d4",
1260
- "#a855f7"
1554
+ "#a855f7",
1555
+ "#ef4444"
1261
1556
  ];
1262
- var W = 600;
1263
- var H = 240;
1264
- var PAD = { top: 12, right: 16, bottom: 28, left: 36 };
1265
- var ChartSvg = ({ chartType, data, xKey, dataKeys, unit }) => {
1266
- if (data.length === 0 || dataKeys.length === 0) {
1267
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(EmptyState, {});
1268
- }
1269
- if (chartType === "pie") {
1270
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PieChart, { data, xKey, dataKey: dataKeys[0] });
1557
+ var PAD_DEFAULT = { top: 12, right: 16, bottom: 26, left: 44 };
1558
+ var PAD_FLUSH = { top: 20, right: 0, bottom: 8, left: 0 };
1559
+ var LineAreaChart = ({
1560
+ data = [],
1561
+ xKey: xKeyProp,
1562
+ series: seriesProp,
1563
+ variant = "area",
1564
+ height = 240,
1565
+ unit,
1566
+ yMax,
1567
+ layout = "default",
1568
+ showGrid = true,
1569
+ showXAxis: showXAxisProp,
1570
+ showYAxis: showYAxisProp,
1571
+ showLegend: showLegendProp,
1572
+ showTooltip = true,
1573
+ formatValue,
1574
+ formatX,
1575
+ className,
1576
+ ariaLabel = "Chart"
1577
+ }) => {
1578
+ const uid = (0, import_react10.useId)();
1579
+ const { ref, width } = useChartWidth();
1580
+ const [active, setActive] = (0, import_react10.useState)(null);
1581
+ const [grown, setGrown] = (0, import_react10.useState)(false);
1582
+ const xKey = xKeyProp ?? inferXKey(data);
1583
+ const series = (0, import_react10.useMemo)(
1584
+ () => resolveSeries(seriesProp, data, xKey),
1585
+ [seriesProp, data, xKey]
1586
+ );
1587
+ const pad = layout === "flush" ? PAD_FLUSH : PAD_DEFAULT;
1588
+ const showXAxis = showXAxisProp ?? layout !== "flush";
1589
+ const showYAxis = showYAxisProp ?? layout !== "flush";
1590
+ const showLegend = showLegendProp ?? (layout !== "flush" && series.length > 1);
1591
+ (0, import_react10.useEffect)(() => {
1592
+ const t = requestAnimationFrame(() => setGrown(true));
1593
+ return () => cancelAnimationFrame(t);
1594
+ }, []);
1595
+ const innerW = Math.max(0, width - pad.left - pad.right);
1596
+ const innerH = Math.max(0, height - pad.top - pad.bottom);
1597
+ const { minV, maxV } = (0, import_react10.useMemo)(() => {
1598
+ let lo = 0;
1599
+ let hi = yMax ?? 0;
1600
+ for (const s of series) {
1601
+ for (const d of data) {
1602
+ const v = toNum(d[s.dataKey]);
1603
+ if (v > hi && yMax == null) hi = v;
1604
+ if (v < lo) lo = v;
1605
+ }
1606
+ }
1607
+ if (hi === lo) hi = lo + 1;
1608
+ return { minV: lo, maxV: yMax != null ? yMax : hi * 1.08 };
1609
+ }, [series, data, yMax]);
1610
+ const ticks = (0, import_react10.useMemo)(() => niceTicks(minV, maxV, 4), [minV, maxV]);
1611
+ if (data.length === 0 || series.length === 0) {
1612
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ChartEmpty, { className, height });
1271
1613
  }
1272
- const innerW = W - PAD.left - PAD.right;
1273
- const innerH = H - PAD.top - PAD.bottom;
1274
- const all = dataKeys.flatMap((k) => data.map((d) => toNum(d[k])));
1275
- const maxV = Math.max(0, ...all);
1276
- const minV = Math.min(0, ...all);
1277
- const range = maxV - minV || 1;
1278
- const yScale = (v) => PAD.top + innerH - (v - minV) / range * innerH;
1614
+ const yScale = (v) => pad.top + innerH - (v - minV) / (maxV - minV || 1) * innerH;
1279
1615
  const xCount = data.length;
1280
1616
  const xStep = xCount > 1 ? innerW / (xCount - 1) : innerW;
1281
- const xPos = (i) => chartType === "bar" ? PAD.left + innerW * (i + 0.5) / xCount : PAD.left + i * xStep;
1282
- const ticks = niceTicks(minV, maxV);
1283
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1284
- "svg",
1285
- {
1286
- viewBox: `0 0 ${W} ${H}`,
1287
- className: "aui-artifact-chart-svg w-full",
1288
- role: "img",
1289
- "aria-label": "Chart",
1290
- children: [
1291
- ticks.map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("g", { children: [
1292
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1617
+ const xPos = (i) => variant === "bar" ? pad.left + innerW * (i + 0.5) / xCount : pad.left + i * xStep;
1618
+ const baseY = yScale(Math.max(0, minV));
1619
+ const fmtV = (v) => formatValue ? formatValue(v) : formatCompact(v, unit);
1620
+ const fmtX = (i) => formatX ? formatX(data[i]?.[xKey], i) : String(data[i]?.[xKey] ?? i);
1621
+ const onMove = (event) => {
1622
+ const rect = event.currentTarget.getBoundingClientRect();
1623
+ const px2 = event.clientX - rect.left - pad.left;
1624
+ const i = Math.round(px2 / (xStep || 1));
1625
+ setActive(Math.max(0, Math.min(xCount - 1, i)));
1626
+ };
1627
+ const labelIdx = pickXLabels(xCount, innerW);
1628
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { ref, className: cn("relative w-full", className), style: { height }, children: [
1629
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1630
+ "svg",
1631
+ {
1632
+ width,
1633
+ height,
1634
+ role: "img",
1635
+ "aria-label": ariaLabel,
1636
+ className: "block overflow-visible",
1637
+ children: [
1638
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("defs", { children: [
1639
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("clipPath", { id: `${uid}-grow`, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1640
+ "rect",
1641
+ {
1642
+ x: pad.left,
1643
+ y: 0,
1644
+ height,
1645
+ width: grown ? innerW : 0,
1646
+ style: { transition: "width 900ms cubic-bezier(0.22,1,0.36,1)" }
1647
+ }
1648
+ ) }),
1649
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("linearGradient", { id: `${uid}-gridfade`, x1: "0%", x2: "100%", y1: "0", y2: "0", children: [
1650
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("stop", { offset: "0%", stopColor: "white", stopOpacity: 0 }),
1651
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("stop", { offset: "8%", stopColor: "white", stopOpacity: 1 }),
1652
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("stop", { offset: "92%", stopColor: "white", stopOpacity: 1 }),
1653
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("stop", { offset: "100%", stopColor: "white", stopOpacity: 0 })
1654
+ ] }),
1655
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("mask", { id: `${uid}-gridmask`, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1656
+ "rect",
1657
+ {
1658
+ x: pad.left,
1659
+ y: pad.top,
1660
+ width: innerW,
1661
+ height: innerH,
1662
+ fill: `url(#${uid}-gridfade)`
1663
+ }
1664
+ ) }),
1665
+ series.map((s, i) => {
1666
+ const color = s.color ?? CHART_PALETTE[i % CHART_PALETTE.length];
1667
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1668
+ "linearGradient",
1669
+ {
1670
+ id: `${uid}-fill-${i}`,
1671
+ x1: "0",
1672
+ x2: "0",
1673
+ y1: "0",
1674
+ y2: "1",
1675
+ children: [
1676
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("stop", { offset: "0%", style: { stopColor: color, stopOpacity: 0.28 } }),
1677
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("stop", { offset: "100%", style: { stopColor: color, stopOpacity: 0 } })
1678
+ ]
1679
+ },
1680
+ s.dataKey
1681
+ );
1682
+ })
1683
+ ] }),
1684
+ showGrid && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("g", { mask: `url(#${uid}-gridmask)`, children: ticks.map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1293
1685
  "line",
1294
1686
  {
1295
- x1: PAD.left,
1296
- x2: W - PAD.right,
1687
+ x1: pad.left,
1688
+ x2: width - pad.right,
1297
1689
  y1: yScale(t),
1298
1690
  y2: yScale(t),
1299
1691
  stroke: "currentColor",
1300
- strokeOpacity: 0.08
1301
- }
1302
- ),
1303
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1692
+ strokeOpacity: 0.14,
1693
+ strokeDasharray: "4 4",
1694
+ className: "text-muted-foreground"
1695
+ },
1696
+ i
1697
+ )) }),
1698
+ showYAxis && ticks.map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1304
1699
  "text",
1305
1700
  {
1306
- x: PAD.left - 6,
1701
+ x: pad.left - 8,
1307
1702
  y: yScale(t),
1308
1703
  textAnchor: "end",
1309
1704
  dominantBaseline: "middle",
1310
- className: "fill-muted-foreground text-[10px]",
1311
- children: formatTick(t, unit)
1705
+ className: "fill-muted-foreground text-[10px] tabular-nums",
1706
+ children: fmtV(t)
1707
+ },
1708
+ i
1709
+ )),
1710
+ showXAxis && labelIdx.map((i) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1711
+ "text",
1712
+ {
1713
+ x: xPos(i),
1714
+ y: height - pad.bottom + 16,
1715
+ textAnchor: i === 0 ? "start" : i === xCount - 1 ? "end" : "middle",
1716
+ className: "fill-muted-foreground text-[10px] tabular-nums",
1717
+ children: fmtX(i)
1718
+ },
1719
+ i
1720
+ )),
1721
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("g", { clipPath: `url(#${uid}-grow)`, children: variant === "bar" ? renderBars({ data, series, xCount, xPos, yScale, baseY, innerW, uid }) : series.map((s, si) => {
1722
+ const color = s.color ?? CHART_PALETTE[si % CHART_PALETTE.length];
1723
+ const pts = data.map((d, i) => ({
1724
+ x: xPos(i),
1725
+ y: yScale(toNum(d[s.dataKey]))
1726
+ }));
1727
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("g", { children: [
1728
+ variant === "area" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("path", { d: monotoneAreaPath(pts, baseY), fill: `url(#${uid}-fill-${si})` }),
1729
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1730
+ "path",
1731
+ {
1732
+ d: monotoneLinePath(pts),
1733
+ fill: "none",
1734
+ stroke: color,
1735
+ strokeWidth: 2,
1736
+ strokeLinecap: "round",
1737
+ strokeLinejoin: "round"
1738
+ }
1739
+ )
1740
+ ] }, s.dataKey);
1741
+ }) }),
1742
+ showTooltip && active != null && variant !== "bar" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("g", { pointerEvents: "none", children: [
1743
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1744
+ "line",
1745
+ {
1746
+ x1: xPos(active),
1747
+ x2: xPos(active),
1748
+ y1: pad.top,
1749
+ y2: pad.top + innerH,
1750
+ stroke: "currentColor",
1751
+ strokeOpacity: 0.25,
1752
+ className: "text-foreground"
1753
+ }
1754
+ ),
1755
+ series.map((s, si) => {
1756
+ const color = s.color ?? CHART_PALETTE[si % CHART_PALETTE.length];
1757
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1758
+ "circle",
1759
+ {
1760
+ cx: xPos(active),
1761
+ cy: yScale(toNum(data[active]?.[s.dataKey])),
1762
+ r: 4,
1763
+ fill: color,
1764
+ stroke: "var(--background, #fff)",
1765
+ strokeWidth: 2
1766
+ },
1767
+ s.dataKey
1768
+ );
1769
+ })
1770
+ ] }),
1771
+ showTooltip && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1772
+ "rect",
1773
+ {
1774
+ x: pad.left,
1775
+ y: pad.top,
1776
+ width: innerW,
1777
+ height: innerH,
1778
+ fill: "transparent",
1779
+ style: { cursor: "crosshair" },
1780
+ onMouseMove: onMove,
1781
+ onMouseLeave: () => setActive(null)
1312
1782
  }
1313
1783
  )
1314
- ] }, i)),
1315
- data.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1316
- "text",
1317
- {
1318
- x: xPos(i),
1319
- y: H - PAD.bottom + 14,
1320
- textAnchor: "middle",
1321
- className: "fill-muted-foreground text-[10px]",
1322
- children: String(d[xKey] ?? i)
1323
- },
1324
- i
1325
- )),
1326
- chartType === "bar" && renderBars({ data, dataKeys, xCount, xPos, yScale, minV, innerW }),
1327
- chartType === "line" && dataKeys.map((k, ki) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1328
- Polyline,
1329
- {
1330
- data,
1331
- dataKey: k,
1332
- xPos,
1333
- yScale,
1334
- color: COLORS[ki % COLORS.length]
1335
- },
1336
- k
1337
- )),
1338
- chartType === "area" && dataKeys.map((k, ki) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1339
- Area,
1340
- {
1341
- data,
1342
- dataKey: k,
1343
- xPos,
1344
- yScale,
1345
- baseY: yScale(Math.max(0, minV)),
1346
- color: COLORS[ki % COLORS.length]
1347
- },
1348
- k
1349
- ))
1350
- ]
1351
- }
1352
- );
1784
+ ]
1785
+ }
1786
+ ),
1787
+ showTooltip && active != null && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1788
+ ChartTooltip,
1789
+ {
1790
+ x: xPos(active),
1791
+ width,
1792
+ title: fmtX(active),
1793
+ rows: series.map((s, si) => ({
1794
+ color: s.color ?? CHART_PALETTE[si % CHART_PALETTE.length],
1795
+ label: s.label ?? s.dataKey,
1796
+ value: fmtV(toNum(data[active]?.[s.dataKey]))
1797
+ }))
1798
+ }
1799
+ ),
1800
+ showLegend ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ChartLegend, { series }) : null
1801
+ ] });
1353
1802
  };
1354
1803
  function renderBars(args) {
1355
- const { data, dataKeys, xCount, xPos, yScale, minV, innerW } = args;
1356
- const groupWidth = innerW / xCount * 0.7;
1357
- const barWidth = groupWidth / dataKeys.length;
1358
- const baseY = yScale(Math.max(0, minV));
1359
- return dataKeys.flatMap(
1360
- (k, ki) => data.map((d, i) => {
1361
- const v = toNum(d[k]);
1362
- const y = yScale(v);
1363
- const x = xPos(i) - groupWidth / 2 + ki * barWidth;
1804
+ const { data, series, xCount, xPos, yScale, baseY, innerW } = args;
1805
+ const groupWidth = innerW / xCount * 0.66;
1806
+ const barWidth = groupWidth / series.length;
1807
+ return series.flatMap(
1808
+ (s, si) => data.map((d, i) => {
1809
+ const color = s.color ?? CHART_PALETTE[si % CHART_PALETTE.length];
1810
+ const y = yScale(toNum(d[s.dataKey]));
1811
+ const x = xPos(i) - groupWidth / 2 + si * barWidth;
1364
1812
  const top = Math.min(y, baseY);
1365
- const height = Math.abs(y - baseY);
1366
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1813
+ const h = Math.max(1, Math.abs(y - baseY));
1814
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1367
1815
  "rect",
1368
1816
  {
1369
1817
  x,
1370
1818
  y: top,
1371
1819
  width: Math.max(1, barWidth - 2),
1372
- height: Math.max(1, height),
1373
- rx: 2,
1374
- fill: COLORS[ki % COLORS.length]
1820
+ height: h,
1821
+ rx: 3,
1822
+ fill: color
1375
1823
  },
1376
- `${k}-${i}`
1824
+ `${s.dataKey}-${i}`
1377
1825
  );
1378
1826
  })
1379
1827
  );
1380
1828
  }
1381
- var Polyline = ({ data, dataKey, xPos, yScale, color }) => {
1382
- const points = data.map((d, i) => `${xPos(i)},${yScale(toNum(d[dataKey]))}`).join(" ");
1383
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1384
- "polyline",
1385
- {
1386
- points,
1387
- fill: "none",
1388
- stroke: color,
1389
- strokeWidth: 2,
1390
- strokeLinejoin: "round",
1391
- strokeLinecap: "round"
1392
- }
1393
- );
1394
- };
1395
- var Area = ({ data, dataKey, xPos, yScale, baseY, color }) => {
1396
- if (data.length === 0) return null;
1397
- const top = data.map((d, i) => `${xPos(i)},${yScale(toNum(d[dataKey]))}`).join(" ");
1398
- const path = `M ${xPos(0)},${baseY} L ${top} L ${xPos(data.length - 1)},${baseY} Z`;
1399
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
1400
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: path, fill: color, fillOpacity: 0.18 }),
1401
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Polyline, { data, dataKey, xPos, yScale, color })
1402
- ] });
1403
- };
1404
- var PieChart = ({ data, xKey, dataKey }) => {
1405
- const cx = W / 2;
1406
- const cy = H / 2;
1407
- const r = Math.min(W, H) / 2 - 16;
1408
- const total = data.reduce((sum, d) => sum + toNum(d[dataKey]), 0) || 1;
1409
- let acc = 0;
1410
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1411
- "svg",
1829
+ var ChartTooltip = ({ x, width, title, rows }) => {
1830
+ const flip = x > width - 160;
1831
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
1832
+ "div",
1412
1833
  {
1413
- viewBox: `0 0 ${W} ${H}`,
1414
- className: "aui-artifact-chart-svg w-full",
1415
- role: "img",
1416
- "aria-label": "Pie chart",
1417
- children: data.map((d, i) => {
1418
- const value = toNum(d[dataKey]);
1419
- const start = acc / total * Math.PI * 2;
1420
- acc += value;
1421
- const end = acc / total * Math.PI * 2;
1422
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1423
- PieSlice,
1424
- {
1425
- cx,
1426
- cy,
1427
- r,
1428
- start,
1429
- end,
1430
- color: COLORS[i % COLORS.length],
1431
- label: String(d[xKey] ?? i)
1432
- },
1433
- i
1434
- );
1435
- })
1834
+ className: "pointer-events-none absolute top-2 z-10 min-w-[8rem] rounded-lg border border-border bg-popover/95 px-2.5 py-2 text-popover-foreground shadow-card-elevated backdrop-blur-sm",
1835
+ style: {
1836
+ left: flip ? void 0 : Math.min(x + 12, width - 8),
1837
+ right: flip ? Math.max(width - x + 12, 8) : void 0
1838
+ },
1839
+ children: [
1840
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "mb-1.5 text-[11px] text-muted-foreground", children: title }),
1841
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "flex flex-col gap-1", children: rows.map((r) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center justify-between gap-4", children: [
1842
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "inline-flex items-center gap-1.5 text-xs text-muted-foreground", children: [
1843
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1844
+ "span",
1845
+ {
1846
+ className: "inline-block size-2 rounded-full",
1847
+ style: { background: r.color }
1848
+ }
1849
+ ),
1850
+ r.label
1851
+ ] }),
1852
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "text-xs font-medium tabular-nums text-foreground", children: r.value })
1853
+ ] }, r.label)) })
1854
+ ]
1436
1855
  }
1437
1856
  );
1438
1857
  };
1439
- var PieSlice = ({ cx, cy, r, start, end, color, label }) => {
1440
- const x1 = cx + Math.sin(start) * r;
1441
- const y1 = cy - Math.cos(start) * r;
1442
- const x2 = cx + Math.sin(end) * r;
1443
- const y2 = cy - Math.cos(end) * r;
1444
- const large = end - start > Math.PI ? 1 : 0;
1445
- const path = `M ${cx} ${cy} L ${x1} ${y1} A ${r} ${r} 0 ${large} 1 ${x2} ${y2} Z`;
1446
- const mid = (start + end) / 2;
1447
- const lx = cx + Math.sin(mid) * (r * 0.65);
1448
- const ly = cy - Math.cos(mid) * (r * 0.65);
1449
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("g", { children: [
1450
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: path, fill: color, stroke: "var(--background, #fff)", strokeWidth: 1 }),
1451
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1452
- "text",
1453
- {
1454
- x: lx,
1455
- y: ly,
1456
- textAnchor: "middle",
1457
- dominantBaseline: "middle",
1458
- className: "fill-white text-[10px] font-semibold",
1459
- children: label
1460
- }
1461
- )
1462
- ] });
1463
- };
1464
- var Legend = ({ dataKeys }) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "aui-artifact-chart-legend mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: dataKeys.map((k, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: "inline-flex items-center gap-1.5", children: [
1465
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1858
+ var ChartLegend = ({ series }) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 pl-10 text-xs text-muted-foreground", children: series.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "inline-flex items-center gap-1.5", children: [
1859
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1466
1860
  "span",
1467
1861
  {
1468
1862
  className: "inline-block size-2 rounded-sm",
1469
- style: { background: COLORS[i % COLORS.length] },
1470
- "aria-hidden": true
1863
+ style: { background: s.color ?? CHART_PALETTE[i % CHART_PALETTE.length] }
1471
1864
  }
1472
1865
  ),
1473
- k
1474
- ] }, k)) });
1475
- var EmptyState = () => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "aui-artifact-chart-empty flex h-32 items-center justify-center text-xs text-muted-foreground", children: "No data" });
1866
+ s.label ?? s.dataKey
1867
+ ] }, s.dataKey)) });
1868
+ var ChartEmpty = ({ className, height }) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1869
+ "div",
1870
+ {
1871
+ className: cn(
1872
+ "flex w-full items-center justify-center text-xs text-muted-foreground",
1873
+ className
1874
+ ),
1875
+ style: { height },
1876
+ children: "No data yet"
1877
+ }
1878
+ );
1476
1879
  function inferXKey(data) {
1477
1880
  if (data.length === 0) return "x";
1478
1881
  for (const k of Object.keys(data[0])) {
@@ -1480,73 +1883,190 @@ function inferXKey(data) {
1480
1883
  }
1481
1884
  return Object.keys(data[0])[0] ?? "x";
1482
1885
  }
1483
- function inferDataKeys(data, xKey) {
1484
- if (data.length === 0) return [];
1485
- return Object.keys(data[0]).filter(
1486
- (k) => k !== xKey && typeof data[0][k] === "number"
1487
- );
1488
- }
1489
- function toNum(value) {
1490
- const n = typeof value === "number" ? value : Number(value);
1491
- return Number.isFinite(n) ? n : 0;
1492
- }
1493
- function niceTicks(min, max, count = 4) {
1494
- if (max === min) return [min];
1495
- const range = max - min;
1496
- const step = niceStep(range / count);
1497
- const start = Math.floor(min / step) * step;
1498
- const out = [];
1499
- for (let v = start; v <= max + step / 2; v += step) {
1500
- out.push(round(v));
1886
+ function resolveSeries(seriesProp, data, xKey) {
1887
+ if (seriesProp && seriesProp.length > 0) {
1888
+ return seriesProp.map((s) => typeof s === "string" ? { dataKey: s } : s);
1501
1889
  }
1502
- return out;
1503
- }
1504
- function niceStep(raw) {
1505
- const exp = Math.floor(Math.log10(Math.abs(raw))) || 0;
1506
- const base = Math.pow(10, exp);
1507
- const norm = raw / base;
1508
- let nice = 1;
1509
- if (norm >= 5) nice = 5;
1510
- else if (norm >= 2) nice = 2;
1511
- return nice * base;
1512
- }
1513
- function round(v) {
1514
- return Math.round(v * 1e6) / 1e6;
1890
+ if (data.length === 0) return [];
1891
+ return Object.keys(data[0]).filter((k) => k !== xKey && typeof data[0][k] === "number").map((dataKey) => ({ dataKey }));
1515
1892
  }
1516
- function formatTick(v, unit) {
1517
- const s = Math.abs(v) >= 1e3 ? `${(v / 1e3).toFixed(1)}k` : String(round(v));
1518
- return unit ? `${s}${unit}` : s;
1893
+ function pickXLabels(count, innerW) {
1894
+ if (count <= 1) return [0];
1895
+ const maxLabels = Math.max(2, Math.min(count, Math.floor(innerW / 64) + 1));
1896
+ if (maxLabels >= count) return Array.from({ length: count }, (_, i) => i);
1897
+ const out = /* @__PURE__ */ new Set([0, count - 1]);
1898
+ const step = (count - 1) / (maxLabels - 1);
1899
+ for (let i = 1; i < maxLabels - 1; i++) out.add(Math.round(i * step));
1900
+ return [...out].sort((a, b) => a - b);
1519
1901
  }
1520
1902
 
1521
- // src/artifacts/question-artifact.tsx
1522
- var import_react10 = require("react");
1523
- var import_react11 = require("@assistant-ui/react");
1524
- var import_lucide_react3 = require("lucide-react");
1525
- var import_jsx_runtime16 = require("react/jsx-runtime");
1526
- function optionKey(option, index) {
1527
- const id = option.id?.trim();
1528
- return id ? id : `__option-${index}`;
1529
- }
1530
- var OptionRadio = ({ selected }) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1531
- "span",
1532
- {
1903
+ // src/artifacts/artifact-card.tsx
1904
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1905
+ var ArtifactCard = ({ title, kind, className, bodyClassName, toolbar, children }) => {
1906
+ const hasHeader = Boolean(title || toolbar);
1907
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1908
+ "div",
1909
+ {
1910
+ className: cn(
1911
+ "aui-artifact-root my-3 overflow-hidden rounded-xl border border-border/60 bg-background shadow-sm",
1912
+ className
1913
+ ),
1914
+ "data-artifact-kind": kind,
1915
+ children: [
1916
+ hasHeader && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "aui-artifact-header flex items-center gap-2 border-b border-border/40 bg-muted/30 px-3 py-1.5", children: [
1917
+ title && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "aui-artifact-title flex-1 truncate text-xs font-semibold text-foreground/80", children: title }),
1918
+ !title && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "flex-1" }),
1919
+ toolbar
1920
+ ] }),
1921
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: cn("aui-artifact-body", bodyClassName), children })
1922
+ ]
1923
+ }
1924
+ );
1925
+ };
1926
+
1927
+ // src/artifacts/chart-artifact.tsx
1928
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1929
+ var ChartArtifactView = ({
1930
+ artifact,
1931
+ embedded = false,
1932
+ height = 300
1933
+ }) => {
1934
+ const plot = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ChartArtifactPlot, { artifact, height });
1935
+ if (embedded) {
1936
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "aui-artifact-chart w-full", children: plot });
1937
+ }
1938
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ArtifactCard, { title: artifact.title, kind: "chart", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "aui-artifact-chart pt-2", children: plot }) });
1939
+ };
1940
+ function ChartArtifactPlot({
1941
+ artifact,
1942
+ height
1943
+ }) {
1944
+ const { chartType = "bar", data = [] } = artifact;
1945
+ const xKey = artifact.xKey ?? inferXKey2(data);
1946
+ const series = (0, import_react11.useMemo)(() => {
1947
+ const keys = Array.isArray(artifact.dataKey) ? artifact.dataKey : typeof artifact.dataKey === "string" ? [artifact.dataKey] : inferDataKeys(data, xKey);
1948
+ return keys.map((dataKey) => ({ dataKey }));
1949
+ }, [artifact.dataKey, data, xKey]);
1950
+ if (chartType === "pie") {
1951
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "px-3 pb-3 pt-2", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(PieChart, { data, xKey, dataKey: series[0]?.dataKey ?? "value" }) });
1952
+ }
1953
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1954
+ LineAreaChart,
1955
+ {
1956
+ data,
1957
+ xKey,
1958
+ series,
1959
+ layout: "flush",
1960
+ height,
1961
+ variant: chartType === "line" ? "line" : chartType === "area" ? "area" : "bar",
1962
+ unit: artifact.unit,
1963
+ ariaLabel: typeof artifact.title === "string" ? artifact.title : "Chart"
1964
+ }
1965
+ );
1966
+ }
1967
+ var PIE_W = 320;
1968
+ var PIE_H = 220;
1969
+ var PieChart = ({ data, xKey, dataKey }) => {
1970
+ if (data.length === 0) {
1971
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "flex h-32 items-center justify-center text-xs text-muted-foreground", children: "No data" });
1972
+ }
1973
+ const cx = PIE_W / 2;
1974
+ const cy = PIE_H / 2;
1975
+ const r = Math.min(PIE_W, PIE_H) / 2 - 16;
1976
+ const total = data.reduce((sum, d) => sum + toNum(d[dataKey]), 0) || 1;
1977
+ let acc = 0;
1978
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col items-center gap-3", children: [
1979
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1980
+ "svg",
1981
+ {
1982
+ viewBox: `0 0 ${PIE_W} ${PIE_H}`,
1983
+ className: "w-full max-w-[20rem]",
1984
+ role: "img",
1985
+ "aria-label": "Pie chart",
1986
+ children: data.map((d, i) => {
1987
+ const value = toNum(d[dataKey]);
1988
+ const start = acc / total * Math.PI * 2;
1989
+ acc += value;
1990
+ const end = acc / total * Math.PI * 2;
1991
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
1992
+ PieSlice,
1993
+ {
1994
+ cx,
1995
+ cy,
1996
+ r,
1997
+ start,
1998
+ end,
1999
+ color: CHART_PALETTE[i % CHART_PALETTE.length]
2000
+ },
2001
+ i
2002
+ );
2003
+ })
2004
+ }
2005
+ ),
2006
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "flex flex-wrap items-center justify-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: data.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { className: "inline-flex items-center gap-1.5", children: [
2007
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2008
+ "span",
2009
+ {
2010
+ className: "inline-block size-2 rounded-sm",
2011
+ style: { background: CHART_PALETTE[i % CHART_PALETTE.length] }
2012
+ }
2013
+ ),
2014
+ String(d[xKey] ?? i)
2015
+ ] }, i)) })
2016
+ ] });
2017
+ };
2018
+ var PieSlice = ({ cx, cy, r, start, end, color }) => {
2019
+ const x1 = cx + Math.sin(start) * r;
2020
+ const y1 = cy - Math.cos(start) * r;
2021
+ const x2 = cx + Math.sin(end) * r;
2022
+ const y2 = cy - Math.cos(end) * r;
2023
+ const large = end - start > Math.PI ? 1 : 0;
2024
+ const path = `M ${cx} ${cy} L ${x1} ${y1} A ${r} ${r} 0 ${large} 1 ${x2} ${y2} Z`;
2025
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("path", { d: path, fill: color, stroke: "var(--background, #fff)", strokeWidth: 1.5 });
2026
+ };
2027
+ function inferXKey2(data) {
2028
+ if (data.length === 0) return "x";
2029
+ for (const k of Object.keys(data[0])) {
2030
+ if (typeof data[0][k] !== "number") return k;
2031
+ }
2032
+ return Object.keys(data[0])[0] ?? "x";
2033
+ }
2034
+ function inferDataKeys(data, xKey) {
2035
+ if (data.length === 0) return [];
2036
+ return Object.keys(data[0]).filter(
2037
+ (k) => k !== xKey && typeof data[0][k] === "number"
2038
+ );
2039
+ }
2040
+
2041
+ // src/artifacts/question-artifact.tsx
2042
+ var import_react12 = require("react");
2043
+ var import_react13 = require("@assistant-ui/react");
2044
+ var import_lucide_react3 = require("lucide-react");
2045
+ var import_jsx_runtime17 = require("react/jsx-runtime");
2046
+ function optionKey(option, index) {
2047
+ const id = option.id?.trim();
2048
+ return id ? id : `__option-${index}`;
2049
+ }
2050
+ var OptionRadio = ({ selected }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2051
+ "span",
2052
+ {
1533
2053
  className: cn(
1534
2054
  "flex size-4 shrink-0 items-center justify-center rounded-full border-2 transition-colors",
1535
2055
  selected ? "border-foreground bg-foreground text-background" : "border-border bg-background"
1536
2056
  ),
1537
2057
  "aria-hidden": true,
1538
- children: selected ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react3.CheckIcon, { className: "size-2.5 stroke-[3]" }) : null
2058
+ children: selected ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react3.CheckIcon, { className: "size-2.5 stroke-[3]" }) : null
1539
2059
  }
1540
2060
  );
1541
2061
  var QuestionArtifactView = ({
1542
2062
  artifact
1543
2063
  }) => {
1544
- const runtime = (0, import_react11.useThreadRuntime)();
1545
- const [selected, setSelected] = (0, import_react10.useState)([]);
1546
- const [submittedIds, setSubmittedIds] = (0, import_react10.useState)(null);
2064
+ const runtime = (0, import_react13.useThreadRuntime)();
2065
+ const [selected, setSelected] = (0, import_react12.useState)([]);
2066
+ const [submittedIds, setSubmittedIds] = (0, import_react12.useState)(null);
1547
2067
  const isMulti = artifact.multi === true;
1548
2068
  const isDisabled = submittedIds !== null;
1549
- const send = (0, import_react10.useCallback)(
2069
+ const send = (0, import_react12.useCallback)(
1550
2070
  (keys) => {
1551
2071
  if (keys.length === 0) return;
1552
2072
  const labels = artifact.options.map((option, index) => ({ option, key: optionKey(option, index) })).filter(({ key }) => keys.includes(key)).map(({ option }) => option.label);
@@ -1558,7 +2078,7 @@ var QuestionArtifactView = ({
1558
2078
  },
1559
2079
  [artifact.options, runtime]
1560
2080
  );
1561
- const onPick = (0, import_react10.useCallback)(
2081
+ const onPick = (0, import_react12.useCallback)(
1562
2082
  (key) => {
1563
2083
  if (isDisabled) return;
1564
2084
  if (!isMulti) {
@@ -1571,15 +2091,15 @@ var QuestionArtifactView = ({
1571
2091
  },
1572
2092
  [isDisabled, isMulti, send]
1573
2093
  );
1574
- const onConfirm = (0, import_react10.useCallback)(() => {
2094
+ const onConfirm = (0, import_react12.useCallback)(() => {
1575
2095
  send(selected);
1576
2096
  }, [selected, send]);
1577
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: studioArtifactShellClass, "data-artifact-kind": "question", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "px-2.5 py-2", children: [
1578
- artifact.prompt ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "mb-2 text-sm font-normal leading-snug text-foreground", children: artifact.prompt }) : null,
1579
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "flex flex-col gap-0.5", role: "list", children: artifact.options.map((option, index) => {
2097
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: studioArtifactShellClass, "data-artifact-kind": "question", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "px-2.5 py-2", children: [
2098
+ artifact.prompt ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "mb-2 text-sm font-normal leading-snug text-foreground", children: artifact.prompt }) : null,
2099
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex flex-col gap-0.5", role: "list", children: artifact.options.map((option, index) => {
1580
2100
  const key = optionKey(option, index);
1581
2101
  const isSelected = submittedIds ? submittedIds.includes(key) : isMulti && selected.includes(key);
1582
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
2102
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
1583
2103
  "button",
1584
2104
  {
1585
2105
  type: "button",
@@ -1591,17 +2111,17 @@ var QuestionArtifactView = ({
1591
2111
  isDisabled && (isSelected ? "cursor-default" : "cursor-not-allowed opacity-50")
1592
2112
  ),
1593
2113
  children: [
1594
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(OptionRadio, { selected: isSelected }),
1595
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { className: "min-w-0 flex-1 text-left", children: [
1596
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "block font-normal text-foreground", children: option.label }),
1597
- option.description ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "mt-0.5 block text-xs text-muted-foreground", children: option.description }) : null
2114
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(OptionRadio, { selected: isSelected }),
2115
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "min-w-0 flex-1 text-left", children: [
2116
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "block font-normal text-foreground", children: option.label }),
2117
+ option.description ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "mt-0.5 block text-xs text-muted-foreground", children: option.description }) : null
1598
2118
  ] })
1599
2119
  ]
1600
2120
  },
1601
2121
  key
1602
2122
  );
1603
2123
  }) }),
1604
- isMulti && !submittedIds ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "mt-2 flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2124
+ isMulti && !submittedIds ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "mt-2 flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1605
2125
  TimbalV2Button,
1606
2126
  {
1607
2127
  type: "button",
@@ -1616,12 +2136,12 @@ var QuestionArtifactView = ({
1616
2136
  };
1617
2137
 
1618
2138
  // src/artifacts/html-artifact.tsx
1619
- var import_jsx_runtime17 = require("react/jsx-runtime");
2139
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1620
2140
  var HtmlArtifactView = ({ artifact }) => {
1621
2141
  const sandboxed = artifact.sandboxed !== false;
1622
2142
  const sandbox = sandboxed ? "allow-scripts allow-same-origin allow-forms allow-modals allow-popups allow-pointer-lock" : void 0;
1623
2143
  const height = artifact.height ?? "320px";
1624
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ArtifactCard, { title: artifact.title, kind: "html", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2144
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ArtifactCard, { title: artifact.title, kind: "html", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1625
2145
  "iframe",
1626
2146
  {
1627
2147
  title: artifact.title ?? "HTML artifact",
@@ -1634,7 +2154,7 @@ var HtmlArtifactView = ({ artifact }) => {
1634
2154
  };
1635
2155
 
1636
2156
  // src/artifacts/json-artifact.tsx
1637
- var import_jsx_runtime18 = require("react/jsx-runtime");
2157
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1638
2158
  var JsonArtifactView = ({
1639
2159
  artifact
1640
2160
  }) => {
@@ -1646,16 +2166,16 @@ var JsonArtifactView = ({
1646
2166
  } catch {
1647
2167
  body = String(data);
1648
2168
  }
1649
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ArtifactCard, { title, kind: "json", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("pre", { className: "aui-artifact-json m-0 max-h-[420px] overflow-auto p-3 font-mono text-[12px] leading-relaxed text-foreground/85", children: body }) });
2169
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ArtifactCard, { title, kind: "json", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("pre", { className: "aui-artifact-json m-0 max-h-[420px] overflow-auto p-3 font-mono text-[12px] leading-relaxed text-foreground/85", children: body }) });
1650
2170
  };
1651
2171
 
1652
2172
  // src/artifacts/table-artifact.tsx
1653
- var import_jsx_runtime19 = require("react/jsx-runtime");
2173
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1654
2174
  var TableArtifactView = ({ artifact }) => {
1655
2175
  const rows = artifact.rows ?? [];
1656
2176
  const columns = artifact.columns ?? deriveColumns(rows);
1657
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ArtifactCard, { title: artifact.title, kind: "table", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "aui-artifact-table-wrap overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("table", { className: "aui-artifact-table w-full border-collapse text-sm", children: [
1658
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("tr", { className: "border-b border-border/40 bg-muted/20", children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2177
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ArtifactCard, { title: artifact.title, kind: "table", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "aui-artifact-table-wrap overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("table", { className: "aui-artifact-table w-full border-collapse text-sm", children: [
2178
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("tr", { className: "border-b border-border/40 bg-muted/20", children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1659
2179
  "th",
1660
2180
  {
1661
2181
  className: "px-3 py-2 text-left text-xs font-semibold uppercase tracking-wider text-muted-foreground",
@@ -1663,11 +2183,11 @@ var TableArtifactView = ({ artifact }) => {
1663
2183
  },
1664
2184
  col.key
1665
2185
  )) }) }),
1666
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("tbody", { children: rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2186
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("tbody", { children: rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1667
2187
  "tr",
1668
2188
  {
1669
2189
  className: "border-b border-border/30 transition-colors last:border-b-0 hover:bg-muted/20",
1670
- children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2190
+ children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1671
2191
  "td",
1672
2192
  {
1673
2193
  className: "px-3 py-2 align-top text-foreground/85",
@@ -1700,7 +2220,7 @@ function formatCell(value) {
1700
2220
  }
1701
2221
 
1702
2222
  // src/artifacts/ui/ui-artifact.tsx
1703
- var import_react16 = require("react");
2223
+ var import_react18 = require("react");
1704
2224
 
1705
2225
  // src/artifacts/ui/types.ts
1706
2226
  function isUiBinding(value) {
@@ -1753,38 +2273,38 @@ function resolveBindable(value, state) {
1753
2273
  }
1754
2274
 
1755
2275
  // src/artifacts/ui/registry.tsx
1756
- var import_react12 = require("react");
1757
- var import_jsx_runtime20 = require("react/jsx-runtime");
1758
- var UiStateContext = (0, import_react12.createContext)({});
1759
- var UiDispatchContext = (0, import_react12.createContext)(() => {
2276
+ var import_react14 = require("react");
2277
+ var import_jsx_runtime21 = require("react/jsx-runtime");
2278
+ var UiStateContext = (0, import_react14.createContext)({});
2279
+ var UiDispatchContext = (0, import_react14.createContext)(() => {
1760
2280
  });
1761
- var UiStateProvider = ({ state, dispatch, children }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(UiStateContext.Provider, { value: state, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(UiDispatchContext.Provider, { value: dispatch, children }) });
2281
+ var UiStateProvider = ({ state, dispatch, children }) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(UiStateContext.Provider, { value: state, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(UiDispatchContext.Provider, { value: dispatch, children }) });
1762
2282
  function useUiState() {
1763
- return (0, import_react12.useContext)(UiStateContext);
2283
+ return (0, import_react14.useContext)(UiStateContext);
1764
2284
  }
1765
2285
  function useUiDispatch() {
1766
- return (0, import_react12.useContext)(UiDispatchContext);
2286
+ return (0, import_react14.useContext)(UiDispatchContext);
1767
2287
  }
1768
- var UiEventContext = (0, import_react12.createContext)(
2288
+ var UiEventContext = (0, import_react14.createContext)(
1769
2289
  null
1770
2290
  );
1771
- var UiEventProvider = ({ onEvent, children }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(UiEventContext.Provider, { value: onEvent, children });
2291
+ var UiEventProvider = ({ onEvent, children }) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(UiEventContext.Provider, { value: onEvent, children });
1772
2292
  function useUiEventEmitter() {
1773
- return (0, import_react12.useContext)(UiEventContext);
2293
+ return (0, import_react14.useContext)(UiEventContext);
1774
2294
  }
1775
- var UiCustomNodeRegistryContext = (0, import_react12.createContext)({});
2295
+ var UiCustomNodeRegistryContext = (0, import_react14.createContext)({});
1776
2296
  function useUiCustomNodeRegistry() {
1777
- return (0, import_react12.useContext)(UiCustomNodeRegistryContext);
2297
+ return (0, import_react14.useContext)(UiCustomNodeRegistryContext);
1778
2298
  }
1779
2299
 
1780
2300
  // src/artifacts/ui/nodes.tsx
1781
- var import_react13 = require("react");
1782
- var import_react14 = require("motion/react");
1783
- var import_react15 = require("@assistant-ui/react");
2301
+ var import_react15 = require("react");
2302
+ var import_react16 = require("motion/react");
2303
+ var import_react17 = require("@assistant-ui/react");
1784
2304
 
1785
2305
  // src/ui/button.tsx
1786
2306
  var import_class_variance_authority = require("class-variance-authority");
1787
- var import_jsx_runtime21 = require("react/jsx-runtime");
2307
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1788
2308
  var LEGACY_SIZE_TO_V2 = {
1789
2309
  default: "md",
1790
2310
  xs: "xs",
@@ -1834,7 +2354,7 @@ function Button({
1834
2354
  const v2Variant = TIMBAL_V2_FROM_LEGACY_BUTTON[variant ?? "default"];
1835
2355
  const v2Size = LEGACY_SIZE_TO_V2[size ?? "default"];
1836
2356
  const isIconOnly = typeof size === "string" && size.startsWith("icon");
1837
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2357
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1838
2358
  TimbalV2Button,
1839
2359
  {
1840
2360
  "data-slot": "button",
@@ -1842,7 +2362,7 @@ function Button({
1842
2362
  "data-size": size,
1843
2363
  variant: v2Variant,
1844
2364
  size: v2Size,
1845
- shape: "rect",
2365
+ shape: "pill",
1846
2366
  isIconOnly,
1847
2367
  asChild,
1848
2368
  className: cn(buttonVariants({ variant, size, className })),
@@ -1852,29 +2372,29 @@ function Button({
1852
2372
  }
1853
2373
 
1854
2374
  // src/artifacts/ui/nodes.tsx
1855
- var import_jsx_runtime22 = require("react/jsx-runtime");
2375
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1856
2376
  var UiNodeView = ({ node }) => {
1857
2377
  switch (node.kind) {
1858
2378
  case "box":
1859
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(BoxNode, { node });
2379
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(BoxNode, { node });
1860
2380
  case "text":
1861
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TextNode, { node });
2381
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TextNode, { node });
1862
2382
  case "heading":
1863
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(HeadingNode, { node });
2383
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(HeadingNode, { node });
1864
2384
  case "badge":
1865
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(BadgeNode, { node });
2385
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(BadgeNode, { node });
1866
2386
  case "button":
1867
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ButtonNode, { node });
2387
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ButtonNode, { node });
1868
2388
  case "toggle":
1869
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToggleNode, { node });
2389
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ToggleNode, { node });
1870
2390
  case "slider":
1871
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SliderNode, { node });
2391
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SliderNode, { node });
1872
2392
  case "tooltip":
1873
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipNode, { node });
2393
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TooltipNode, { node });
1874
2394
  case "draggable":
1875
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DraggableNode, { node });
2395
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(DraggableNode, { node });
1876
2396
  case "custom":
1877
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CustomNode, { node });
2397
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CustomNode, { node });
1878
2398
  default:
1879
2399
  return null;
1880
2400
  }
@@ -1882,9 +2402,9 @@ var UiNodeView = ({ node }) => {
1882
2402
  function useActionRunner() {
1883
2403
  const state = useUiState();
1884
2404
  const dispatch = useUiDispatch();
1885
- const runtime = (0, import_react15.useThreadRuntime)();
2405
+ const runtime = (0, import_react17.useThreadRuntime)();
1886
2406
  const emit = useUiEventEmitter();
1887
- return (0, import_react13.useCallback)(
2407
+ return (0, import_react15.useCallback)(
1888
2408
  (actions) => {
1889
2409
  if (!actions) return;
1890
2410
  const list = Array.isArray(actions) ? actions : [actions];
@@ -1934,7 +2454,7 @@ var JUSTIFY_CLS = {
1934
2454
  };
1935
2455
  var BoxNode = ({ node }) => {
1936
2456
  const dir = node.direction ?? "col";
1937
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2457
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1938
2458
  "div",
1939
2459
  {
1940
2460
  className: cn(
@@ -1949,7 +2469,7 @@ var BoxNode = ({ node }) => {
1949
2469
  gap: node.gap !== void 0 ? `${node.gap * 0.25}rem` : void 0,
1950
2470
  padding: node.padding !== void 0 ? `${node.padding * 0.25}rem` : void 0
1951
2471
  },
1952
- children: node.children?.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(UiNodeView, { node: child }, child.id ?? i))
2472
+ children: node.children?.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(UiNodeView, { node: child }, child.id ?? i))
1953
2473
  }
1954
2474
  );
1955
2475
  };
@@ -1968,7 +2488,7 @@ var TEXT_WEIGHT = {
1968
2488
  var TextNode = ({ node }) => {
1969
2489
  const state = useUiState();
1970
2490
  const value = resolveBindable(node.value, state);
1971
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2491
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1972
2492
  "span",
1973
2493
  {
1974
2494
  className: cn(
@@ -1999,13 +2519,13 @@ var HeadingNode = ({ node }) => {
1999
2519
  );
2000
2520
  switch (level) {
2001
2521
  case 1:
2002
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h1", { className: cls, children: value });
2522
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h1", { className: cls, children: value });
2003
2523
  case 2:
2004
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h2", { className: cls, children: value });
2524
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { className: cls, children: value });
2005
2525
  case 3:
2006
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h3", { className: cls, children: value });
2526
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h3", { className: cls, children: value });
2007
2527
  case 4:
2008
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("h4", { className: cls, children: value });
2528
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h4", { className: cls, children: value });
2009
2529
  }
2010
2530
  };
2011
2531
  var BADGE_TONE = {
@@ -2018,7 +2538,7 @@ var BADGE_TONE = {
2018
2538
  var BadgeNode = ({ node }) => {
2019
2539
  const state = useUiState();
2020
2540
  const value = String(resolveBindable(node.value, state) ?? "");
2021
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2541
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2022
2542
  "span",
2023
2543
  {
2024
2544
  className: cn(
@@ -2035,7 +2555,7 @@ var ButtonNode = ({ node }) => {
2035
2555
  const run = useActionRunner();
2036
2556
  const label = String(resolveBindable(node.label, state) ?? "");
2037
2557
  const disabled = node.disabled !== void 0 ? Boolean(resolveBindable(node.disabled, state)) : false;
2038
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2558
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2039
2559
  Button,
2040
2560
  {
2041
2561
  variant: node.variant ?? "default",
@@ -2057,7 +2577,7 @@ var ToggleNode = ({ node }) => {
2057
2577
  dispatch({ type: "toggle", path: node.binding });
2058
2578
  run(node.onChange);
2059
2579
  };
2060
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
2580
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
2061
2581
  "label",
2062
2582
  {
2063
2583
  className: cn(
@@ -2065,7 +2585,7 @@ var ToggleNode = ({ node }) => {
2065
2585
  node.className
2066
2586
  ),
2067
2587
  children: [
2068
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2588
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2069
2589
  "button",
2070
2590
  {
2071
2591
  type: "button",
@@ -2076,7 +2596,7 @@ var ToggleNode = ({ node }) => {
2076
2596
  "relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-[background,box-shadow,border-color] duration-200",
2077
2597
  value ? "border-foreground/15 bg-gradient-to-b from-primary-fill-from to-primary-fill-to shadow-card" : cn(TIMBAL_V2_SWITCH_TRACK_OFF, "hover:from-secondary-fill-hover-from hover:to-secondary-fill-hover-to")
2078
2598
  ),
2079
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2599
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2080
2600
  "span",
2081
2601
  {
2082
2602
  className: cn(
@@ -2089,7 +2609,7 @@ var ToggleNode = ({ node }) => {
2089
2609
  )
2090
2610
  }
2091
2611
  ),
2092
- label && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-foreground/85", children: label })
2612
+ label && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-foreground/85", children: label })
2093
2613
  ]
2094
2614
  }
2095
2615
  );
@@ -2109,12 +2629,12 @@ var SliderNode = ({ node }) => {
2109
2629
  const next = Number(e.target.value);
2110
2630
  dispatch({ type: "set", path: node.binding, value: next });
2111
2631
  };
2112
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: cn("aui-ui-slider flex flex-col gap-1", node.className), children: [
2113
- (label || showValue) && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: [
2114
- label && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: label }),
2115
- showValue && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "font-mono", children: value })
2632
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: cn("aui-ui-slider flex flex-col gap-1", node.className), children: [
2633
+ (label || showValue) && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: [
2634
+ label && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: label }),
2635
+ showValue && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "font-mono", children: value })
2116
2636
  ] }),
2117
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2637
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2118
2638
  "input",
2119
2639
  {
2120
2640
  type: "range",
@@ -2136,9 +2656,9 @@ var SliderNode = ({ node }) => {
2136
2656
  var TooltipNode = ({ node }) => {
2137
2657
  const state = useUiState();
2138
2658
  const content = String(resolveBindable(node.content, state) ?? "");
2139
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
2140
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: cn("aui-ui-tooltip-trigger inline-flex", node.className), children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(UiNodeView, { node: node.child }) }) }),
2141
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { side: node.side ?? "top", children: content })
2659
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Tooltip, { children: [
2660
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: cn("aui-ui-tooltip-trigger inline-flex", node.className), children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(UiNodeView, { node: node.child }) }) }),
2661
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TooltipContent, { side: node.side ?? "top", children: content })
2142
2662
  ] }) });
2143
2663
  };
2144
2664
  var DraggableNode = ({ node }) => {
@@ -2146,8 +2666,8 @@ var DraggableNode = ({ node }) => {
2146
2666
  const snapBack = node.snapBack ?? true;
2147
2667
  const axis = node.axis ?? "both";
2148
2668
  const dragProp = axis === "both" ? true : axis;
2149
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2150
- import_react14.motion.div,
2669
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2670
+ import_react16.motion.div,
2151
2671
  {
2152
2672
  drag: dragProp,
2153
2673
  dragMomentum: false,
@@ -2158,7 +2678,7 @@ var DraggableNode = ({ node }) => {
2158
2678
  "aui-ui-draggable inline-block cursor-grab touch-none",
2159
2679
  node.className
2160
2680
  ),
2161
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(UiNodeView, { node: node.child })
2681
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(UiNodeView, { node: node.child })
2162
2682
  }
2163
2683
  );
2164
2684
  };
@@ -2168,8 +2688,8 @@ var CustomNode = ({ node }) => {
2168
2688
  const Renderer = registry[node.name];
2169
2689
  if (!Renderer) return null;
2170
2690
  const resolvedProps = resolveProps(node.props ?? {}, state);
2171
- const children = node.children?.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(UiNodeView, { node: child }, child.id ?? i));
2172
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Renderer, { props: resolvedProps, children });
2691
+ const children = node.children?.map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(UiNodeView, { node: child }, child.id ?? i));
2692
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Renderer, { props: resolvedProps, children });
2173
2693
  };
2174
2694
  function resolveProps(props, state) {
2175
2695
  const out = {};
@@ -2180,17 +2700,17 @@ function resolveProps(props, state) {
2180
2700
  }
2181
2701
 
2182
2702
  // src/artifacts/ui/ui-artifact.tsx
2183
- var import_jsx_runtime23 = require("react/jsx-runtime");
2703
+ var import_jsx_runtime24 = require("react/jsx-runtime");
2184
2704
  var UiArtifactView = ({ artifact }) => {
2185
- const [state, dispatch] = (0, import_react16.useReducer)(
2705
+ const [state, dispatch] = (0, import_react18.useReducer)(
2186
2706
  uiStateReducer,
2187
2707
  artifact.initialState ?? {}
2188
2708
  );
2189
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ArtifactCard, { title: artifact.title, kind: "ui", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(UiStateProvider, { state, dispatch, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "aui-ui-root p-3", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(UiNodeView, { node: artifact.root }) }) }) });
2709
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ArtifactCard, { title: artifact.title, kind: "ui", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(UiStateProvider, { state, dispatch, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "aui-ui-root p-3", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(UiNodeView, { node: artifact.root }) }) }) });
2190
2710
  };
2191
2711
 
2192
2712
  // src/artifacts/registry.tsx
2193
- var import_jsx_runtime24 = require("react/jsx-runtime");
2713
+ var import_jsx_runtime25 = require("react/jsx-runtime");
2194
2714
  var defaultArtifactRenderers = {
2195
2715
  chart: ChartArtifactView,
2196
2716
  question: QuestionArtifactView,
@@ -2199,25 +2719,25 @@ var defaultArtifactRenderers = {
2199
2719
  table: TableArtifactView,
2200
2720
  ui: UiArtifactView
2201
2721
  };
2202
- var ArtifactRegistryContext = (0, import_react17.createContext)(
2722
+ var ArtifactRegistryContext = (0, import_react19.createContext)(
2203
2723
  defaultArtifactRenderers
2204
2724
  );
2205
2725
  var ArtifactRegistryProvider = ({ renderers, override, children }) => {
2206
- const merged = (0, import_react17.useMemo)(() => {
2726
+ const merged = (0, import_react19.useMemo)(() => {
2207
2727
  if (!renderers) return defaultArtifactRenderers;
2208
2728
  if (override) return renderers;
2209
2729
  return { ...defaultArtifactRenderers, ...renderers };
2210
2730
  }, [renderers, override]);
2211
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ArtifactRegistryContext.Provider, { value: merged, children });
2731
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ArtifactRegistryContext.Provider, { value: merged, children });
2212
2732
  };
2213
2733
  function useArtifactRegistry() {
2214
- return (0, import_react17.useContext)(ArtifactRegistryContext);
2734
+ return (0, import_react19.useContext)(ArtifactRegistryContext);
2215
2735
  }
2216
2736
  var ArtifactView = ({ artifact }) => {
2217
2737
  const registry = useArtifactRegistry();
2218
2738
  const Renderer = registry[artifact.type] ?? registry.json;
2219
2739
  if (!Renderer) return null;
2220
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Renderer, { artifact });
2740
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Renderer, { artifact });
2221
2741
  };
2222
2742
 
2223
2743
  // src/artifacts/types.ts
@@ -2298,7 +2818,7 @@ var import_c = __toESM(require("shiki/langs/c.mjs"), 1);
2298
2818
  var import_cpp = __toESM(require("shiki/langs/cpp.mjs"), 1);
2299
2819
  var import_vitesse_dark = __toESM(require("shiki/themes/vitesse-dark.mjs"), 1);
2300
2820
  var import_vitesse_light = __toESM(require("shiki/themes/vitesse-light.mjs"), 1);
2301
- var import_jsx_runtime25 = require("react/jsx-runtime");
2821
+ var import_jsx_runtime26 = require("react/jsx-runtime");
2302
2822
  var SHIKI_THEME_DARK = "vitesse-dark";
2303
2823
  var SHIKI_THEME_LIGHT = "vitesse-light";
2304
2824
  var highlighterPromise = null;
@@ -2336,8 +2856,8 @@ var ShikiSyntaxHighlighter = ({
2336
2856
  language,
2337
2857
  code
2338
2858
  }) => {
2339
- const [html, setHtml] = (0, import_react18.useState)(null);
2340
- (0, import_react18.useEffect)(() => {
2859
+ const [html, setHtml] = (0, import_react20.useState)(null);
2860
+ (0, import_react20.useEffect)(() => {
2341
2861
  let cancelled = false;
2342
2862
  (async () => {
2343
2863
  try {
@@ -2367,13 +2887,13 @@ var ShikiSyntaxHighlighter = ({
2367
2887
  try {
2368
2888
  const parsed = JSON.parse(code);
2369
2889
  if (isArtifact(parsed)) {
2370
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ArtifactView, { artifact: parsed });
2890
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ArtifactView, { artifact: parsed });
2371
2891
  }
2372
2892
  } catch {
2373
2893
  }
2374
2894
  }
2375
2895
  if (html) {
2376
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2896
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2377
2897
  "div",
2378
2898
  {
2379
2899
  className: "shiki-wrapper [&>pre]:!m-0 [&>pre]:!rounded-t-none [&>pre]:!rounded-b-lg [&>pre]:!border [&>pre]:!border-t-0 [&>pre]:!border-border/50 [&>pre]:!p-3 [&>pre]:!text-xs [&>pre]:!leading-relaxed [&>pre]:overflow-x-auto",
@@ -2381,14 +2901,14 @@ var ShikiSyntaxHighlighter = ({
2381
2901
  }
2382
2902
  );
2383
2903
  }
2384
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Pre, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Code2, { children: code }) });
2904
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Pre, { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Code2, { children: code }) });
2385
2905
  };
2386
2906
  var syntax_highlighter_default = ShikiSyntaxHighlighter;
2387
2907
 
2388
2908
  // src/chat/markdown-text.tsx
2389
- var import_jsx_runtime26 = require("react/jsx-runtime");
2909
+ var import_jsx_runtime27 = require("react/jsx-runtime");
2390
2910
  var MarkdownTextImpl = () => {
2391
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2911
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2392
2912
  import_react_markdown.MarkdownTextPrimitive,
2393
2913
  {
2394
2914
  remarkPlugins: [import_remark_gfm.default, import_remark_math.default],
@@ -2401,7 +2921,7 @@ var MarkdownTextImpl = () => {
2401
2921
  }
2402
2922
  );
2403
2923
  };
2404
- var MarkdownText = (0, import_react19.memo)(MarkdownTextImpl);
2924
+ var MarkdownText = (0, import_react21.memo)(MarkdownTextImpl);
2405
2925
  var CodeHeader = ({ language, code }) => {
2406
2926
  const { isCopied, copyToClipboard } = useCopyToClipboard();
2407
2927
  if (isArtifactFenceLanguage(language)) return null;
@@ -2409,20 +2929,20 @@ var CodeHeader = ({ language, code }) => {
2409
2929
  if (!code || isCopied) return;
2410
2930
  copyToClipboard(code);
2411
2931
  };
2412
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "aui-code-header flex items-center justify-between rounded-t-lg border border-b-0 border-border/50 bg-code-header-bg px-4 py-2", children: [
2413
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "flex items-center gap-2 text-xs font-semibold tracking-wide text-muted-foreground/80 uppercase", children: [
2414
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "inline-block h-2 w-2 rounded-full bg-primary/40" }),
2932
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "aui-code-header flex items-center justify-between rounded-t-lg border border-b-0 border-border/50 bg-code-header-bg px-4 py-2", children: [
2933
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "flex items-center gap-2 text-xs font-semibold tracking-wide text-muted-foreground/80 uppercase", children: [
2934
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "inline-block h-2 w-2 rounded-full bg-primary/40" }),
2415
2935
  language
2416
2936
  ] }),
2417
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
2937
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
2418
2938
  TooltipIconButton,
2419
2939
  {
2420
2940
  tooltip: isCopied ? "Copied!" : "Copy",
2421
2941
  onClick: onCopy,
2422
2942
  className: "transition-colors hover:text-foreground",
2423
2943
  children: [
2424
- !isCopied && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react4.CopyIcon, { className: "h-3.5 w-3.5" }),
2425
- isCopied && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react4.CheckIcon, { className: "h-3.5 w-3.5 text-emerald-500" })
2944
+ !isCopied && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react4.CopyIcon, { className: "h-3.5 w-3.5" }),
2945
+ isCopied && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react4.CheckIcon, { className: "h-3.5 w-3.5 text-emerald-500" })
2426
2946
  ]
2427
2947
  }
2428
2948
  )
@@ -2431,7 +2951,7 @@ var CodeHeader = ({ language, code }) => {
2431
2951
  var useCopyToClipboard = ({
2432
2952
  copiedDuration = 3e3
2433
2953
  } = {}) => {
2434
- const [isCopied, setIsCopied] = (0, import_react19.useState)(false);
2954
+ const [isCopied, setIsCopied] = (0, import_react21.useState)(false);
2435
2955
  const copyToClipboard = (value) => {
2436
2956
  if (!value) return;
2437
2957
  navigator.clipboard.writeText(value).then(() => {
@@ -2442,7 +2962,7 @@ var useCopyToClipboard = ({
2442
2962
  return { isCopied, copyToClipboard };
2443
2963
  };
2444
2964
  var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownComponents)({
2445
- h1: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2965
+ h1: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2446
2966
  "h1",
2447
2967
  {
2448
2968
  className: cn(
@@ -2452,7 +2972,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2452
2972
  ...props
2453
2973
  }
2454
2974
  ),
2455
- h2: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2975
+ h2: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2456
2976
  "h2",
2457
2977
  {
2458
2978
  className: cn(
@@ -2462,7 +2982,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2462
2982
  ...props
2463
2983
  }
2464
2984
  ),
2465
- h3: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2985
+ h3: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2466
2986
  "h3",
2467
2987
  {
2468
2988
  className: cn(
@@ -2472,7 +2992,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2472
2992
  ...props
2473
2993
  }
2474
2994
  ),
2475
- h4: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2995
+ h4: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2476
2996
  "h4",
2477
2997
  {
2478
2998
  className: cn(
@@ -2482,7 +3002,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2482
3002
  ...props
2483
3003
  }
2484
3004
  ),
2485
- h5: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3005
+ h5: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2486
3006
  "h5",
2487
3007
  {
2488
3008
  className: cn(
@@ -2492,7 +3012,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2492
3012
  ...props
2493
3013
  }
2494
3014
  ),
2495
- h6: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3015
+ h6: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2496
3016
  "h6",
2497
3017
  {
2498
3018
  className: cn(
@@ -2502,7 +3022,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2502
3022
  ...props
2503
3023
  }
2504
3024
  ),
2505
- p: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3025
+ p: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2506
3026
  "p",
2507
3027
  {
2508
3028
  className: cn(
@@ -2512,7 +3032,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2512
3032
  ...props
2513
3033
  }
2514
3034
  ),
2515
- a: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3035
+ a: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2516
3036
  "a",
2517
3037
  {
2518
3038
  className: cn(
@@ -2524,7 +3044,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2524
3044
  ...props
2525
3045
  }
2526
3046
  ),
2527
- blockquote: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3047
+ blockquote: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2528
3048
  "blockquote",
2529
3049
  {
2530
3050
  className: cn(
@@ -2534,7 +3054,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2534
3054
  ...props
2535
3055
  }
2536
3056
  ),
2537
- ul: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3057
+ ul: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2538
3058
  "ul",
2539
3059
  {
2540
3060
  className: cn(
@@ -2544,7 +3064,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2544
3064
  ...props
2545
3065
  }
2546
3066
  ),
2547
- ol: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3067
+ ol: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2548
3068
  "ol",
2549
3069
  {
2550
3070
  className: cn(
@@ -2554,7 +3074,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2554
3074
  ...props
2555
3075
  }
2556
3076
  ),
2557
- hr: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3077
+ hr: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2558
3078
  "hr",
2559
3079
  {
2560
3080
  className: cn(
@@ -2564,14 +3084,14 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2564
3084
  ...props
2565
3085
  }
2566
3086
  ),
2567
- table: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "my-4 w-full overflow-x-auto rounded-lg border border-border/50", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3087
+ table: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "my-4 w-full overflow-x-auto rounded-lg border border-border/50", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2568
3088
  "table",
2569
3089
  {
2570
3090
  className: cn("aui-md-table w-full border-collapse text-sm", className),
2571
3091
  ...props
2572
3092
  }
2573
3093
  ) }),
2574
- th: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3094
+ th: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2575
3095
  "th",
2576
3096
  {
2577
3097
  className: cn(
@@ -2581,7 +3101,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2581
3101
  ...props
2582
3102
  }
2583
3103
  ),
2584
- td: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3104
+ td: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2585
3105
  "td",
2586
3106
  {
2587
3107
  className: cn(
@@ -2591,7 +3111,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2591
3111
  ...props
2592
3112
  }
2593
3113
  ),
2594
- tr: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3114
+ tr: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2595
3115
  "tr",
2596
3116
  {
2597
3117
  className: cn(
@@ -2601,8 +3121,8 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2601
3121
  ...props
2602
3122
  }
2603
3123
  ),
2604
- li: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("li", { className: cn("aui-md-li leading-[1.7]", className), ...props }),
2605
- sup: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3124
+ li: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("li", { className: cn("aui-md-li leading-[1.7]", className), ...props }),
3125
+ sup: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2606
3126
  "sup",
2607
3127
  {
2608
3128
  className: cn(
@@ -2612,7 +3132,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2612
3132
  ...props
2613
3133
  }
2614
3134
  ),
2615
- pre: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3135
+ pre: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2616
3136
  "pre",
2617
3137
  {
2618
3138
  className: cn(
@@ -2624,7 +3144,7 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2624
3144
  ),
2625
3145
  code: function Code({ className, ...props }) {
2626
3146
  const isCodeBlock = (0, import_react_markdown.useIsMarkdownCodeBlock)();
2627
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
3147
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2628
3148
  "code",
2629
3149
  {
2630
3150
  className: cn(
@@ -2635,20 +3155,20 @@ var defaultComponents = (0, import_react_markdown.unstable_memoizeMarkdownCompon
2635
3155
  }
2636
3156
  );
2637
3157
  },
2638
- strong: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("strong", { className: cn("font-semibold text-foreground", className), ...props }),
2639
- em: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("em", { className: cn("italic", className), ...props }),
3158
+ strong: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("strong", { className: cn("font-semibold text-foreground", className), ...props }),
3159
+ em: ({ className, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("em", { className: cn("italic", className), ...props }),
2640
3160
  CodeHeader
2641
3161
  });
2642
3162
 
2643
3163
  // src/chat/tool-fallback.tsx
2644
- var import_react26 = require("react");
3164
+ var import_react28 = require("react");
2645
3165
  var import_lucide_react5 = require("lucide-react");
2646
- var import_react27 = require("@assistant-ui/react");
3166
+ var import_react29 = require("@assistant-ui/react");
2647
3167
 
2648
3168
  // src/ui/shimmer.tsx
2649
- var import_react20 = require("motion/react");
2650
- var import_react21 = require("react");
2651
- var import_jsx_runtime27 = require("react/jsx-runtime");
3169
+ var import_react22 = require("motion/react");
3170
+ var import_react23 = require("react");
3171
+ var import_jsx_runtime28 = require("react/jsx-runtime");
2652
3172
  var ShimmerComponent = ({
2653
3173
  children,
2654
3174
  as: Component = "p",
@@ -2656,14 +3176,14 @@ var ShimmerComponent = ({
2656
3176
  duration = 2,
2657
3177
  spread = 2
2658
3178
  }) => {
2659
- const MotionComponent = import_react20.motion.create(
3179
+ const MotionComponent = import_react22.motion.create(
2660
3180
  Component
2661
3181
  );
2662
- const dynamicSpread = (0, import_react21.useMemo)(
3182
+ const dynamicSpread = (0, import_react23.useMemo)(
2663
3183
  () => (children?.length ?? 0) * spread,
2664
3184
  [children, spread]
2665
3185
  );
2666
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3186
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2667
3187
  MotionComponent,
2668
3188
  {
2669
3189
  animate: { backgroundPosition: "0% center" },
@@ -2686,11 +3206,11 @@ var ShimmerComponent = ({
2686
3206
  }
2687
3207
  );
2688
3208
  };
2689
- var Shimmer = (0, import_react21.memo)(ShimmerComponent);
3209
+ var Shimmer = (0, import_react23.memo)(ShimmerComponent);
2690
3210
 
2691
3211
  // src/chat/motion.tsx
2692
- var import_react22 = require("motion/react");
2693
- var import_jsx_runtime28 = require("react/jsx-runtime");
3212
+ var import_react24 = require("motion/react");
3213
+ var import_jsx_runtime29 = require("react/jsx-runtime");
2694
3214
  var luxuryEase = [0.16, 1, 0.3, 1];
2695
3215
  var TOOL_ENTER_MS = 0.78;
2696
3216
  var TOOL_EXIT_MS = 0.28;
@@ -2716,10 +3236,10 @@ function toolMotionState(reduced, entering, variant) {
2716
3236
  return entering ? { opacity: 0, y: 14, filter: "blur(10px)" } : { opacity: 1, y: 0, filter: "blur(0px)" };
2717
3237
  }
2718
3238
  function ToolMotion({ children, className, motionKey }) {
2719
- const reduced = (0, import_react22.useReducedMotion)() ?? false;
3239
+ const reduced = (0, import_react24.useReducedMotion)() ?? false;
2720
3240
  const { enter, exit } = toolPresenceTransition(reduced);
2721
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2722
- import_react22.motion.div,
3241
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
3242
+ import_react24.motion.div,
2723
3243
  {
2724
3244
  className: cn("aui-tool-motion w-full min-w-0", className),
2725
3245
  initial: toolMotionState(reduced, true, "settled"),
@@ -2738,11 +3258,11 @@ function ToolPresence({
2738
3258
  className,
2739
3259
  variant = "settled"
2740
3260
  }) {
2741
- const reduced = (0, import_react22.useReducedMotion)() ?? false;
3261
+ const reduced = (0, import_react24.useReducedMotion)() ?? false;
2742
3262
  const { enter, exit } = toolPresenceTransition(reduced);
2743
3263
  const enterTransition = variant === "executing" ? { duration: reduced ? 0.3 : 0.52, ease: luxuryEase } : enter;
2744
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react22.AnimatePresence, { mode: "wait", initial: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2745
- import_react22.motion.div,
3264
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react24.AnimatePresence, { mode: "wait", initial: true, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
3265
+ import_react24.motion.div,
2746
3266
  {
2747
3267
  className: cn("aui-tool-presence w-full min-w-0", className),
2748
3268
  initial: toolMotionState(reduced, true, variant),
@@ -2762,8 +3282,8 @@ function ToolBodyPresence({
2762
3282
  children,
2763
3283
  className
2764
3284
  }) {
2765
- const reduced = (0, import_react22.useReducedMotion)() ?? false;
2766
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3285
+ const reduced = (0, import_react24.useReducedMotion)() ?? false;
3286
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
2767
3287
  "div",
2768
3288
  {
2769
3289
  className: cn(
@@ -2771,7 +3291,7 @@ function ToolBodyPresence({
2771
3291
  open ? reduced ? "duration-200 ease-out" : "duration-[340ms] ease-[cubic-bezier(0.16,1,0.3,1)]" : reduced ? "duration-150 ease-[cubic-bezier(0.4,0,0.2,1)]" : "duration-200 ease-[cubic-bezier(0.4,0,0.2,1)]"
2772
3292
  ),
2773
3293
  style: { gridTemplateRows: open ? "1fr" : "0fr" },
2774
- children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "min-h-0 overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3294
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "min-h-0 overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
2775
3295
  "div",
2776
3296
  {
2777
3297
  className: cn(
@@ -2787,8 +3307,8 @@ function ToolBodyPresence({
2787
3307
  }
2788
3308
 
2789
3309
  // src/runtime/provider.tsx
2790
- var import_react24 = require("react");
2791
- var import_react25 = require("@assistant-ui/react");
3310
+ var import_react26 = require("react");
3311
+ var import_react27 = require("@assistant-ui/react");
2792
3312
  var import_timbal_sdk = require("@timbal-ai/timbal-sdk");
2793
3313
 
2794
3314
  // src/auth/tokens.ts
@@ -3203,17 +3723,17 @@ function buildPromptBody({
3203
3723
  }
3204
3724
 
3205
3725
  // src/runtime/attachments-context.tsx
3206
- var import_react23 = require("react");
3207
- var import_jsx_runtime29 = require("react/jsx-runtime");
3208
- var TimbalAttachmentsEnabledContext = (0, import_react23.createContext)(false);
3726
+ var import_react25 = require("react");
3727
+ var import_jsx_runtime30 = require("react/jsx-runtime");
3728
+ var TimbalAttachmentsEnabledContext = (0, import_react25.createContext)(false);
3209
3729
  function TimbalAttachmentsEnabledProvider({
3210
3730
  enabled,
3211
3731
  children
3212
3732
  }) {
3213
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TimbalAttachmentsEnabledContext.Provider, { value: enabled, children });
3733
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TimbalAttachmentsEnabledContext.Provider, { value: enabled, children });
3214
3734
  }
3215
3735
  function useTimbalAttachmentsEnabled() {
3216
- return (0, import_react23.useContext)(TimbalAttachmentsEnabledContext);
3736
+ return (0, import_react25.useContext)(TimbalAttachmentsEnabledContext);
3217
3737
  }
3218
3738
 
3219
3739
  // src/runtime/upload-adapter.ts
@@ -3322,7 +3842,7 @@ function resolveAttachmentAdapter(attachments, options = {}) {
3322
3842
  }
3323
3843
 
3324
3844
  // src/runtime/provider.tsx
3325
- var import_jsx_runtime30 = require("react/jsx-runtime");
3845
+ var import_jsx_runtime31 = require("react/jsx-runtime");
3326
3846
  function projectAttachment(attachment) {
3327
3847
  const filename = attachment.name ?? "attachment";
3328
3848
  const mimeType = attachment.contentType ?? "application/octet-stream";
@@ -3387,22 +3907,22 @@ function useTimbalStream({
3387
3907
  fetch: fetchFn,
3388
3908
  debug = false
3389
3909
  }) {
3390
- const [messages, setMessages] = (0, import_react24.useState)([]);
3391
- const [isRunning, setIsRunning] = (0, import_react24.useState)(false);
3392
- const abortRef = (0, import_react24.useRef)(null);
3393
- const messagesRef = (0, import_react24.useRef)([]);
3394
- const fetchFnRef = (0, import_react24.useRef)(fetchFn ?? authFetch);
3395
- (0, import_react24.useEffect)(() => {
3910
+ const [messages, setMessages] = (0, import_react26.useState)([]);
3911
+ const [isRunning, setIsRunning] = (0, import_react26.useState)(false);
3912
+ const abortRef = (0, import_react26.useRef)(null);
3913
+ const messagesRef = (0, import_react26.useRef)([]);
3914
+ const fetchFnRef = (0, import_react26.useRef)(fetchFn ?? authFetch);
3915
+ (0, import_react26.useEffect)(() => {
3396
3916
  fetchFnRef.current = fetchFn ?? authFetch;
3397
3917
  }, [fetchFn]);
3398
- const debugRef = (0, import_react24.useRef)(debug);
3399
- (0, import_react24.useEffect)(() => {
3918
+ const debugRef = (0, import_react26.useRef)(debug);
3919
+ (0, import_react26.useEffect)(() => {
3400
3920
  debugRef.current = debug;
3401
3921
  }, [debug]);
3402
- (0, import_react24.useEffect)(() => {
3922
+ (0, import_react26.useEffect)(() => {
3403
3923
  messagesRef.current = messages;
3404
3924
  }, [messages]);
3405
- const streamAssistantResponse = (0, import_react24.useCallback)(
3925
+ const streamAssistantResponse = (0, import_react26.useCallback)(
3406
3926
  async (input, attachments, userId, assistantId, parentId, signal) => {
3407
3927
  const state = createReducerState();
3408
3928
  const flush = () => {
@@ -3481,7 +4001,7 @@ function useTimbalStream({
3481
4001
  },
3482
4002
  [workforceId, baseUrl]
3483
4003
  );
3484
- const send = (0, import_react24.useCallback)(
4004
+ const send = (0, import_react26.useCallback)(
3485
4005
  async (input, options) => {
3486
4006
  const userId = crypto.randomUUID();
3487
4007
  const assistantId = crypto.randomUUID();
@@ -3512,7 +4032,7 @@ function useTimbalStream({
3512
4032
  },
3513
4033
  [streamAssistantResponse]
3514
4034
  );
3515
- const reload = (0, import_react24.useCallback)(
4035
+ const reload = (0, import_react26.useCallback)(
3516
4036
  async (messageId) => {
3517
4037
  const current = messagesRef.current;
3518
4038
  const idx = messageId ? current.findIndex((m) => m.id === messageId) : current.length - 2;
@@ -3541,14 +4061,14 @@ function useTimbalStream({
3541
4061
  },
3542
4062
  [streamAssistantResponse]
3543
4063
  );
3544
- const cancel = (0, import_react24.useCallback)(() => {
4064
+ const cancel = (0, import_react26.useCallback)(() => {
3545
4065
  abortRef.current?.abort();
3546
4066
  }, []);
3547
- const clear = (0, import_react24.useCallback)(() => {
4067
+ const clear = (0, import_react26.useCallback)(() => {
3548
4068
  abortRef.current?.abort();
3549
4069
  setMessages([]);
3550
4070
  }, []);
3551
- return (0, import_react24.useMemo)(
4071
+ return (0, import_react26.useMemo)(
3552
4072
  () => ({ messages, isRunning, send, reload, cancel, clear }),
3553
4073
  [messages, isRunning, send, reload, cancel, clear]
3554
4074
  );
@@ -3559,9 +4079,9 @@ function readTopLevelStartRunId(event) {
3559
4079
  }
3560
4080
  return null;
3561
4081
  }
3562
- var TimbalStreamContext = (0, import_react24.createContext)(null);
4082
+ var TimbalStreamContext = (0, import_react26.createContext)(null);
3563
4083
  function useTimbalRuntime() {
3564
- const ctx = (0, import_react24.useContext)(TimbalStreamContext);
4084
+ const ctx = (0, import_react26.useContext)(TimbalStreamContext);
3565
4085
  if (!ctx) {
3566
4086
  throw new Error(
3567
4087
  "useTimbalRuntime must be used inside a <TimbalRuntimeProvider>."
@@ -3585,7 +4105,7 @@ function TimbalRuntimeProvider({
3585
4105
  fetch: fetchFn,
3586
4106
  debug
3587
4107
  });
3588
- const attachmentAdapter = (0, import_react24.useMemo)(
4108
+ const attachmentAdapter = (0, import_react26.useMemo)(
3589
4109
  () => resolveAttachmentAdapter(attachments, {
3590
4110
  baseUrl,
3591
4111
  fetch: fetchFn,
@@ -3594,7 +4114,7 @@ function TimbalRuntimeProvider({
3594
4114
  }),
3595
4115
  [attachments, attachmentsUploadUrl, attachmentsAccept, baseUrl, fetchFn]
3596
4116
  );
3597
- const onNew = (0, import_react24.useCallback)(
4117
+ const onNew = (0, import_react26.useCallback)(
3598
4118
  async (message) => {
3599
4119
  const textPart = message.content.find((c) => c.type === "text");
3600
4120
  const input = textPart && textPart.type === "text" ? textPart.text : "";
@@ -3609,16 +4129,16 @@ function TimbalRuntimeProvider({
3609
4129
  },
3610
4130
  [stream]
3611
4131
  );
3612
- const onReload = (0, import_react24.useCallback)(
4132
+ const onReload = (0, import_react26.useCallback)(
3613
4133
  async (messageId) => {
3614
4134
  await stream.reload(messageId);
3615
4135
  },
3616
4136
  [stream]
3617
4137
  );
3618
- const onCancel = (0, import_react24.useCallback)(async () => {
4138
+ const onCancel = (0, import_react26.useCallback)(async () => {
3619
4139
  stream.cancel();
3620
4140
  }, [stream]);
3621
- const runtime = (0, import_react25.useExternalStoreRuntime)({
4141
+ const runtime = (0, import_react27.useExternalStoreRuntime)({
3622
4142
  isRunning: stream.isRunning,
3623
4143
  messages: stream.messages,
3624
4144
  convertMessage,
@@ -3628,7 +4148,7 @@ function TimbalRuntimeProvider({
3628
4148
  onCancel,
3629
4149
  ...attachmentAdapter ? { adapters: { attachments: attachmentAdapter } } : {}
3630
4150
  });
3631
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TimbalStreamContext.Provider, { value: stream, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TimbalAttachmentsEnabledProvider, { enabled: attachmentAdapter !== void 0, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react25.AssistantRuntimeProvider, { runtime, children }) }) });
4151
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TimbalStreamContext.Provider, { value: stream, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TimbalAttachmentsEnabledProvider, { enabled: attachmentAdapter !== void 0, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react27.AssistantRuntimeProvider, { runtime, children }) }) });
3632
4152
  }
3633
4153
  function findParentIdFromAuiParent(messages, auiParentId) {
3634
4154
  const idx = messages.findIndex((m) => m.id === auiParentId);
@@ -3637,7 +4157,7 @@ function findParentIdFromAuiParent(messages, auiParentId) {
3637
4157
  }
3638
4158
 
3639
4159
  // src/chat/tool-fallback.tsx
3640
- var import_jsx_runtime31 = require("react/jsx-runtime");
4160
+ var import_jsx_runtime32 = require("react/jsx-runtime");
3641
4161
  function detectRunning({
3642
4162
  status,
3643
4163
  result,
@@ -3651,7 +4171,7 @@ function detectRunning({
3651
4171
  }
3652
4172
  function useToolRunning(props) {
3653
4173
  const { isRunning: streamRunning } = useTimbalRuntime();
3654
- const partStatus = (0, import_react27.useAuiState)((s) => s.part.status);
4174
+ const partStatus = (0, import_react29.useAuiState)((s) => s.part.status);
3655
4175
  return detectRunning({
3656
4176
  status: partStatus ?? props.status,
3657
4177
  result: props.result,
@@ -3669,8 +4189,8 @@ function formatToolResult(result) {
3669
4189
  return String(result);
3670
4190
  }
3671
4191
  }
3672
- var TimelineActionLabel = ({ action, detail, shimmer = false }) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "inline-flex min-w-0 max-w-full items-baseline gap-1", children: [
3673
- action ? shimmer ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
4192
+ var TimelineActionLabel = ({ action, detail, shimmer = false }) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "inline-flex min-w-0 max-w-full items-baseline gap-1", children: [
4193
+ action ? shimmer ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3674
4194
  Shimmer,
3675
4195
  {
3676
4196
  as: "span",
@@ -3679,10 +4199,10 @@ var TimelineActionLabel = ({ action, detail, shimmer = false }) => /* @__PURE__
3679
4199
  spread: 2.5,
3680
4200
  children: action
3681
4201
  }
3682
- ) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: studioTimelineActionClass, children: action }) : null,
3683
- detail ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: studioTimelineDetailClass, children: detail }) : null
4202
+ ) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: studioTimelineActionClass, children: action }) : null,
4203
+ detail ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: studioTimelineDetailClass, children: detail }) : null
3684
4204
  ] });
3685
- var TimelineHoverChevron = ({ expanded }) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
4205
+ var TimelineHoverChevron = ({ expanded }) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3686
4206
  import_lucide_react5.ChevronRightIcon,
3687
4207
  {
3688
4208
  className: studioTimelineChevronClass(expanded),
@@ -3690,9 +4210,9 @@ var TimelineHoverChevron = ({ expanded }) => /* @__PURE__ */ (0, import_jsx_runt
3690
4210
  }
3691
4211
  );
3692
4212
  var ToolPanel = ({ toolName, argsText, result, isError }) => {
3693
- const [open, setOpen] = (0, import_react26.useState)(false);
4213
+ const [open, setOpen] = (0, import_react28.useState)(false);
3694
4214
  const detail = formatToolLabel(toolName);
3695
- const formattedArgs = (0, import_react26.useMemo)(() => {
4215
+ const formattedArgs = (0, import_react28.useMemo)(() => {
3696
4216
  if (!argsText || argsText === "{}") return null;
3697
4217
  try {
3698
4218
  return JSON.stringify(JSON.parse(argsText), null, 2);
@@ -3700,17 +4220,17 @@ var ToolPanel = ({ toolName, argsText, result, isError }) => {
3700
4220
  return argsText;
3701
4221
  }
3702
4222
  }, [argsText]);
3703
- const formattedResult = (0, import_react26.useMemo)(() => {
4223
+ const formattedResult = (0, import_react28.useMemo)(() => {
3704
4224
  if (result === void 0 || result === null) return null;
3705
4225
  return formatToolResult(result);
3706
4226
  }, [result]);
3707
4227
  const hasBody = Boolean(formattedArgs || formattedResult);
3708
4228
  const action = isError ? "Failed" : "Used";
3709
4229
  if (!hasBody) {
3710
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "aui-tool-row w-full min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TimelineActionLabel, { action, detail }) });
4230
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "aui-tool-row w-full min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TimelineActionLabel, { action, detail }) });
3711
4231
  }
3712
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "aui-tool-row w-full min-w-0", children: [
3713
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
4232
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "aui-tool-row w-full min-w-0", children: [
4233
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3714
4234
  "button",
3715
4235
  {
3716
4236
  type: "button",
@@ -3718,7 +4238,7 @@ var ToolPanel = ({ toolName, argsText, result, isError }) => {
3718
4238
  "aria-expanded": open,
3719
4239
  "aria-label": `${action} ${detail}`,
3720
4240
  className: studioTimelineRowButtonClass,
3721
- children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
4241
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
3722
4242
  "span",
3723
4243
  {
3724
4244
  className: cn(
@@ -3727,37 +4247,37 @@ var ToolPanel = ({ toolName, argsText, result, isError }) => {
3727
4247
  "text-foreground"
3728
4248
  ),
3729
4249
  children: [
3730
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TimelineActionLabel, { action, detail }),
3731
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(TimelineHoverChevron, { expanded: open })
4250
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TimelineActionLabel, { action, detail }),
4251
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TimelineHoverChevron, { expanded: open })
3732
4252
  ]
3733
4253
  }
3734
4254
  )
3735
4255
  }
3736
4256
  ),
3737
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
4257
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
3738
4258
  ToolBodyPresence,
3739
4259
  {
3740
4260
  open,
3741
4261
  className: cn(studioTimelineBodyPadClass, "gap-2"),
3742
4262
  children: [
3743
- formattedArgs ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
4263
+ formattedArgs ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3744
4264
  "div",
3745
4265
  {
3746
4266
  className: cn(
3747
4267
  studioComposerIoWellClass,
3748
4268
  "max-h-48 overflow-auto px-2.5 py-2"
3749
4269
  ),
3750
- children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] font-normal leading-relaxed text-foreground", children: formattedArgs })
4270
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] font-normal leading-relaxed text-foreground", children: formattedArgs })
3751
4271
  }
3752
4272
  ) : null,
3753
- formattedResult ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
4273
+ formattedResult ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3754
4274
  "div",
3755
4275
  {
3756
4276
  className: cn(
3757
4277
  studioComposerIoWellClass,
3758
4278
  "max-h-48 overflow-auto px-2.5 py-2"
3759
4279
  ),
3760
- children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] font-normal leading-relaxed text-foreground", children: formattedResult })
4280
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("pre", { className: "whitespace-pre-wrap break-words font-mono text-[11px] font-normal leading-relaxed text-foreground", children: formattedResult })
3761
4281
  }
3762
4282
  ) : null
3763
4283
  ]
@@ -3774,20 +4294,20 @@ var ToolFallbackImpl = ({
3774
4294
  const isRunning = useToolRunning({ status, result });
3775
4295
  const isError = status?.type === "incomplete" && status.reason !== "cancelled";
3776
4296
  const presenceKey = isRunning ? "running" : isError ? "error" : "complete";
3777
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
4297
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3778
4298
  ToolPresence,
3779
4299
  {
3780
4300
  presenceKey,
3781
4301
  variant: isRunning ? "executing" : "settled",
3782
4302
  className: "py-0.5",
3783
- children: isRunning ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "aui-tool-running", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
4303
+ children: isRunning ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "aui-tool-running", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3784
4304
  TimelineActionLabel,
3785
4305
  {
3786
4306
  action: "Using",
3787
4307
  detail: formatToolLabel(toolName),
3788
4308
  shimmer: true
3789
4309
  }
3790
- ) }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
4310
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
3791
4311
  ToolPanel,
3792
4312
  {
3793
4313
  toolName,
@@ -3799,13 +4319,13 @@ var ToolFallbackImpl = ({
3799
4319
  }
3800
4320
  );
3801
4321
  };
3802
- var ToolFallback = (0, import_react26.memo)(
4322
+ var ToolFallback = (0, import_react28.memo)(
3803
4323
  ToolFallbackImpl
3804
4324
  );
3805
4325
  ToolFallback.displayName = "ToolFallback";
3806
4326
 
3807
4327
  // src/artifacts/tool-artifact.tsx
3808
- var import_jsx_runtime32 = require("react/jsx-runtime");
4328
+ var import_jsx_runtime33 = require("react/jsx-runtime");
3809
4329
  var ToolArtifactFallback = (props) => {
3810
4330
  const registry = useArtifactRegistry();
3811
4331
  const isRunning = useToolRunning({
@@ -3817,24 +4337,24 @@ var ToolArtifactFallback = (props) => {
3817
4337
  if (artifact) {
3818
4338
  const Renderer = registry[artifact.type];
3819
4339
  if (Renderer) {
3820
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
4340
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
3821
4341
  ToolMotion,
3822
4342
  {
3823
4343
  motionKey: `artifact-${artifact.type}`,
3824
4344
  className: "aui-tool-artifact",
3825
- children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Renderer, { artifact })
4345
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Renderer, { artifact })
3826
4346
  }
3827
4347
  );
3828
4348
  }
3829
4349
  }
3830
4350
  }
3831
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ToolFallback, { ...props });
4351
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ToolFallback, { ...props });
3832
4352
  };
3833
4353
 
3834
4354
  // src/chat/composer.tsx
3835
- var import_react28 = require("@assistant-ui/react");
4355
+ var import_react30 = require("@assistant-ui/react");
3836
4356
  var import_lucide_react6 = require("lucide-react");
3837
- var import_jsx_runtime33 = require("react/jsx-runtime");
4357
+ var import_jsx_runtime34 = require("react/jsx-runtime");
3838
4358
  var Composer = ({
3839
4359
  placeholder = "Send a message...",
3840
4360
  showAttachments,
@@ -3845,10 +4365,10 @@ var Composer = ({
3845
4365
  }) => {
3846
4366
  const attachmentsEnabled = useTimbalAttachmentsEnabled();
3847
4367
  const attachUi = showAttachments !== false && attachmentsEnabled;
3848
- const shell = /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
3849
- attachUi && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ComposerAttachments, {}),
3850
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ComposerInput, { placeholder, autoFocus: !noAutoFocus }),
3851
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
4368
+ const shell = /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
4369
+ attachUi && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ComposerAttachments, {}),
4370
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ComposerInput, { placeholder, autoFocus: !noAutoFocus }),
4371
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
3852
4372
  ComposerToolbar,
3853
4373
  {
3854
4374
  showAttachments: attachUi,
@@ -3857,15 +4377,15 @@ var Composer = ({
3857
4377
  }
3858
4378
  )
3859
4379
  ] });
3860
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
3861
- import_react28.ComposerPrimitive.Root,
4380
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
4381
+ import_react30.ComposerPrimitive.Root,
3862
4382
  {
3863
4383
  className: cn(
3864
4384
  "aui-composer-root relative flex w-full flex-col",
3865
4385
  className
3866
4386
  ),
3867
- children: attachUi ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
3868
- import_react28.ComposerPrimitive.AttachmentDropzone,
4387
+ children: attachUi ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
4388
+ import_react30.ComposerPrimitive.AttachmentDropzone,
3869
4389
  {
3870
4390
  className: cn(
3871
4391
  studioComposeInputShellClass,
@@ -3873,7 +4393,7 @@ var Composer = ({
3873
4393
  ),
3874
4394
  children: shell
3875
4395
  }
3876
- ) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: studioComposeInputShellClass, children: shell })
4396
+ ) : /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: studioComposeInputShellClass, children: shell })
3877
4397
  }
3878
4398
  );
3879
4399
  };
@@ -3881,7 +4401,7 @@ var ComposerInput = ({
3881
4401
  placeholder,
3882
4402
  autoFocus
3883
4403
  }) => {
3884
- const composer = (0, import_react28.useComposerRuntime)();
4404
+ const composer = (0, import_react30.useComposerRuntime)();
3885
4405
  const onKeyDown = (e) => {
3886
4406
  if (e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
3887
4407
  e.preventDefault();
@@ -3893,8 +4413,8 @@ var ComposerInput = ({
3893
4413
  el.style.height = "auto";
3894
4414
  el.style.height = `${Math.min(el.scrollHeight, 240)}px`;
3895
4415
  };
3896
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
3897
- import_react28.ComposerPrimitive.Input,
4416
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
4417
+ import_react30.ComposerPrimitive.Input,
3898
4418
  {
3899
4419
  placeholder,
3900
4420
  className: "aui-composer-input max-h-60 min-h-14 w-full resize-none bg-composer-bg px-3 pt-3 pb-1 text-sm outline-none placeholder:text-muted-foreground/70 focus-visible:ring-0",
@@ -3907,17 +4427,17 @@ var ComposerInput = ({
3907
4427
  );
3908
4428
  };
3909
4429
  var ComposerToolbar = ({ showAttachments, toolbar, sendTooltip }) => {
3910
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "aui-composer-action-wrapper relative z-[1] flex items-center justify-between gap-1 bg-composer-bg px-2.5 pb-2.5", children: [
3911
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center gap-1", children: [
3912
- showAttachments && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ComposerAddAttachment, {}),
4430
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "aui-composer-action-wrapper relative z-[1] flex items-center justify-between gap-1 bg-composer-bg px-2.5 pb-2.5", children: [
4431
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center gap-1", children: [
4432
+ showAttachments && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ComposerAddAttachment, {}),
3913
4433
  toolbar
3914
4434
  ] }),
3915
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ComposerSendOrCancel, { sendTooltip })
4435
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ComposerSendOrCancel, { sendTooltip })
3916
4436
  ] });
3917
4437
  };
3918
4438
  var ComposerSendOrCancel = ({ sendTooltip }) => {
3919
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
3920
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_react28.AuiIf, { condition: (s) => !s.thread.isRunning, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_react28.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
4439
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
4440
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react30.AuiIf, { condition: (s) => !s.thread.isRunning, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react30.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
3921
4441
  TooltipIconButton,
3922
4442
  {
3923
4443
  tooltip: sendTooltip,
@@ -3925,34 +4445,34 @@ var ComposerSendOrCancel = ({ sendTooltip }) => {
3925
4445
  type: "submit",
3926
4446
  className: "aui-composer-send shrink-0 disabled:opacity-30",
3927
4447
  "aria-label": "Send message",
3928
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react6.ArrowUpIcon, { className: "aui-composer-send-icon size-4" })
4448
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react6.ArrowUpIcon, { className: "aui-composer-send-icon size-4" })
3929
4449
  }
3930
4450
  ) }) }),
3931
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_react28.AuiIf, { condition: (s) => s.thread.isRunning, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_react28.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
4451
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react30.AuiIf, { condition: (s) => s.thread.isRunning, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react30.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
3932
4452
  TooltipIconButton,
3933
4453
  {
3934
4454
  tooltip: "Stop generating",
3935
4455
  variant: "primary",
3936
4456
  className: "aui-composer-cancel shrink-0",
3937
4457
  "aria-label": "Stop generating",
3938
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react6.SquareIcon, { className: "aui-composer-cancel-icon size-3 fill-current" })
4458
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react6.SquareIcon, { className: "aui-composer-cancel-icon size-3 fill-current" })
3939
4459
  }
3940
4460
  ) }) })
3941
4461
  ] });
3942
4462
  };
3943
4463
 
3944
4464
  // src/chat/suggestions.tsx
3945
- var import_react29 = require("react");
3946
- var import_react30 = require("@assistant-ui/react");
4465
+ var import_react31 = require("react");
4466
+ var import_react32 = require("@assistant-ui/react");
3947
4467
  var import_lucide_react7 = require("lucide-react");
3948
- var import_jsx_runtime34 = require("react/jsx-runtime");
4468
+ var import_jsx_runtime35 = require("react/jsx-runtime");
3949
4469
  var Suggestions = ({
3950
4470
  suggestions,
3951
4471
  className
3952
4472
  }) => {
3953
4473
  const items = useResolvedSuggestions(suggestions);
3954
4474
  if (!items || items.length === 0) return null;
3955
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
4475
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
3956
4476
  "div",
3957
4477
  {
3958
4478
  className: cn(
@@ -3961,17 +4481,17 @@ var Suggestions = ({
3961
4481
  ),
3962
4482
  role: "list",
3963
4483
  "aria-label": "Suggested prompts",
3964
- children: items.map((suggestion, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(SuggestionRow, { suggestion }, (suggestion.prompt ?? suggestion.title) + i))
4484
+ children: items.map((suggestion, i) => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(SuggestionRow, { suggestion }, (suggestion.prompt ?? suggestion.title) + i))
3965
4485
  }
3966
4486
  );
3967
4487
  };
3968
4488
  var SuggestionRow = ({ suggestion }) => {
3969
- const runtime = (0, import_react30.useThreadRuntime)();
4489
+ const runtime = (0, import_react32.useThreadRuntime)();
3970
4490
  const onClick = () => {
3971
4491
  const text = suggestion.prompt ?? suggestion.title;
3972
4492
  runtime.append({ role: "user", content: [{ type: "text", text }] });
3973
4493
  };
3974
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
4494
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
3975
4495
  "button",
3976
4496
  {
3977
4497
  type: "button",
@@ -3979,20 +4499,20 @@ var SuggestionRow = ({ suggestion }) => {
3979
4499
  onClick,
3980
4500
  className: cn("aui-thread-suggestion", studioListRowButtonClass),
3981
4501
  children: [
3982
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "aui-thread-suggestion-icon shrink-0 text-muted-foreground", children: suggestion.icon ?? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react7.ArrowUpIcon, { className: "size-4", strokeWidth: 1.75, "aria-hidden": true }) }),
3983
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { className: "aui-thread-suggestion-text min-w-0 flex-1 text-left", children: [
3984
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "aui-thread-suggestion-text-1 block truncate text-sm font-normal text-foreground", children: suggestion.title }),
3985
- suggestion.description && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "aui-thread-suggestion-text-2 mt-0.5 block truncate text-xs text-muted-foreground", children: suggestion.description })
4502
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "aui-thread-suggestion-icon shrink-0 text-muted-foreground", children: suggestion.icon ?? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react7.ArrowUpIcon, { className: "size-4", strokeWidth: 1.75, "aria-hidden": true }) }),
4503
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "aui-thread-suggestion-text min-w-0 flex-1 text-left", children: [
4504
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "aui-thread-suggestion-text-1 block truncate text-sm font-normal text-foreground", children: suggestion.title }),
4505
+ suggestion.description && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "aui-thread-suggestion-text-2 mt-0.5 block truncate text-xs text-muted-foreground", children: suggestion.description })
3986
4506
  ] })
3987
4507
  ]
3988
4508
  }
3989
4509
  );
3990
4510
  };
3991
4511
  function useResolvedSuggestions(source) {
3992
- const [resolved, setResolved] = (0, import_react29.useState)(
4512
+ const [resolved, setResolved] = (0, import_react31.useState)(
3993
4513
  () => Array.isArray(source) ? source : void 0
3994
4514
  );
3995
- (0, import_react29.useEffect)(() => {
4515
+ (0, import_react31.useEffect)(() => {
3996
4516
  if (!source) {
3997
4517
  setResolved(void 0);
3998
4518
  return;
@@ -4011,7 +4531,7 @@ function useResolvedSuggestions(source) {
4011
4531
  cancelled = true;
4012
4532
  };
4013
4533
  }, [source]);
4014
- return (0, import_react29.useMemo)(() => resolved, [resolved]);
4534
+ return (0, import_react31.useMemo)(() => resolved, [resolved]);
4015
4535
  }
4016
4536
 
4017
4537
  // src/design/theme-sanity.ts
@@ -4084,21 +4604,22 @@ function scheduleThemeSanityCheck() {
4084
4604
  }
4085
4605
 
4086
4606
  // src/chat/thread-variant.tsx
4087
- var import_react31 = require("react");
4088
- var ThreadVariantContext = (0, import_react31.createContext)("default");
4607
+ var import_react33 = require("react");
4608
+ var ThreadVariantContext = (0, import_react33.createContext)("default");
4089
4609
  var ThreadVariantProvider = ThreadVariantContext.Provider;
4090
4610
  function useThreadVariant() {
4091
- return (0, import_react31.useContext)(ThreadVariantContext);
4611
+ return (0, import_react33.useContext)(ThreadVariantContext);
4092
4612
  }
4093
4613
 
4094
4614
  // src/chat/thread.tsx
4095
- var import_jsx_runtime35 = require("react/jsx-runtime");
4615
+ var import_jsx_runtime36 = require("react/jsx-runtime");
4096
4616
  var Thread = ({
4097
4617
  className,
4098
4618
  variant = "default",
4099
4619
  maxWidth: maxWidthProp,
4100
4620
  welcome,
4101
4621
  suggestions,
4622
+ showWelcomeSuggestions,
4102
4623
  composerPlaceholder,
4103
4624
  components,
4104
4625
  artifacts,
@@ -4114,17 +4635,17 @@ var Thread = ({
4114
4635
  const EditComposerSlot = components?.EditComposer ?? EditComposer;
4115
4636
  const ScrollToBottomSlot = components?.ScrollToBottom ?? ThreadScrollToBottom;
4116
4637
  const SuggestionsSlot = components?.Suggestions ?? Suggestions;
4117
- (0, import_react32.useEffect)(() => {
4638
+ (0, import_react34.useEffect)(() => {
4118
4639
  scheduleThemeSanityCheck();
4119
4640
  }, []);
4120
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ThreadVariantProvider, { value: variant, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4641
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ThreadVariantProvider, { value: variant, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4121
4642
  ArtifactRegistryProvider,
4122
4643
  {
4123
4644
  renderers: artifacts?.renderers,
4124
4645
  override: artifacts?.override,
4125
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(UiEventProvider, { onEvent: onArtifactEvent ?? (() => {
4126
- }), children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4127
- import_react33.ThreadPrimitive.Root,
4646
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(UiEventProvider, { onEvent: onArtifactEvent ?? (() => {
4647
+ }), children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4648
+ import_react35.ThreadPrimitive.Root,
4128
4649
  {
4129
4650
  className: cn(
4130
4651
  "aui-root aui-thread-root @container flex h-full flex-col bg-transparent",
@@ -4133,8 +4654,8 @@ var Thread = ({
4133
4654
  ),
4134
4655
  style: { ["--thread-max-width"]: maxWidth },
4135
4656
  "data-thread-variant": variant,
4136
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
4137
- import_react33.ThreadPrimitive.Viewport,
4657
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4658
+ import_react35.ThreadPrimitive.Viewport,
4138
4659
  {
4139
4660
  turnAnchor: "bottom",
4140
4661
  className: cn(
@@ -4142,16 +4663,17 @@ var Thread = ({
4142
4663
  isPanel ? "px-2 pt-2" : "px-4 pt-4"
4143
4664
  ),
4144
4665
  children: [
4145
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4666
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4146
4667
  WelcomeSlot,
4147
4668
  {
4148
4669
  config: welcome,
4149
4670
  suggestions,
4671
+ showWelcomeSuggestions,
4150
4672
  Suggestions: SuggestionsSlot
4151
4673
  }
4152
4674
  ),
4153
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4154
- import_react33.ThreadPrimitive.Messages,
4675
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4676
+ import_react35.ThreadPrimitive.Messages,
4155
4677
  {
4156
4678
  components: {
4157
4679
  UserMessage: UserMessageSlot,
@@ -4160,14 +4682,14 @@ var Thread = ({
4160
4682
  }
4161
4683
  }
4162
4684
  ),
4163
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4164
- import_react33.ThreadPrimitive.ViewportFooter,
4685
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4686
+ import_react35.ThreadPrimitive.ViewportFooter,
4165
4687
  {
4166
4688
  className: cn(
4167
4689
  "aui-thread-viewport-footer sticky bottom-0 z-10 mt-auto w-full isolate pt-2",
4168
4690
  isPanel ? "bg-card pb-2" : "bg-background pb-4 md:pb-6"
4169
4691
  ),
4170
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
4692
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4171
4693
  "div",
4172
4694
  {
4173
4695
  className: cn(
@@ -4175,8 +4697,8 @@ var Thread = ({
4175
4697
  isPanel ? "gap-2" : "gap-4"
4176
4698
  ),
4177
4699
  children: [
4178
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ScrollToBottomSlot, {}),
4179
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ComposerSlot, { placeholder })
4700
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ScrollToBottomSlot, {}),
4701
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ComposerSlot, { placeholder })
4180
4702
  ]
4181
4703
  }
4182
4704
  )
@@ -4191,13 +4713,13 @@ var Thread = ({
4191
4713
  ) });
4192
4714
  };
4193
4715
  var ThreadScrollToBottom = () => {
4194
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4716
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4195
4717
  TooltipIconButton,
4196
4718
  {
4197
4719
  tooltip: "Scroll to bottom",
4198
4720
  variant: "secondary",
4199
4721
  className: "aui-thread-scroll-to-bottom absolute -top-12 z-10 self-center disabled:invisible",
4200
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react8.ArrowDownIcon, { className: "size-4" })
4722
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react8.ArrowDownIcon, { className: "size-4" })
4201
4723
  }
4202
4724
  ) });
4203
4725
  };
@@ -4227,16 +4749,18 @@ var welcomeIcon = {
4227
4749
  var ThreadWelcome = ({
4228
4750
  config,
4229
4751
  suggestions,
4752
+ showWelcomeSuggestions: showWelcomeSuggestionsProp,
4230
4753
  Suggestions: SuggestionsSlot = Suggestions
4231
4754
  }) => {
4232
- const isEmpty = (0, import_react33.useThread)((s) => s.messages.length === 0);
4755
+ const isEmpty = (0, import_react35.useThread)((s) => s.messages.length === 0);
4233
4756
  const isPanel = useThreadVariant() === "panel";
4757
+ const showWelcomeSuggestions = showWelcomeSuggestionsProp ?? !isPanel;
4234
4758
  if (!isEmpty) return null;
4235
4759
  const defaultHeading = isPanel ? "Ask about this page" : "How can I help you today?";
4236
4760
  const defaultSubheading = isPanel ? "The assistant can use dashboard context from your app." : "Send a message to start a conversation.";
4237
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col", children: [
4238
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "aui-thread-welcome-center flex w-full grow flex-col items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
4239
- import_react34.motion.div,
4761
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col", children: [
4762
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "aui-thread-welcome-center flex w-full grow flex-col items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4763
+ import_react36.motion.div,
4240
4764
  {
4241
4765
  className: cn(
4242
4766
  "aui-thread-welcome-message flex flex-col items-center justify-center text-center",
@@ -4246,9 +4770,9 @@ var ThreadWelcome = ({
4246
4770
  initial: "initial",
4247
4771
  animate: "animate",
4248
4772
  children: [
4249
- config?.icon && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react34.motion.div, { variants: welcomeIcon, className: isPanel ? "mb-3" : "mb-5", children: config.icon }),
4250
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4251
- import_react34.motion.h1,
4773
+ config?.icon && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react36.motion.div, { variants: welcomeIcon, className: isPanel ? "mb-3" : "mb-5", children: config.icon }),
4774
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4775
+ import_react36.motion.h1,
4252
4776
  {
4253
4777
  variants: welcomeItem,
4254
4778
  className: cn(
@@ -4258,8 +4782,8 @@ var ThreadWelcome = ({
4258
4782
  children: config?.heading ?? defaultHeading
4259
4783
  }
4260
4784
  ),
4261
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4262
- import_react34.motion.p,
4785
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4786
+ import_react36.motion.p,
4263
4787
  {
4264
4788
  variants: welcomeItem,
4265
4789
  className: "aui-thread-welcome-message-inner mt-1.5 text-muted-foreground text-sm",
@@ -4269,16 +4793,16 @@ var ThreadWelcome = ({
4269
4793
  ]
4270
4794
  }
4271
4795
  ) }),
4272
- suggestions && !isPanel ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "aui-thread-welcome-suggestions mx-auto w-full max-w-(--thread-max-width) px-2", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(SuggestionsSlot, { suggestions }) }) : null
4796
+ showWelcomeSuggestions && suggestions ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "aui-thread-welcome-suggestions mx-auto w-full max-w-(--thread-max-width) px-2", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(SuggestionsSlot, { suggestions }) }) : null
4273
4797
  ] });
4274
4798
  };
4275
4799
  var MessageError = () => {
4276
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.MessagePrimitive.Error, { children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.ErrorPrimitive.Root, { className: "aui-message-error-root mt-2 rounded-md border border-destructive bg-destructive/10 p-3 text-destructive text-sm", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.ErrorPrimitive.Message, { className: "aui-message-error-message line-clamp-2" }) }) });
4800
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.MessagePrimitive.Error, { children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.ErrorPrimitive.Root, { className: "aui-message-error-root mt-2 rounded-md border border-destructive bg-destructive/10 p-3 text-destructive text-sm", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.ErrorPrimitive.Message, { className: "aui-message-error-message line-clamp-2" }) }) });
4277
4801
  };
4278
4802
  var AssistantMessage = () => {
4279
4803
  const isPanel = useThreadVariant() === "panel";
4280
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
4281
- import_react33.MessagePrimitive.Root,
4804
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4805
+ import_react35.MessagePrimitive.Root,
4282
4806
  {
4283
4807
  className: cn(
4284
4808
  "aui-assistant-message-root fade-in slide-in-from-bottom-1 relative mx-auto w-full max-w-(--thread-max-width) animate-in duration-150",
@@ -4286,7 +4810,7 @@ var AssistantMessage = () => {
4286
4810
  ),
4287
4811
  "data-role": "assistant",
4288
4812
  children: [
4289
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
4813
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4290
4814
  "div",
4291
4815
  {
4292
4816
  className: cn(
@@ -4294,8 +4818,8 @@ var AssistantMessage = () => {
4294
4818
  isPanel ? "px-1 text-sm" : "px-2"
4295
4819
  ),
4296
4820
  children: [
4297
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4298
- import_react33.MessagePrimitive.Parts,
4821
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4822
+ import_react35.MessagePrimitive.Parts,
4299
4823
  {
4300
4824
  components: {
4301
4825
  Text: MarkdownText,
@@ -4305,11 +4829,11 @@ var AssistantMessage = () => {
4305
4829
  }
4306
4830
  }
4307
4831
  ),
4308
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(MessageError, {})
4832
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(MessageError, {})
4309
4833
  ]
4310
4834
  }
4311
4835
  ),
4312
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "aui-assistant-message-footer mt-1 mb-3 ml-1 flex", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(AssistantActionBar, {}) })
4836
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "aui-assistant-message-footer mt-1 mb-3 ml-1 flex", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(AssistantActionBar, {}) })
4313
4837
  ]
4314
4838
  }
4315
4839
  );
@@ -4322,36 +4846,36 @@ var ASSISTANT_ACTION_ICON_CLASS = cn(
4322
4846
  "[&>span:first-child]:group-hover/tbv2:bg-ghost-fill-hover"
4323
4847
  );
4324
4848
  var AssistantActionBar = () => {
4325
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
4326
- import_react33.ActionBarPrimitive.Root,
4849
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4850
+ import_react35.ActionBarPrimitive.Root,
4327
4851
  {
4328
4852
  hideWhenRunning: true,
4329
4853
  autohide: "never",
4330
4854
  className: "aui-assistant-action-bar-root flex items-center gap-0 bg-transparent px-0 py-0.5 text-muted-foreground/60",
4331
4855
  children: [
4332
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
4856
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4333
4857
  TooltipIconButton,
4334
4858
  {
4335
4859
  tooltip: "Copy",
4336
4860
  variant: "ghost",
4337
4861
  className: ASSISTANT_ACTION_ICON_CLASS,
4338
4862
  children: [
4339
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.AuiIf, { condition: (s) => s.message.isCopied, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react8.CheckIcon, { className: "size-3" }) }),
4340
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.AuiIf, { condition: (s) => !s.message.isCopied, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react8.CopyIcon, { className: "size-3" }) })
4863
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.AuiIf, { condition: (s) => s.message.isCopied, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react8.CheckIcon, { className: "size-3" }) }),
4864
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.AuiIf, { condition: (s) => !s.message.isCopied, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react8.CopyIcon, { className: "size-3" }) })
4341
4865
  ]
4342
4866
  }
4343
4867
  ) }),
4344
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.ActionBarPrimitive.Reload, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4868
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.ActionBarPrimitive.Reload, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4345
4869
  TooltipIconButton,
4346
4870
  {
4347
4871
  tooltip: "Regenerate",
4348
4872
  variant: "ghost",
4349
4873
  className: ASSISTANT_ACTION_ICON_CLASS,
4350
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react8.RefreshCwIcon, { className: "size-3" })
4874
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react8.RefreshCwIcon, { className: "size-3" })
4351
4875
  }
4352
4876
  ) }),
4353
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_react33.ActionBarMorePrimitive.Root, { children: [
4354
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.ActionBarMorePrimitive.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4877
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_react35.ActionBarMorePrimitive.Root, { children: [
4878
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.ActionBarMorePrimitive.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4355
4879
  TooltipIconButton,
4356
4880
  {
4357
4881
  tooltip: "More",
@@ -4360,17 +4884,17 @@ var AssistantActionBar = () => {
4360
4884
  ASSISTANT_ACTION_ICON_CLASS,
4361
4885
  "data-[state=open]:text-muted-foreground/80"
4362
4886
  ),
4363
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react8.MoreHorizontalIcon, { className: "size-3" })
4887
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react8.MoreHorizontalIcon, { className: "size-3" })
4364
4888
  }
4365
4889
  ) }),
4366
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4367
- import_react33.ActionBarMorePrimitive.Content,
4890
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4891
+ import_react35.ActionBarMorePrimitive.Content,
4368
4892
  {
4369
4893
  side: "bottom",
4370
4894
  align: "start",
4371
4895
  className: "aui-action-bar-more-content z-50 min-w-36 overflow-hidden rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-card-elevated",
4372
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.ActionBarPrimitive.ExportMarkdown, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_react33.ActionBarMorePrimitive.Item, { className: "aui-action-bar-more-item flex cursor-pointer select-none items-center gap-2 rounded-md px-2 py-1.5 text-sm outline-none hover:bg-muted focus:bg-muted", children: [
4373
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react8.DownloadIcon, { className: "size-4 shrink-0" }),
4896
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.ActionBarPrimitive.ExportMarkdown, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_react35.ActionBarMorePrimitive.Item, { className: "aui-action-bar-more-item flex cursor-pointer select-none items-center gap-2 rounded-md px-2 py-1.5 text-sm outline-none hover:bg-muted focus:bg-muted", children: [
4897
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react8.DownloadIcon, { className: "size-4 shrink-0" }),
4374
4898
  "Export as Markdown"
4375
4899
  ] }) })
4376
4900
  }
@@ -4381,12 +4905,12 @@ var AssistantActionBar = () => {
4381
4905
  );
4382
4906
  };
4383
4907
  var UserMessageText = () => {
4384
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "whitespace-pre-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.MessagePartPrimitive.Text, { smooth: false }) });
4908
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "whitespace-pre-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.MessagePartPrimitive.Text, { smooth: false }) });
4385
4909
  };
4386
4910
  var UserMessage = () => {
4387
4911
  const isPanel = useThreadVariant() === "panel";
4388
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
4389
- import_react33.MessagePrimitive.Root,
4912
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4913
+ import_react35.MessagePrimitive.Root,
4390
4914
  {
4391
4915
  className: cn(
4392
4916
  "aui-user-message-root mx-auto flex w-full max-w-(--thread-max-width) flex-col items-end gap-2",
@@ -4394,9 +4918,9 @@ var UserMessage = () => {
4394
4918
  ),
4395
4919
  "data-role": "user",
4396
4920
  children: [
4397
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(UserMessageAttachments, {}),
4398
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
4399
- import_react34.motion.div,
4921
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(UserMessageAttachments, {}),
4922
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4923
+ import_react36.motion.div,
4400
4924
  {
4401
4925
  className: cn(
4402
4926
  "aui-user-message-content relative inline-block max-w-[85%] rounded-2xl bg-bubble-user text-bubble-user-foreground",
@@ -4406,8 +4930,8 @@ var UserMessage = () => {
4406
4930
  animate: { opacity: 1, y: 0, scale: 1 },
4407
4931
  transition: { duration: 0.65, ease: luxuryEase },
4408
4932
  children: [
4409
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.MessagePrimitive.Parts, { components: { Text: UserMessageText } }),
4410
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "aui-user-action-bar-wrapper absolute top-1/2 left-0 -translate-x-full -translate-y-1/2 pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(UserActionBar, {}) })
4933
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.MessagePrimitive.Parts, { components: { Text: UserMessageText } }),
4934
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "aui-user-action-bar-wrapper absolute top-1/2 left-0 -translate-x-full -translate-y-1/2 pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(UserActionBar, {}) })
4411
4935
  ]
4412
4936
  }
4413
4937
  )
@@ -4416,46 +4940,45 @@ var UserMessage = () => {
4416
4940
  );
4417
4941
  };
4418
4942
  var UserActionBar = () => {
4419
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4420
- import_react33.ActionBarPrimitive.Root,
4943
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4944
+ import_react35.ActionBarPrimitive.Root,
4421
4945
  {
4422
4946
  hideWhenRunning: true,
4423
4947
  autohide: "always",
4424
4948
  className: "aui-user-action-bar-root flex flex-col items-end",
4425
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.ActionBarPrimitive.Edit, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4949
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.ActionBarPrimitive.Edit, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4426
4950
  TooltipIconButton,
4427
4951
  {
4428
4952
  tooltip: "Edit",
4429
4953
  variant: "ghost",
4430
4954
  className: ASSISTANT_ACTION_ICON_CLASS,
4431
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react8.PencilIcon, { className: "size-3" })
4955
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react8.PencilIcon, { className: "size-3" })
4432
4956
  }
4433
4957
  ) })
4434
4958
  }
4435
4959
  );
4436
4960
  };
4437
4961
  var EditComposer = () => {
4438
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.MessagePrimitive.Root, { className: "aui-edit-composer-wrapper mx-auto flex w-full max-w-(--thread-max-width) flex-col px-2 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_react33.ComposerPrimitive.Root, { className: "aui-edit-composer-root ml-auto flex w-full max-w-[85%] flex-col rounded-2xl bg-muted", children: [
4439
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4440
- import_react33.ComposerPrimitive.Input,
4962
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.MessagePrimitive.Root, { className: "aui-edit-composer-wrapper mx-auto flex w-full max-w-(--thread-max-width) flex-col px-2 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_react35.ComposerPrimitive.Root, { className: "aui-edit-composer-root ml-auto flex w-full max-w-[85%] flex-col rounded-2xl bg-muted", children: [
4963
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4964
+ import_react35.ComposerPrimitive.Input,
4441
4965
  {
4442
4966
  className: "aui-edit-composer-input min-h-14 w-full resize-none bg-transparent p-4 text-foreground text-sm outline-none",
4443
4967
  autoFocus: true
4444
4968
  }
4445
4969
  ),
4446
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "aui-edit-composer-footer mx-3 mb-3 flex items-center gap-2 self-end", children: [
4447
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(TimbalV2Button, { variant: "ghost", size: "sm", children: "Cancel" }) }),
4448
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(TimbalV2Button, { variant: "primary", size: "sm", children: "Update" }) })
4970
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "aui-edit-composer-footer mx-3 mb-3 flex items-center gap-2 self-end", children: [
4971
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(TimbalV2Button, { variant: "ghost", size: "sm", children: "Cancel" }) }),
4972
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(TimbalV2Button, { variant: "primary", size: "sm", children: "Update" }) })
4449
4973
  ] })
4450
4974
  ] }) });
4451
4975
  };
4452
4976
 
4453
4977
  // src/app/chat/AppChatPanel.tsx
4454
- var import_jsx_runtime36 = require("react/jsx-runtime");
4978
+ var import_jsx_runtime37 = require("react/jsx-runtime");
4455
4979
  var shellClass = "aui-app-chat-panel flex h-full min-h-0 flex-col overflow-hidden";
4456
4980
  var chromeClass = cn(
4457
- "aui-app-chat-panel-chrome relative z-20 flex min-h-12 shrink-0 items-center justify-end",
4458
- "bg-card/90 px-2 pt-3 pb-3 backdrop-blur-sm"
4981
+ "aui-app-chat-panel-chrome relative z-20 flex min-h-10 shrink-0 items-center justify-end px-2 pt-2"
4459
4982
  );
4460
4983
  var closeButtonClass = cn(
4461
4984
  "aui-app-chat-panel-close flex size-8 shrink-0 items-center justify-center rounded-md",
@@ -4472,8 +4995,9 @@ var bodyClass = cn(
4472
4995
  "[&_.aui-thread-viewport]:[scrollbar-gutter:stable_both-edges]",
4473
4996
  // Tighter symmetric horizontal inset for panel + composer
4474
4997
  "[&_.aui-thread-viewport]:!px-2",
4475
- "[&_.aui-thread-viewport]:!pt-2",
4998
+ "[&_.aui-thread-viewport]:!pt-1",
4476
4999
  "[&_.aui-user-message-root]:!px-0",
5000
+ "[&_.aui-user-message-root]:!pe-1",
4477
5001
  "[&_.aui-composer-input]:!px-2",
4478
5002
  "[&_.aui-composer-action-wrapper]:!px-2"
4479
5003
  );
@@ -4488,6 +5012,7 @@ var AppChatPanel = ({
4488
5012
  debug,
4489
5013
  welcome,
4490
5014
  suggestions,
5015
+ showWelcomeSuggestions,
4491
5016
  composerPlaceholder,
4492
5017
  components,
4493
5018
  artifacts,
@@ -4495,18 +5020,18 @@ var AppChatPanel = ({
4495
5020
  ...rest
4496
5021
  }) => {
4497
5022
  const shellChat = useAppShellChat();
4498
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: cn(shellClass, className), children: [
4499
- shellChat?.collapsible ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: chromeClass, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
5023
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: cn(shellClass, className), children: [
5024
+ shellChat?.collapsible ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: chromeClass, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
4500
5025
  "button",
4501
5026
  {
4502
5027
  type: "button",
4503
5028
  className: closeButtonClass,
4504
5029
  onClick: () => shellChat.setOpen(false),
4505
5030
  "aria-label": "Close assistant",
4506
- children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react9.XIcon, { className: "size-4", "aria-hidden": true })
5031
+ children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react9.XIcon, { className: "size-4", "aria-hidden": true })
4507
5032
  }
4508
5033
  ) }) : null,
4509
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: bodyClass, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
5034
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: bodyClass, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
4510
5035
  TimbalRuntimeProvider,
4511
5036
  {
4512
5037
  workforceId,
@@ -4516,13 +5041,14 @@ var AppChatPanel = ({
4516
5041
  attachmentsUploadUrl,
4517
5042
  attachmentsAccept,
4518
5043
  debug,
4519
- children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
5044
+ children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
4520
5045
  Thread,
4521
5046
  {
4522
5047
  variant: "panel",
4523
5048
  className: "aui-app-chat-panel-thread",
4524
5049
  welcome,
4525
5050
  suggestions,
5051
+ showWelcomeSuggestions,
4526
5052
  composerPlaceholder,
4527
5053
  components,
4528
5054
  artifacts,
@@ -4536,38 +5062,38 @@ var AppChatPanel = ({
4536
5062
  };
4537
5063
 
4538
5064
  // src/app/surfaces/SurfaceCard.tsx
4539
- var import_jsx_runtime37 = require("react/jsx-runtime");
5065
+ var import_jsx_runtime38 = require("react/jsx-runtime");
4540
5066
  var SurfaceCard = ({ children, className }) => {
4541
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: cn("aui-app-surface-card", appSurfaceCardClass, className), children });
5067
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: cn("aui-app-surface-card", appSurfaceCardClass, className), children });
4542
5068
  };
4543
5069
 
4544
5070
  // src/app/surfaces/StatTile.tsx
4545
- var import_jsx_runtime38 = require("react/jsx-runtime");
5071
+ var import_jsx_runtime39 = require("react/jsx-runtime");
4546
5072
  var StatTile = ({ label, value, hint, className }) => {
4547
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: cn("aui-app-stat-tile", appStatTileClass, className), children: [
4548
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: appStatLabelClass, children: label }),
4549
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: appStatValueClass, children: value }),
4550
- hint ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "text-xs text-muted-foreground", children: hint }) : null
5073
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: cn("aui-app-stat-tile", appStatTileClass, className), children: [
5074
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: appStatLabelClass, children: label }),
5075
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: appStatValueClass, children: value }),
5076
+ hint ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-xs text-muted-foreground", children: hint }) : null
4551
5077
  ] });
4552
5078
  };
4553
5079
 
4554
5080
  // src/app/surfaces/EmptyState.tsx
4555
- var import_jsx_runtime39 = require("react/jsx-runtime");
4556
- var EmptyState2 = ({
5081
+ var import_jsx_runtime40 = require("react/jsx-runtime");
5082
+ var EmptyState = ({
4557
5083
  title,
4558
5084
  description,
4559
5085
  action,
4560
5086
  className
4561
5087
  }) => {
4562
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: cn("aui-app-empty-state", appEmptyStateClass, className), children: [
4563
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: appEmptyStateTitleClass, children: title }),
4564
- description ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: appEmptyStateDescriptionClass, children: description }) : null,
5088
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: cn("aui-app-empty-state", appEmptyStateClass, className), children: [
5089
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: appEmptyStateTitleClass, children: title }),
5090
+ description ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: appEmptyStateDescriptionClass, children: description }) : null,
4565
5091
  action
4566
5092
  ] });
4567
5093
  };
4568
5094
 
4569
5095
  // src/app/surfaces/StatusBadge.tsx
4570
- var import_jsx_runtime40 = require("react/jsx-runtime");
5096
+ var import_jsx_runtime41 = require("react/jsx-runtime");
4571
5097
  var statusBadgeToneClass = {
4572
5098
  default: "bg-muted text-foreground",
4573
5099
  primary: "bg-primary/10 text-primary",
@@ -4580,7 +5106,7 @@ var StatusBadge = ({
4580
5106
  tone = "default",
4581
5107
  className
4582
5108
  }) => {
4583
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
5109
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
4584
5110
  "span",
4585
5111
  {
4586
5112
  className: cn(
@@ -4594,7 +5120,7 @@ var StatusBadge = ({
4594
5120
  };
4595
5121
 
4596
5122
  // src/app/surfaces/AppConfirmDialog.tsx
4597
- var import_jsx_runtime41 = require("react/jsx-runtime");
5123
+ var import_jsx_runtime42 = require("react/jsx-runtime");
4598
5124
  var bodyClass2 = "flex flex-col gap-4 p-6";
4599
5125
  var titleClass = "pr-8";
4600
5126
  var actionsClass = "flex flex-wrap justify-end gap-2";
@@ -4609,15 +5135,15 @@ var AppConfirmDialog = ({
4609
5135
  destructive = false,
4610
5136
  className
4611
5137
  }) => {
4612
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Dialog, { open, onOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
5138
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Dialog, { open, onOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4613
5139
  DialogContent,
4614
5140
  {
4615
5141
  className: cn("gap-0 p-0 sm:max-w-md", className),
4616
- children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: bodyClass2, children: [
4617
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(DialogTitle, { className: titleClass, children: title }),
4618
- description ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "text-sm text-muted-foreground", children: description }) : null,
4619
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: actionsClass, children: [
4620
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
5142
+ children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: bodyClass2, children: [
5143
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(DialogTitle, { className: titleClass, children: title }),
5144
+ description ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-sm text-muted-foreground", children: description }) : null,
5145
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: actionsClass, children: [
5146
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4621
5147
  TimbalV2Button,
4622
5148
  {
4623
5149
  type: "button",
@@ -4627,7 +5153,7 @@ var AppConfirmDialog = ({
4627
5153
  children: cancelLabel
4628
5154
  }
4629
5155
  ),
4630
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
5156
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4631
5157
  TimbalV2Button,
4632
5158
  {
4633
5159
  type: "button",
@@ -4646,30 +5172,640 @@ var AppConfirmDialog = ({
4646
5172
  ) });
4647
5173
  };
4648
5174
 
4649
- // src/ui/pill-segmented-tabs.tsx
4650
- var import_react35 = require("react");
4651
- var import_react36 = require("motion/react");
5175
+ // src/app/surfaces/InfoCard.tsx
5176
+ var import_jsx_runtime43 = require("react/jsx-runtime");
5177
+ var toneClass = {
5178
+ neutral: "border-border bg-muted/40",
5179
+ info: "border-primary/25 bg-primary/5",
5180
+ success: "border-emerald-500/25 bg-emerald-500/5",
5181
+ warn: "border-amber-500/25 bg-amber-500/5",
5182
+ danger: "border-destructive/25 bg-destructive/5"
5183
+ };
5184
+ var InfoCard = ({
5185
+ title,
5186
+ children,
5187
+ icon,
5188
+ action,
5189
+ tone = "neutral",
5190
+ className
5191
+ }) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
5192
+ "div",
5193
+ {
5194
+ className: cn(
5195
+ "flex items-start gap-3 rounded-xl border p-4",
5196
+ toneClass[tone],
5197
+ className
5198
+ ),
5199
+ children: [
5200
+ icon ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "mt-0.5 shrink-0 text-muted-foreground", children: icon }) : null,
5201
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "min-w-0 flex-1", children: [
5202
+ title ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-sm font-medium text-foreground", children: title }) : null,
5203
+ children ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: cn("text-sm text-muted-foreground", title && "mt-1"), children }) : null
5204
+ ] }),
5205
+ action ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "shrink-0", children: action }) : null
5206
+ ]
5207
+ }
5208
+ );
4652
5209
 
4653
- // src/design/pill-segmented-classes.ts
4654
- var pillSegmentedTrackBase = "inline-flex w-fit max-w-max shrink-0 self-start items-center rounded-full";
4655
- var pillSegmentedTrackSurface = cn(
4656
- "bg-pill-segmented-track border border-[var(--pill-segmented-track-border)]",
4657
- "shadow-[var(--pill-segmented-track-shadow)]"
5210
+ // src/app/surfaces/StatusDot.tsx
5211
+ var import_jsx_runtime44 = require("react/jsx-runtime");
5212
+ var dotClass = {
5213
+ online: "bg-emerald-500",
5214
+ busy: "bg-amber-500",
5215
+ offline: "bg-muted-foreground/50",
5216
+ error: "bg-destructive",
5217
+ neutral: "bg-muted-foreground"
5218
+ };
5219
+ var StatusDot = ({
5220
+ tone = "neutral",
5221
+ label,
5222
+ pulse = false,
5223
+ className
5224
+ }) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: cn("inline-flex items-center gap-1.5", className), children: [
5225
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "relative flex size-2", children: [
5226
+ pulse ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
5227
+ "span",
5228
+ {
5229
+ className: cn(
5230
+ "absolute inline-flex size-full animate-ping rounded-full opacity-60",
5231
+ dotClass[tone]
5232
+ )
5233
+ }
5234
+ ) : null,
5235
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: cn("relative inline-flex size-2 rounded-full", dotClass[tone]) })
5236
+ ] }),
5237
+ label ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-xs text-muted-foreground", children: label }) : null
5238
+ ] });
5239
+
5240
+ // src/app/surfaces/DescriptionList.tsx
5241
+ var import_jsx_runtime45 = require("react/jsx-runtime");
5242
+ var DescriptionList = ({
5243
+ items,
5244
+ stacked = false,
5245
+ className
5246
+ }) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
5247
+ "dl",
5248
+ {
5249
+ className: cn(
5250
+ "divide-y divide-border rounded-xl border border-border bg-card",
5251
+ className
5252
+ ),
5253
+ children: items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
5254
+ "div",
5255
+ {
5256
+ className: cn(
5257
+ "px-4 py-3",
5258
+ stacked ? "flex flex-col gap-0.5" : "flex items-center justify-between gap-4"
5259
+ ),
5260
+ children: [
5261
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("dt", { className: "text-sm text-muted-foreground", children: item.label }),
5262
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
5263
+ "dd",
5264
+ {
5265
+ className: cn(
5266
+ "text-sm text-foreground",
5267
+ !stacked && "text-right tabular-nums"
5268
+ ),
5269
+ children: item.value
5270
+ }
5271
+ )
5272
+ ]
5273
+ },
5274
+ i
5275
+ ))
5276
+ }
4658
5277
  );
4659
- var pillSegmentedTrackClass = cn(
4660
- pillSegmentedTrackBase,
4661
- pillSegmentedTrackSurface,
4662
- "gap-1 p-1"
5278
+
5279
+ // src/app/surfaces/ExpandableSection.tsx
5280
+ var import_react37 = require("react");
5281
+ var import_react38 = require("motion/react");
5282
+ var import_jsx_runtime46 = require("react/jsx-runtime");
5283
+ var Chevron = ({ open }) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
5284
+ "svg",
5285
+ {
5286
+ viewBox: "0 0 24 24",
5287
+ className: cn(
5288
+ "size-4 text-muted-foreground transition-transform duration-200",
5289
+ open && "rotate-180"
5290
+ ),
5291
+ fill: "none",
5292
+ stroke: "currentColor",
5293
+ strokeWidth: 2,
5294
+ strokeLinecap: "round",
5295
+ strokeLinejoin: "round",
5296
+ "aria-hidden": true,
5297
+ children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("path", { d: "m6 9 6 6 6-6" })
5298
+ }
4663
5299
  );
4664
- var pillSegmentedTrackFlushClass = cn(
4665
- pillSegmentedTrackBase,
4666
- pillSegmentedTrackSurface,
4667
- "h-[var(--studio-chrome-pill-height)] items-center gap-0.5 overflow-visible p-0.5"
5300
+ var ExpandableSection = ({
5301
+ title,
5302
+ icon,
5303
+ count,
5304
+ children,
5305
+ open: openProp,
5306
+ defaultOpen = false,
5307
+ onOpenChange,
5308
+ className
5309
+ }) => {
5310
+ const reduceMotion = (0, import_react38.useReducedMotion)();
5311
+ const panelId = (0, import_react37.useId)();
5312
+ const [internalOpen, setInternalOpen] = (0, import_react37.useState)(defaultOpen);
5313
+ const open = openProp ?? internalOpen;
5314
+ const toggle = () => {
5315
+ if (openProp == null) setInternalOpen((o) => !o);
5316
+ onOpenChange?.(!open);
5317
+ };
5318
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: cn("border-b border-border last:border-0", className), children: [
5319
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
5320
+ "button",
5321
+ {
5322
+ type: "button",
5323
+ onClick: toggle,
5324
+ "aria-expanded": open,
5325
+ "aria-controls": panelId,
5326
+ className: "flex w-full items-center justify-between gap-3 bg-transparent px-4 py-3 text-left hover:bg-transparent active:bg-transparent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-foreground/10",
5327
+ children: [
5328
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "flex min-w-0 items-center gap-3", children: [
5329
+ icon ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "flex size-8 items-center justify-center rounded-lg border border-border bg-muted text-muted-foreground", children: icon }) : null,
5330
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "truncate text-sm font-medium text-foreground", children: title }),
5331
+ count != null ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "rounded-full border border-border bg-muted px-2 py-0.5 text-xs text-muted-foreground", children: count }) : null
5332
+ ] }),
5333
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Chevron, { open })
5334
+ ]
5335
+ }
5336
+ ),
5337
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_react38.AnimatePresence, { initial: false, children: open ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
5338
+ import_react38.motion.div,
5339
+ {
5340
+ id: panelId,
5341
+ initial: reduceMotion ? void 0 : { height: 0, opacity: 0 },
5342
+ animate: { height: "auto", opacity: 1 },
5343
+ exit: reduceMotion ? void 0 : { height: 0, opacity: 0 },
5344
+ transition: { duration: 0.2, ease: "easeOut" },
5345
+ className: "overflow-hidden",
5346
+ children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "bg-muted/20", children })
5347
+ },
5348
+ "body"
5349
+ ) : null })
5350
+ ] });
5351
+ };
5352
+
5353
+ // src/app/surfaces/ResourceCard.tsx
5354
+ var import_jsx_runtime47 = require("react/jsx-runtime");
5355
+ var resourceCardShellClass = cn(
5356
+ "flex min-h-[8.5rem] flex-col rounded-2xl p-4 text-left font-normal",
5357
+ TIMBAL_V2_ELEVATED_SURFACE
4668
5358
  );
4669
- var pillSegmentedSegmentClass = cn(
4670
- "relative flex items-center gap-1.5 rounded-full px-4 py-1.5 text-xs font-normal transition-colors"
5359
+ var mediaShellClass = cn(
5360
+ "flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-xl text-sm font-normal text-foreground",
5361
+ TIMBAL_V2_LOGO_TILE
4671
5362
  );
4672
- var pillSegmentedFlushSegmentClass = cn(
5363
+ var resourceCardInteractiveClass = cn(
5364
+ resourceCardShellClass,
5365
+ "cursor-pointer bg-transparent hover:bg-transparent active:bg-transparent",
5366
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15 focus-visible:ring-offset-2 focus-visible:ring-offset-background"
5367
+ );
5368
+ var ResourceCard = ({
5369
+ title,
5370
+ subtitle,
5371
+ media,
5372
+ badge,
5373
+ footer,
5374
+ action,
5375
+ onClick,
5376
+ ariaLabel,
5377
+ className
5378
+ }) => {
5379
+ const body = /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
5380
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-start gap-3", children: [
5381
+ media ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: mediaShellClass, children: media }) : null,
5382
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "min-w-0 flex-1 pt-0.5", children: [
5383
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "truncate text-sm font-normal leading-snug text-foreground", children: title }),
5384
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "mt-1 line-clamp-2 text-xs font-normal text-muted-foreground", children: subtitle }) : null
5385
+ ] }),
5386
+ badge ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "shrink-0 pt-0.5", children: badge }) : null
5387
+ ] }),
5388
+ footer || action ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "mt-auto flex items-center justify-between gap-3 border-t border-border/40 pt-3 text-xs font-normal text-muted-foreground", children: [
5389
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "min-w-0 truncate", children: footer }),
5390
+ action ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "shrink-0 opacity-80", children: action }) : null
5391
+ ] }) : null
5392
+ ] });
5393
+ if (onClick) {
5394
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", onClick, "aria-label": ariaLabel, className: cn(resourceCardInteractiveClass, className), children: body });
5395
+ }
5396
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("article", { className: cn(resourceCardShellClass, className), children: body });
5397
+ };
5398
+
5399
+ // src/app/settings/SettingsSection.tsx
5400
+ var import_jsx_runtime48 = require("react/jsx-runtime");
5401
+ var SettingsSectionHeader = ({
5402
+ title,
5403
+ description,
5404
+ className
5405
+ }) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: cn("flex flex-col", className), children: [
5406
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("h3", { className: "text-[17px] font-medium leading-tight text-foreground", children: title }),
5407
+ description ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null
5408
+ ] });
5409
+ var SettingsSection = ({
5410
+ title,
5411
+ description,
5412
+ descriptionFooter,
5413
+ children,
5414
+ noBorderTop = false,
5415
+ className
5416
+ }) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
5417
+ "section",
5418
+ {
5419
+ className: cn(
5420
+ "grid grid-cols-1 gap-y-4 lg:grid-cols-[minmax(200px,280px)_minmax(0,1fr)] lg:gap-x-12 lg:gap-y-0",
5421
+ noBorderTop ? "pb-6" : "border-t border-border py-6",
5422
+ className
5423
+ ),
5424
+ children: [
5425
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "min-w-0", children: [
5426
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("h2", { className: "text-sm font-medium text-foreground", children: title }),
5427
+ description ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null,
5428
+ descriptionFooter ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "mt-3 min-w-0", children: descriptionFooter }) : null
5429
+ ] }),
5430
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "min-w-0 space-y-3", children })
5431
+ ]
5432
+ }
5433
+ );
5434
+
5435
+ // src/app/settings/FieldRow.tsx
5436
+ var import_jsx_runtime49 = require("react/jsx-runtime");
5437
+ var FieldRow = ({
5438
+ label,
5439
+ children,
5440
+ description,
5441
+ inline = false,
5442
+ htmlFor,
5443
+ className
5444
+ }) => {
5445
+ if (inline) {
5446
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
5447
+ "div",
5448
+ {
5449
+ className: cn(
5450
+ "flex items-center justify-between gap-4 rounded-lg border border-border bg-card px-3.5 py-3",
5451
+ className
5452
+ ),
5453
+ children: [
5454
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "min-w-0", children: [
5455
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
5456
+ "label",
5457
+ {
5458
+ htmlFor,
5459
+ className: "block text-sm font-medium text-foreground",
5460
+ children: label
5461
+ }
5462
+ ),
5463
+ description ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "mt-0.5 text-xs text-muted-foreground", children: description }) : null
5464
+ ] }),
5465
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "shrink-0", children })
5466
+ ]
5467
+ }
5468
+ );
5469
+ }
5470
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: cn("flex flex-col gap-1.5", className), children: [
5471
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("label", { htmlFor, className: "text-sm font-medium text-foreground", children: label }),
5472
+ children,
5473
+ description ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-xs text-muted-foreground", children: description }) : null
5474
+ ] });
5475
+ };
5476
+
5477
+ // src/app/settings/FloatingUnsavedChangesBar.tsx
5478
+ var import_react39 = require("react");
5479
+ var import_react_dom = require("react-dom");
5480
+ var import_react40 = require("motion/react");
5481
+ var import_jsx_runtime50 = require("react/jsx-runtime");
5482
+ var FloatingUnsavedChangesBar = ({
5483
+ visible,
5484
+ message = "Unsaved changes",
5485
+ discardLabel = "Discard",
5486
+ saveLabel = "Save changes",
5487
+ isSaving = false,
5488
+ saveDisabled = false,
5489
+ onDiscard,
5490
+ onSave,
5491
+ ariaLabel = "Unsaved changes",
5492
+ className
5493
+ }) => {
5494
+ const reduceMotion = (0, import_react40.useReducedMotion)();
5495
+ const [mounted, setMounted] = (0, import_react39.useState)(false);
5496
+ (0, import_react39.useEffect)(() => setMounted(true), []);
5497
+ if (!mounted || typeof document === "undefined") return null;
5498
+ return (0, import_react_dom.createPortal)(
5499
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_react40.AnimatePresence, { children: visible ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "pointer-events-none fixed inset-x-0 bottom-5 z-50 flex justify-center px-4", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
5500
+ import_react40.motion.div,
5501
+ {
5502
+ role: "region",
5503
+ "aria-label": ariaLabel,
5504
+ initial: reduceMotion ? { opacity: 0 } : { opacity: 0, y: 28, scale: 0.94 },
5505
+ animate: { opacity: 1, y: 0, scale: 1 },
5506
+ exit: reduceMotion ? { opacity: 0 } : { opacity: 0, y: 18, scale: 0.96 },
5507
+ transition: { type: "spring", stiffness: 420, damping: 32 },
5508
+ className: cn(
5509
+ "pointer-events-auto inline-flex max-w-[calc(100vw-2rem)] items-center gap-3 rounded-full border border-border bg-card py-1.5 pl-4 pr-1.5 shadow-card-elevated",
5510
+ className
5511
+ ),
5512
+ children: [
5513
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "text-sm text-muted-foreground", children: message }),
5514
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "flex items-center gap-1.5", children: [
5515
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(Button, { variant: "ghost", size: "sm", onClick: onDiscard, disabled: isSaving, children: discardLabel }),
5516
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(Button, { size: "sm", onClick: onSave, disabled: saveDisabled || isSaving, children: isSaving ? "Saving\u2026" : saveLabel })
5517
+ ] })
5518
+ ]
5519
+ }
5520
+ ) }) : null }),
5521
+ document.body
5522
+ );
5523
+ };
5524
+
5525
+ // src/app/settings/DangerZone.tsx
5526
+ var import_jsx_runtime51 = require("react/jsx-runtime");
5527
+ var DangerZoneAction = ({
5528
+ title,
5529
+ description,
5530
+ action,
5531
+ className
5532
+ }) => /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
5533
+ "div",
5534
+ {
5535
+ className: cn(
5536
+ "flex flex-col gap-3 px-4 py-3.5 sm:flex-row sm:items-center sm:justify-between",
5537
+ className
5538
+ ),
5539
+ children: [
5540
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "min-w-0", children: [
5541
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("p", { className: "text-sm font-medium text-foreground", children: title }),
5542
+ description ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
5543
+ ] }),
5544
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "shrink-0", children: action })
5545
+ ]
5546
+ }
5547
+ );
5548
+ var DangerZone = ({
5549
+ title = "Danger zone",
5550
+ description,
5551
+ children,
5552
+ className
5553
+ }) => /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
5554
+ "section",
5555
+ {
5556
+ className: cn(
5557
+ "overflow-hidden rounded-xl border border-destructive/30",
5558
+ className
5559
+ ),
5560
+ children: [
5561
+ (title || description) && /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("header", { className: "border-b border-destructive/20 bg-destructive/5 px-4 py-3", children: [
5562
+ title ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("h3", { className: "text-sm font-semibold text-destructive", children: title }) : null,
5563
+ description ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
5564
+ ] }),
5565
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "divide-y divide-border bg-card", children })
5566
+ ]
5567
+ }
5568
+ );
5569
+
5570
+ // src/app/integrations/IntegrationCard.tsx
5571
+ var import_react41 = require("react");
5572
+ var import_jsx_runtime52 = require("react/jsx-runtime");
5573
+ var INTEGRATION_CATALOG_CARD_HEIGHT_CLASS = "h-[12.25rem] min-h-[12.25rem] max-h-[12.25rem]";
5574
+ var statusLabel = {
5575
+ available: null,
5576
+ connected: "Connected",
5577
+ disabled: "Disabled",
5578
+ locked: "Locked"
5579
+ };
5580
+ var catalogCardShellClass = cn(
5581
+ "group relative box-border flex flex-col overflow-hidden rounded-2xl px-4 pb-4 pt-4 text-left font-normal",
5582
+ INTEGRATION_CATALOG_CARD_HEIGHT_CLASS,
5583
+ TIMBAL_V2_ELEVATED_SURFACE,
5584
+ "transition-opacity duration-200 ease-out"
5585
+ );
5586
+ var catalogCardInteractiveClass = cn(
5587
+ catalogCardShellClass,
5588
+ "cursor-pointer bg-transparent hover:bg-transparent active:bg-transparent",
5589
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15 focus-visible:ring-offset-2 focus-visible:ring-offset-background"
5590
+ );
5591
+ var catalogCardMutedClass = cn(
5592
+ "border-border/60 saturate-[0.72]",
5593
+ "from-muted/80 to-muted/50 dark:border-white/[0.06] dark:from-white/[0.04] dark:to-white/[0.02]"
5594
+ );
5595
+ var logoShellClass = cn(
5596
+ "relative flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-xl",
5597
+ TIMBAL_V2_LOGO_TILE
5598
+ );
5599
+ var IntegrationCard = ({
5600
+ name,
5601
+ description,
5602
+ logo,
5603
+ badge,
5604
+ status = "available",
5605
+ action,
5606
+ onClick,
5607
+ ariaLabel,
5608
+ className
5609
+ }) => {
5610
+ const titleId = (0, import_react41.useId)();
5611
+ const locked = status === "locked";
5612
+ const dimmed = status === "disabled" || locked;
5613
+ const body = /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "flex h-full min-h-0 flex-col", children: [
5614
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "flex shrink-0 items-start gap-3 pr-2", children: [
5615
+ logo ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: logoShellClass, "aria-hidden": Boolean(ariaLabel), children: logo }) : null,
5616
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "min-w-0 flex-1 pt-0.5", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "flex items-start justify-between gap-2", children: [
5617
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "min-w-0", children: [
5618
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
5619
+ "h4",
5620
+ {
5621
+ id: onClick && !action ? void 0 : titleId,
5622
+ className: "truncate text-sm font-normal leading-snug text-foreground",
5623
+ children: name
5624
+ }
5625
+ ),
5626
+ statusLabel[status] ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("p", { className: "mt-0.5 text-xs text-muted-foreground", children: statusLabel[status] }) : null
5627
+ ] }),
5628
+ badge ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "shrink-0", children: badge }) : null
5629
+ ] }) })
5630
+ ] }),
5631
+ description ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
5632
+ "p",
5633
+ {
5634
+ className: cn(
5635
+ "mt-3 line-clamp-3 shrink-0 text-sm leading-relaxed text-muted-foreground",
5636
+ dimmed && "text-muted-foreground/80"
5637
+ ),
5638
+ children: description
5639
+ }
5640
+ ) : null,
5641
+ action ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_jsx_runtime52.Fragment, { children: [
5642
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "min-h-0 flex-1", "aria-hidden": true }),
5643
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "relative mt-3 shrink-0", children: action })
5644
+ ] }) : null
5645
+ ] });
5646
+ const shellClass3 = cn(
5647
+ catalogCardShellClass,
5648
+ dimmed && catalogCardMutedClass,
5649
+ locked && "cursor-default opacity-75",
5650
+ className
5651
+ );
5652
+ if (onClick && !action) {
5653
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
5654
+ "button",
5655
+ {
5656
+ type: "button",
5657
+ onClick,
5658
+ disabled: locked,
5659
+ "aria-label": ariaLabel,
5660
+ className: cn(
5661
+ catalogCardInteractiveClass,
5662
+ dimmed && catalogCardMutedClass,
5663
+ locked && "cursor-default opacity-75",
5664
+ className
5665
+ ),
5666
+ children: body
5667
+ }
5668
+ );
5669
+ }
5670
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("article", { className: shellClass3, "aria-labelledby": titleId, children: body });
5671
+ };
5672
+
5673
+ // src/app/integrations/IntegrationsEmptyState.tsx
5674
+ var import_react42 = require("react");
5675
+ var import_jsx_runtime53 = require("react/jsx-runtime");
5676
+ var IntegrationsEmptyState = ({
5677
+ title = "No integrations yet",
5678
+ description = "Connect a provider to start syncing data and powering your workforce.",
5679
+ icon,
5680
+ action,
5681
+ className
5682
+ }) => {
5683
+ const titleId = (0, import_react42.useId)();
5684
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
5685
+ "section",
5686
+ {
5687
+ className: cn(
5688
+ "flex flex-col items-center justify-center gap-3 rounded-2xl px-6 py-14 text-center",
5689
+ TIMBAL_V2_ELEVATED_SURFACE,
5690
+ className
5691
+ ),
5692
+ "aria-labelledby": titleId,
5693
+ children: [
5694
+ icon ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
5695
+ "span",
5696
+ {
5697
+ className: cn(
5698
+ "flex size-14 items-center justify-center overflow-hidden rounded-2xl",
5699
+ TIMBAL_V2_LOGO_TILE,
5700
+ "text-muted-foreground"
5701
+ ),
5702
+ "aria-hidden": true,
5703
+ children: icon
5704
+ }
5705
+ ) : null,
5706
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("h3", { id: titleId, className: "text-base font-normal text-foreground", children: title }),
5707
+ description ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("p", { className: "max-w-sm text-sm text-muted-foreground", children: description }) : null,
5708
+ action ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "mt-1", children: action }) : null
5709
+ ]
5710
+ }
5711
+ );
5712
+ };
5713
+
5714
+ // src/app/integrations/PlanBadge.tsx
5715
+ var import_jsx_runtime54 = require("react/jsx-runtime");
5716
+ var planBadgeClass = "inline-flex h-5 max-w-full shrink-0 items-center rounded-md border border-border bg-muted/90 px-2 text-[11px] font-normal text-muted-foreground dark:border-white/10 dark:bg-white/5 dark:text-muted-foreground";
5717
+ var PlanBadge = ({ children, className }) => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: cn(planBadgeClass, className), children });
5718
+
5719
+ // src/app/integrations/ConnectionRow.tsx
5720
+ var import_jsx_runtime55 = require("react/jsx-runtime");
5721
+ var logoShellClass2 = cn(
5722
+ "flex size-9 shrink-0 items-center justify-center overflow-hidden rounded-lg",
5723
+ TIMBAL_V2_LOGO_TILE
5724
+ );
5725
+ var ConnectionRow = ({
5726
+ name,
5727
+ logo,
5728
+ meta,
5729
+ badge,
5730
+ action,
5731
+ onClick,
5732
+ ariaLabel,
5733
+ className
5734
+ }) => {
5735
+ const inner = /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_jsx_runtime55.Fragment, { children: [
5736
+ logo ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: logoShellClass2, children: logo }) : null,
5737
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "min-w-0 flex-1", children: [
5738
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "truncate text-sm font-normal text-foreground", children: name }),
5739
+ meta ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "truncate text-xs text-muted-foreground", children: meta }) : null
5740
+ ] }),
5741
+ badge ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "shrink-0", children: badge }) : null,
5742
+ action ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "shrink-0", children: action }) : null
5743
+ ] });
5744
+ const rowClass2 = cn(
5745
+ "flex w-full items-center gap-3 px-4 py-3 text-left",
5746
+ onClick && "cursor-pointer bg-transparent hover:bg-transparent active:bg-transparent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-foreground/10",
5747
+ className
5748
+ );
5749
+ if (onClick) {
5750
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
5751
+ "button",
5752
+ {
5753
+ type: "button",
5754
+ role: "listitem",
5755
+ onClick,
5756
+ "aria-label": ariaLabel,
5757
+ className: rowClass2,
5758
+ children: inner
5759
+ }
5760
+ );
5761
+ }
5762
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { role: "listitem", className: rowClass2, children: inner });
5763
+ };
5764
+ var connectionRowListClass = cn(
5765
+ "overflow-hidden rounded-2xl",
5766
+ TIMBAL_V2_ELEVATED_SURFACE
5767
+ );
5768
+
5769
+ // src/app/integrations/ConnectionRowList.tsx
5770
+ var import_jsx_runtime56 = require("react/jsx-runtime");
5771
+ var ConnectionRowList = ({
5772
+ children,
5773
+ "aria-label": ariaLabel = "Connected integrations",
5774
+ className
5775
+ }) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
5776
+ "div",
5777
+ {
5778
+ role: "list",
5779
+ "aria-label": ariaLabel,
5780
+ className: cn(connectionRowListClass, "divide-y divide-border", className),
5781
+ children
5782
+ }
5783
+ );
5784
+
5785
+ // src/ui/pill-segmented-tabs.tsx
5786
+ var import_react43 = require("react");
5787
+ var import_react44 = require("motion/react");
5788
+
5789
+ // src/design/pill-segmented-classes.ts
5790
+ var pillSegmentedTrackBase = "inline-flex w-fit max-w-max shrink-0 self-start items-center rounded-full";
5791
+ var pillSegmentedTrackSurface = cn(
5792
+ "bg-pill-segmented-track border border-[var(--pill-segmented-track-border)]",
5793
+ "shadow-[var(--pill-segmented-track-shadow)]"
5794
+ );
5795
+ var pillSegmentedTrackClass = cn(
5796
+ pillSegmentedTrackBase,
5797
+ pillSegmentedTrackSurface,
5798
+ "gap-1 p-1"
5799
+ );
5800
+ var pillSegmentedTrackFlushClass = cn(
5801
+ pillSegmentedTrackBase,
5802
+ pillSegmentedTrackSurface,
5803
+ "h-[var(--studio-chrome-pill-height)] items-center gap-0.5 overflow-visible p-0.5"
5804
+ );
5805
+ var pillSegmentedSegmentClass = cn(
5806
+ "relative flex items-center gap-1.5 rounded-full px-4 py-1.5 text-xs font-normal transition-colors"
5807
+ );
5808
+ var pillSegmentedFlushSegmentClass = cn(
4673
5809
  "relative box-border inline-flex h-9 min-h-9 items-center justify-center gap-1.5 rounded-full px-3.5 py-0",
4674
5810
  "text-sm font-normal leading-tight transition-colors"
4675
5811
  );
@@ -4681,7 +5817,7 @@ var pillSegmentedActiveIndicatorClass = cn(
4681
5817
  );
4682
5818
 
4683
5819
  // src/ui/pill-segmented-tabs.tsx
4684
- var import_jsx_runtime42 = require("react/jsx-runtime");
5820
+ var import_jsx_runtime57 = require("react/jsx-runtime");
4685
5821
  var PillTab = ({
4686
5822
  tabKey,
4687
5823
  label,
@@ -4692,10 +5828,10 @@ var PillTab = ({
4692
5828
  segmentClassName,
4693
5829
  animateIndicator
4694
5830
  }) => {
4695
- const handlePress = (0, import_react35.useCallback)(() => {
5831
+ const handlePress = (0, import_react43.useCallback)(() => {
4696
5832
  if (!disabled) onSelect(tabKey);
4697
5833
  }, [disabled, onSelect, tabKey]);
4698
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
5834
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
4699
5835
  "button",
4700
5836
  {
4701
5837
  type: "button",
@@ -4708,15 +5844,15 @@ var PillTab = ({
4708
5844
  !disabled && (isActive ? "text-foreground" : "text-muted-foreground hover:text-foreground")
4709
5845
  ),
4710
5846
  children: [
4711
- isActive && animateIndicator ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4712
- import_react36.motion.div,
5847
+ isActive && animateIndicator ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
5848
+ import_react44.motion.div,
4713
5849
  {
4714
5850
  layoutId,
4715
5851
  className: pillSegmentedActiveIndicatorClass,
4716
5852
  transition: { type: "spring", duration: 0.3, bounce: 0.15 }
4717
5853
  }
4718
- ) : isActive ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: pillSegmentedActiveIndicatorClass, "aria-hidden": true }) : null,
4719
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "relative z-10 whitespace-nowrap", children: label })
5854
+ ) : isActive ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: pillSegmentedActiveIndicatorClass, "aria-hidden": true }) : null,
5855
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "relative z-10 whitespace-nowrap", children: label })
4720
5856
  ]
4721
5857
  }
4722
5858
  );
@@ -4730,13 +5866,13 @@ var PillSegmentedTabs = ({
4730
5866
  layoutId: layoutIdProp,
4731
5867
  "aria-label": ariaLabel
4732
5868
  }) => {
4733
- const reactId = (0, import_react35.useId)();
5869
+ const reactId = (0, import_react43.useId)();
4734
5870
  const layoutId = layoutIdProp ?? `pill-segmented-${reactId.replace(/:/g, "")}`;
4735
- const reducedMotion = (0, import_react36.useReducedMotion)();
5871
+ const reducedMotion = (0, import_react44.useReducedMotion)();
4736
5872
  const isFlush = trackVariant === "flush";
4737
5873
  const trackClass2 = isFlush ? pillSegmentedTrackFlushClass : pillSegmentedTrackClass;
4738
5874
  const segmentClassName = isFlush ? pillSegmentedFlushSegmentClass : pillSegmentedSegmentClass;
4739
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { role: "group", "aria-label": ariaLabel, className: cn(trackClass2, className), children: tabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
5875
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { role: "group", "aria-label": ariaLabel, className: cn(trackClass2, className), children: tabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
4740
5876
  PillTab,
4741
5877
  {
4742
5878
  tabKey: tab.key,
@@ -4751,10 +5887,10 @@ var PillSegmentedTabs = ({
4751
5887
  tab.key
4752
5888
  )) });
4753
5889
  };
4754
- var MemoPillSegmentedTabs = (0, import_react35.memo)(PillSegmentedTabs);
5890
+ var MemoPillSegmentedTabs = (0, import_react43.memo)(PillSegmentedTabs);
4755
5891
 
4756
5892
  // src/app/navigation/SubNav.tsx
4757
- var import_jsx_runtime43 = require("react/jsx-runtime");
5893
+ var import_jsx_runtime58 = require("react/jsx-runtime");
4758
5894
  var SubNav = ({
4759
5895
  items,
4760
5896
  activeId,
@@ -4763,7 +5899,7 @@ var SubNav = ({
4763
5899
  "aria-label": ariaLabel = "Section navigation",
4764
5900
  layoutId
4765
5901
  }) => {
4766
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("nav", { className: cn("aui-app-sub-nav", className), "aria-label": ariaLabel, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
5902
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)("nav", { className: cn("aui-app-sub-nav", className), "aria-label": ariaLabel, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
4767
5903
  PillSegmentedTabs,
4768
5904
  {
4769
5905
  value: activeId,
@@ -4777,13 +5913,13 @@ var SubNav = ({
4777
5913
  };
4778
5914
 
4779
5915
  // src/app/navigation/Breadcrumbs.tsx
4780
- var import_jsx_runtime44 = require("react/jsx-runtime");
5916
+ var import_jsx_runtime59 = require("react/jsx-runtime");
4781
5917
  var Breadcrumbs = ({ items, className }) => {
4782
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("nav", { className: cn("aui-app-breadcrumbs", appBreadcrumbsClass, className), "aria-label": "Breadcrumb", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("ol", { className: "flex flex-wrap items-center gap-1.5", children: items.map((item, index) => {
5918
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("nav", { className: cn("aui-app-breadcrumbs", appBreadcrumbsClass, className), "aria-label": "Breadcrumb", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("ol", { className: "flex flex-wrap items-center gap-1.5", children: items.map((item, index) => {
4783
5919
  const isLast = index === items.length - 1;
4784
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("li", { className: "inline-flex items-center gap-1.5", children: [
4785
- index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-muted-foreground/50", "aria-hidden": true, children: "/" }) : null,
4786
- isLast ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-foreground", "aria-current": "page", children: item.label }) : item.href ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("a", { href: item.href, className: appBreadcrumbLinkClass, children: item.label }) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
5920
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("li", { className: "inline-flex items-center gap-1.5", children: [
5921
+ index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "text-muted-foreground/50", "aria-hidden": true, children: "/" }) : null,
5922
+ isLast ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "text-foreground", "aria-current": "page", children: item.label }) : item.href ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("a", { href: item.href, className: appBreadcrumbLinkClass, children: item.label }) : /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
4787
5923
  "button",
4788
5924
  {
4789
5925
  type: "button",
@@ -4797,7 +5933,7 @@ var Breadcrumbs = ({ items, className }) => {
4797
5933
  };
4798
5934
 
4799
5935
  // src/app/forms/Field.tsx
4800
- var import_jsx_runtime45 = require("react/jsx-runtime");
5936
+ var import_jsx_runtime60 = require("react/jsx-runtime");
4801
5937
  var Field = ({
4802
5938
  label,
4803
5939
  hint,
@@ -4806,11 +5942,11 @@ var Field = ({
4806
5942
  className,
4807
5943
  htmlFor
4808
5944
  }) => {
4809
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: cn("aui-app-field", appFieldClass, className), children: [
4810
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("label", { className: appFieldLabelClass, htmlFor, children: label }),
5945
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: cn("aui-app-field", appFieldClass, className), children: [
5946
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("label", { className: appFieldLabelClass, htmlFor, children: label }),
4811
5947
  children,
4812
- hint && !error ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: appFieldHintClass, children: hint }) : null,
4813
- error ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: "text-xs text-destructive", role: "alert", children: error }) : null
5948
+ hint && !error ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { className: appFieldHintClass, children: hint }) : null,
5949
+ error ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { className: "text-xs text-destructive", role: "alert", children: error }) : null
4814
5950
  ] });
4815
5951
  };
4816
5952
  var FieldInput = ({
@@ -4823,7 +5959,7 @@ var FieldInput = ({
4823
5959
  ...inputProps
4824
5960
  }) => {
4825
5961
  const inputId = id ?? inputProps.name;
4826
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
5962
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
4827
5963
  Field,
4828
5964
  {
4829
5965
  label,
@@ -4831,7 +5967,7 @@ var FieldInput = ({
4831
5967
  error,
4832
5968
  htmlFor: inputId,
4833
5969
  className: fieldClassName,
4834
- children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
5970
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
4835
5971
  "input",
4836
5972
  {
4837
5973
  id: inputId,
@@ -4845,7 +5981,7 @@ var FieldInput = ({
4845
5981
  };
4846
5982
 
4847
5983
  // src/app/forms/FieldTextarea.tsx
4848
- var import_jsx_runtime46 = require("react/jsx-runtime");
5984
+ var import_jsx_runtime61 = require("react/jsx-runtime");
4849
5985
  var textareaClass = cn(
4850
5986
  appInputClass,
4851
5987
  "min-h-[5.5rem] resize-y py-2.5 leading-relaxed"
@@ -4860,7 +5996,7 @@ var FieldTextarea = ({
4860
5996
  ...props
4861
5997
  }) => {
4862
5998
  const textareaId = id ?? props.name;
4863
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
5999
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
4864
6000
  Field,
4865
6001
  {
4866
6002
  label,
@@ -4868,7 +6004,7 @@ var FieldTextarea = ({
4868
6004
  error,
4869
6005
  htmlFor: textareaId,
4870
6006
  className: fieldClassName,
4871
- children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
6007
+ children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
4872
6008
  "textarea",
4873
6009
  {
4874
6010
  id: textareaId,
@@ -4883,7 +6019,7 @@ var FieldTextarea = ({
4883
6019
 
4884
6020
  // src/app/forms/FieldSelect.tsx
4885
6021
  var import_lucide_react10 = require("lucide-react");
4886
- var import_jsx_runtime47 = require("react/jsx-runtime");
6022
+ var import_jsx_runtime62 = require("react/jsx-runtime");
4887
6023
  var selectWrapClass = "relative";
4888
6024
  var selectClass = cn(
4889
6025
  appInputClass,
@@ -4900,7 +6036,7 @@ var FieldSelect = ({
4900
6036
  ...props
4901
6037
  }) => {
4902
6038
  const selectId = id ?? props.name;
4903
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
6039
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
4904
6040
  Field,
4905
6041
  {
4906
6042
  label,
@@ -4908,8 +6044,8 @@ var FieldSelect = ({
4908
6044
  error,
4909
6045
  htmlFor: selectId,
4910
6046
  className: fieldClassName,
4911
- children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: selectWrapClass, children: [
4912
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
6047
+ children: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: selectWrapClass, children: [
6048
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
4913
6049
  "select",
4914
6050
  {
4915
6051
  id: selectId,
@@ -4919,7 +6055,7 @@ var FieldSelect = ({
4919
6055
  children
4920
6056
  }
4921
6057
  ),
4922
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
6058
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
4923
6059
  import_lucide_react10.ChevronDownIcon,
4924
6060
  {
4925
6061
  className: "pointer-events-none absolute top-1/2 right-3 size-4 -translate-y-1/2 text-muted-foreground",
@@ -4932,7 +6068,7 @@ var FieldSelect = ({
4932
6068
  };
4933
6069
 
4934
6070
  // src/app/forms/FieldSwitch.tsx
4935
- var import_jsx_runtime48 = require("react/jsx-runtime");
6071
+ var import_jsx_runtime63 = require("react/jsx-runtime");
4936
6072
  var trackClass = cn(
4937
6073
  "relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-[background,box-shadow,border-color] duration-200",
4938
6074
  "peer-focus-visible:ring-2 peer-focus-visible:ring-foreground/10",
@@ -4953,7 +6089,7 @@ var FieldSwitch = ({
4953
6089
  ...props
4954
6090
  }) => {
4955
6091
  const inputId = id ?? props.name ?? "switch";
4956
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
6092
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
4957
6093
  "label",
4958
6094
  {
4959
6095
  className: cn(
@@ -4962,8 +6098,8 @@ var FieldSwitch = ({
4962
6098
  ),
4963
6099
  htmlFor: inputId,
4964
6100
  children: [
4965
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "relative mt-0.5", children: [
4966
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
6101
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { className: "relative mt-0.5", children: [
6102
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
4967
6103
  "input",
4968
6104
  {
4969
6105
  id: inputId,
@@ -4973,11 +6109,11 @@ var FieldSwitch = ({
4973
6109
  ...props
4974
6110
  }
4975
6111
  ),
4976
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: trackClass, "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: thumbClass }) })
6112
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: trackClass, "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: thumbClass }) })
4977
6113
  ] }),
4978
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "flex min-w-0 flex-col gap-0.5", children: [
4979
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "text-sm font-medium text-foreground", children: label }),
4980
- description ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "text-xs text-muted-foreground", children: description }) : null
6114
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { className: "flex min-w-0 flex-col gap-0.5", children: [
6115
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "text-sm font-medium text-foreground", children: label }),
6116
+ description ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "text-xs text-muted-foreground", children: description }) : null
4981
6117
  ] })
4982
6118
  ]
4983
6119
  }
@@ -4986,13 +6122,13 @@ var FieldSwitch = ({
4986
6122
 
4987
6123
  // src/app/forms/SearchInput.tsx
4988
6124
  var import_lucide_react11 = require("lucide-react");
4989
- var import_jsx_runtime49 = require("react/jsx-runtime");
6125
+ var import_jsx_runtime64 = require("react/jsx-runtime");
4990
6126
  var SearchInput = ({
4991
6127
  className,
4992
6128
  placeholder = "Search\u2026",
4993
6129
  ...props
4994
6130
  }) => {
4995
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
6131
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
4996
6132
  "label",
4997
6133
  {
4998
6134
  className: cn(
@@ -5001,8 +6137,8 @@ var SearchInput = ({
5001
6137
  className
5002
6138
  ),
5003
6139
  children: [
5004
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_lucide_react11.SearchIcon, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": true }),
5005
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
6140
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(import_lucide_react11.SearchIcon, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": true }),
6141
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
5006
6142
  "input",
5007
6143
  {
5008
6144
  type: "search",
@@ -5017,18 +6153,18 @@ var SearchInput = ({
5017
6153
  };
5018
6154
 
5019
6155
  // src/app/forms/FormSection.tsx
5020
- var import_jsx_runtime50 = require("react/jsx-runtime");
6156
+ var import_jsx_runtime65 = require("react/jsx-runtime");
5021
6157
  var FormSection = ({ title, children, className }) => {
5022
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("fieldset", { className: cn("aui-app-form-section", appSectionClass, "border-0 p-0", className), children: [
5023
- title ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("legend", { className: cn(appSectionTitleClass, "mb-3 px-0"), children: title }) : null,
5024
- /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "flex flex-col gap-4", children })
6158
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("fieldset", { className: cn("aui-app-form-section", appSectionClass, "border-0 p-0", className), children: [
6159
+ title ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("legend", { className: cn(appSectionTitleClass, "mb-3 px-0"), children: title }) : null,
6160
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { className: "flex flex-col gap-4", children })
5025
6161
  ] });
5026
6162
  };
5027
6163
 
5028
6164
  // src/app/data/FilterBar.tsx
5029
- var import_jsx_runtime51 = require("react/jsx-runtime");
6165
+ var import_jsx_runtime66 = require("react/jsx-runtime");
5030
6166
  var FilterBar = ({ children, className }) => {
5031
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
6167
+ return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
5032
6168
  "div",
5033
6169
  {
5034
6170
  className: cn("aui-app-filter-bar", appFilterBarClass, className),
@@ -5040,9 +6176,9 @@ var FilterBar = ({ children, className }) => {
5040
6176
  };
5041
6177
 
5042
6178
  // src/app/data/DataTable.tsx
5043
- var import_react37 = require("react");
6179
+ var import_react45 = require("react");
5044
6180
  var import_lucide_react12 = require("lucide-react");
5045
- var import_jsx_runtime52 = require("react/jsx-runtime");
6181
+ var import_jsx_runtime67 = require("react/jsx-runtime");
5046
6182
  var shellClass2 = "overflow-hidden rounded-xl border border-border bg-card shadow-card";
5047
6183
  var tableClass = "w-full border-collapse bg-transparent text-sm";
5048
6184
  var headCellClass = "border-b border-border/60 bg-transparent px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide text-muted-foreground";
@@ -5082,12 +6218,12 @@ function SortIndicator({
5082
6218
  }) {
5083
6219
  const iconClass = "size-3.5 shrink-0 opacity-60 group-hover:opacity-100";
5084
6220
  if (!active) {
5085
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react12.ArrowUpDownIcon, { className: iconClass, "aria-hidden": true });
6221
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(import_lucide_react12.ArrowUpDownIcon, { className: iconClass, "aria-hidden": true });
5086
6222
  }
5087
6223
  if (direction === "desc") {
5088
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react12.ArrowDownIcon, { className: iconClass, "aria-hidden": true });
6224
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(import_lucide_react12.ArrowDownIcon, { className: iconClass, "aria-hidden": true });
5089
6225
  }
5090
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react12.ArrowUpIcon, { className: iconClass, "aria-hidden": true });
6226
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(import_lucide_react12.ArrowUpIcon, { className: iconClass, "aria-hidden": true });
5091
6227
  }
5092
6228
  function DataTable({
5093
6229
  columns,
@@ -5108,7 +6244,7 @@ function DataTable({
5108
6244
  dense = false,
5109
6245
  caption
5110
6246
  }) {
5111
- const [uncontrolledSort, setUncontrolledSort] = (0, import_react37.useState)(
6247
+ const [uncontrolledSort, setUncontrolledSort] = (0, import_react45.useState)(
5112
6248
  defaultSort
5113
6249
  );
5114
6250
  const isSortControlled = sortProp !== void 0;
@@ -5119,7 +6255,7 @@ function DataTable({
5119
6255
  }
5120
6256
  onSortChange?.(next);
5121
6257
  };
5122
- const sortedRows = (0, import_react37.useMemo)(() => {
6258
+ const sortedRows = (0, import_react45.useMemo)(() => {
5123
6259
  if (!sort) return rows;
5124
6260
  const column = columns.find((col) => col.id === sort.columnId);
5125
6261
  if (!column?.sortable) return rows;
@@ -5138,28 +6274,28 @@ function DataTable({
5138
6274
  const cellPad = dense ? "px-3 py-2" : void 0;
5139
6275
  const headPad = dense ? "px-3 py-2" : void 0;
5140
6276
  if (rows.length === 0 && emptyMode === "replace") {
5141
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(EmptyState2, { title: emptyTitle, description: emptyDescription, className });
6277
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(EmptyState, { title: emptyTitle, description: emptyDescription, className });
5142
6278
  }
5143
6279
  const rowCountText = rowCountLabel?.(sortedRows.length) ?? `${sortedRows.length} row${sortedRows.length === 1 ? "" : "s"}`;
5144
6280
  const hasFoot = Boolean((showRowCount || footer) && sortedRows.length > 0);
5145
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: cn("aui-app-data-table", shellClass2, className), children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("table", { className: tableClass, children: [
5146
- caption ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("caption", { className: "sr-only", children: caption }) : null,
5147
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("thead", { className: cn(stickyHeader && stickyHeadClass), children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("tr", { children: columns.map((col) => {
6281
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { className: cn("aui-app-data-table", shellClass2, className), children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("div", { className: "overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("table", { className: tableClass, children: [
6282
+ caption ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("caption", { className: "sr-only", children: caption }) : null,
6283
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("thead", { className: cn(stickyHeader && stickyHeadClass), children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("tr", { children: columns.map((col) => {
5148
6284
  const isSorted = sort?.columnId === col.id;
5149
6285
  const ariaSort = col.sortable ? isSorted ? sort.direction === "asc" ? "ascending" : "descending" : "none" : void 0;
5150
- const headerContent = col.sortable ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
6286
+ const headerContent = col.sortable ? /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
5151
6287
  "button",
5152
6288
  {
5153
6289
  type: "button",
5154
6290
  className: sortButtonClass,
5155
6291
  onClick: () => setSort(nextSort(sort, col.id)),
5156
6292
  children: [
5157
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "truncate", children: col.header }),
5158
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(SortIndicator, { active: Boolean(isSorted), direction: sort?.direction })
6293
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "truncate", children: col.header }),
6294
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(SortIndicator, { active: Boolean(isSorted), direction: sort?.direction })
5159
6295
  ]
5160
6296
  }
5161
6297
  ) : col.header;
5162
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
6298
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
5163
6299
  "th",
5164
6300
  {
5165
6301
  scope: "col",
@@ -5175,10 +6311,10 @@ function DataTable({
5175
6311
  col.id
5176
6312
  );
5177
6313
  }) }) }),
5178
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("tbody", { className: cn(!hasFoot && "[&_tr:last-child_td]:border-b-0"), children: sortedRows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("td", { colSpan: columns.length, className: emptyCellClass, children: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "flex flex-col items-center gap-1", children: [
5179
- /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("p", { className: "font-medium text-foreground", children: emptyTitle }),
5180
- emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("p", { className: "max-w-sm text-muted-foreground", children: emptyDescription }) : null
5181
- ] }) }) }) : sortedRows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
6314
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("tbody", { className: cn(!hasFoot && "[&_tr:last-child_td]:border-b-0"), children: sortedRows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("td", { colSpan: columns.length, className: emptyCellClass, children: /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)("div", { className: "flex flex-col items-center gap-1", children: [
6315
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("p", { className: "font-medium text-foreground", children: emptyTitle }),
6316
+ emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("p", { className: "max-w-sm text-muted-foreground", children: emptyDescription }) : null
6317
+ ] }) }) }) : sortedRows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
5182
6318
  "tr",
5183
6319
  {
5184
6320
  className: rowClass,
@@ -5192,7 +6328,7 @@ function DataTable({
5192
6328
  } : void 0,
5193
6329
  tabIndex: onRowClick ? 0 : void 0,
5194
6330
  role: onRowClick ? "button" : void 0,
5195
- children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
6331
+ children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
5196
6332
  "td",
5197
6333
  {
5198
6334
  className: cn(
@@ -5208,7 +6344,7 @@ function DataTable({
5208
6344
  },
5209
6345
  getRowKey(row)
5210
6346
  )) }),
5211
- hasFoot ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("tfoot", { children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("td", { colSpan: columns.length, className: footCellClass, children: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
6347
+ hasFoot ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("tfoot", { children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("td", { colSpan: columns.length, className: footCellClass, children: /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
5212
6348
  "div",
5213
6349
  {
5214
6350
  className: cn(
@@ -5216,7 +6352,7 @@ function DataTable({
5216
6352
  showRowCount && footer ? "justify-between" : "justify-start"
5217
6353
  ),
5218
6354
  children: [
5219
- showRowCount ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { children: rowCountText }) : null,
6355
+ showRowCount ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { children: rowCountText }) : null,
5220
6356
  footer
5221
6357
  ]
5222
6358
  }
@@ -5225,27 +6361,415 @@ function DataTable({
5225
6361
  }
5226
6362
 
5227
6363
  // src/app/data/ChartPanel.tsx
5228
- var import_jsx_runtime53 = require("react/jsx-runtime");
5229
- var chartEmbedClass = "[&_.aui-artifact-root]:my-0 [&_.aui-artifact-root]:rounded-none [&_.aui-artifact-root]:border-0 [&_.aui-artifact-root]:bg-transparent [&_.aui-artifact-root]:shadow-none";
6364
+ var import_react46 = require("react");
6365
+
6366
+ // src/app/data/metrics-shared.tsx
6367
+ var import_jsx_runtime68 = require("react/jsx-runtime");
6368
+ var metricCardShellClass = cn(
6369
+ studioIntegrationCardClass,
6370
+ "aui-app-metric-card shadow-none",
6371
+ "flex flex-col overflow-hidden"
6372
+ );
6373
+ var metricCardHeaderClass = "flex items-start justify-between gap-3 px-4 pb-1 pt-3";
6374
+ var metricTilesRowClass = "grid w-full min-w-0";
6375
+ var metricChartRegionClass = "relative min-h-0 w-full border-t border-border/40 pt-2";
6376
+ var metricChartPlotRegionClass = "relative min-h-0 w-full border-t border-border/40 px-0 pt-5 pb-3";
6377
+ var metricCellDividerClass = "border-r border-border/40";
6378
+ var MetricCardHeader = ({
6379
+ title,
6380
+ titleId,
6381
+ description,
6382
+ actions
6383
+ }) => {
6384
+ if (!title && !description && !actions) return null;
6385
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("header", { className: metricCardHeaderClass, children: [
6386
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "min-w-0", children: [
6387
+ title ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("h3", { id: titleId, className: "text-base font-normal text-foreground", children: title }) : null,
6388
+ description ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
6389
+ ] }),
6390
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "shrink-0", children: actions }) : null
6391
+ ] });
6392
+ };
6393
+ function metricTilesGridColsClass(n) {
6394
+ switch (n) {
6395
+ case 1:
6396
+ return "grid-cols-1";
6397
+ case 2:
6398
+ return "grid-cols-2";
6399
+ case 3:
6400
+ return "grid-cols-3";
6401
+ case 5:
6402
+ return "grid-cols-2 sm:grid-cols-5";
6403
+ case 6:
6404
+ return "grid-cols-2 sm:grid-cols-3 lg:grid-cols-6";
6405
+ default:
6406
+ return "grid-cols-2 md:grid-cols-4";
6407
+ }
6408
+ }
6409
+
6410
+ // src/app/data/ChartPanel.tsx
6411
+ var import_jsx_runtime69 = require("react/jsx-runtime");
5230
6412
  var ChartPanel = ({
5231
6413
  title,
6414
+ description,
5232
6415
  artifact,
5233
6416
  children,
5234
6417
  actions,
6418
+ height = 300,
5235
6419
  className
5236
6420
  }) => {
5237
- const body = children ?? (artifact ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: chartEmbedClass, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(ChartArtifactView, { artifact }) }) : null);
5238
- return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: cn("aui-app-chart-panel", appChartPanelClass, className), children: [
5239
- title || actions ? /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
5240
- title ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("h3", { className: appChartPanelTitleClass, children: title }) : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", {}),
5241
- actions
5242
- ] }) : null,
5243
- /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "min-h-[12rem] w-full", children: body })
6421
+ const titleId = (0, import_react46.useId)();
6422
+ const resolvedTitle = title ?? artifact?.title;
6423
+ const hasHeader = Boolean(resolvedTitle || description || actions);
6424
+ const body = children ?? (artifact ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(ChartArtifactView, { artifact, embedded: true, height }) : null);
6425
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
6426
+ "section",
6427
+ {
6428
+ className: cn(metricCardShellClass, "aui-app-chart-panel", className),
6429
+ "aria-labelledby": resolvedTitle ? titleId : void 0,
6430
+ children: [
6431
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
6432
+ MetricCardHeader,
6433
+ {
6434
+ title: resolvedTitle,
6435
+ titleId,
6436
+ description,
6437
+ actions
6438
+ }
6439
+ ),
6440
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
6441
+ "div",
6442
+ {
6443
+ className: cn(
6444
+ "relative min-h-0 w-full",
6445
+ hasHeader ? metricChartPlotRegionClass : "pt-2 pb-3"
6446
+ ),
6447
+ children: body ?? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
6448
+ "div",
6449
+ {
6450
+ className: "flex items-center justify-center text-sm font-normal text-muted-foreground",
6451
+ style: { minHeight: height },
6452
+ role: "status",
6453
+ children: "No chart"
6454
+ }
6455
+ )
6456
+ }
6457
+ )
6458
+ ]
6459
+ }
6460
+ );
6461
+ };
6462
+
6463
+ // src/app/data/MetricTile.tsx
6464
+ var import_jsx_runtime70 = require("react/jsx-runtime");
6465
+ var trendToneClass = {
6466
+ up: "border-border/80 bg-muted/40 text-muted-foreground",
6467
+ down: "border-border/80 bg-muted/40 text-muted-foreground",
6468
+ neutral: "border-border/80 bg-muted/30 text-muted-foreground"
6469
+ };
6470
+ var metricTileBaseClass = "relative flex min-w-0 flex-1 flex-col gap-1 px-4 py-3 text-left font-normal";
6471
+ var metricTileInteractiveClass = cn(
6472
+ metricTileBaseClass,
6473
+ "bg-transparent hover:bg-transparent active:bg-transparent",
6474
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-foreground/10"
6475
+ );
6476
+ var MetricTile = ({
6477
+ label,
6478
+ value,
6479
+ unit,
6480
+ trend,
6481
+ trendTone = "neutral",
6482
+ active = false,
6483
+ showDivider = false,
6484
+ onSelect,
6485
+ ariaLabel,
6486
+ className
6487
+ }) => {
6488
+ const content = /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(import_jsx_runtime70.Fragment, { children: [
6489
+ active ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
6490
+ "span",
6491
+ {
6492
+ "aria-hidden": true,
6493
+ className: "absolute inset-x-0 bottom-0 h-0.5 bg-foreground dark:bg-white"
6494
+ }
6495
+ ) : null,
6496
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "text-xs font-normal text-muted-foreground", children: label }),
6497
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "flex items-center gap-2", children: [
6498
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "flex items-baseline gap-1", children: [
6499
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "text-2xl font-normal tracking-tight text-foreground tabular-nums", children: value }),
6500
+ unit ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "text-xs font-normal text-muted-foreground", children: unit }) : null
6501
+ ] }),
6502
+ trend ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
6503
+ "span",
6504
+ {
6505
+ className: cn(
6506
+ "rounded-full border px-1.5 py-0.5 text-xs font-normal",
6507
+ trendToneClass[trendTone]
6508
+ ),
6509
+ children: trend
6510
+ }
6511
+ ) : null
6512
+ ] })
5244
6513
  ] });
6514
+ const divider = showDivider ? metricCellDividerClass : void 0;
6515
+ if (onSelect) {
6516
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
6517
+ "button",
6518
+ {
6519
+ type: "button",
6520
+ onClick: onSelect,
6521
+ "aria-pressed": active,
6522
+ "aria-label": ariaLabel,
6523
+ className: cn(metricTileInteractiveClass, divider, className),
6524
+ children: content
6525
+ }
6526
+ );
6527
+ }
6528
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: cn(metricTileBaseClass, divider, className), children: content });
6529
+ };
6530
+
6531
+ // src/app/data/MetricRow.tsx
6532
+ var import_react47 = require("react");
6533
+ var import_jsx_runtime71 = require("react/jsx-runtime");
6534
+ var MetricRow = ({
6535
+ title,
6536
+ description,
6537
+ actions,
6538
+ metrics,
6539
+ activeMetricId,
6540
+ defaultActiveMetricId,
6541
+ onMetricChange,
6542
+ metricsAriaLabel = "Metrics",
6543
+ className
6544
+ }) => {
6545
+ const titleId = (0, import_react47.useId)();
6546
+ const selectable = onMetricChange != null || activeMetricId != null;
6547
+ const [internalId, setInternalId] = (0, import_react47.useState)(
6548
+ defaultActiveMetricId ?? metrics[0]?.id
6549
+ );
6550
+ const activeId = activeMetricId ?? internalId;
6551
+ const select = (id) => {
6552
+ if (activeMetricId == null) setInternalId(id);
6553
+ onMetricChange?.(id);
6554
+ };
6555
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
6556
+ "section",
6557
+ {
6558
+ className: cn(metricCardShellClass, className),
6559
+ "aria-labelledby": title ? titleId : void 0,
6560
+ children: [
6561
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
6562
+ MetricCardHeader,
6563
+ {
6564
+ title,
6565
+ titleId,
6566
+ description,
6567
+ actions
6568
+ }
6569
+ ),
6570
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
6571
+ "div",
6572
+ {
6573
+ role: selectable ? "group" : void 0,
6574
+ "aria-label": selectable ? metricsAriaLabel : void 0,
6575
+ className: cn(
6576
+ metricTilesRowClass,
6577
+ metricTilesGridColsClass(metrics.length),
6578
+ (title || description || actions) && "mt-3"
6579
+ ),
6580
+ children: metrics.map((m, index) => /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
6581
+ MetricTile,
6582
+ {
6583
+ label: m.label,
6584
+ value: m.value,
6585
+ unit: m.unit,
6586
+ trend: m.trend,
6587
+ trendTone: m.trendTone,
6588
+ active: selectable && m.id === activeId,
6589
+ showDivider: index < metrics.length - 1,
6590
+ onSelect: selectable ? () => select(m.id) : void 0
6591
+ },
6592
+ m.id
6593
+ ))
6594
+ }
6595
+ )
6596
+ ]
6597
+ }
6598
+ );
6599
+ };
6600
+
6601
+ // src/app/data/MetricChartCard.tsx
6602
+ var import_react48 = require("react");
6603
+ var import_jsx_runtime72 = require("react/jsx-runtime");
6604
+ var MetricChartCard = ({
6605
+ title,
6606
+ description,
6607
+ actions,
6608
+ metrics,
6609
+ activeMetricId,
6610
+ defaultActiveMetricId,
6611
+ onMetricChange,
6612
+ xKey = "date",
6613
+ variant = "area",
6614
+ height = 300,
6615
+ formatX,
6616
+ formatValue,
6617
+ emptyLabel = "No data yet",
6618
+ metricsAriaLabel = "Metrics",
6619
+ className
6620
+ }) => {
6621
+ const titleId = (0, import_react48.useId)();
6622
+ const [internalId, setInternalId] = (0, import_react48.useState)(
6623
+ defaultActiveMetricId ?? metrics[0]?.id
6624
+ );
6625
+ const activeId = activeMetricId ?? internalId;
6626
+ const active = metrics.find((m) => m.id === activeId) ?? metrics[0];
6627
+ const select = (id) => {
6628
+ if (activeMetricId == null) setInternalId(id);
6629
+ onMetricChange?.(id);
6630
+ };
6631
+ const hasHeader = Boolean(title || description || actions);
6632
+ const chartAriaLabel = typeof active?.label === "string" ? `${active.label} over time` : "Metric chart";
6633
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
6634
+ "section",
6635
+ {
6636
+ className: cn(metricCardShellClass, className),
6637
+ "aria-labelledby": title ? titleId : void 0,
6638
+ children: [
6639
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
6640
+ MetricCardHeader,
6641
+ {
6642
+ title,
6643
+ titleId,
6644
+ description,
6645
+ actions
6646
+ }
6647
+ ),
6648
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
6649
+ "div",
6650
+ {
6651
+ role: "group",
6652
+ "aria-label": metricsAriaLabel,
6653
+ className: cn(
6654
+ metricTilesRowClass,
6655
+ metricTilesGridColsClass(metrics.length),
6656
+ hasHeader && "mt-3"
6657
+ ),
6658
+ children: metrics.map((m, index) => /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
6659
+ MetricTile,
6660
+ {
6661
+ label: m.label,
6662
+ value: m.value,
6663
+ unit: m.unit,
6664
+ trend: m.trend,
6665
+ trendTone: m.trendTone,
6666
+ active: m.id === active?.id,
6667
+ showDivider: index < metrics.length - 1,
6668
+ onSelect: () => select(m.id)
6669
+ },
6670
+ m.id
6671
+ ))
6672
+ }
6673
+ ),
6674
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)("div", { className: metricChartRegionClass, "aria-live": "polite", "aria-atomic": "true", children: active?.data && active.data.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
6675
+ LineAreaChart,
6676
+ {
6677
+ data: active.data,
6678
+ xKey,
6679
+ series: [
6680
+ {
6681
+ dataKey: active.dataKey ?? "value",
6682
+ label: typeof active.label === "string" ? active.label : active.id,
6683
+ color: active.color
6684
+ }
6685
+ ],
6686
+ variant,
6687
+ layout: "flush",
6688
+ height,
6689
+ formatX,
6690
+ formatValue,
6691
+ ariaLabel: chartAriaLabel
6692
+ },
6693
+ active.id
6694
+ ) : /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
6695
+ "div",
6696
+ {
6697
+ className: "flex w-full items-center justify-center text-sm font-normal text-muted-foreground",
6698
+ style: { height },
6699
+ role: "status",
6700
+ children: emptyLabel
6701
+ }
6702
+ ) })
6703
+ ]
6704
+ }
6705
+ );
6706
+ };
6707
+
6708
+ // src/charts/sparkline.tsx
6709
+ var import_react49 = require("react");
6710
+ var import_jsx_runtime73 = require("react/jsx-runtime");
6711
+ var Sparkline = ({
6712
+ data,
6713
+ dataKey = "value",
6714
+ color = "var(--primary, #6366f1)",
6715
+ area = true,
6716
+ width = 96,
6717
+ height = 28,
6718
+ strokeWidth = 1.5,
6719
+ className,
6720
+ ariaLabel = "Trend"
6721
+ }) => {
6722
+ const uid = (0, import_react49.useId)();
6723
+ const values = data.map((d) => typeof d === "number" ? d : toNum(d[dataKey]));
6724
+ if (values.length === 0) {
6725
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: cn("inline-block", className), style: { width, height } });
6726
+ }
6727
+ const pad = strokeWidth + 1;
6728
+ const min = Math.min(...values);
6729
+ const max = Math.max(...values);
6730
+ const range = max - min || 1;
6731
+ const innerW = width - pad * 2;
6732
+ const innerH = height - pad * 2;
6733
+ const points = values.map((v, i) => ({
6734
+ x: pad + (values.length > 1 ? i / (values.length - 1) * innerW : innerW / 2),
6735
+ y: pad + innerH - (v - min) / range * innerH
6736
+ }));
6737
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
6738
+ "svg",
6739
+ {
6740
+ width,
6741
+ height,
6742
+ viewBox: `0 0 ${width} ${height}`,
6743
+ className: cn("block", className),
6744
+ role: "img",
6745
+ "aria-label": ariaLabel,
6746
+ preserveAspectRatio: "none",
6747
+ children: [
6748
+ area && /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(import_jsx_runtime73.Fragment, { children: [
6749
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("linearGradient", { id: `${uid}-spark`, x1: "0", x2: "0", y1: "0", y2: "1", children: [
6750
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("stop", { offset: "0%", style: { stopColor: color, stopOpacity: 0.25 } }),
6751
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("stop", { offset: "100%", style: { stopColor: color, stopOpacity: 0 } })
6752
+ ] }) }),
6753
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("path", { d: monotoneAreaPath(points, height - pad), fill: `url(#${uid}-spark)` })
6754
+ ] }),
6755
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
6756
+ "path",
6757
+ {
6758
+ d: monotoneLinePath(points),
6759
+ fill: "none",
6760
+ stroke: color,
6761
+ strokeWidth,
6762
+ strokeLinecap: "round",
6763
+ strokeLinejoin: "round"
6764
+ }
6765
+ )
6766
+ ]
6767
+ }
6768
+ );
5245
6769
  };
5246
6770
 
5247
6771
  // src/chat/chat.tsx
5248
- var import_jsx_runtime54 = require("react/jsx-runtime");
6772
+ var import_jsx_runtime74 = require("react/jsx-runtime");
5249
6773
  function TimbalChat({
5250
6774
  workforceId,
5251
6775
  baseUrl,
@@ -5256,7 +6780,7 @@ function TimbalChat({
5256
6780
  debug,
5257
6781
  ...threadProps
5258
6782
  }) {
5259
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
6783
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
5260
6784
  TimbalRuntimeProvider,
5261
6785
  {
5262
6786
  workforceId,
@@ -5266,12 +6790,13 @@ function TimbalChat({
5266
6790
  attachmentsUploadUrl,
5267
6791
  attachmentsAccept,
5268
6792
  debug,
5269
- children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Thread, { ...threadProps })
6793
+ children: /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Thread, { ...threadProps })
5270
6794
  }
5271
6795
  );
5272
6796
  }
5273
6797
  // Annotate the CommonJS export names for ESM import in node:
5274
6798
  0 && (module.exports = {
6799
+ APP_KIT_AGENT_INSTRUCTIONS,
5275
6800
  AppChatPanel,
5276
6801
  AppConfirmDialog,
5277
6802
  AppCopilotProvider,
@@ -5279,23 +6804,47 @@ function TimbalChat({
5279
6804
  AppShellChatTrigger,
5280
6805
  AppShellTopbar,
5281
6806
  Breadcrumbs,
6807
+ Button,
6808
+ CHART_PALETTE,
5282
6809
  ChartArtifactView,
5283
6810
  ChartPanel,
6811
+ ConnectionRow,
6812
+ ConnectionRowList,
6813
+ DangerZone,
6814
+ DangerZoneAction,
5284
6815
  DataTable,
6816
+ DescriptionList,
5285
6817
  EmptyState,
6818
+ ExpandableSection,
5286
6819
  Field,
5287
6820
  FieldInput,
6821
+ FieldRow,
5288
6822
  FieldSelect,
5289
6823
  FieldSwitch,
5290
6824
  FieldTextarea,
5291
6825
  FilterBar,
6826
+ FloatingUnsavedChangesBar,
5292
6827
  FormSection,
6828
+ INTEGRATION_CATALOG_CARD_HEIGHT_CLASS,
6829
+ InfoCard,
6830
+ IntegrationCard,
6831
+ IntegrationsEmptyState,
6832
+ LineAreaChart,
6833
+ MetricChartCard,
6834
+ MetricRow,
6835
+ MetricTile,
5293
6836
  Page,
5294
6837
  PageHeader,
6838
+ PlanBadge,
6839
+ ResourceCard,
5295
6840
  SearchInput,
5296
6841
  Section,
6842
+ SettingsSection,
6843
+ SettingsSectionHeader,
6844
+ Sparkline,
5297
6845
  StatTile,
5298
6846
  StatusBadge,
6847
+ StatusDot,
5299
6848
  SubNav,
5300
6849
  SurfaceCard,
5301
6850
  TimbalChat,
@@ -5306,6 +6855,7 @@ function TimbalChat({
5306
6855
  appShellTopbarInsetClass,
5307
6856
  appStatTileClass,
5308
6857
  appSurfaceCardClass,
6858
+ connectionRowListClass,
5309
6859
  useAppCopilotContext,
5310
6860
  useAppShellChat
5311
6861
  });