@timbal-ai/timbal-react 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +24 -5
  3. package/dist/app.cjs +2282 -738
  4. package/dist/app.d.cts +4 -1
  5. package/dist/app.d.ts +4 -1
  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-BFDz8Tf9.d.ts +756 -0
  10. package/dist/chart-artifact-bWUa-iSG.d.cts +756 -0
  11. package/dist/chat.cjs +872 -562
  12. package/dist/chat.d.cts +2 -2
  13. package/dist/chat.d.ts +2 -2
  14. package/dist/chat.esm.js +3 -3
  15. package/dist/{chunk-4TCJQSIX.esm.js → chunk-2XZ3S4OP.esm.js} +14 -3
  16. package/dist/chunk-533MK5EA.esm.js +2294 -0
  17. package/dist/{chunk-OVHR7J3J.esm.js → chunk-7O5VY3TP.esm.js} +38 -11
  18. package/dist/{chunk-WLTW56MC.esm.js → chunk-N3PYVTY5.esm.js} +2 -2
  19. package/dist/{chunk-IYENDIRY.esm.js → chunk-TDIJHV4I.esm.js} +1 -1
  20. package/dist/{chunk-YJQLLFKP.esm.js → chunk-TLUF2RUL.esm.js} +813 -507
  21. package/dist/{chunk-OFHLFNJH.esm.js → chunk-Z27GBSOT.esm.js} +3 -1
  22. package/dist/index.cjs +2587 -1016
  23. package/dist/index.d.cts +6 -5
  24. package/dist/index.d.ts +6 -5
  25. package/dist/index.esm.js +57 -7
  26. package/dist/{layout-CQWngNQ7.d.ts → layout-BTJyU8wd.d.ts} +1 -1
  27. package/dist/{layout-B9VayJhZ.d.cts → layout-C2G-FcER.d.cts} +1 -1
  28. package/dist/studio.cjs +1127 -788
  29. package/dist/studio.d.cts +1 -1
  30. package/dist/studio.d.ts +1 -1
  31. package/dist/studio.esm.js +6 -6
  32. package/dist/{timbal-v2-button-F4-z7m33.d.ts → timbal-v2-button-CNfdwGq4.d.cts} +1 -1
  33. package/dist/{timbal-v2-button-F4-z7m33.d.cts → timbal-v2-button-CNfdwGq4.d.ts} +1 -1
  34. package/dist/ui.cjs +12 -3
  35. package/dist/ui.d.cts +5 -16
  36. package/dist/ui.d.ts +5 -16
  37. package/dist/ui.esm.js +2 -2
  38. package/dist/{welcome-BOizSp5h.d.ts → welcome-BBmB3tl7.d.ts} +4 -3
  39. package/dist/{welcome--80i_O0p.d.cts → welcome-C89Mgdaw.d.cts} +4 -3
  40. package/package.json +2 -1
  41. package/vite/local-dev.mjs +45 -3
  42. package/dist/chart-artifact-C71dk4xI.d.ts +0 -329
  43. package/dist/chart-artifact-CPEpOmtV.d.cts +0 -329
  44. 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,15 +4604,15 @@ 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",
@@ -4114,17 +4634,17 @@ var Thread = ({
4114
4634
  const EditComposerSlot = components?.EditComposer ?? EditComposer;
4115
4635
  const ScrollToBottomSlot = components?.ScrollToBottom ?? ThreadScrollToBottom;
4116
4636
  const SuggestionsSlot = components?.Suggestions ?? Suggestions;
4117
- (0, import_react32.useEffect)(() => {
4637
+ (0, import_react34.useEffect)(() => {
4118
4638
  scheduleThemeSanityCheck();
4119
4639
  }, []);
4120
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ThreadVariantProvider, { value: variant, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4640
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ThreadVariantProvider, { value: variant, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4121
4641
  ArtifactRegistryProvider,
4122
4642
  {
4123
4643
  renderers: artifacts?.renderers,
4124
4644
  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,
4645
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(UiEventProvider, { onEvent: onArtifactEvent ?? (() => {
4646
+ }), children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4647
+ import_react35.ThreadPrimitive.Root,
4128
4648
  {
4129
4649
  className: cn(
4130
4650
  "aui-root aui-thread-root @container flex h-full flex-col bg-transparent",
@@ -4133,8 +4653,8 @@ var Thread = ({
4133
4653
  ),
4134
4654
  style: { ["--thread-max-width"]: maxWidth },
4135
4655
  "data-thread-variant": variant,
4136
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
4137
- import_react33.ThreadPrimitive.Viewport,
4656
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4657
+ import_react35.ThreadPrimitive.Viewport,
4138
4658
  {
4139
4659
  turnAnchor: "bottom",
4140
4660
  className: cn(
@@ -4142,7 +4662,7 @@ var Thread = ({
4142
4662
  isPanel ? "px-2 pt-2" : "px-4 pt-4"
4143
4663
  ),
4144
4664
  children: [
4145
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4665
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4146
4666
  WelcomeSlot,
4147
4667
  {
4148
4668
  config: welcome,
@@ -4150,8 +4670,8 @@ var Thread = ({
4150
4670
  Suggestions: SuggestionsSlot
4151
4671
  }
4152
4672
  ),
4153
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4154
- import_react33.ThreadPrimitive.Messages,
4673
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4674
+ import_react35.ThreadPrimitive.Messages,
4155
4675
  {
4156
4676
  components: {
4157
4677
  UserMessage: UserMessageSlot,
@@ -4160,14 +4680,14 @@ var Thread = ({
4160
4680
  }
4161
4681
  }
4162
4682
  ),
4163
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4164
- import_react33.ThreadPrimitive.ViewportFooter,
4683
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4684
+ import_react35.ThreadPrimitive.ViewportFooter,
4165
4685
  {
4166
4686
  className: cn(
4167
4687
  "aui-thread-viewport-footer sticky bottom-0 z-10 mt-auto w-full isolate pt-2",
4168
4688
  isPanel ? "bg-card pb-2" : "bg-background pb-4 md:pb-6"
4169
4689
  ),
4170
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
4690
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4171
4691
  "div",
4172
4692
  {
4173
4693
  className: cn(
@@ -4175,8 +4695,8 @@ var Thread = ({
4175
4695
  isPanel ? "gap-2" : "gap-4"
4176
4696
  ),
4177
4697
  children: [
4178
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ScrollToBottomSlot, {}),
4179
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ComposerSlot, { placeholder })
4698
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ScrollToBottomSlot, {}),
4699
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ComposerSlot, { placeholder })
4180
4700
  ]
4181
4701
  }
4182
4702
  )
@@ -4191,13 +4711,13 @@ var Thread = ({
4191
4711
  ) });
4192
4712
  };
4193
4713
  var ThreadScrollToBottom = () => {
4194
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4714
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.ThreadPrimitive.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4195
4715
  TooltipIconButton,
4196
4716
  {
4197
4717
  tooltip: "Scroll to bottom",
4198
4718
  variant: "secondary",
4199
4719
  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" })
4720
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react8.ArrowDownIcon, { className: "size-4" })
4201
4721
  }
4202
4722
  ) });
4203
4723
  };
@@ -4229,14 +4749,14 @@ var ThreadWelcome = ({
4229
4749
  suggestions,
4230
4750
  Suggestions: SuggestionsSlot = Suggestions
4231
4751
  }) => {
4232
- const isEmpty = (0, import_react33.useThread)((s) => s.messages.length === 0);
4752
+ const isEmpty = (0, import_react35.useThread)((s) => s.messages.length === 0);
4233
4753
  const isPanel = useThreadVariant() === "panel";
4234
4754
  if (!isEmpty) return null;
4235
4755
  const defaultHeading = isPanel ? "Ask about this page" : "How can I help you today?";
4236
4756
  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,
4757
+ 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: [
4758
+ /* @__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)(
4759
+ import_react36.motion.div,
4240
4760
  {
4241
4761
  className: cn(
4242
4762
  "aui-thread-welcome-message flex flex-col items-center justify-center text-center",
@@ -4246,9 +4766,9 @@ var ThreadWelcome = ({
4246
4766
  initial: "initial",
4247
4767
  animate: "animate",
4248
4768
  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,
4769
+ config?.icon && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react36.motion.div, { variants: welcomeIcon, className: isPanel ? "mb-3" : "mb-5", children: config.icon }),
4770
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4771
+ import_react36.motion.h1,
4252
4772
  {
4253
4773
  variants: welcomeItem,
4254
4774
  className: cn(
@@ -4258,8 +4778,8 @@ var ThreadWelcome = ({
4258
4778
  children: config?.heading ?? defaultHeading
4259
4779
  }
4260
4780
  ),
4261
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4262
- import_react34.motion.p,
4781
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4782
+ import_react36.motion.p,
4263
4783
  {
4264
4784
  variants: welcomeItem,
4265
4785
  className: "aui-thread-welcome-message-inner mt-1.5 text-muted-foreground text-sm",
@@ -4269,16 +4789,16 @@ var ThreadWelcome = ({
4269
4789
  ]
4270
4790
  }
4271
4791
  ) }),
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
4792
+ suggestions && !isPanel ? /* @__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
4793
  ] });
4274
4794
  };
4275
4795
  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" }) }) });
4796
+ 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
4797
  };
4278
4798
  var AssistantMessage = () => {
4279
4799
  const isPanel = useThreadVariant() === "panel";
4280
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
4281
- import_react33.MessagePrimitive.Root,
4800
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4801
+ import_react35.MessagePrimitive.Root,
4282
4802
  {
4283
4803
  className: cn(
4284
4804
  "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 +4806,7 @@ var AssistantMessage = () => {
4286
4806
  ),
4287
4807
  "data-role": "assistant",
4288
4808
  children: [
4289
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
4809
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4290
4810
  "div",
4291
4811
  {
4292
4812
  className: cn(
@@ -4294,8 +4814,8 @@ var AssistantMessage = () => {
4294
4814
  isPanel ? "px-1 text-sm" : "px-2"
4295
4815
  ),
4296
4816
  children: [
4297
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4298
- import_react33.MessagePrimitive.Parts,
4817
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4818
+ import_react35.MessagePrimitive.Parts,
4299
4819
  {
4300
4820
  components: {
4301
4821
  Text: MarkdownText,
@@ -4305,11 +4825,11 @@ var AssistantMessage = () => {
4305
4825
  }
4306
4826
  }
4307
4827
  ),
4308
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(MessageError, {})
4828
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(MessageError, {})
4309
4829
  ]
4310
4830
  }
4311
4831
  ),
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, {}) })
4832
+ /* @__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
4833
  ]
4314
4834
  }
4315
4835
  );
@@ -4322,36 +4842,36 @@ var ASSISTANT_ACTION_ICON_CLASS = cn(
4322
4842
  "[&>span:first-child]:group-hover/tbv2:bg-ghost-fill-hover"
4323
4843
  );
4324
4844
  var AssistantActionBar = () => {
4325
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
4326
- import_react33.ActionBarPrimitive.Root,
4845
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4846
+ import_react35.ActionBarPrimitive.Root,
4327
4847
  {
4328
4848
  hideWhenRunning: true,
4329
4849
  autohide: "never",
4330
4850
  className: "aui-assistant-action-bar-root flex items-center gap-0 bg-transparent px-0 py-0.5 text-muted-foreground/60",
4331
4851
  children: [
4332
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
4852
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4333
4853
  TooltipIconButton,
4334
4854
  {
4335
4855
  tooltip: "Copy",
4336
4856
  variant: "ghost",
4337
4857
  className: ASSISTANT_ACTION_ICON_CLASS,
4338
4858
  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" }) })
4859
+ /* @__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" }) }),
4860
+ /* @__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
4861
  ]
4342
4862
  }
4343
4863
  ) }),
4344
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react33.ActionBarPrimitive.Reload, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4864
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.ActionBarPrimitive.Reload, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4345
4865
  TooltipIconButton,
4346
4866
  {
4347
4867
  tooltip: "Regenerate",
4348
4868
  variant: "ghost",
4349
4869
  className: ASSISTANT_ACTION_ICON_CLASS,
4350
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react8.RefreshCwIcon, { className: "size-3" })
4870
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react8.RefreshCwIcon, { className: "size-3" })
4351
4871
  }
4352
4872
  ) }),
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)(
4873
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_react35.ActionBarMorePrimitive.Root, { children: [
4874
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.ActionBarMorePrimitive.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4355
4875
  TooltipIconButton,
4356
4876
  {
4357
4877
  tooltip: "More",
@@ -4360,17 +4880,17 @@ var AssistantActionBar = () => {
4360
4880
  ASSISTANT_ACTION_ICON_CLASS,
4361
4881
  "data-[state=open]:text-muted-foreground/80"
4362
4882
  ),
4363
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react8.MoreHorizontalIcon, { className: "size-3" })
4883
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react8.MoreHorizontalIcon, { className: "size-3" })
4364
4884
  }
4365
4885
  ) }),
4366
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4367
- import_react33.ActionBarMorePrimitive.Content,
4886
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4887
+ import_react35.ActionBarMorePrimitive.Content,
4368
4888
  {
4369
4889
  side: "bottom",
4370
4890
  align: "start",
4371
4891
  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" }),
4892
+ 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: [
4893
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react8.DownloadIcon, { className: "size-4 shrink-0" }),
4374
4894
  "Export as Markdown"
4375
4895
  ] }) })
4376
4896
  }
@@ -4381,12 +4901,12 @@ var AssistantActionBar = () => {
4381
4901
  );
4382
4902
  };
4383
4903
  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 }) });
4904
+ 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
4905
  };
4386
4906
  var UserMessage = () => {
4387
4907
  const isPanel = useThreadVariant() === "panel";
4388
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
4389
- import_react33.MessagePrimitive.Root,
4908
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4909
+ import_react35.MessagePrimitive.Root,
4390
4910
  {
4391
4911
  className: cn(
4392
4912
  "aui-user-message-root mx-auto flex w-full max-w-(--thread-max-width) flex-col items-end gap-2",
@@ -4394,9 +4914,9 @@ var UserMessage = () => {
4394
4914
  ),
4395
4915
  "data-role": "user",
4396
4916
  children: [
4397
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(UserMessageAttachments, {}),
4398
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
4399
- import_react34.motion.div,
4917
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(UserMessageAttachments, {}),
4918
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
4919
+ import_react36.motion.div,
4400
4920
  {
4401
4921
  className: cn(
4402
4922
  "aui-user-message-content relative inline-block max-w-[85%] rounded-2xl bg-bubble-user text-bubble-user-foreground",
@@ -4406,8 +4926,8 @@ var UserMessage = () => {
4406
4926
  animate: { opacity: 1, y: 0, scale: 1 },
4407
4927
  transition: { duration: 0.65, ease: luxuryEase },
4408
4928
  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, {}) })
4929
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.MessagePrimitive.Parts, { components: { Text: UserMessageText } }),
4930
+ /* @__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
4931
  ]
4412
4932
  }
4413
4933
  )
@@ -4416,42 +4936,42 @@ var UserMessage = () => {
4416
4936
  );
4417
4937
  };
4418
4938
  var UserActionBar = () => {
4419
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
4420
- import_react33.ActionBarPrimitive.Root,
4939
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4940
+ import_react35.ActionBarPrimitive.Root,
4421
4941
  {
4422
4942
  hideWhenRunning: true,
4423
4943
  autohide: "always",
4424
4944
  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)(
4945
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_react35.ActionBarPrimitive.Edit, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4426
4946
  TooltipIconButton,
4427
4947
  {
4428
4948
  tooltip: "Edit",
4429
4949
  variant: "ghost",
4430
4950
  className: ASSISTANT_ACTION_ICON_CLASS,
4431
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react8.PencilIcon, { className: "size-3" })
4951
+ children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react8.PencilIcon, { className: "size-3" })
4432
4952
  }
4433
4953
  ) })
4434
4954
  }
4435
4955
  );
4436
4956
  };
4437
4957
  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,
4958
+ 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: [
4959
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
4960
+ import_react35.ComposerPrimitive.Input,
4441
4961
  {
4442
4962
  className: "aui-edit-composer-input min-h-14 w-full resize-none bg-transparent p-4 text-foreground text-sm outline-none",
4443
4963
  autoFocus: true
4444
4964
  }
4445
4965
  ),
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" }) })
4966
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "aui-edit-composer-footer mx-3 mb-3 flex items-center gap-2 self-end", children: [
4967
+ /* @__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" }) }),
4968
+ /* @__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
4969
  ] })
4450
4970
  ] }) });
4451
4971
  };
4452
4972
 
4453
4973
  // src/app/chat/AppChatPanel.tsx
4454
- var import_jsx_runtime36 = require("react/jsx-runtime");
4974
+ var import_jsx_runtime37 = require("react/jsx-runtime");
4455
4975
  var shellClass = "aui-app-chat-panel flex h-full min-h-0 flex-col overflow-hidden";
4456
4976
  var chromeClass = cn(
4457
4977
  "aui-app-chat-panel-chrome relative z-20 flex min-h-12 shrink-0 items-center justify-end",
@@ -4495,18 +5015,18 @@ var AppChatPanel = ({
4495
5015
  ...rest
4496
5016
  }) => {
4497
5017
  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)(
5018
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: cn(shellClass, className), children: [
5019
+ shellChat?.collapsible ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: chromeClass, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
4500
5020
  "button",
4501
5021
  {
4502
5022
  type: "button",
4503
5023
  className: closeButtonClass,
4504
5024
  onClick: () => shellChat.setOpen(false),
4505
5025
  "aria-label": "Close assistant",
4506
- children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react9.XIcon, { className: "size-4", "aria-hidden": true })
5026
+ children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react9.XIcon, { className: "size-4", "aria-hidden": true })
4507
5027
  }
4508
5028
  ) }) : null,
4509
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: bodyClass, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
5029
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: bodyClass, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
4510
5030
  TimbalRuntimeProvider,
4511
5031
  {
4512
5032
  workforceId,
@@ -4516,7 +5036,7 @@ var AppChatPanel = ({
4516
5036
  attachmentsUploadUrl,
4517
5037
  attachmentsAccept,
4518
5038
  debug,
4519
- children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
5039
+ children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
4520
5040
  Thread,
4521
5041
  {
4522
5042
  variant: "panel",
@@ -4536,38 +5056,38 @@ var AppChatPanel = ({
4536
5056
  };
4537
5057
 
4538
5058
  // src/app/surfaces/SurfaceCard.tsx
4539
- var import_jsx_runtime37 = require("react/jsx-runtime");
5059
+ var import_jsx_runtime38 = require("react/jsx-runtime");
4540
5060
  var SurfaceCard = ({ children, className }) => {
4541
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: cn("aui-app-surface-card", appSurfaceCardClass, className), children });
5061
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: cn("aui-app-surface-card", appSurfaceCardClass, className), children });
4542
5062
  };
4543
5063
 
4544
5064
  // src/app/surfaces/StatTile.tsx
4545
- var import_jsx_runtime38 = require("react/jsx-runtime");
5065
+ var import_jsx_runtime39 = require("react/jsx-runtime");
4546
5066
  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
5067
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: cn("aui-app-stat-tile", appStatTileClass, className), children: [
5068
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: appStatLabelClass, children: label }),
5069
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: appStatValueClass, children: value }),
5070
+ hint ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-xs text-muted-foreground", children: hint }) : null
4551
5071
  ] });
4552
5072
  };
4553
5073
 
4554
5074
  // src/app/surfaces/EmptyState.tsx
4555
- var import_jsx_runtime39 = require("react/jsx-runtime");
4556
- var EmptyState2 = ({
5075
+ var import_jsx_runtime40 = require("react/jsx-runtime");
5076
+ var EmptyState = ({
4557
5077
  title,
4558
5078
  description,
4559
5079
  action,
4560
5080
  className
4561
5081
  }) => {
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,
5082
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: cn("aui-app-empty-state", appEmptyStateClass, className), children: [
5083
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: appEmptyStateTitleClass, children: title }),
5084
+ description ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: appEmptyStateDescriptionClass, children: description }) : null,
4565
5085
  action
4566
5086
  ] });
4567
5087
  };
4568
5088
 
4569
5089
  // src/app/surfaces/StatusBadge.tsx
4570
- var import_jsx_runtime40 = require("react/jsx-runtime");
5090
+ var import_jsx_runtime41 = require("react/jsx-runtime");
4571
5091
  var statusBadgeToneClass = {
4572
5092
  default: "bg-muted text-foreground",
4573
5093
  primary: "bg-primary/10 text-primary",
@@ -4580,7 +5100,7 @@ var StatusBadge = ({
4580
5100
  tone = "default",
4581
5101
  className
4582
5102
  }) => {
4583
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
5103
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
4584
5104
  "span",
4585
5105
  {
4586
5106
  className: cn(
@@ -4594,7 +5114,7 @@ var StatusBadge = ({
4594
5114
  };
4595
5115
 
4596
5116
  // src/app/surfaces/AppConfirmDialog.tsx
4597
- var import_jsx_runtime41 = require("react/jsx-runtime");
5117
+ var import_jsx_runtime42 = require("react/jsx-runtime");
4598
5118
  var bodyClass2 = "flex flex-col gap-4 p-6";
4599
5119
  var titleClass = "pr-8";
4600
5120
  var actionsClass = "flex flex-wrap justify-end gap-2";
@@ -4609,15 +5129,15 @@ var AppConfirmDialog = ({
4609
5129
  destructive = false,
4610
5130
  className
4611
5131
  }) => {
4612
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Dialog, { open, onOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
5132
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Dialog, { open, onOpenChange, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4613
5133
  DialogContent,
4614
5134
  {
4615
5135
  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)(
5136
+ children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: bodyClass2, children: [
5137
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(DialogTitle, { className: titleClass, children: title }),
5138
+ description ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-sm text-muted-foreground", children: description }) : null,
5139
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: actionsClass, children: [
5140
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4621
5141
  TimbalV2Button,
4622
5142
  {
4623
5143
  type: "button",
@@ -4627,7 +5147,7 @@ var AppConfirmDialog = ({
4627
5147
  children: cancelLabel
4628
5148
  }
4629
5149
  ),
4630
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
5150
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4631
5151
  TimbalV2Button,
4632
5152
  {
4633
5153
  type: "button",
@@ -4646,30 +5166,640 @@ var AppConfirmDialog = ({
4646
5166
  ) });
4647
5167
  };
4648
5168
 
4649
- // src/ui/pill-segmented-tabs.tsx
4650
- var import_react35 = require("react");
4651
- var import_react36 = require("motion/react");
5169
+ // src/app/surfaces/InfoCard.tsx
5170
+ var import_jsx_runtime43 = require("react/jsx-runtime");
5171
+ var toneClass = {
5172
+ neutral: "border-border bg-muted/40",
5173
+ info: "border-primary/25 bg-primary/5",
5174
+ success: "border-emerald-500/25 bg-emerald-500/5",
5175
+ warn: "border-amber-500/25 bg-amber-500/5",
5176
+ danger: "border-destructive/25 bg-destructive/5"
5177
+ };
5178
+ var InfoCard = ({
5179
+ title,
5180
+ children,
5181
+ icon,
5182
+ action,
5183
+ tone = "neutral",
5184
+ className
5185
+ }) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
5186
+ "div",
5187
+ {
5188
+ className: cn(
5189
+ "flex items-start gap-3 rounded-xl border p-4",
5190
+ toneClass[tone],
5191
+ className
5192
+ ),
5193
+ children: [
5194
+ icon ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "mt-0.5 shrink-0 text-muted-foreground", children: icon }) : null,
5195
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "min-w-0 flex-1", children: [
5196
+ title ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-sm font-medium text-foreground", children: title }) : null,
5197
+ children ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: cn("text-sm text-muted-foreground", title && "mt-1"), children }) : null
5198
+ ] }),
5199
+ action ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "shrink-0", children: action }) : null
5200
+ ]
5201
+ }
5202
+ );
4652
5203
 
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)]"
5204
+ // src/app/surfaces/StatusDot.tsx
5205
+ var import_jsx_runtime44 = require("react/jsx-runtime");
5206
+ var dotClass = {
5207
+ online: "bg-emerald-500",
5208
+ busy: "bg-amber-500",
5209
+ offline: "bg-muted-foreground/50",
5210
+ error: "bg-destructive",
5211
+ neutral: "bg-muted-foreground"
5212
+ };
5213
+ var StatusDot = ({
5214
+ tone = "neutral",
5215
+ label,
5216
+ pulse = false,
5217
+ className
5218
+ }) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: cn("inline-flex items-center gap-1.5", className), children: [
5219
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "relative flex size-2", children: [
5220
+ pulse ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
5221
+ "span",
5222
+ {
5223
+ className: cn(
5224
+ "absolute inline-flex size-full animate-ping rounded-full opacity-60",
5225
+ dotClass[tone]
5226
+ )
5227
+ }
5228
+ ) : null,
5229
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: cn("relative inline-flex size-2 rounded-full", dotClass[tone]) })
5230
+ ] }),
5231
+ label ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-xs text-muted-foreground", children: label }) : null
5232
+ ] });
5233
+
5234
+ // src/app/surfaces/DescriptionList.tsx
5235
+ var import_jsx_runtime45 = require("react/jsx-runtime");
5236
+ var DescriptionList = ({
5237
+ items,
5238
+ stacked = false,
5239
+ className
5240
+ }) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
5241
+ "dl",
5242
+ {
5243
+ className: cn(
5244
+ "divide-y divide-border rounded-xl border border-border bg-card",
5245
+ className
5246
+ ),
5247
+ children: items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
5248
+ "div",
5249
+ {
5250
+ className: cn(
5251
+ "px-4 py-3",
5252
+ stacked ? "flex flex-col gap-0.5" : "flex items-center justify-between gap-4"
5253
+ ),
5254
+ children: [
5255
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("dt", { className: "text-sm text-muted-foreground", children: item.label }),
5256
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
5257
+ "dd",
5258
+ {
5259
+ className: cn(
5260
+ "text-sm text-foreground",
5261
+ !stacked && "text-right tabular-nums"
5262
+ ),
5263
+ children: item.value
5264
+ }
5265
+ )
5266
+ ]
5267
+ },
5268
+ i
5269
+ ))
5270
+ }
4658
5271
  );
4659
- var pillSegmentedTrackClass = cn(
4660
- pillSegmentedTrackBase,
4661
- pillSegmentedTrackSurface,
4662
- "gap-1 p-1"
5272
+
5273
+ // src/app/surfaces/ExpandableSection.tsx
5274
+ var import_react37 = require("react");
5275
+ var import_react38 = require("motion/react");
5276
+ var import_jsx_runtime46 = require("react/jsx-runtime");
5277
+ var Chevron = ({ open }) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
5278
+ "svg",
5279
+ {
5280
+ viewBox: "0 0 24 24",
5281
+ className: cn(
5282
+ "size-4 text-muted-foreground transition-transform duration-200",
5283
+ open && "rotate-180"
5284
+ ),
5285
+ fill: "none",
5286
+ stroke: "currentColor",
5287
+ strokeWidth: 2,
5288
+ strokeLinecap: "round",
5289
+ strokeLinejoin: "round",
5290
+ "aria-hidden": true,
5291
+ children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("path", { d: "m6 9 6 6 6-6" })
5292
+ }
4663
5293
  );
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"
5294
+ var ExpandableSection = ({
5295
+ title,
5296
+ icon,
5297
+ count,
5298
+ children,
5299
+ open: openProp,
5300
+ defaultOpen = false,
5301
+ onOpenChange,
5302
+ className
5303
+ }) => {
5304
+ const reduceMotion = (0, import_react38.useReducedMotion)();
5305
+ const panelId = (0, import_react37.useId)();
5306
+ const [internalOpen, setInternalOpen] = (0, import_react37.useState)(defaultOpen);
5307
+ const open = openProp ?? internalOpen;
5308
+ const toggle = () => {
5309
+ if (openProp == null) setInternalOpen((o) => !o);
5310
+ onOpenChange?.(!open);
5311
+ };
5312
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: cn("border-b border-border last:border-0", className), children: [
5313
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
5314
+ "button",
5315
+ {
5316
+ type: "button",
5317
+ onClick: toggle,
5318
+ "aria-expanded": open,
5319
+ "aria-controls": panelId,
5320
+ 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",
5321
+ children: [
5322
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "flex min-w-0 items-center gap-3", children: [
5323
+ 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,
5324
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "truncate text-sm font-medium text-foreground", children: title }),
5325
+ 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
5326
+ ] }),
5327
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Chevron, { open })
5328
+ ]
5329
+ }
5330
+ ),
5331
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_react38.AnimatePresence, { initial: false, children: open ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
5332
+ import_react38.motion.div,
5333
+ {
5334
+ id: panelId,
5335
+ initial: reduceMotion ? void 0 : { height: 0, opacity: 0 },
5336
+ animate: { height: "auto", opacity: 1 },
5337
+ exit: reduceMotion ? void 0 : { height: 0, opacity: 0 },
5338
+ transition: { duration: 0.2, ease: "easeOut" },
5339
+ className: "overflow-hidden",
5340
+ children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "bg-muted/20", children })
5341
+ },
5342
+ "body"
5343
+ ) : null })
5344
+ ] });
5345
+ };
5346
+
5347
+ // src/app/surfaces/ResourceCard.tsx
5348
+ var import_jsx_runtime47 = require("react/jsx-runtime");
5349
+ var resourceCardShellClass = cn(
5350
+ "flex min-h-[8.5rem] flex-col rounded-2xl p-4 text-left font-normal",
5351
+ TIMBAL_V2_ELEVATED_SURFACE
4668
5352
  );
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"
5353
+ var mediaShellClass = cn(
5354
+ "flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-xl text-sm font-normal text-foreground",
5355
+ TIMBAL_V2_LOGO_TILE
4671
5356
  );
4672
- var pillSegmentedFlushSegmentClass = cn(
5357
+ var resourceCardInteractiveClass = cn(
5358
+ resourceCardShellClass,
5359
+ "cursor-pointer bg-transparent hover:bg-transparent active:bg-transparent",
5360
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15 focus-visible:ring-offset-2 focus-visible:ring-offset-background"
5361
+ );
5362
+ var ResourceCard = ({
5363
+ title,
5364
+ subtitle,
5365
+ media,
5366
+ badge,
5367
+ footer,
5368
+ action,
5369
+ onClick,
5370
+ ariaLabel,
5371
+ className
5372
+ }) => {
5373
+ const body = /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
5374
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-start gap-3", children: [
5375
+ media ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: mediaShellClass, children: media }) : null,
5376
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "min-w-0 flex-1 pt-0.5", children: [
5377
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "truncate text-sm font-normal leading-snug text-foreground", children: title }),
5378
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "mt-1 line-clamp-2 text-xs font-normal text-muted-foreground", children: subtitle }) : null
5379
+ ] }),
5380
+ badge ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "shrink-0 pt-0.5", children: badge }) : null
5381
+ ] }),
5382
+ 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: [
5383
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "min-w-0 truncate", children: footer }),
5384
+ action ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "shrink-0 opacity-80", children: action }) : null
5385
+ ] }) : null
5386
+ ] });
5387
+ if (onClick) {
5388
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", onClick, "aria-label": ariaLabel, className: cn(resourceCardInteractiveClass, className), children: body });
5389
+ }
5390
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("article", { className: cn(resourceCardShellClass, className), children: body });
5391
+ };
5392
+
5393
+ // src/app/settings/SettingsSection.tsx
5394
+ var import_jsx_runtime48 = require("react/jsx-runtime");
5395
+ var SettingsSectionHeader = ({
5396
+ title,
5397
+ description,
5398
+ className
5399
+ }) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: cn("flex flex-col", className), children: [
5400
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("h3", { className: "text-[17px] font-medium leading-tight text-foreground", children: title }),
5401
+ description ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null
5402
+ ] });
5403
+ var SettingsSection = ({
5404
+ title,
5405
+ description,
5406
+ descriptionFooter,
5407
+ children,
5408
+ noBorderTop = false,
5409
+ className
5410
+ }) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
5411
+ "section",
5412
+ {
5413
+ className: cn(
5414
+ "grid grid-cols-1 gap-y-4 lg:grid-cols-[minmax(200px,280px)_minmax(0,1fr)] lg:gap-x-12 lg:gap-y-0",
5415
+ noBorderTop ? "pb-6" : "border-t border-border py-6",
5416
+ className
5417
+ ),
5418
+ children: [
5419
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "min-w-0", children: [
5420
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("h2", { className: "text-sm font-medium text-foreground", children: title }),
5421
+ description ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null,
5422
+ descriptionFooter ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "mt-3 min-w-0", children: descriptionFooter }) : null
5423
+ ] }),
5424
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "min-w-0 space-y-3", children })
5425
+ ]
5426
+ }
5427
+ );
5428
+
5429
+ // src/app/settings/FieldRow.tsx
5430
+ var import_jsx_runtime49 = require("react/jsx-runtime");
5431
+ var FieldRow = ({
5432
+ label,
5433
+ children,
5434
+ description,
5435
+ inline = false,
5436
+ htmlFor,
5437
+ className
5438
+ }) => {
5439
+ if (inline) {
5440
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
5441
+ "div",
5442
+ {
5443
+ className: cn(
5444
+ "flex items-center justify-between gap-4 rounded-lg border border-border bg-card px-3.5 py-3",
5445
+ className
5446
+ ),
5447
+ children: [
5448
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "min-w-0", children: [
5449
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
5450
+ "label",
5451
+ {
5452
+ htmlFor,
5453
+ className: "block text-sm font-medium text-foreground",
5454
+ children: label
5455
+ }
5456
+ ),
5457
+ description ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "mt-0.5 text-xs text-muted-foreground", children: description }) : null
5458
+ ] }),
5459
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "shrink-0", children })
5460
+ ]
5461
+ }
5462
+ );
5463
+ }
5464
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: cn("flex flex-col gap-1.5", className), children: [
5465
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("label", { htmlFor, className: "text-sm font-medium text-foreground", children: label }),
5466
+ children,
5467
+ description ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-xs text-muted-foreground", children: description }) : null
5468
+ ] });
5469
+ };
5470
+
5471
+ // src/app/settings/FloatingUnsavedChangesBar.tsx
5472
+ var import_react39 = require("react");
5473
+ var import_react_dom = require("react-dom");
5474
+ var import_react40 = require("motion/react");
5475
+ var import_jsx_runtime50 = require("react/jsx-runtime");
5476
+ var FloatingUnsavedChangesBar = ({
5477
+ visible,
5478
+ message = "Unsaved changes",
5479
+ discardLabel = "Discard",
5480
+ saveLabel = "Save changes",
5481
+ isSaving = false,
5482
+ saveDisabled = false,
5483
+ onDiscard,
5484
+ onSave,
5485
+ ariaLabel = "Unsaved changes",
5486
+ className
5487
+ }) => {
5488
+ const reduceMotion = (0, import_react40.useReducedMotion)();
5489
+ const [mounted, setMounted] = (0, import_react39.useState)(false);
5490
+ (0, import_react39.useEffect)(() => setMounted(true), []);
5491
+ if (!mounted || typeof document === "undefined") return null;
5492
+ return (0, import_react_dom.createPortal)(
5493
+ /* @__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)(
5494
+ import_react40.motion.div,
5495
+ {
5496
+ role: "region",
5497
+ "aria-label": ariaLabel,
5498
+ initial: reduceMotion ? { opacity: 0 } : { opacity: 0, y: 28, scale: 0.94 },
5499
+ animate: { opacity: 1, y: 0, scale: 1 },
5500
+ exit: reduceMotion ? { opacity: 0 } : { opacity: 0, y: 18, scale: 0.96 },
5501
+ transition: { type: "spring", stiffness: 420, damping: 32 },
5502
+ className: cn(
5503
+ "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",
5504
+ className
5505
+ ),
5506
+ children: [
5507
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "text-sm text-muted-foreground", children: message }),
5508
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "flex items-center gap-1.5", children: [
5509
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(Button, { variant: "ghost", size: "sm", onClick: onDiscard, disabled: isSaving, children: discardLabel }),
5510
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(Button, { size: "sm", onClick: onSave, disabled: saveDisabled || isSaving, children: isSaving ? "Saving\u2026" : saveLabel })
5511
+ ] })
5512
+ ]
5513
+ }
5514
+ ) }) : null }),
5515
+ document.body
5516
+ );
5517
+ };
5518
+
5519
+ // src/app/settings/DangerZone.tsx
5520
+ var import_jsx_runtime51 = require("react/jsx-runtime");
5521
+ var DangerZoneAction = ({
5522
+ title,
5523
+ description,
5524
+ action,
5525
+ className
5526
+ }) => /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
5527
+ "div",
5528
+ {
5529
+ className: cn(
5530
+ "flex flex-col gap-3 px-4 py-3.5 sm:flex-row sm:items-center sm:justify-between",
5531
+ className
5532
+ ),
5533
+ children: [
5534
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "min-w-0", children: [
5535
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("p", { className: "text-sm font-medium text-foreground", children: title }),
5536
+ description ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
5537
+ ] }),
5538
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "shrink-0", children: action })
5539
+ ]
5540
+ }
5541
+ );
5542
+ var DangerZone = ({
5543
+ title = "Danger zone",
5544
+ description,
5545
+ children,
5546
+ className
5547
+ }) => /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
5548
+ "section",
5549
+ {
5550
+ className: cn(
5551
+ "overflow-hidden rounded-xl border border-destructive/30",
5552
+ className
5553
+ ),
5554
+ children: [
5555
+ (title || description) && /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("header", { className: "border-b border-destructive/20 bg-destructive/5 px-4 py-3", children: [
5556
+ title ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("h3", { className: "text-sm font-semibold text-destructive", children: title }) : null,
5557
+ description ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
5558
+ ] }),
5559
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "divide-y divide-border bg-card", children })
5560
+ ]
5561
+ }
5562
+ );
5563
+
5564
+ // src/app/integrations/IntegrationCard.tsx
5565
+ var import_react41 = require("react");
5566
+ var import_jsx_runtime52 = require("react/jsx-runtime");
5567
+ var INTEGRATION_CATALOG_CARD_HEIGHT_CLASS = "h-[12.25rem] min-h-[12.25rem] max-h-[12.25rem]";
5568
+ var statusLabel = {
5569
+ available: null,
5570
+ connected: "Connected",
5571
+ disabled: "Disabled",
5572
+ locked: "Locked"
5573
+ };
5574
+ var catalogCardShellClass = cn(
5575
+ "group relative box-border flex flex-col overflow-hidden rounded-2xl px-4 pb-4 pt-4 text-left font-normal",
5576
+ INTEGRATION_CATALOG_CARD_HEIGHT_CLASS,
5577
+ TIMBAL_V2_ELEVATED_SURFACE,
5578
+ "transition-opacity duration-200 ease-out"
5579
+ );
5580
+ var catalogCardInteractiveClass = cn(
5581
+ catalogCardShellClass,
5582
+ "cursor-pointer bg-transparent hover:bg-transparent active:bg-transparent",
5583
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/15 focus-visible:ring-offset-2 focus-visible:ring-offset-background"
5584
+ );
5585
+ var catalogCardMutedClass = cn(
5586
+ "border-border/60 saturate-[0.72]",
5587
+ "from-muted/80 to-muted/50 dark:border-white/[0.06] dark:from-white/[0.04] dark:to-white/[0.02]"
5588
+ );
5589
+ var logoShellClass = cn(
5590
+ "relative flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-xl",
5591
+ TIMBAL_V2_LOGO_TILE
5592
+ );
5593
+ var IntegrationCard = ({
5594
+ name,
5595
+ description,
5596
+ logo,
5597
+ badge,
5598
+ status = "available",
5599
+ action,
5600
+ onClick,
5601
+ ariaLabel,
5602
+ className
5603
+ }) => {
5604
+ const titleId = (0, import_react41.useId)();
5605
+ const locked = status === "locked";
5606
+ const dimmed = status === "disabled" || locked;
5607
+ const body = /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "flex h-full min-h-0 flex-col", children: [
5608
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "flex shrink-0 items-start gap-3 pr-2", children: [
5609
+ logo ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: logoShellClass, "aria-hidden": Boolean(ariaLabel), children: logo }) : null,
5610
+ /* @__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: [
5611
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "min-w-0", children: [
5612
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
5613
+ "h4",
5614
+ {
5615
+ id: onClick && !action ? void 0 : titleId,
5616
+ className: "truncate text-sm font-normal leading-snug text-foreground",
5617
+ children: name
5618
+ }
5619
+ ),
5620
+ statusLabel[status] ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("p", { className: "mt-0.5 text-xs text-muted-foreground", children: statusLabel[status] }) : null
5621
+ ] }),
5622
+ badge ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "shrink-0", children: badge }) : null
5623
+ ] }) })
5624
+ ] }),
5625
+ description ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
5626
+ "p",
5627
+ {
5628
+ className: cn(
5629
+ "mt-3 line-clamp-3 shrink-0 text-sm leading-relaxed text-muted-foreground",
5630
+ dimmed && "text-muted-foreground/80"
5631
+ ),
5632
+ children: description
5633
+ }
5634
+ ) : null,
5635
+ action ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_jsx_runtime52.Fragment, { children: [
5636
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "min-h-0 flex-1", "aria-hidden": true }),
5637
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "relative mt-3 shrink-0", children: action })
5638
+ ] }) : null
5639
+ ] });
5640
+ const shellClass3 = cn(
5641
+ catalogCardShellClass,
5642
+ dimmed && catalogCardMutedClass,
5643
+ locked && "cursor-default opacity-75",
5644
+ className
5645
+ );
5646
+ if (onClick && !action) {
5647
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
5648
+ "button",
5649
+ {
5650
+ type: "button",
5651
+ onClick,
5652
+ disabled: locked,
5653
+ "aria-label": ariaLabel,
5654
+ className: cn(
5655
+ catalogCardInteractiveClass,
5656
+ dimmed && catalogCardMutedClass,
5657
+ locked && "cursor-default opacity-75",
5658
+ className
5659
+ ),
5660
+ children: body
5661
+ }
5662
+ );
5663
+ }
5664
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("article", { className: shellClass3, "aria-labelledby": titleId, children: body });
5665
+ };
5666
+
5667
+ // src/app/integrations/IntegrationsEmptyState.tsx
5668
+ var import_react42 = require("react");
5669
+ var import_jsx_runtime53 = require("react/jsx-runtime");
5670
+ var IntegrationsEmptyState = ({
5671
+ title = "No integrations yet",
5672
+ description = "Connect a provider to start syncing data and powering your workforce.",
5673
+ icon,
5674
+ action,
5675
+ className
5676
+ }) => {
5677
+ const titleId = (0, import_react42.useId)();
5678
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
5679
+ "section",
5680
+ {
5681
+ className: cn(
5682
+ "flex flex-col items-center justify-center gap-3 rounded-2xl px-6 py-14 text-center",
5683
+ TIMBAL_V2_ELEVATED_SURFACE,
5684
+ className
5685
+ ),
5686
+ "aria-labelledby": titleId,
5687
+ children: [
5688
+ icon ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
5689
+ "span",
5690
+ {
5691
+ className: cn(
5692
+ "flex size-14 items-center justify-center overflow-hidden rounded-2xl",
5693
+ TIMBAL_V2_LOGO_TILE,
5694
+ "text-muted-foreground"
5695
+ ),
5696
+ "aria-hidden": true,
5697
+ children: icon
5698
+ }
5699
+ ) : null,
5700
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("h3", { id: titleId, className: "text-base font-normal text-foreground", children: title }),
5701
+ description ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("p", { className: "max-w-sm text-sm text-muted-foreground", children: description }) : null,
5702
+ action ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "mt-1", children: action }) : null
5703
+ ]
5704
+ }
5705
+ );
5706
+ };
5707
+
5708
+ // src/app/integrations/PlanBadge.tsx
5709
+ var import_jsx_runtime54 = require("react/jsx-runtime");
5710
+ 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";
5711
+ var PlanBadge = ({ children, className }) => /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: cn(planBadgeClass, className), children });
5712
+
5713
+ // src/app/integrations/ConnectionRow.tsx
5714
+ var import_jsx_runtime55 = require("react/jsx-runtime");
5715
+ var logoShellClass2 = cn(
5716
+ "flex size-9 shrink-0 items-center justify-center overflow-hidden rounded-lg",
5717
+ TIMBAL_V2_LOGO_TILE
5718
+ );
5719
+ var ConnectionRow = ({
5720
+ name,
5721
+ logo,
5722
+ meta,
5723
+ badge,
5724
+ action,
5725
+ onClick,
5726
+ ariaLabel,
5727
+ className
5728
+ }) => {
5729
+ const inner = /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_jsx_runtime55.Fragment, { children: [
5730
+ logo ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: logoShellClass2, children: logo }) : null,
5731
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "min-w-0 flex-1", children: [
5732
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "truncate text-sm font-normal text-foreground", children: name }),
5733
+ meta ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "truncate text-xs text-muted-foreground", children: meta }) : null
5734
+ ] }),
5735
+ badge ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "shrink-0", children: badge }) : null,
5736
+ action ? /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "shrink-0", children: action }) : null
5737
+ ] });
5738
+ const rowClass2 = cn(
5739
+ "flex w-full items-center gap-3 px-4 py-3 text-left",
5740
+ 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",
5741
+ className
5742
+ );
5743
+ if (onClick) {
5744
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
5745
+ "button",
5746
+ {
5747
+ type: "button",
5748
+ role: "listitem",
5749
+ onClick,
5750
+ "aria-label": ariaLabel,
5751
+ className: rowClass2,
5752
+ children: inner
5753
+ }
5754
+ );
5755
+ }
5756
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { role: "listitem", className: rowClass2, children: inner });
5757
+ };
5758
+ var connectionRowListClass = cn(
5759
+ "overflow-hidden rounded-2xl",
5760
+ TIMBAL_V2_ELEVATED_SURFACE
5761
+ );
5762
+
5763
+ // src/app/integrations/ConnectionRowList.tsx
5764
+ var import_jsx_runtime56 = require("react/jsx-runtime");
5765
+ var ConnectionRowList = ({
5766
+ children,
5767
+ "aria-label": ariaLabel = "Connected integrations",
5768
+ className
5769
+ }) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
5770
+ "div",
5771
+ {
5772
+ role: "list",
5773
+ "aria-label": ariaLabel,
5774
+ className: cn(connectionRowListClass, "divide-y divide-border", className),
5775
+ children
5776
+ }
5777
+ );
5778
+
5779
+ // src/ui/pill-segmented-tabs.tsx
5780
+ var import_react43 = require("react");
5781
+ var import_react44 = require("motion/react");
5782
+
5783
+ // src/design/pill-segmented-classes.ts
5784
+ var pillSegmentedTrackBase = "inline-flex w-fit max-w-max shrink-0 self-start items-center rounded-full";
5785
+ var pillSegmentedTrackSurface = cn(
5786
+ "bg-pill-segmented-track border border-[var(--pill-segmented-track-border)]",
5787
+ "shadow-[var(--pill-segmented-track-shadow)]"
5788
+ );
5789
+ var pillSegmentedTrackClass = cn(
5790
+ pillSegmentedTrackBase,
5791
+ pillSegmentedTrackSurface,
5792
+ "gap-1 p-1"
5793
+ );
5794
+ var pillSegmentedTrackFlushClass = cn(
5795
+ pillSegmentedTrackBase,
5796
+ pillSegmentedTrackSurface,
5797
+ "h-[var(--studio-chrome-pill-height)] items-center gap-0.5 overflow-visible p-0.5"
5798
+ );
5799
+ var pillSegmentedSegmentClass = cn(
5800
+ "relative flex items-center gap-1.5 rounded-full px-4 py-1.5 text-xs font-normal transition-colors"
5801
+ );
5802
+ var pillSegmentedFlushSegmentClass = cn(
4673
5803
  "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
5804
  "text-sm font-normal leading-tight transition-colors"
4675
5805
  );
@@ -4681,7 +5811,7 @@ var pillSegmentedActiveIndicatorClass = cn(
4681
5811
  );
4682
5812
 
4683
5813
  // src/ui/pill-segmented-tabs.tsx
4684
- var import_jsx_runtime42 = require("react/jsx-runtime");
5814
+ var import_jsx_runtime57 = require("react/jsx-runtime");
4685
5815
  var PillTab = ({
4686
5816
  tabKey,
4687
5817
  label,
@@ -4692,10 +5822,10 @@ var PillTab = ({
4692
5822
  segmentClassName,
4693
5823
  animateIndicator
4694
5824
  }) => {
4695
- const handlePress = (0, import_react35.useCallback)(() => {
5825
+ const handlePress = (0, import_react43.useCallback)(() => {
4696
5826
  if (!disabled) onSelect(tabKey);
4697
5827
  }, [disabled, onSelect, tabKey]);
4698
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
5828
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
4699
5829
  "button",
4700
5830
  {
4701
5831
  type: "button",
@@ -4708,15 +5838,15 @@ var PillTab = ({
4708
5838
  !disabled && (isActive ? "text-foreground" : "text-muted-foreground hover:text-foreground")
4709
5839
  ),
4710
5840
  children: [
4711
- isActive && animateIndicator ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
4712
- import_react36.motion.div,
5841
+ isActive && animateIndicator ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
5842
+ import_react44.motion.div,
4713
5843
  {
4714
5844
  layoutId,
4715
5845
  className: pillSegmentedActiveIndicatorClass,
4716
5846
  transition: { type: "spring", duration: 0.3, bounce: 0.15 }
4717
5847
  }
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 })
5848
+ ) : isActive ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: pillSegmentedActiveIndicatorClass, "aria-hidden": true }) : null,
5849
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "relative z-10 whitespace-nowrap", children: label })
4720
5850
  ]
4721
5851
  }
4722
5852
  );
@@ -4730,13 +5860,13 @@ var PillSegmentedTabs = ({
4730
5860
  layoutId: layoutIdProp,
4731
5861
  "aria-label": ariaLabel
4732
5862
  }) => {
4733
- const reactId = (0, import_react35.useId)();
5863
+ const reactId = (0, import_react43.useId)();
4734
5864
  const layoutId = layoutIdProp ?? `pill-segmented-${reactId.replace(/:/g, "")}`;
4735
- const reducedMotion = (0, import_react36.useReducedMotion)();
5865
+ const reducedMotion = (0, import_react44.useReducedMotion)();
4736
5866
  const isFlush = trackVariant === "flush";
4737
5867
  const trackClass2 = isFlush ? pillSegmentedTrackFlushClass : pillSegmentedTrackClass;
4738
5868
  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)(
5869
+ 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
5870
  PillTab,
4741
5871
  {
4742
5872
  tabKey: tab.key,
@@ -4751,10 +5881,10 @@ var PillSegmentedTabs = ({
4751
5881
  tab.key
4752
5882
  )) });
4753
5883
  };
4754
- var MemoPillSegmentedTabs = (0, import_react35.memo)(PillSegmentedTabs);
5884
+ var MemoPillSegmentedTabs = (0, import_react43.memo)(PillSegmentedTabs);
4755
5885
 
4756
5886
  // src/app/navigation/SubNav.tsx
4757
- var import_jsx_runtime43 = require("react/jsx-runtime");
5887
+ var import_jsx_runtime58 = require("react/jsx-runtime");
4758
5888
  var SubNav = ({
4759
5889
  items,
4760
5890
  activeId,
@@ -4763,7 +5893,7 @@ var SubNav = ({
4763
5893
  "aria-label": ariaLabel = "Section navigation",
4764
5894
  layoutId
4765
5895
  }) => {
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)(
5896
+ 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
5897
  PillSegmentedTabs,
4768
5898
  {
4769
5899
  value: activeId,
@@ -4777,13 +5907,13 @@ var SubNav = ({
4777
5907
  };
4778
5908
 
4779
5909
  // src/app/navigation/Breadcrumbs.tsx
4780
- var import_jsx_runtime44 = require("react/jsx-runtime");
5910
+ var import_jsx_runtime59 = require("react/jsx-runtime");
4781
5911
  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) => {
5912
+ 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
5913
  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)(
5914
+ return /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("li", { className: "inline-flex items-center gap-1.5", children: [
5915
+ index > 0 ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "text-muted-foreground/50", "aria-hidden": true, children: "/" }) : null,
5916
+ 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
5917
  "button",
4788
5918
  {
4789
5919
  type: "button",
@@ -4797,7 +5927,7 @@ var Breadcrumbs = ({ items, className }) => {
4797
5927
  };
4798
5928
 
4799
5929
  // src/app/forms/Field.tsx
4800
- var import_jsx_runtime45 = require("react/jsx-runtime");
5930
+ var import_jsx_runtime60 = require("react/jsx-runtime");
4801
5931
  var Field = ({
4802
5932
  label,
4803
5933
  hint,
@@ -4806,11 +5936,11 @@ var Field = ({
4806
5936
  className,
4807
5937
  htmlFor
4808
5938
  }) => {
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 }),
5939
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("div", { className: cn("aui-app-field", appFieldClass, className), children: [
5940
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("label", { className: appFieldLabelClass, htmlFor, children: label }),
4811
5941
  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
5942
+ hint && !error ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { className: appFieldHintClass, children: hint }) : null,
5943
+ error ? /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("p", { className: "text-xs text-destructive", role: "alert", children: error }) : null
4814
5944
  ] });
4815
5945
  };
4816
5946
  var FieldInput = ({
@@ -4823,7 +5953,7 @@ var FieldInput = ({
4823
5953
  ...inputProps
4824
5954
  }) => {
4825
5955
  const inputId = id ?? inputProps.name;
4826
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
5956
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
4827
5957
  Field,
4828
5958
  {
4829
5959
  label,
@@ -4831,7 +5961,7 @@ var FieldInput = ({
4831
5961
  error,
4832
5962
  htmlFor: inputId,
4833
5963
  className: fieldClassName,
4834
- children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
5964
+ children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
4835
5965
  "input",
4836
5966
  {
4837
5967
  id: inputId,
@@ -4845,7 +5975,7 @@ var FieldInput = ({
4845
5975
  };
4846
5976
 
4847
5977
  // src/app/forms/FieldTextarea.tsx
4848
- var import_jsx_runtime46 = require("react/jsx-runtime");
5978
+ var import_jsx_runtime61 = require("react/jsx-runtime");
4849
5979
  var textareaClass = cn(
4850
5980
  appInputClass,
4851
5981
  "min-h-[5.5rem] resize-y py-2.5 leading-relaxed"
@@ -4860,7 +5990,7 @@ var FieldTextarea = ({
4860
5990
  ...props
4861
5991
  }) => {
4862
5992
  const textareaId = id ?? props.name;
4863
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
5993
+ return /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
4864
5994
  Field,
4865
5995
  {
4866
5996
  label,
@@ -4868,7 +5998,7 @@ var FieldTextarea = ({
4868
5998
  error,
4869
5999
  htmlFor: textareaId,
4870
6000
  className: fieldClassName,
4871
- children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
6001
+ children: /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
4872
6002
  "textarea",
4873
6003
  {
4874
6004
  id: textareaId,
@@ -4883,7 +6013,7 @@ var FieldTextarea = ({
4883
6013
 
4884
6014
  // src/app/forms/FieldSelect.tsx
4885
6015
  var import_lucide_react10 = require("lucide-react");
4886
- var import_jsx_runtime47 = require("react/jsx-runtime");
6016
+ var import_jsx_runtime62 = require("react/jsx-runtime");
4887
6017
  var selectWrapClass = "relative";
4888
6018
  var selectClass = cn(
4889
6019
  appInputClass,
@@ -4900,7 +6030,7 @@ var FieldSelect = ({
4900
6030
  ...props
4901
6031
  }) => {
4902
6032
  const selectId = id ?? props.name;
4903
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
6033
+ return /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
4904
6034
  Field,
4905
6035
  {
4906
6036
  label,
@@ -4908,8 +6038,8 @@ var FieldSelect = ({
4908
6038
  error,
4909
6039
  htmlFor: selectId,
4910
6040
  className: fieldClassName,
4911
- children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: selectWrapClass, children: [
4912
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
6041
+ children: /* @__PURE__ */ (0, import_jsx_runtime62.jsxs)("div", { className: selectWrapClass, children: [
6042
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
4913
6043
  "select",
4914
6044
  {
4915
6045
  id: selectId,
@@ -4919,7 +6049,7 @@ var FieldSelect = ({
4919
6049
  children
4920
6050
  }
4921
6051
  ),
4922
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
6052
+ /* @__PURE__ */ (0, import_jsx_runtime62.jsx)(
4923
6053
  import_lucide_react10.ChevronDownIcon,
4924
6054
  {
4925
6055
  className: "pointer-events-none absolute top-1/2 right-3 size-4 -translate-y-1/2 text-muted-foreground",
@@ -4932,7 +6062,7 @@ var FieldSelect = ({
4932
6062
  };
4933
6063
 
4934
6064
  // src/app/forms/FieldSwitch.tsx
4935
- var import_jsx_runtime48 = require("react/jsx-runtime");
6065
+ var import_jsx_runtime63 = require("react/jsx-runtime");
4936
6066
  var trackClass = cn(
4937
6067
  "relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-[background,box-shadow,border-color] duration-200",
4938
6068
  "peer-focus-visible:ring-2 peer-focus-visible:ring-foreground/10",
@@ -4953,7 +6083,7 @@ var FieldSwitch = ({
4953
6083
  ...props
4954
6084
  }) => {
4955
6085
  const inputId = id ?? props.name ?? "switch";
4956
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
6086
+ return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
4957
6087
  "label",
4958
6088
  {
4959
6089
  className: cn(
@@ -4962,8 +6092,8 @@ var FieldSwitch = ({
4962
6092
  ),
4963
6093
  htmlFor: inputId,
4964
6094
  children: [
4965
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "relative mt-0.5", children: [
4966
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
6095
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { className: "relative mt-0.5", children: [
6096
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)(
4967
6097
  "input",
4968
6098
  {
4969
6099
  id: inputId,
@@ -4973,11 +6103,11 @@ var FieldSwitch = ({
4973
6103
  ...props
4974
6104
  }
4975
6105
  ),
4976
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: trackClass, "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: thumbClass }) })
6106
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: trackClass, "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: thumbClass }) })
4977
6107
  ] }),
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
6108
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)("span", { className: "flex min-w-0 flex-col gap-0.5", children: [
6109
+ /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "text-sm font-medium text-foreground", children: label }),
6110
+ description ? /* @__PURE__ */ (0, import_jsx_runtime63.jsx)("span", { className: "text-xs text-muted-foreground", children: description }) : null
4981
6111
  ] })
4982
6112
  ]
4983
6113
  }
@@ -4986,13 +6116,13 @@ var FieldSwitch = ({
4986
6116
 
4987
6117
  // src/app/forms/SearchInput.tsx
4988
6118
  var import_lucide_react11 = require("lucide-react");
4989
- var import_jsx_runtime49 = require("react/jsx-runtime");
6119
+ var import_jsx_runtime64 = require("react/jsx-runtime");
4990
6120
  var SearchInput = ({
4991
6121
  className,
4992
6122
  placeholder = "Search\u2026",
4993
6123
  ...props
4994
6124
  }) => {
4995
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
6125
+ return /* @__PURE__ */ (0, import_jsx_runtime64.jsxs)(
4996
6126
  "label",
4997
6127
  {
4998
6128
  className: cn(
@@ -5001,8 +6131,8 @@ var SearchInput = ({
5001
6131
  className
5002
6132
  ),
5003
6133
  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)(
6134
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(import_lucide_react11.SearchIcon, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": true }),
6135
+ /* @__PURE__ */ (0, import_jsx_runtime64.jsx)(
5006
6136
  "input",
5007
6137
  {
5008
6138
  type: "search",
@@ -5017,18 +6147,18 @@ var SearchInput = ({
5017
6147
  };
5018
6148
 
5019
6149
  // src/app/forms/FormSection.tsx
5020
- var import_jsx_runtime50 = require("react/jsx-runtime");
6150
+ var import_jsx_runtime65 = require("react/jsx-runtime");
5021
6151
  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 })
6152
+ return /* @__PURE__ */ (0, import_jsx_runtime65.jsxs)("fieldset", { className: cn("aui-app-form-section", appSectionClass, "border-0 p-0", className), children: [
6153
+ title ? /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("legend", { className: cn(appSectionTitleClass, "mb-3 px-0"), children: title }) : null,
6154
+ /* @__PURE__ */ (0, import_jsx_runtime65.jsx)("div", { className: "flex flex-col gap-4", children })
5025
6155
  ] });
5026
6156
  };
5027
6157
 
5028
6158
  // src/app/data/FilterBar.tsx
5029
- var import_jsx_runtime51 = require("react/jsx-runtime");
6159
+ var import_jsx_runtime66 = require("react/jsx-runtime");
5030
6160
  var FilterBar = ({ children, className }) => {
5031
- return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
6161
+ return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
5032
6162
  "div",
5033
6163
  {
5034
6164
  className: cn("aui-app-filter-bar", appFilterBarClass, className),
@@ -5040,9 +6170,9 @@ var FilterBar = ({ children, className }) => {
5040
6170
  };
5041
6171
 
5042
6172
  // src/app/data/DataTable.tsx
5043
- var import_react37 = require("react");
6173
+ var import_react45 = require("react");
5044
6174
  var import_lucide_react12 = require("lucide-react");
5045
- var import_jsx_runtime52 = require("react/jsx-runtime");
6175
+ var import_jsx_runtime67 = require("react/jsx-runtime");
5046
6176
  var shellClass2 = "overflow-hidden rounded-xl border border-border bg-card shadow-card";
5047
6177
  var tableClass = "w-full border-collapse bg-transparent text-sm";
5048
6178
  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 +6212,12 @@ function SortIndicator({
5082
6212
  }) {
5083
6213
  const iconClass = "size-3.5 shrink-0 opacity-60 group-hover:opacity-100";
5084
6214
  if (!active) {
5085
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react12.ArrowUpDownIcon, { className: iconClass, "aria-hidden": true });
6215
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(import_lucide_react12.ArrowUpDownIcon, { className: iconClass, "aria-hidden": true });
5086
6216
  }
5087
6217
  if (direction === "desc") {
5088
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react12.ArrowDownIcon, { className: iconClass, "aria-hidden": true });
6218
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(import_lucide_react12.ArrowDownIcon, { className: iconClass, "aria-hidden": true });
5089
6219
  }
5090
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react12.ArrowUpIcon, { className: iconClass, "aria-hidden": true });
6220
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(import_lucide_react12.ArrowUpIcon, { className: iconClass, "aria-hidden": true });
5091
6221
  }
5092
6222
  function DataTable({
5093
6223
  columns,
@@ -5108,7 +6238,7 @@ function DataTable({
5108
6238
  dense = false,
5109
6239
  caption
5110
6240
  }) {
5111
- const [uncontrolledSort, setUncontrolledSort] = (0, import_react37.useState)(
6241
+ const [uncontrolledSort, setUncontrolledSort] = (0, import_react45.useState)(
5112
6242
  defaultSort
5113
6243
  );
5114
6244
  const isSortControlled = sortProp !== void 0;
@@ -5119,7 +6249,7 @@ function DataTable({
5119
6249
  }
5120
6250
  onSortChange?.(next);
5121
6251
  };
5122
- const sortedRows = (0, import_react37.useMemo)(() => {
6252
+ const sortedRows = (0, import_react45.useMemo)(() => {
5123
6253
  if (!sort) return rows;
5124
6254
  const column = columns.find((col) => col.id === sort.columnId);
5125
6255
  if (!column?.sortable) return rows;
@@ -5138,28 +6268,28 @@ function DataTable({
5138
6268
  const cellPad = dense ? "px-3 py-2" : void 0;
5139
6269
  const headPad = dense ? "px-3 py-2" : void 0;
5140
6270
  if (rows.length === 0 && emptyMode === "replace") {
5141
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(EmptyState2, { title: emptyTitle, description: emptyDescription, className });
6271
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(EmptyState, { title: emptyTitle, description: emptyDescription, className });
5142
6272
  }
5143
6273
  const rowCountText = rowCountLabel?.(sortedRows.length) ?? `${sortedRows.length} row${sortedRows.length === 1 ? "" : "s"}`;
5144
6274
  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) => {
6275
+ 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: [
6276
+ caption ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("caption", { className: "sr-only", children: caption }) : null,
6277
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("thead", { className: cn(stickyHeader && stickyHeadClass), children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("tr", { children: columns.map((col) => {
5148
6278
  const isSorted = sort?.columnId === col.id;
5149
6279
  const ariaSort = col.sortable ? isSorted ? sort.direction === "asc" ? "ascending" : "descending" : "none" : void 0;
5150
- const headerContent = col.sortable ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
6280
+ const headerContent = col.sortable ? /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
5151
6281
  "button",
5152
6282
  {
5153
6283
  type: "button",
5154
6284
  className: sortButtonClass,
5155
6285
  onClick: () => setSort(nextSort(sort, col.id)),
5156
6286
  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 })
6287
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "truncate", children: col.header }),
6288
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(SortIndicator, { active: Boolean(isSorted), direction: sort?.direction })
5159
6289
  ]
5160
6290
  }
5161
6291
  ) : col.header;
5162
- return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
6292
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
5163
6293
  "th",
5164
6294
  {
5165
6295
  scope: "col",
@@ -5175,10 +6305,10 @@ function DataTable({
5175
6305
  col.id
5176
6306
  );
5177
6307
  }) }) }),
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)(
6308
+ /* @__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: [
6309
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("p", { className: "font-medium text-foreground", children: emptyTitle }),
6310
+ emptyDescription ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("p", { className: "max-w-sm text-muted-foreground", children: emptyDescription }) : null
6311
+ ] }) }) }) : sortedRows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
5182
6312
  "tr",
5183
6313
  {
5184
6314
  className: rowClass,
@@ -5192,7 +6322,7 @@ function DataTable({
5192
6322
  } : void 0,
5193
6323
  tabIndex: onRowClick ? 0 : void 0,
5194
6324
  role: onRowClick ? "button" : void 0,
5195
- children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
6325
+ children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
5196
6326
  "td",
5197
6327
  {
5198
6328
  className: cn(
@@ -5208,7 +6338,7 @@ function DataTable({
5208
6338
  },
5209
6339
  getRowKey(row)
5210
6340
  )) }),
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)(
6341
+ 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
6342
  "div",
5213
6343
  {
5214
6344
  className: cn(
@@ -5216,7 +6346,7 @@ function DataTable({
5216
6346
  showRowCount && footer ? "justify-between" : "justify-start"
5217
6347
  ),
5218
6348
  children: [
5219
- showRowCount ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { children: rowCountText }) : null,
6349
+ showRowCount ? /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { children: rowCountText }) : null,
5220
6350
  footer
5221
6351
  ]
5222
6352
  }
@@ -5225,27 +6355,415 @@ function DataTable({
5225
6355
  }
5226
6356
 
5227
6357
  // 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";
6358
+ var import_react46 = require("react");
6359
+
6360
+ // src/app/data/metrics-shared.tsx
6361
+ var import_jsx_runtime68 = require("react/jsx-runtime");
6362
+ var metricCardShellClass = cn(
6363
+ studioIntegrationCardClass,
6364
+ "aui-app-metric-card shadow-none",
6365
+ "flex flex-col overflow-hidden"
6366
+ );
6367
+ var metricCardHeaderClass = "flex items-start justify-between gap-3 px-4 pb-1 pt-3";
6368
+ var metricTilesRowClass = "grid w-full min-w-0";
6369
+ var metricChartRegionClass = "relative min-h-0 w-full border-t border-border/40 pt-2";
6370
+ var metricChartPlotRegionClass = "relative min-h-0 w-full border-t border-border/40 px-0 pt-5 pb-3";
6371
+ var metricCellDividerClass = "border-r border-border/40";
6372
+ var MetricCardHeader = ({
6373
+ title,
6374
+ titleId,
6375
+ description,
6376
+ actions
6377
+ }) => {
6378
+ if (!title && !description && !actions) return null;
6379
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("header", { className: metricCardHeaderClass, children: [
6380
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "min-w-0", children: [
6381
+ title ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("h3", { id: titleId, className: "text-base font-normal text-foreground", children: title }) : null,
6382
+ description ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
6383
+ ] }),
6384
+ actions ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "shrink-0", children: actions }) : null
6385
+ ] });
6386
+ };
6387
+ function metricTilesGridColsClass(n) {
6388
+ switch (n) {
6389
+ case 1:
6390
+ return "grid-cols-1";
6391
+ case 2:
6392
+ return "grid-cols-2";
6393
+ case 3:
6394
+ return "grid-cols-3";
6395
+ case 5:
6396
+ return "grid-cols-2 sm:grid-cols-5";
6397
+ case 6:
6398
+ return "grid-cols-2 sm:grid-cols-3 lg:grid-cols-6";
6399
+ default:
6400
+ return "grid-cols-2 md:grid-cols-4";
6401
+ }
6402
+ }
6403
+
6404
+ // src/app/data/ChartPanel.tsx
6405
+ var import_jsx_runtime69 = require("react/jsx-runtime");
5230
6406
  var ChartPanel = ({
5231
6407
  title,
6408
+ description,
5232
6409
  artifact,
5233
6410
  children,
5234
6411
  actions,
6412
+ height = 300,
5235
6413
  className
5236
6414
  }) => {
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 })
6415
+ const titleId = (0, import_react46.useId)();
6416
+ const resolvedTitle = title ?? artifact?.title;
6417
+ const hasHeader = Boolean(resolvedTitle || description || actions);
6418
+ const body = children ?? (artifact ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(ChartArtifactView, { artifact, embedded: true, height }) : null);
6419
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
6420
+ "section",
6421
+ {
6422
+ className: cn(metricCardShellClass, "aui-app-chart-panel", className),
6423
+ "aria-labelledby": resolvedTitle ? titleId : void 0,
6424
+ children: [
6425
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
6426
+ MetricCardHeader,
6427
+ {
6428
+ title: resolvedTitle,
6429
+ titleId,
6430
+ description,
6431
+ actions
6432
+ }
6433
+ ),
6434
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
6435
+ "div",
6436
+ {
6437
+ className: cn(
6438
+ "relative min-h-0 w-full",
6439
+ hasHeader ? metricChartPlotRegionClass : "pt-2 pb-3"
6440
+ ),
6441
+ children: body ?? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
6442
+ "div",
6443
+ {
6444
+ className: "flex items-center justify-center text-sm font-normal text-muted-foreground",
6445
+ style: { minHeight: height },
6446
+ role: "status",
6447
+ children: "No chart"
6448
+ }
6449
+ )
6450
+ }
6451
+ )
6452
+ ]
6453
+ }
6454
+ );
6455
+ };
6456
+
6457
+ // src/app/data/MetricTile.tsx
6458
+ var import_jsx_runtime70 = require("react/jsx-runtime");
6459
+ var trendToneClass = {
6460
+ up: "border-border/80 bg-muted/40 text-muted-foreground",
6461
+ down: "border-border/80 bg-muted/40 text-muted-foreground",
6462
+ neutral: "border-border/80 bg-muted/30 text-muted-foreground"
6463
+ };
6464
+ var metricTileBaseClass = "relative flex min-w-0 flex-1 flex-col gap-1 px-4 py-3 text-left font-normal";
6465
+ var metricTileInteractiveClass = cn(
6466
+ metricTileBaseClass,
6467
+ "bg-transparent hover:bg-transparent active:bg-transparent",
6468
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-foreground/10"
6469
+ );
6470
+ var MetricTile = ({
6471
+ label,
6472
+ value,
6473
+ unit,
6474
+ trend,
6475
+ trendTone = "neutral",
6476
+ active = false,
6477
+ showDivider = false,
6478
+ onSelect,
6479
+ ariaLabel,
6480
+ className
6481
+ }) => {
6482
+ const content = /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)(import_jsx_runtime70.Fragment, { children: [
6483
+ active ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
6484
+ "span",
6485
+ {
6486
+ "aria-hidden": true,
6487
+ className: "absolute inset-x-0 bottom-0 h-0.5 bg-foreground dark:bg-white"
6488
+ }
6489
+ ) : null,
6490
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "text-xs font-normal text-muted-foreground", children: label }),
6491
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "flex items-center gap-2", children: [
6492
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsxs)("span", { className: "flex items-baseline gap-1", children: [
6493
+ /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "text-2xl font-normal tracking-tight text-foreground tabular-nums", children: value }),
6494
+ unit ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("span", { className: "text-xs font-normal text-muted-foreground", children: unit }) : null
6495
+ ] }),
6496
+ trend ? /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
6497
+ "span",
6498
+ {
6499
+ className: cn(
6500
+ "rounded-full border px-1.5 py-0.5 text-xs font-normal",
6501
+ trendToneClass[trendTone]
6502
+ ),
6503
+ children: trend
6504
+ }
6505
+ ) : null
6506
+ ] })
5244
6507
  ] });
6508
+ const divider = showDivider ? metricCellDividerClass : void 0;
6509
+ if (onSelect) {
6510
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
6511
+ "button",
6512
+ {
6513
+ type: "button",
6514
+ onClick: onSelect,
6515
+ "aria-pressed": active,
6516
+ "aria-label": ariaLabel,
6517
+ className: cn(metricTileInteractiveClass, divider, className),
6518
+ children: content
6519
+ }
6520
+ );
6521
+ }
6522
+ return /* @__PURE__ */ (0, import_jsx_runtime70.jsx)("div", { className: cn(metricTileBaseClass, divider, className), children: content });
6523
+ };
6524
+
6525
+ // src/app/data/MetricRow.tsx
6526
+ var import_react47 = require("react");
6527
+ var import_jsx_runtime71 = require("react/jsx-runtime");
6528
+ var MetricRow = ({
6529
+ title,
6530
+ description,
6531
+ actions,
6532
+ metrics,
6533
+ activeMetricId,
6534
+ defaultActiveMetricId,
6535
+ onMetricChange,
6536
+ metricsAriaLabel = "Metrics",
6537
+ className
6538
+ }) => {
6539
+ const titleId = (0, import_react47.useId)();
6540
+ const selectable = onMetricChange != null || activeMetricId != null;
6541
+ const [internalId, setInternalId] = (0, import_react47.useState)(
6542
+ defaultActiveMetricId ?? metrics[0]?.id
6543
+ );
6544
+ const activeId = activeMetricId ?? internalId;
6545
+ const select = (id) => {
6546
+ if (activeMetricId == null) setInternalId(id);
6547
+ onMetricChange?.(id);
6548
+ };
6549
+ return /* @__PURE__ */ (0, import_jsx_runtime71.jsxs)(
6550
+ "section",
6551
+ {
6552
+ className: cn(metricCardShellClass, className),
6553
+ "aria-labelledby": title ? titleId : void 0,
6554
+ children: [
6555
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
6556
+ MetricCardHeader,
6557
+ {
6558
+ title,
6559
+ titleId,
6560
+ description,
6561
+ actions
6562
+ }
6563
+ ),
6564
+ /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
6565
+ "div",
6566
+ {
6567
+ role: selectable ? "group" : void 0,
6568
+ "aria-label": selectable ? metricsAriaLabel : void 0,
6569
+ className: cn(
6570
+ metricTilesRowClass,
6571
+ metricTilesGridColsClass(metrics.length),
6572
+ (title || description || actions) && "mt-3"
6573
+ ),
6574
+ children: metrics.map((m, index) => /* @__PURE__ */ (0, import_jsx_runtime71.jsx)(
6575
+ MetricTile,
6576
+ {
6577
+ label: m.label,
6578
+ value: m.value,
6579
+ unit: m.unit,
6580
+ trend: m.trend,
6581
+ trendTone: m.trendTone,
6582
+ active: selectable && m.id === activeId,
6583
+ showDivider: index < metrics.length - 1,
6584
+ onSelect: selectable ? () => select(m.id) : void 0
6585
+ },
6586
+ m.id
6587
+ ))
6588
+ }
6589
+ )
6590
+ ]
6591
+ }
6592
+ );
6593
+ };
6594
+
6595
+ // src/app/data/MetricChartCard.tsx
6596
+ var import_react48 = require("react");
6597
+ var import_jsx_runtime72 = require("react/jsx-runtime");
6598
+ var MetricChartCard = ({
6599
+ title,
6600
+ description,
6601
+ actions,
6602
+ metrics,
6603
+ activeMetricId,
6604
+ defaultActiveMetricId,
6605
+ onMetricChange,
6606
+ xKey = "date",
6607
+ variant = "area",
6608
+ height = 300,
6609
+ formatX,
6610
+ formatValue,
6611
+ emptyLabel = "No data yet",
6612
+ metricsAriaLabel = "Metrics",
6613
+ className
6614
+ }) => {
6615
+ const titleId = (0, import_react48.useId)();
6616
+ const [internalId, setInternalId] = (0, import_react48.useState)(
6617
+ defaultActiveMetricId ?? metrics[0]?.id
6618
+ );
6619
+ const activeId = activeMetricId ?? internalId;
6620
+ const active = metrics.find((m) => m.id === activeId) ?? metrics[0];
6621
+ const select = (id) => {
6622
+ if (activeMetricId == null) setInternalId(id);
6623
+ onMetricChange?.(id);
6624
+ };
6625
+ const hasHeader = Boolean(title || description || actions);
6626
+ const chartAriaLabel = typeof active?.label === "string" ? `${active.label} over time` : "Metric chart";
6627
+ return /* @__PURE__ */ (0, import_jsx_runtime72.jsxs)(
6628
+ "section",
6629
+ {
6630
+ className: cn(metricCardShellClass, className),
6631
+ "aria-labelledby": title ? titleId : void 0,
6632
+ children: [
6633
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
6634
+ MetricCardHeader,
6635
+ {
6636
+ title,
6637
+ titleId,
6638
+ description,
6639
+ actions
6640
+ }
6641
+ ),
6642
+ /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
6643
+ "div",
6644
+ {
6645
+ role: "group",
6646
+ "aria-label": metricsAriaLabel,
6647
+ className: cn(
6648
+ metricTilesRowClass,
6649
+ metricTilesGridColsClass(metrics.length),
6650
+ hasHeader && "mt-3"
6651
+ ),
6652
+ children: metrics.map((m, index) => /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
6653
+ MetricTile,
6654
+ {
6655
+ label: m.label,
6656
+ value: m.value,
6657
+ unit: m.unit,
6658
+ trend: m.trend,
6659
+ trendTone: m.trendTone,
6660
+ active: m.id === active?.id,
6661
+ showDivider: index < metrics.length - 1,
6662
+ onSelect: () => select(m.id)
6663
+ },
6664
+ m.id
6665
+ ))
6666
+ }
6667
+ ),
6668
+ /* @__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)(
6669
+ LineAreaChart,
6670
+ {
6671
+ data: active.data,
6672
+ xKey,
6673
+ series: [
6674
+ {
6675
+ dataKey: active.dataKey ?? "value",
6676
+ label: typeof active.label === "string" ? active.label : active.id,
6677
+ color: active.color
6678
+ }
6679
+ ],
6680
+ variant,
6681
+ layout: "flush",
6682
+ height,
6683
+ formatX,
6684
+ formatValue,
6685
+ ariaLabel: chartAriaLabel
6686
+ },
6687
+ active.id
6688
+ ) : /* @__PURE__ */ (0, import_jsx_runtime72.jsx)(
6689
+ "div",
6690
+ {
6691
+ className: "flex w-full items-center justify-center text-sm font-normal text-muted-foreground",
6692
+ style: { height },
6693
+ role: "status",
6694
+ children: emptyLabel
6695
+ }
6696
+ ) })
6697
+ ]
6698
+ }
6699
+ );
6700
+ };
6701
+
6702
+ // src/charts/sparkline.tsx
6703
+ var import_react49 = require("react");
6704
+ var import_jsx_runtime73 = require("react/jsx-runtime");
6705
+ var Sparkline = ({
6706
+ data,
6707
+ dataKey = "value",
6708
+ color = "var(--primary, #6366f1)",
6709
+ area = true,
6710
+ width = 96,
6711
+ height = 28,
6712
+ strokeWidth = 1.5,
6713
+ className,
6714
+ ariaLabel = "Trend"
6715
+ }) => {
6716
+ const uid = (0, import_react49.useId)();
6717
+ const values = data.map((d) => typeof d === "number" ? d : toNum(d[dataKey]));
6718
+ if (values.length === 0) {
6719
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: cn("inline-block", className), style: { width, height } });
6720
+ }
6721
+ const pad = strokeWidth + 1;
6722
+ const min = Math.min(...values);
6723
+ const max = Math.max(...values);
6724
+ const range = max - min || 1;
6725
+ const innerW = width - pad * 2;
6726
+ const innerH = height - pad * 2;
6727
+ const points = values.map((v, i) => ({
6728
+ x: pad + (values.length > 1 ? i / (values.length - 1) * innerW : innerW / 2),
6729
+ y: pad + innerH - (v - min) / range * innerH
6730
+ }));
6731
+ return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
6732
+ "svg",
6733
+ {
6734
+ width,
6735
+ height,
6736
+ viewBox: `0 0 ${width} ${height}`,
6737
+ className: cn("block", className),
6738
+ role: "img",
6739
+ "aria-label": ariaLabel,
6740
+ preserveAspectRatio: "none",
6741
+ children: [
6742
+ area && /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(import_jsx_runtime73.Fragment, { children: [
6743
+ /* @__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: [
6744
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("stop", { offset: "0%", style: { stopColor: color, stopOpacity: 0.25 } }),
6745
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("stop", { offset: "100%", style: { stopColor: color, stopOpacity: 0 } })
6746
+ ] }) }),
6747
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("path", { d: monotoneAreaPath(points, height - pad), fill: `url(#${uid}-spark)` })
6748
+ ] }),
6749
+ /* @__PURE__ */ (0, import_jsx_runtime73.jsx)(
6750
+ "path",
6751
+ {
6752
+ d: monotoneLinePath(points),
6753
+ fill: "none",
6754
+ stroke: color,
6755
+ strokeWidth,
6756
+ strokeLinecap: "round",
6757
+ strokeLinejoin: "round"
6758
+ }
6759
+ )
6760
+ ]
6761
+ }
6762
+ );
5245
6763
  };
5246
6764
 
5247
6765
  // src/chat/chat.tsx
5248
- var import_jsx_runtime54 = require("react/jsx-runtime");
6766
+ var import_jsx_runtime74 = require("react/jsx-runtime");
5249
6767
  function TimbalChat({
5250
6768
  workforceId,
5251
6769
  baseUrl,
@@ -5256,7 +6774,7 @@ function TimbalChat({
5256
6774
  debug,
5257
6775
  ...threadProps
5258
6776
  }) {
5259
- return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
6777
+ return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
5260
6778
  TimbalRuntimeProvider,
5261
6779
  {
5262
6780
  workforceId,
@@ -5266,12 +6784,13 @@ function TimbalChat({
5266
6784
  attachmentsUploadUrl,
5267
6785
  attachmentsAccept,
5268
6786
  debug,
5269
- children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(Thread, { ...threadProps })
6787
+ children: /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(Thread, { ...threadProps })
5270
6788
  }
5271
6789
  );
5272
6790
  }
5273
6791
  // Annotate the CommonJS export names for ESM import in node:
5274
6792
  0 && (module.exports = {
6793
+ APP_KIT_AGENT_INSTRUCTIONS,
5275
6794
  AppChatPanel,
5276
6795
  AppConfirmDialog,
5277
6796
  AppCopilotProvider,
@@ -5279,23 +6798,47 @@ function TimbalChat({
5279
6798
  AppShellChatTrigger,
5280
6799
  AppShellTopbar,
5281
6800
  Breadcrumbs,
6801
+ Button,
6802
+ CHART_PALETTE,
5282
6803
  ChartArtifactView,
5283
6804
  ChartPanel,
6805
+ ConnectionRow,
6806
+ ConnectionRowList,
6807
+ DangerZone,
6808
+ DangerZoneAction,
5284
6809
  DataTable,
6810
+ DescriptionList,
5285
6811
  EmptyState,
6812
+ ExpandableSection,
5286
6813
  Field,
5287
6814
  FieldInput,
6815
+ FieldRow,
5288
6816
  FieldSelect,
5289
6817
  FieldSwitch,
5290
6818
  FieldTextarea,
5291
6819
  FilterBar,
6820
+ FloatingUnsavedChangesBar,
5292
6821
  FormSection,
6822
+ INTEGRATION_CATALOG_CARD_HEIGHT_CLASS,
6823
+ InfoCard,
6824
+ IntegrationCard,
6825
+ IntegrationsEmptyState,
6826
+ LineAreaChart,
6827
+ MetricChartCard,
6828
+ MetricRow,
6829
+ MetricTile,
5293
6830
  Page,
5294
6831
  PageHeader,
6832
+ PlanBadge,
6833
+ ResourceCard,
5295
6834
  SearchInput,
5296
6835
  Section,
6836
+ SettingsSection,
6837
+ SettingsSectionHeader,
6838
+ Sparkline,
5297
6839
  StatTile,
5298
6840
  StatusBadge,
6841
+ StatusDot,
5299
6842
  SubNav,
5300
6843
  SurfaceCard,
5301
6844
  TimbalChat,
@@ -5306,6 +6849,7 @@ function TimbalChat({
5306
6849
  appShellTopbarInsetClass,
5307
6850
  appStatTileClass,
5308
6851
  appSurfaceCardClass,
6852
+ connectionRowListClass,
5309
6853
  useAppCopilotContext,
5310
6854
  useAppShellChat
5311
6855
  });