@timbal-ai/timbal-react 1.0.0 → 1.2.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 (42) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +55 -8
  3. package/dist/app.cjs +2369 -1189
  4. package/dist/app.d.cts +8 -4
  5. package/dist/app.d.ts +8 -4
  6. package/dist/app.esm.js +32 -7
  7. package/dist/{chart-artifact-DOkwSTjQ.d.cts → chart-artifact-E58ve76I.d.cts} +279 -12
  8. package/dist/{chart-artifact-CBo9x8Ch.d.ts → chart-artifact-_PEJgCpQ.d.ts} +279 -12
  9. package/dist/{chat-Bed4FQSl.d.cts → chat-ClmzWzCX.d.cts} +33 -4
  10. package/dist/{chat-Bed4FQSl.d.ts → chat-ClmzWzCX.d.ts} +33 -4
  11. package/dist/chat.cjs +1446 -776
  12. package/dist/chat.d.cts +1 -1
  13. package/dist/chat.d.ts +1 -1
  14. package/dist/chat.esm.js +3 -3
  15. package/dist/{chunk-YEFBANNF.esm.js → chunk-4VULP3CJ.esm.js} +242 -288
  16. package/dist/{chunk-RZ6QC6RG.esm.js → chunk-AGJKK6R7.esm.js} +2 -2
  17. package/dist/{chunk-FOD67Z6G.esm.js → chunk-BMXFXLVV.esm.js} +341 -12
  18. package/dist/chunk-FEYZUVBM.esm.js +52 -0
  19. package/dist/{chunk-C6IXFM4T.esm.js → chunk-MTYXREHK.esm.js} +4 -4
  20. package/dist/{chunk-AYHOVAMI.esm.js → chunk-NAMKO2MU.esm.js} +1 -1
  21. package/dist/{chunk-SNLXVG7H.esm.js → chunk-UY7AKWJL.esm.js} +1108 -656
  22. package/dist/{chunk-GLPOVYEA.esm.js → chunk-XDIY2WSL.esm.js} +669 -279
  23. package/dist/index.cjs +2967 -1824
  24. package/dist/index.d.cts +5 -5
  25. package/dist/index.d.ts +5 -5
  26. package/dist/index.esm.js +41 -11
  27. package/dist/pill-segmented-tabs-BsIOW1Lo.d.cts +528 -0
  28. package/dist/pill-segmented-tabs-BsIOW1Lo.d.ts +528 -0
  29. package/dist/studio.cjs +1685 -1015
  30. package/dist/studio.d.cts +2 -2
  31. package/dist/studio.d.ts +2 -2
  32. package/dist/studio.esm.js +5 -5
  33. package/dist/styles.css +24 -0
  34. package/dist/ui.cjs +387 -49
  35. package/dist/ui.d.cts +71 -491
  36. package/dist/ui.d.ts +71 -491
  37. package/dist/ui.esm.js +26 -6
  38. package/dist/{welcome-COOb05a5.d.cts → welcome-BFGRoNfK.d.cts} +1 -1
  39. package/dist/{welcome-DE08m9ca.d.ts → welcome-DXqsGTwH.d.ts} +1 -1
  40. package/package.json +7 -3
  41. package/vite/local-dev.d.ts +5 -1
  42. package/vite/local-dev.mjs +17 -13
@@ -15,10 +15,14 @@ import {
15
15
  studioIntegrationCardClass,
16
16
  studioTopbarPillHeightClass,
17
17
  toNum
18
- } from "./chunk-SNLXVG7H.esm.js";
18
+ } from "./chunk-UY7AKWJL.esm.js";
19
+ import {
20
+ Checkbox,
21
+ Skeleton
22
+ } from "./chunk-FEYZUVBM.esm.js";
19
23
  import {
20
24
  PillSegmentedTabs
21
- } from "./chunk-AYHOVAMI.esm.js";
25
+ } from "./chunk-NAMKO2MU.esm.js";
22
26
  import {
23
27
  Button,
24
28
  Dialog,
@@ -31,7 +35,7 @@ import {
31
35
  TimbalV2Button,
32
36
  cn,
33
37
  controlClass
34
- } from "./chunk-FOD67Z6G.esm.js";
38
+ } from "./chunk-BMXFXLVV.esm.js";
35
39
 
36
40
  // src/design/ui-vocabulary.ts
37
41
  var SEMANTIC_COLOR_TOKENS = [
@@ -194,8 +198,8 @@ var HOUSE_RULES = [
194
198
  },
195
199
  {
196
200
  id: "no-data-gradient",
197
- rule: "Gradients are reserved for chrome (composer, elevated surface, playground). Never on a data card, tile, or table.",
198
- why: "Gradient stat cards are the canonical 'AI dashboard' look."
201
+ rule: "Gradients are reserved for chrome (composer, elevated surface, playground) and built-in chart/avatar fills \u2014 never on a data card shell, stat tile, or table row background.",
202
+ why: `Gradient stat cards are the canonical 'AI dashboard' look; SVG bar/pie fills and AvatarFallback variant="secondary" (Action button chrome) are kit-owned exceptions.`
199
203
  },
200
204
  {
201
205
  id: "compose-from-blocks",
@@ -241,12 +245,12 @@ Presentational groups \u2014 import from the package root, not from these paths:
241
245
 
242
246
  | Folder | Components |
243
247
  |--------|------------|
244
- | \`data/\` | \`MetricRow\`, \`MetricChartCard\`, \`MetricTile\`, \`DataTable\`, \`FilterBar\`, \`ChartPanel\` |
248
+ | \`data/\` | \`MetricRow\`, \`MetricChartCard\`, \`MetricTile\`, \`DataTable\`, \`FilterBar\`, \`FilterField\`, \`ChartPanel\` |
245
249
  | \`integrations/\` | \`IntegrationCard\`, \`ConnectionRow\`, \`ConnectionRowList\`, \`IntegrationsEmptyState\`, \`PlanBadge\` |
246
250
  | \`settings/\` | \`SettingsSection\`, \`FieldRow\`, \`DangerZone\`, \`FloatingUnsavedChangesBar\` |
247
251
  | \`surfaces/\` | \`StatTile\`, \`InfoCard\`, \`ResourceCard\`, \`DescriptionList\`, \`ExpandableSection\`, \`StatusDot\`, \`StatusBadge\`, \`EmptyState\` |
248
252
  | \`layout/\` | \`AppShell\`, \`Page\`, \`Section\` |
249
- | \`charts\` (re-exported) | \`LineAreaChart\`, \`Sparkline\`, \`CHART_PALETTE\` |
253
+ | \`charts\` (re-exported) | \`LineAreaChart\`, \`PieChart\`, \`RadialChart\`, \`RadarChart\`, \`Sparkline\`, \`CHART_PALETTE\` |
250
254
 
251
255
  Also re-exported: \`Button\`, \`TimbalChat\`, \`ChartArtifactView\`, \`APP_KIT_AGENT_INSTRUCTIONS\`.
252
256
 
@@ -261,7 +265,7 @@ Theming helpers (import from the package root or \`/app\`): \`createTimbalTheme\
261
265
  | **Context** | Do not show raw JSON context in the panel header; keep context in \`AppCopilotProvider\` only. |
262
266
  | **Theming** | Use semantic Tailwind tokens (\`bg-background\`, \`text-foreground\`, \`border-border\`, \`bg-elevated-from\`, etc.) from the host app's \`styles.css\`. To rebrand, **never hand-author OKLCH** \u2014 call \`createTimbalTheme({ brand })\` + \`themeToCss\`/\`applyTimbalTheme\`, or apply a catalog preset (\`TIMBAL_THEME_PRESETS\` / \`applyThemePreset\`). To offer styles, render \`ThemePresetGallery\`. See \`THEME_AGENT_INSTRUCTIONS\`. |
263
267
  | **Layout chrome** | \`Page\` \u2192 \`Section\` for main content hierarchy. \`AppShellTopbar\` for global actions (auth, theme). |
264
- | **Data** | Prefer \`DataTable\` with typed \`columns\` / \`rows\` / \`getRowKey\`; use \`ChartPanel\` with \`ChartArtifact\` for charts. |
268
+ | **Data** | Prefer \`DataTable\` with typed \`columns\` / \`rows\` / \`getRowKey\`; use \`ChartPanel\` with a \`ChartArtifact\` for charts (set \`chartType\` + options \u2014 see the chart catalog). Chart colors come from the theme \`--chart-1..6\` tokens; pass \`series[].color\` / \`colors\` only to override, never raw hex on every series. |
265
269
  | **Modals** | Use \`AppConfirmDialog\` for destructive/export confirmations. |
266
270
  | **Metrics** | Overview KPIs \u2192 \`MetricRow\` or \`MetricChartCard\` (not four separate heavy cards). Values use **normal** font weight, not bold. |
267
271
  | **Integrations** | Catalog \u2192 \`IntegrationCard\` grid; connected list \u2192 \`ConnectionRow\` inside \`ConnectionRowList\`. Footer CTAs: \`Button variant="secondary"\`. |
@@ -304,11 +308,13 @@ The cause of slop is dropping **below** the curated block layer into raw primiti
304
308
  | \`Breadcrumbs\` | Trail: \`items: [{ label, href? }]\`. |
305
309
  | \`Button\` | Actions \u2014 \`variant="secondary"\` for catalog/secondary CTAs; \`variant="default"\` for primary. |
306
310
  | \`StatTile\` | Single KPI in its own card (grid of scattered stats). Prefer \`MetricRow\` for a unified overview strip. |
307
- | \`StatusBadge\` | Status pill: \`tone\` (\`success\`, \`warn\`, \u2026), children. |
308
- | \`FilterBar\` | Horizontal filter row (wraps \`SearchInput\`, buttons, etc.). |
311
+ | \`StatusBadge\` | Status pill: \`tone\` (\`default\`\\|\`primary\`\\|\`success\`\\|\`warn\`\\|\`danger\`\\|\`muted\`), children. Use \`danger\` for critical/error severity. |
312
+ | \`FilterBar\` | Horizontal filter row \u2014 bottom-aligns controls. Mix \`SearchInput\` with labeled \`FilterField\` + \`Select\` (or \`Field\` + \`Select\`); labels sit above, control baselines match. |
313
+ | \`FilterField\` | Optional label wrapper for a filter control inside \`FilterBar\` (severity, status, \u2026). Omit \`label\` for search-only fields. |
309
314
  | \`SearchInput\` | Filter field with consistent app styling. |
310
- | \`DataTable\` | Sortable table: \`columns\`, \`rows\`, \`getRowKey\`, optional \`sort\` / \`onSortChange\`, \`emptyTitle\`, \`showRowCount\`, \`caption\` for screen readers. |
311
- | \`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\`. |
315
+ | \`DataTable\` | Sortable table: \`columns\`, \`rows\`, \`getRowKey\`, optional \`sort\` / \`onSortChange\`, \`emptyTitle\`, \`showRowCount\`, \`caption\`, \`truncate: true\` on columns with long text. **Scales:** \`pageSize\` (built-in client pager), \`selectable\` + \`onSelectionChange\` (checkbox column for bulk actions), \`loading\` (skeleton rows). \`onRowClick\` for row \u2192 detail (open a \`Sheet\`). |
316
+ | \`Avatar\` / \`AvatarFallback\` | User initials: \`variant="secondary"\` (or \`primary\` / \`chart\` alias) on **both** \`Avatar\` and \`AvatarFallback\` \u2014 same chrome as catalog **Action** buttons (\`Button variant="secondary"\`: elevated gradient, \`border-border\`, \`shadow-card\`, \`text-foreground\`). Never dark primary CTA fill or raw \`bg-blue-600\`. |
317
+ | \`ChartPanel\` | Same shell as \`MetricChartCard\`: title row (\`px-4 pt-4\`), flush plot (\`pt-2\` only) with **no axis ticks** \u2014 hover tooltips show category + value. Pass \`title\` + \`artifact\` (omit \`artifact.title\` to avoid duplicates) or \`children\`. \`loading\` renders a plot-height skeleton. |
312
318
  | \`FieldInput\`, \`FieldTextarea\`, \`FieldSelect\`, \`FieldSwitch\` | Settings-style forms with labels and hints. |
313
319
  | \`FormSection\` | Grouped form block. |
314
320
  | \`AppConfirmDialog\` | Confirm/cancel modal: \`open\`, \`onOpenChange\`, \`title\`, \`description\`, \`onConfirm\`. |
@@ -317,13 +323,18 @@ The cause of slop is dropping **below** the curated block layer into raw primiti
317
323
 
318
324
  #### Charts & metrics
319
325
 
326
+ Charts run on **recharts** with shadcn \`ChartContainer\` / \`ChartTooltipContent\` chrome (see \`src/ui/chart.tsx\`). Series colors default to \`--chart-1..6\`; override those CSS tokens to rebrand every chart.
327
+
320
328
  | Component | Use for |
321
329
  |-----------|---------|
322
- | \`LineAreaChart\` | Chart engine. Props: \`data\`, \`xKey\`, \`series\`, \`variant\` (\`"area"\`), \`layout\` (\`"flush"\`), \`height\`, \`ariaLabel\`, \`formatX\`, \`formatValue\`. |
330
+ | \`LineAreaChart\` | Cartesian engine (shadcn-style chrome). Bar fills use theme gradients automatically. Props: \`data\`, \`xKey\`, \`series: [{ dataKey, label?, color? }]\`, \`variant\` (\`area\`\\|\`line\`\\|\`bar\`), \`orientation\` (\`horizontal\` for horizontal bars), \`stacked\`, \`curve\`, \`dots\`, \`gridLines\`, \`tooltipIndicator\`, \`layout\` (\`flush\` \u2014 hides axes by default; category + values on hover tooltip), \`showXAxis\` / \`showYAxis\` to opt back in, \`clipTicks\` (truncates long axis labels when axes are on), \`height\`, \`showLegend\`, \`formatX\`, \`formatValue\`, \`ariaLabel\`. |
331
+ | \`PieChart\` | Pie / donut: \`data\`, \`nameKey\`, \`dataKey\`, \`innerRadius\` (>0 = donut), \`centerValue\`/\`centerLabel\` (donut hole KPI), \`showLabels\`, \`colors\`. |
332
+ | \`RadialChart\` | Concentric progress rings: \`data\`, \`nameKey\`, \`dataKey\`, \`maxValue\`, \`centerValue\`/\`centerLabel\`. Good for gauges / share-of-target. |
333
+ | \`RadarChart\` | Spider chart (\u22653 axes): \`data\`, \`nameKey\`, \`series\`, \`maxValue\`. Compare a few metrics across entities. |
323
334
  | \`Sparkline\` | Tiny inline trend (table cells): \`data\`, \`color\`, \`area\`. |
324
335
  | \`MetricTile\` | Low-level KPI cell \u2014 prefer \`MetricRow\` / \`MetricChartCard\` instead of hand-wiring tiles. |
325
- | \`MetricRow\` | KPI strip in one elevated card (no chart). Props: \`metrics: [{ id, label, value, unit?, trend? }]\`, optional \`onMetricChange\`, \`metricsAriaLabel\`. |
326
- | \`MetricChartCard\` | KPI strip + flush chart; tile click swaps series. Same metrics shape + \`data\` per metric. Default chart height 300. |
336
+ | \`MetricRow\` | KPI strip in one elevated card (no chart). Props: \`metrics: [{ id, label, value, unit?, trend?, trendTone? }]\`, optional \`onMetricChange\`, \`metricsAriaLabel\`, \`loading\` (skeleton tiles). |
337
+ | \`MetricChartCard\` | KPI strip + flush chart; tile click swaps series. Same metrics shape + \`data\` per metric. Default chart height 300. \`loading\` renders skeleton tiles + chart. |
327
338
 
328
339
  #### Settings
329
340
 
@@ -368,6 +379,7 @@ Ready-made **section patterns** assembled from the components above. Each is a c
368
379
  - **Metrics row** \u2014 KPI strip in one elevated card. Compose \`MetricRow\` + \`MetricTile\`.
369
380
  - **Analytics card** \u2014 selectable KPI tiles driving a shared chart. Compose \`MetricChartCard\` + \`LineAreaChart\`.
370
381
  - **Charts panel** \u2014 embedded chart artifact. Compose \`ChartPanel\` + \`ChartArtifactView\`.
382
+ - **Chart catalog** \u2014 every chart kind (stacked area, multi-line, step, bar, stacked + horizontal bar, donut, radial, radar) in \`ChartPanel\` cards. Pick a \`chartType\` + options on a \`ChartArtifact\`; theme via \`--chart-N\`.
371
383
  - **Table + filters** \u2014 \`FilterBar\` above a sortable \`DataTable\` (+ \`StatusBadge\` in cells).
372
384
 
373
385
  **Collections**
@@ -415,6 +427,7 @@ import {
415
427
  Button,
416
428
  DataTable,
417
429
  FilterBar,
430
+ FilterField,
418
431
  } from "@timbal-ai/timbal-react/app";
419
432
  \`\`\`
420
433
 
@@ -1313,8 +1326,8 @@ var metricCardShellClass = cn(
1313
1326
  );
1314
1327
  var metricCardHeaderClass = "flex items-start justify-between gap-3 px-4 pb-1 pt-3";
1315
1328
  var metricTilesRowClass = "grid w-full min-w-0";
1316
- var metricChartRegionClass = "relative min-h-0 w-full border-t border-border/40 pt-2";
1317
- var metricChartPlotRegionClass = "relative min-h-0 w-full border-t border-border/40 px-0 pt-5 pb-3";
1329
+ var metricChartRegionClass = "relative min-h-0 w-full overflow-x-hidden border-t border-border/40 pt-2";
1330
+ var metricChartPlotRegionClass = "relative min-h-0 w-full overflow-x-hidden border-t border-border/40 px-0 pt-5 pb-3";
1318
1331
  var metricCellDividerClass = "border-r border-border/40";
1319
1332
  var MetricCardHeader = ({
1320
1333
  title,
@@ -1504,7 +1517,7 @@ var appShellTopbarRowClass = cn(
1504
1517
  "flex w-full items-center justify-between gap-2"
1505
1518
  );
1506
1519
  var appShellTopbarStickyClass = cn(
1507
- "sticky top-0 z-20 shrink-0 bg-background pb-2",
1520
+ "shrink-0 bg-background pb-2",
1508
1521
  appShellInsetTopClass
1509
1522
  );
1510
1523
  var appPageHeaderClass = cn(
@@ -1524,10 +1537,7 @@ var appStatTileClass = cn(
1524
1537
  );
1525
1538
  var appStatValueClass = "text-2xl font-normal tracking-tight text-foreground tabular-nums";
1526
1539
  var appStatLabelClass = "text-xs font-normal text-muted-foreground";
1527
- var appFilterBarClass = cn(
1528
- "flex flex-wrap items-center gap-2",
1529
- studioTopbarPillHeightClass
1530
- );
1540
+ var appFilterBarClass = "flex flex-wrap items-end gap-2";
1531
1541
  var appSearchInputClass = controlClass({}, "inline-flex items-center gap-2");
1532
1542
  var appBreadcrumbsClass = "flex flex-wrap items-center gap-1.5 text-sm text-muted-foreground";
1533
1543
  var appBreadcrumbLinkClass = "transition-colors hover:text-foreground";
@@ -1551,9 +1561,23 @@ function useAppShellChat() {
1551
1561
  return useContext(AppShellChatContext);
1552
1562
  }
1553
1563
 
1564
+ // src/app/layout/app-shell-nav-context.tsx
1565
+ import { createContext as createContext2, useContext as useContext2 } from "react";
1566
+ var AppShellNavContext = createContext2(null);
1567
+ var AppShellNavProvider = AppShellNavContext.Provider;
1568
+ function useAppShellNav() {
1569
+ return useContext2(AppShellNavContext) ?? {
1570
+ open: false,
1571
+ setOpen: () => {
1572
+ },
1573
+ toggle: () => {
1574
+ }
1575
+ };
1576
+ }
1577
+
1554
1578
  // src/app/layout/AppShell.tsx
1555
1579
  import { motion, useReducedMotion } from "motion/react";
1556
- import { useCallback, useState } from "react";
1580
+ import { useCallback, useMemo, useState } from "react";
1557
1581
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1558
1582
  var floatingTriggerClass = cn(
1559
1583
  "aui-app-shell-chat-trigger-fixed fixed z-50 rounded-full px-5 py-2.5 text-sm font-medium shadow-card-elevated",
@@ -1620,11 +1644,29 @@ var AppShell = ({
1620
1644
  chatCollapsible = true,
1621
1645
  chatTriggerLabel = "Assistant",
1622
1646
  hideChatTrigger = false,
1647
+ navOpen: navOpenProp,
1648
+ defaultNavOpen = false,
1649
+ onNavOpenChange,
1623
1650
  className,
1624
1651
  mainClassName
1625
1652
  }) => {
1626
1653
  const topbarContent = topbar ?? header;
1627
1654
  const hasChat = Boolean(chat);
1655
+ const [uncontrolledNavOpen, setUncontrolledNavOpen] = useState(defaultNavOpen);
1656
+ const isNavControlled = navOpenProp !== void 0;
1657
+ const navOpen = isNavControlled ? navOpenProp : uncontrolledNavOpen;
1658
+ const setNavOpen = useCallback(
1659
+ (open) => {
1660
+ if (!isNavControlled) setUncontrolledNavOpen(open);
1661
+ onNavOpenChange?.(open);
1662
+ },
1663
+ [isNavControlled, onNavOpenChange]
1664
+ );
1665
+ const toggleNav = useCallback(() => setNavOpen(!navOpen), [navOpen, setNavOpen]);
1666
+ const navControls = useMemo(
1667
+ () => ({ open: navOpen, setOpen: setNavOpen, toggle: toggleNav }),
1668
+ [navOpen, setNavOpen, toggleNav]
1669
+ );
1628
1670
  const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultChatOpen);
1629
1671
  const isChatControlled = chatOpenProp !== void 0;
1630
1672
  const chatOpen = isChatControlled ? chatOpenProp : uncontrolledOpen;
@@ -1668,6 +1710,15 @@ var AppShell = ({
1668
1710
  style: studioChromeShellStyle,
1669
1711
  children: [
1670
1712
  sidebar,
1713
+ sidebar && navOpen ? /* @__PURE__ */ jsx5(
1714
+ "button",
1715
+ {
1716
+ type: "button",
1717
+ "aria-label": "Close navigation",
1718
+ onClick: () => setNavOpen(false),
1719
+ className: "fixed inset-0 z-40 bg-foreground/30 backdrop-blur-[2px] md:hidden"
1720
+ }
1721
+ ) : null,
1671
1722
  shellBody,
1672
1723
  hasChat && chatOpen ? /* @__PURE__ */ jsx5(
1673
1724
  "div",
@@ -1695,8 +1746,9 @@ var AppShell = ({
1695
1746
  ]
1696
1747
  }
1697
1748
  ) });
1749
+ const withNav = /* @__PURE__ */ jsx5(AppShellNavProvider, { value: navControls, children: tree });
1698
1750
  if (!hasChat) {
1699
- return tree;
1751
+ return withNav;
1700
1752
  }
1701
1753
  return /* @__PURE__ */ jsx5(
1702
1754
  AppShellChatProvider,
@@ -1707,7 +1759,7 @@ var AppShell = ({
1707
1759
  toggle: toggleChat,
1708
1760
  collapsible: chatCollapsible
1709
1761
  },
1710
- children: tree
1762
+ children: withNav
1711
1763
  }
1712
1764
  );
1713
1765
  };
@@ -1758,8 +1810,33 @@ var AppShellChatTrigger = ({
1758
1810
  );
1759
1811
  };
1760
1812
 
1813
+ // src/app/layout/AppShellSidebarTrigger.tsx
1814
+ import { MenuIcon } from "lucide-react";
1815
+ import { jsx as jsx8 } from "react/jsx-runtime";
1816
+ var AppShellSidebarTrigger = ({
1817
+ label = "Open navigation",
1818
+ className
1819
+ }) => {
1820
+ const nav = useAppShellNav();
1821
+ return /* @__PURE__ */ jsx8(
1822
+ "button",
1823
+ {
1824
+ type: "button",
1825
+ onClick: nav.toggle,
1826
+ "aria-label": label,
1827
+ "aria-expanded": nav.open,
1828
+ className: cn(
1829
+ "inline-flex size-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-foreground/[0.04] hover:text-foreground md:hidden",
1830
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/10",
1831
+ className
1832
+ ),
1833
+ children: /* @__PURE__ */ jsx8(MenuIcon, { className: "size-5", "aria-hidden": true })
1834
+ }
1835
+ );
1836
+ };
1837
+
1761
1838
  // src/app/layout/PageHeader.tsx
1762
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
1839
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
1763
1840
  var PageHeader = ({
1764
1841
  title,
1765
1842
  description,
@@ -1768,15 +1845,15 @@ var PageHeader = ({
1768
1845
  }) => {
1769
1846
  return /* @__PURE__ */ jsxs7("header", { className: cn("aui-app-page-header", appPageHeaderClass, className), children: [
1770
1847
  /* @__PURE__ */ jsxs7("div", { className: "min-w-0", children: [
1771
- /* @__PURE__ */ jsx8("h1", { className: "text-2xl font-semibold tracking-tight text-foreground", children: title }),
1772
- description ? /* @__PURE__ */ jsx8("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null
1848
+ /* @__PURE__ */ jsx9("h1", { className: "text-2xl font-semibold tracking-tight text-foreground", children: title }),
1849
+ description ? /* @__PURE__ */ jsx9("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null
1773
1850
  ] }),
1774
- actions ? /* @__PURE__ */ jsx8("div", { className: "aui-app-page-header-actions flex shrink-0 flex-wrap items-center gap-2", children: actions }) : null
1851
+ actions ? /* @__PURE__ */ jsx9("div", { className: "aui-app-page-header-actions flex shrink-0 flex-wrap items-center gap-2", children: actions }) : null
1775
1852
  ] });
1776
1853
  };
1777
1854
 
1778
1855
  // src/app/layout/Page.tsx
1779
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
1856
+ import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
1780
1857
  var Page = ({
1781
1858
  children,
1782
1859
  breadcrumbs,
@@ -1785,13 +1862,13 @@ var Page = ({
1785
1862
  }) => {
1786
1863
  return /* @__PURE__ */ jsxs8("div", { className: cn("aui-app-page", appPageColumnClass, className), children: [
1787
1864
  breadcrumbs,
1788
- /* @__PURE__ */ jsx9(PageHeader, { ...headerProps }),
1865
+ /* @__PURE__ */ jsx10(PageHeader, { ...headerProps }),
1789
1866
  children
1790
1867
  ] });
1791
1868
  };
1792
1869
 
1793
1870
  // src/app/layout/Section.tsx
1794
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1871
+ import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
1795
1872
  var Section = ({
1796
1873
  title,
1797
1874
  description,
@@ -1799,29 +1876,29 @@ var Section = ({
1799
1876
  className
1800
1877
  }) => {
1801
1878
  return /* @__PURE__ */ jsxs9("section", { className: cn("aui-app-section", appSectionClass, className), children: [
1802
- title ? /* @__PURE__ */ jsx10("h2", { className: appSectionTitleClass, children: title }) : null,
1803
- description ? /* @__PURE__ */ jsx10("p", { className: appSectionDescriptionClass, children: description }) : null,
1879
+ title ? /* @__PURE__ */ jsx11("h2", { className: appSectionTitleClass, children: title }) : null,
1880
+ description ? /* @__PURE__ */ jsx11("p", { className: appSectionDescriptionClass, children: description }) : null,
1804
1881
  children
1805
1882
  ] });
1806
1883
  };
1807
1884
 
1808
1885
  // src/app/copilot/app-copilot-context.tsx
1809
- import { createContext as createContext2, useContext as useContext2 } from "react";
1810
- import { jsx as jsx11 } from "react/jsx-runtime";
1811
- var AppCopilotContext = createContext2(null);
1886
+ import { createContext as createContext3, useContext as useContext3 } from "react";
1887
+ import { jsx as jsx12 } from "react/jsx-runtime";
1888
+ var AppCopilotContext = createContext3(null);
1812
1889
  var AppCopilotProvider = ({
1813
1890
  value,
1814
1891
  children
1815
1892
  }) => {
1816
- return /* @__PURE__ */ jsx11(AppCopilotContext.Provider, { value, children });
1893
+ return /* @__PURE__ */ jsx12(AppCopilotContext.Provider, { value, children });
1817
1894
  };
1818
1895
  function useAppCopilotContext() {
1819
- return useContext2(AppCopilotContext) ?? {};
1896
+ return useContext3(AppCopilotContext) ?? {};
1820
1897
  }
1821
1898
 
1822
1899
  // src/app/chat/AppChatPanel.tsx
1823
1900
  import { XIcon } from "lucide-react";
1824
- import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
1901
+ import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
1825
1902
  var shellClass = "aui-app-chat-panel flex h-full min-h-0 flex-col overflow-hidden";
1826
1903
  var chromeClass = cn(
1827
1904
  "aui-app-chat-panel-chrome relative z-20 flex min-h-10 shrink-0 items-center justify-end px-2 pt-2"
@@ -1867,17 +1944,17 @@ var AppChatPanel = ({
1867
1944
  }) => {
1868
1945
  const shellChat = useAppShellChat();
1869
1946
  return /* @__PURE__ */ jsxs10("div", { className: cn(shellClass, className), children: [
1870
- shellChat?.collapsible ? /* @__PURE__ */ jsx12("div", { className: chromeClass, children: /* @__PURE__ */ jsx12(
1947
+ shellChat?.collapsible ? /* @__PURE__ */ jsx13("div", { className: chromeClass, children: /* @__PURE__ */ jsx13(
1871
1948
  "button",
1872
1949
  {
1873
1950
  type: "button",
1874
1951
  className: closeButtonClass,
1875
1952
  onClick: () => shellChat.setOpen(false),
1876
1953
  "aria-label": "Close assistant",
1877
- children: /* @__PURE__ */ jsx12(XIcon, { className: "size-4", "aria-hidden": true })
1954
+ children: /* @__PURE__ */ jsx13(XIcon, { className: "size-4", "aria-hidden": true })
1878
1955
  }
1879
1956
  ) }) : null,
1880
- /* @__PURE__ */ jsx12("div", { className: bodyClass, children: /* @__PURE__ */ jsx12(
1957
+ /* @__PURE__ */ jsx13("div", { className: bodyClass, children: /* @__PURE__ */ jsx13(
1881
1958
  TimbalRuntimeProvider,
1882
1959
  {
1883
1960
  workforceId,
@@ -1887,7 +1964,7 @@ var AppChatPanel = ({
1887
1964
  attachmentsUploadUrl,
1888
1965
  attachmentsAccept,
1889
1966
  debug,
1890
- children: /* @__PURE__ */ jsx12(
1967
+ children: /* @__PURE__ */ jsx13(
1891
1968
  Thread,
1892
1969
  {
1893
1970
  variant: "panel",
@@ -1908,23 +1985,23 @@ var AppChatPanel = ({
1908
1985
  };
1909
1986
 
1910
1987
  // src/app/surfaces/SurfaceCard.tsx
1911
- import { jsx as jsx13 } from "react/jsx-runtime";
1988
+ import { jsx as jsx14 } from "react/jsx-runtime";
1912
1989
  var SurfaceCard = ({ children, className }) => {
1913
- return /* @__PURE__ */ jsx13("div", { className: cn("aui-app-surface-card", appSurfaceCardClass, className), children });
1990
+ return /* @__PURE__ */ jsx14("div", { className: cn("aui-app-surface-card", appSurfaceCardClass, className), children });
1914
1991
  };
1915
1992
 
1916
1993
  // src/app/surfaces/StatTile.tsx
1917
- import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
1994
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
1918
1995
  var StatTile = ({ label, value, hint, className }) => {
1919
1996
  return /* @__PURE__ */ jsxs11("div", { className: cn("aui-app-stat-tile", appStatTileClass, className), children: [
1920
- /* @__PURE__ */ jsx14("span", { className: appStatLabelClass, children: label }),
1921
- /* @__PURE__ */ jsx14("span", { className: appStatValueClass, children: value }),
1922
- hint ? /* @__PURE__ */ jsx14("span", { className: "text-xs text-muted-foreground", children: hint }) : null
1997
+ /* @__PURE__ */ jsx15("span", { className: appStatLabelClass, children: label }),
1998
+ /* @__PURE__ */ jsx15("span", { className: appStatValueClass, children: value }),
1999
+ hint ? /* @__PURE__ */ jsx15("span", { className: "text-xs text-muted-foreground", children: hint }) : null
1923
2000
  ] });
1924
2001
  };
1925
2002
 
1926
2003
  // src/app/surfaces/EmptyState.tsx
1927
- import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
2004
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
1928
2005
  var EmptyState = ({
1929
2006
  title,
1930
2007
  description,
@@ -1932,19 +2009,20 @@ var EmptyState = ({
1932
2009
  className
1933
2010
  }) => {
1934
2011
  return /* @__PURE__ */ jsxs12("div", { className: cn("aui-app-empty-state", appEmptyStateClass, className), children: [
1935
- /* @__PURE__ */ jsx15("p", { className: appEmptyStateTitleClass, children: title }),
1936
- description ? /* @__PURE__ */ jsx15("p", { className: appEmptyStateDescriptionClass, children: description }) : null,
2012
+ /* @__PURE__ */ jsx16("p", { className: appEmptyStateTitleClass, children: title }),
2013
+ description ? /* @__PURE__ */ jsx16("p", { className: appEmptyStateDescriptionClass, children: description }) : null,
1937
2014
  action
1938
2015
  ] });
1939
2016
  };
1940
2017
 
1941
2018
  // src/app/surfaces/StatusBadge.tsx
1942
- import { jsx as jsx16 } from "react/jsx-runtime";
2019
+ import { jsx as jsx17 } from "react/jsx-runtime";
1943
2020
  var statusBadgeToneClass = {
1944
2021
  default: "bg-muted text-foreground",
1945
2022
  primary: "bg-primary/10 text-primary",
1946
2023
  success: "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400",
1947
2024
  warn: "bg-amber-500/10 text-amber-600 dark:text-amber-400",
2025
+ danger: "bg-destructive/10 text-destructive",
1948
2026
  muted: "bg-muted/80 text-muted-foreground"
1949
2027
  };
1950
2028
  var StatusBadge = ({
@@ -1952,7 +2030,7 @@ var StatusBadge = ({
1952
2030
  tone = "default",
1953
2031
  className
1954
2032
  }) => {
1955
- return /* @__PURE__ */ jsx16(
2033
+ return /* @__PURE__ */ jsx17(
1956
2034
  "span",
1957
2035
  {
1958
2036
  className: cn(
@@ -1966,7 +2044,7 @@ var StatusBadge = ({
1966
2044
  };
1967
2045
 
1968
2046
  // src/app/surfaces/AppConfirmDialog.tsx
1969
- import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
2047
+ import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
1970
2048
  var bodyClass2 = "flex flex-col gap-4 p-6";
1971
2049
  var titleClass = "pr-8";
1972
2050
  var actionsClass = "flex flex-wrap justify-end gap-2";
@@ -1981,15 +2059,15 @@ var AppConfirmDialog = ({
1981
2059
  destructive = false,
1982
2060
  className
1983
2061
  }) => {
1984
- return /* @__PURE__ */ jsx17(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsx17(
2062
+ return /* @__PURE__ */ jsx18(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsx18(
1985
2063
  DialogContent,
1986
2064
  {
1987
2065
  className: cn("gap-0 p-0 sm:max-w-md", className),
1988
2066
  children: /* @__PURE__ */ jsxs13("div", { className: bodyClass2, children: [
1989
- /* @__PURE__ */ jsx17(DialogTitle, { className: titleClass, children: title }),
1990
- description ? /* @__PURE__ */ jsx17("p", { className: "text-sm text-muted-foreground", children: description }) : null,
2067
+ /* @__PURE__ */ jsx18(DialogTitle, { className: titleClass, children: title }),
2068
+ description ? /* @__PURE__ */ jsx18("p", { className: "text-sm text-muted-foreground", children: description }) : null,
1991
2069
  /* @__PURE__ */ jsxs13("div", { className: actionsClass, children: [
1992
- /* @__PURE__ */ jsx17(
2070
+ /* @__PURE__ */ jsx18(
1993
2071
  TimbalV2Button,
1994
2072
  {
1995
2073
  type: "button",
@@ -1999,7 +2077,7 @@ var AppConfirmDialog = ({
1999
2077
  children: cancelLabel
2000
2078
  }
2001
2079
  ),
2002
- /* @__PURE__ */ jsx17(
2080
+ /* @__PURE__ */ jsx18(
2003
2081
  TimbalV2Button,
2004
2082
  {
2005
2083
  type: "button",
@@ -2019,7 +2097,7 @@ var AppConfirmDialog = ({
2019
2097
  };
2020
2098
 
2021
2099
  // src/app/surfaces/InfoCard.tsx
2022
- import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
2100
+ import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
2023
2101
  var toneClass = {
2024
2102
  neutral: "border-border bg-muted/40",
2025
2103
  info: "border-primary/25 bg-primary/5",
@@ -2043,18 +2121,18 @@ var InfoCard = ({
2043
2121
  className
2044
2122
  ),
2045
2123
  children: [
2046
- icon ? /* @__PURE__ */ jsx18("span", { className: "mt-0.5 shrink-0 text-muted-foreground", children: icon }) : null,
2124
+ icon ? /* @__PURE__ */ jsx19("span", { className: "mt-0.5 shrink-0 text-muted-foreground", children: icon }) : null,
2047
2125
  /* @__PURE__ */ jsxs14("div", { className: "min-w-0 flex-1", children: [
2048
- title ? /* @__PURE__ */ jsx18("p", { className: "text-sm font-medium text-foreground", children: title }) : null,
2049
- children ? /* @__PURE__ */ jsx18("div", { className: cn("text-sm text-muted-foreground", title && "mt-1"), children }) : null
2126
+ title ? /* @__PURE__ */ jsx19("p", { className: "text-sm font-medium text-foreground", children: title }) : null,
2127
+ children ? /* @__PURE__ */ jsx19("div", { className: cn("text-sm text-muted-foreground", title && "mt-1"), children }) : null
2050
2128
  ] }),
2051
- action ? /* @__PURE__ */ jsx18("div", { className: "shrink-0", children: action }) : null
2129
+ action ? /* @__PURE__ */ jsx19("div", { className: "shrink-0", children: action }) : null
2052
2130
  ]
2053
2131
  }
2054
2132
  );
2055
2133
 
2056
2134
  // src/app/surfaces/StatusDot.tsx
2057
- import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
2135
+ import { jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
2058
2136
  var dotClass = {
2059
2137
  online: "bg-emerald-500",
2060
2138
  busy: "bg-amber-500",
@@ -2069,7 +2147,7 @@ var StatusDot = ({
2069
2147
  className
2070
2148
  }) => /* @__PURE__ */ jsxs15("span", { className: cn("inline-flex items-center gap-1.5", className), children: [
2071
2149
  /* @__PURE__ */ jsxs15("span", { className: "relative flex size-2", children: [
2072
- pulse ? /* @__PURE__ */ jsx19(
2150
+ pulse ? /* @__PURE__ */ jsx20(
2073
2151
  "span",
2074
2152
  {
2075
2153
  className: cn(
@@ -2078,18 +2156,18 @@ var StatusDot = ({
2078
2156
  )
2079
2157
  }
2080
2158
  ) : null,
2081
- /* @__PURE__ */ jsx19("span", { className: cn("relative inline-flex size-2 rounded-full", dotClass[tone]) })
2159
+ /* @__PURE__ */ jsx20("span", { className: cn("relative inline-flex size-2 rounded-full", dotClass[tone]) })
2082
2160
  ] }),
2083
- label ? /* @__PURE__ */ jsx19("span", { className: "text-xs text-muted-foreground", children: label }) : null
2161
+ label ? /* @__PURE__ */ jsx20("span", { className: "text-xs text-muted-foreground", children: label }) : null
2084
2162
  ] });
2085
2163
 
2086
2164
  // src/app/surfaces/DescriptionList.tsx
2087
- import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
2165
+ import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
2088
2166
  var DescriptionList = ({
2089
2167
  items,
2090
2168
  stacked = false,
2091
2169
  className
2092
- }) => /* @__PURE__ */ jsx20(
2170
+ }) => /* @__PURE__ */ jsx21(
2093
2171
  "dl",
2094
2172
  {
2095
2173
  className: cn(
@@ -2104,8 +2182,8 @@ var DescriptionList = ({
2104
2182
  stacked ? "flex flex-col gap-0.5" : "flex items-center justify-between gap-4"
2105
2183
  ),
2106
2184
  children: [
2107
- /* @__PURE__ */ jsx20("dt", { className: "text-sm text-muted-foreground", children: item.label }),
2108
- /* @__PURE__ */ jsx20(
2185
+ /* @__PURE__ */ jsx21("dt", { className: "text-sm text-muted-foreground", children: item.label }),
2186
+ /* @__PURE__ */ jsx21(
2109
2187
  "dd",
2110
2188
  {
2111
2189
  className: cn(
@@ -2125,8 +2203,8 @@ var DescriptionList = ({
2125
2203
  // src/app/surfaces/ExpandableSection.tsx
2126
2204
  import { useId, useState as useState2 } from "react";
2127
2205
  import { AnimatePresence, motion as motion2, useReducedMotion as useReducedMotion2 } from "motion/react";
2128
- import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
2129
- var Chevron = ({ open }) => /* @__PURE__ */ jsx21(
2206
+ import { jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
2207
+ var Chevron = ({ open }) => /* @__PURE__ */ jsx22(
2130
2208
  "svg",
2131
2209
  {
2132
2210
  viewBox: "0 0 24 24",
@@ -2140,7 +2218,7 @@ var Chevron = ({ open }) => /* @__PURE__ */ jsx21(
2140
2218
  strokeLinecap: "round",
2141
2219
  strokeLinejoin: "round",
2142
2220
  "aria-hidden": true,
2143
- children: /* @__PURE__ */ jsx21("path", { d: "m6 9 6 6 6-6" })
2221
+ children: /* @__PURE__ */ jsx22("path", { d: "m6 9 6 6 6-6" })
2144
2222
  }
2145
2223
  );
2146
2224
  var ExpandableSection = ({
@@ -2172,15 +2250,15 @@ var ExpandableSection = ({
2172
2250
  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",
2173
2251
  children: [
2174
2252
  /* @__PURE__ */ jsxs17("span", { className: "flex min-w-0 items-center gap-3", children: [
2175
- icon ? /* @__PURE__ */ jsx21("span", { className: "flex size-8 items-center justify-center rounded-lg border border-border bg-muted text-muted-foreground", children: icon }) : null,
2176
- /* @__PURE__ */ jsx21("span", { className: "truncate text-sm font-medium text-foreground", children: title }),
2177
- count != null ? /* @__PURE__ */ jsx21("span", { className: "rounded-full border border-border bg-muted px-2 py-0.5 text-xs text-muted-foreground", children: count }) : null
2253
+ icon ? /* @__PURE__ */ jsx22("span", { className: "flex size-8 items-center justify-center rounded-lg border border-border bg-muted text-muted-foreground", children: icon }) : null,
2254
+ /* @__PURE__ */ jsx22("span", { className: "truncate text-sm font-medium text-foreground", children: title }),
2255
+ count != null ? /* @__PURE__ */ jsx22("span", { className: "rounded-full border border-border bg-muted px-2 py-0.5 text-xs text-muted-foreground", children: count }) : null
2178
2256
  ] }),
2179
- /* @__PURE__ */ jsx21(Chevron, { open })
2257
+ /* @__PURE__ */ jsx22(Chevron, { open })
2180
2258
  ]
2181
2259
  }
2182
2260
  ),
2183
- /* @__PURE__ */ jsx21(AnimatePresence, { initial: false, children: open ? /* @__PURE__ */ jsx21(
2261
+ /* @__PURE__ */ jsx22(AnimatePresence, { initial: false, children: open ? /* @__PURE__ */ jsx22(
2184
2262
  motion2.div,
2185
2263
  {
2186
2264
  id: panelId,
@@ -2189,7 +2267,7 @@ var ExpandableSection = ({
2189
2267
  exit: reduceMotion ? void 0 : { height: 0, opacity: 0 },
2190
2268
  transition: { duration: 0.2, ease: "easeOut" },
2191
2269
  className: "overflow-hidden",
2192
- children: /* @__PURE__ */ jsx21("div", { className: "bg-muted/20", children })
2270
+ children: /* @__PURE__ */ jsx22("div", { className: "bg-muted/20", children })
2193
2271
  },
2194
2272
  "body"
2195
2273
  ) : null })
@@ -2197,7 +2275,7 @@ var ExpandableSection = ({
2197
2275
  };
2198
2276
 
2199
2277
  // src/app/surfaces/ResourceCard.tsx
2200
- import { Fragment as Fragment3, jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
2278
+ import { Fragment as Fragment3, jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
2201
2279
  var resourceCardShellClass = cn(
2202
2280
  "flex min-h-[8.5rem] flex-col rounded-2xl p-4 text-left font-normal",
2203
2281
  TIMBAL_V2_ELEVATED_SURFACE
@@ -2224,33 +2302,33 @@ var ResourceCard = ({
2224
2302
  }) => {
2225
2303
  const body = /* @__PURE__ */ jsxs18(Fragment3, { children: [
2226
2304
  /* @__PURE__ */ jsxs18("div", { className: "flex items-start gap-3", children: [
2227
- media ? /* @__PURE__ */ jsx22("span", { className: mediaShellClass, children: media }) : null,
2305
+ media ? /* @__PURE__ */ jsx23("span", { className: mediaShellClass, children: media }) : null,
2228
2306
  /* @__PURE__ */ jsxs18("div", { className: "min-w-0 flex-1 pt-0.5", children: [
2229
- /* @__PURE__ */ jsx22("p", { className: "truncate text-sm font-normal leading-snug text-foreground", children: title }),
2230
- subtitle ? /* @__PURE__ */ jsx22("p", { className: "mt-1 line-clamp-2 text-xs font-normal text-muted-foreground", children: subtitle }) : null
2307
+ /* @__PURE__ */ jsx23("p", { className: "truncate text-sm font-normal leading-snug text-foreground", children: title }),
2308
+ subtitle ? /* @__PURE__ */ jsx23("p", { className: "mt-1 line-clamp-2 text-xs font-normal text-muted-foreground", children: subtitle }) : null
2231
2309
  ] }),
2232
- badge ? /* @__PURE__ */ jsx22("span", { className: "shrink-0 pt-0.5", children: badge }) : null
2310
+ badge ? /* @__PURE__ */ jsx23("span", { className: "shrink-0 pt-0.5", children: badge }) : null
2233
2311
  ] }),
2234
2312
  footer || action ? /* @__PURE__ */ jsxs18("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: [
2235
- /* @__PURE__ */ jsx22("span", { className: "min-w-0 truncate", children: footer }),
2236
- action ? /* @__PURE__ */ jsx22("span", { className: "shrink-0 opacity-80", children: action }) : null
2313
+ /* @__PURE__ */ jsx23("span", { className: "min-w-0 truncate", children: footer }),
2314
+ action ? /* @__PURE__ */ jsx23("span", { className: "shrink-0 opacity-80", children: action }) : null
2237
2315
  ] }) : null
2238
2316
  ] });
2239
2317
  if (onClick) {
2240
- return /* @__PURE__ */ jsx22("button", { type: "button", onClick, "aria-label": ariaLabel, className: cn(resourceCardInteractiveClass, className), children: body });
2318
+ return /* @__PURE__ */ jsx23("button", { type: "button", onClick, "aria-label": ariaLabel, className: cn(resourceCardInteractiveClass, className), children: body });
2241
2319
  }
2242
- return /* @__PURE__ */ jsx22("article", { className: cn(resourceCardShellClass, className), children: body });
2320
+ return /* @__PURE__ */ jsx23("article", { className: cn(resourceCardShellClass, className), children: body });
2243
2321
  };
2244
2322
 
2245
2323
  // src/app/settings/SettingsSection.tsx
2246
- import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
2324
+ import { jsx as jsx24, jsxs as jsxs19 } from "react/jsx-runtime";
2247
2325
  var SettingsSectionHeader = ({
2248
2326
  title,
2249
2327
  description,
2250
2328
  className
2251
2329
  }) => /* @__PURE__ */ jsxs19("div", { className: cn("flex flex-col", className), children: [
2252
- /* @__PURE__ */ jsx23("h3", { className: "text-[17px] font-medium leading-tight text-foreground", children: title }),
2253
- description ? /* @__PURE__ */ jsx23("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null
2330
+ /* @__PURE__ */ jsx24("h3", { className: "text-[17px] font-medium leading-tight text-foreground", children: title }),
2331
+ description ? /* @__PURE__ */ jsx24("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null
2254
2332
  ] });
2255
2333
  var SettingsSection = ({
2256
2334
  title,
@@ -2269,17 +2347,17 @@ var SettingsSection = ({
2269
2347
  ),
2270
2348
  children: [
2271
2349
  /* @__PURE__ */ jsxs19("div", { className: "min-w-0", children: [
2272
- /* @__PURE__ */ jsx23("h2", { className: "text-sm font-medium text-foreground", children: title }),
2273
- description ? /* @__PURE__ */ jsx23("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null,
2274
- descriptionFooter ? /* @__PURE__ */ jsx23("div", { className: "mt-3 min-w-0", children: descriptionFooter }) : null
2350
+ /* @__PURE__ */ jsx24("h2", { className: "text-sm font-medium text-foreground", children: title }),
2351
+ description ? /* @__PURE__ */ jsx24("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null,
2352
+ descriptionFooter ? /* @__PURE__ */ jsx24("div", { className: "mt-3 min-w-0", children: descriptionFooter }) : null
2275
2353
  ] }),
2276
- /* @__PURE__ */ jsx23("div", { className: "min-w-0 space-y-3", children })
2354
+ /* @__PURE__ */ jsx24("div", { className: "min-w-0 space-y-3", children })
2277
2355
  ]
2278
2356
  }
2279
2357
  );
2280
2358
 
2281
2359
  // src/app/settings/FieldRow.tsx
2282
- import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
2360
+ import { jsx as jsx25, jsxs as jsxs20 } from "react/jsx-runtime";
2283
2361
  var FieldRow = ({
2284
2362
  label,
2285
2363
  children,
@@ -2298,7 +2376,7 @@ var FieldRow = ({
2298
2376
  ),
2299
2377
  children: [
2300
2378
  /* @__PURE__ */ jsxs20("div", { className: "min-w-0", children: [
2301
- /* @__PURE__ */ jsx24(
2379
+ /* @__PURE__ */ jsx25(
2302
2380
  "label",
2303
2381
  {
2304
2382
  htmlFor,
@@ -2306,17 +2384,17 @@ var FieldRow = ({
2306
2384
  children: label
2307
2385
  }
2308
2386
  ),
2309
- description ? /* @__PURE__ */ jsx24("p", { className: "mt-0.5 text-xs text-muted-foreground", children: description }) : null
2387
+ description ? /* @__PURE__ */ jsx25("p", { className: "mt-0.5 text-xs text-muted-foreground", children: description }) : null
2310
2388
  ] }),
2311
- /* @__PURE__ */ jsx24("div", { className: "shrink-0", children })
2389
+ /* @__PURE__ */ jsx25("div", { className: "shrink-0", children })
2312
2390
  ]
2313
2391
  }
2314
2392
  );
2315
2393
  }
2316
2394
  return /* @__PURE__ */ jsxs20("div", { className: cn("flex flex-col gap-1.5", className), children: [
2317
- /* @__PURE__ */ jsx24("label", { htmlFor, className: "text-sm font-medium text-foreground", children: label }),
2395
+ /* @__PURE__ */ jsx25("label", { htmlFor, className: "text-sm font-medium text-foreground", children: label }),
2318
2396
  children,
2319
- description ? /* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: description }) : null
2397
+ description ? /* @__PURE__ */ jsx25("p", { className: "text-xs text-muted-foreground", children: description }) : null
2320
2398
  ] });
2321
2399
  };
2322
2400
 
@@ -2324,7 +2402,7 @@ var FieldRow = ({
2324
2402
  import { useEffect, useState as useState3 } from "react";
2325
2403
  import { createPortal } from "react-dom";
2326
2404
  import { AnimatePresence as AnimatePresence2, motion as motion3, useReducedMotion as useReducedMotion3 } from "motion/react";
2327
- import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
2405
+ import { jsx as jsx26, jsxs as jsxs21 } from "react/jsx-runtime";
2328
2406
  var FloatingUnsavedChangesBar = ({
2329
2407
  visible,
2330
2408
  message = "Unsaved changes",
@@ -2342,7 +2420,7 @@ var FloatingUnsavedChangesBar = ({
2342
2420
  useEffect(() => setMounted(true), []);
2343
2421
  if (!mounted || typeof document === "undefined") return null;
2344
2422
  return createPortal(
2345
- /* @__PURE__ */ jsx25(AnimatePresence2, { children: visible ? /* @__PURE__ */ jsx25("div", { className: "pointer-events-none fixed inset-x-0 bottom-5 z-50 flex justify-center px-4", children: /* @__PURE__ */ jsxs21(
2423
+ /* @__PURE__ */ jsx26(AnimatePresence2, { children: visible ? /* @__PURE__ */ jsx26("div", { className: "pointer-events-none fixed inset-x-0 bottom-5 z-50 flex justify-center px-4", children: /* @__PURE__ */ jsxs21(
2346
2424
  motion3.div,
2347
2425
  {
2348
2426
  role: "region",
@@ -2356,10 +2434,10 @@ var FloatingUnsavedChangesBar = ({
2356
2434
  className
2357
2435
  ),
2358
2436
  children: [
2359
- /* @__PURE__ */ jsx25("span", { className: "text-sm text-muted-foreground", children: message }),
2437
+ /* @__PURE__ */ jsx26("span", { className: "text-sm text-muted-foreground", children: message }),
2360
2438
  /* @__PURE__ */ jsxs21("span", { className: "flex items-center gap-1.5", children: [
2361
- /* @__PURE__ */ jsx25(Button, { variant: "ghost", size: "sm", onClick: onDiscard, disabled: isSaving, children: discardLabel }),
2362
- /* @__PURE__ */ jsx25(Button, { size: "sm", onClick: onSave, disabled: saveDisabled || isSaving, children: isSaving ? "Saving\u2026" : saveLabel })
2439
+ /* @__PURE__ */ jsx26(Button, { variant: "ghost", size: "sm", onClick: onDiscard, disabled: isSaving, children: discardLabel }),
2440
+ /* @__PURE__ */ jsx26(Button, { size: "sm", onClick: onSave, disabled: saveDisabled || isSaving, children: isSaving ? "Saving\u2026" : saveLabel })
2363
2441
  ] })
2364
2442
  ]
2365
2443
  }
@@ -2369,7 +2447,7 @@ var FloatingUnsavedChangesBar = ({
2369
2447
  };
2370
2448
 
2371
2449
  // src/app/settings/DangerZone.tsx
2372
- import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
2450
+ import { jsx as jsx27, jsxs as jsxs22 } from "react/jsx-runtime";
2373
2451
  var DangerZoneAction = ({
2374
2452
  title,
2375
2453
  description,
@@ -2384,10 +2462,10 @@ var DangerZoneAction = ({
2384
2462
  ),
2385
2463
  children: [
2386
2464
  /* @__PURE__ */ jsxs22("div", { className: "min-w-0", children: [
2387
- /* @__PURE__ */ jsx26("p", { className: "text-sm font-medium text-foreground", children: title }),
2388
- description ? /* @__PURE__ */ jsx26("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
2465
+ /* @__PURE__ */ jsx27("p", { className: "text-sm font-medium text-foreground", children: title }),
2466
+ description ? /* @__PURE__ */ jsx27("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
2389
2467
  ] }),
2390
- /* @__PURE__ */ jsx26("div", { className: "shrink-0", children: action })
2468
+ /* @__PURE__ */ jsx27("div", { className: "shrink-0", children: action })
2391
2469
  ]
2392
2470
  }
2393
2471
  );
@@ -2405,17 +2483,17 @@ var DangerZone = ({
2405
2483
  ),
2406
2484
  children: [
2407
2485
  (title || description) && /* @__PURE__ */ jsxs22("header", { className: "border-b border-destructive/20 bg-destructive/5 px-4 py-3", children: [
2408
- title ? /* @__PURE__ */ jsx26("h3", { className: "text-sm font-semibold text-destructive", children: title }) : null,
2409
- description ? /* @__PURE__ */ jsx26("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
2486
+ title ? /* @__PURE__ */ jsx27("h3", { className: "text-sm font-semibold text-destructive", children: title }) : null,
2487
+ description ? /* @__PURE__ */ jsx27("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
2410
2488
  ] }),
2411
- /* @__PURE__ */ jsx26("div", { className: "divide-y divide-border bg-card", children })
2489
+ /* @__PURE__ */ jsx27("div", { className: "divide-y divide-border bg-card", children })
2412
2490
  ]
2413
2491
  }
2414
2492
  );
2415
2493
 
2416
2494
  // src/app/integrations/IntegrationCard.tsx
2417
2495
  import { useId as useId2 } from "react";
2418
- import { Fragment as Fragment4, jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
2496
+ import { Fragment as Fragment4, jsx as jsx28, jsxs as jsxs23 } from "react/jsx-runtime";
2419
2497
  var INTEGRATION_CATALOG_CARD_HEIGHT_CLASS = "h-[12.25rem] min-h-[12.25rem] max-h-[12.25rem]";
2420
2498
  var statusLabel = {
2421
2499
  available: null,
@@ -2458,10 +2536,10 @@ var IntegrationCard = ({
2458
2536
  const dimmed = status === "disabled" || locked;
2459
2537
  const body = /* @__PURE__ */ jsxs23("div", { className: "flex h-full min-h-0 flex-col", children: [
2460
2538
  /* @__PURE__ */ jsxs23("div", { className: "flex shrink-0 items-start gap-3 pr-2", children: [
2461
- logo ? /* @__PURE__ */ jsx27("span", { className: logoShellClass, "aria-hidden": Boolean(ariaLabel), children: logo }) : null,
2462
- /* @__PURE__ */ jsx27("div", { className: "min-w-0 flex-1 pt-0.5", children: /* @__PURE__ */ jsxs23("div", { className: "flex items-start justify-between gap-2", children: [
2539
+ logo ? /* @__PURE__ */ jsx28("span", { className: logoShellClass, "aria-hidden": Boolean(ariaLabel), children: logo }) : null,
2540
+ /* @__PURE__ */ jsx28("div", { className: "min-w-0 flex-1 pt-0.5", children: /* @__PURE__ */ jsxs23("div", { className: "flex items-start justify-between gap-2", children: [
2463
2541
  /* @__PURE__ */ jsxs23("div", { className: "min-w-0", children: [
2464
- /* @__PURE__ */ jsx27(
2542
+ /* @__PURE__ */ jsx28(
2465
2543
  "h4",
2466
2544
  {
2467
2545
  id: onClick && !action ? void 0 : titleId,
@@ -2469,12 +2547,12 @@ var IntegrationCard = ({
2469
2547
  children: name
2470
2548
  }
2471
2549
  ),
2472
- statusLabel[status] ? /* @__PURE__ */ jsx27("p", { className: "mt-0.5 text-xs text-muted-foreground", children: statusLabel[status] }) : null
2550
+ statusLabel[status] ? /* @__PURE__ */ jsx28("p", { className: "mt-0.5 text-xs text-muted-foreground", children: statusLabel[status] }) : null
2473
2551
  ] }),
2474
- badge ? /* @__PURE__ */ jsx27("span", { className: "shrink-0", children: badge }) : null
2552
+ badge ? /* @__PURE__ */ jsx28("span", { className: "shrink-0", children: badge }) : null
2475
2553
  ] }) })
2476
2554
  ] }),
2477
- description ? /* @__PURE__ */ jsx27(
2555
+ description ? /* @__PURE__ */ jsx28(
2478
2556
  "p",
2479
2557
  {
2480
2558
  className: cn(
@@ -2485,8 +2563,8 @@ var IntegrationCard = ({
2485
2563
  }
2486
2564
  ) : null,
2487
2565
  action ? /* @__PURE__ */ jsxs23(Fragment4, { children: [
2488
- /* @__PURE__ */ jsx27("div", { className: "min-h-0 flex-1", "aria-hidden": true }),
2489
- /* @__PURE__ */ jsx27("div", { className: "relative mt-3 shrink-0", children: action })
2566
+ /* @__PURE__ */ jsx28("div", { className: "min-h-0 flex-1", "aria-hidden": true }),
2567
+ /* @__PURE__ */ jsx28("div", { className: "relative mt-3 shrink-0", children: action })
2490
2568
  ] }) : null
2491
2569
  ] });
2492
2570
  const shellClass3 = cn(
@@ -2496,7 +2574,7 @@ var IntegrationCard = ({
2496
2574
  className
2497
2575
  );
2498
2576
  if (onClick && !action) {
2499
- return /* @__PURE__ */ jsx27(
2577
+ return /* @__PURE__ */ jsx28(
2500
2578
  "button",
2501
2579
  {
2502
2580
  type: "button",
@@ -2513,12 +2591,12 @@ var IntegrationCard = ({
2513
2591
  }
2514
2592
  );
2515
2593
  }
2516
- return /* @__PURE__ */ jsx27("article", { className: shellClass3, "aria-labelledby": titleId, children: body });
2594
+ return /* @__PURE__ */ jsx28("article", { className: shellClass3, "aria-labelledby": titleId, children: body });
2517
2595
  };
2518
2596
 
2519
2597
  // src/app/integrations/IntegrationsEmptyState.tsx
2520
2598
  import { useId as useId3 } from "react";
2521
- import { jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
2599
+ import { jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
2522
2600
  var IntegrationsEmptyState = ({
2523
2601
  title = "No integrations yet",
2524
2602
  description = "Connect a provider to start syncing data and powering your workforce.",
@@ -2537,7 +2615,7 @@ var IntegrationsEmptyState = ({
2537
2615
  ),
2538
2616
  "aria-labelledby": titleId,
2539
2617
  children: [
2540
- icon ? /* @__PURE__ */ jsx28(
2618
+ icon ? /* @__PURE__ */ jsx29(
2541
2619
  "span",
2542
2620
  {
2543
2621
  className: cn(
@@ -2549,21 +2627,21 @@ var IntegrationsEmptyState = ({
2549
2627
  children: icon
2550
2628
  }
2551
2629
  ) : null,
2552
- /* @__PURE__ */ jsx28("h3", { id: titleId, className: "text-base font-normal text-foreground", children: title }),
2553
- description ? /* @__PURE__ */ jsx28("p", { className: "max-w-sm text-sm text-muted-foreground", children: description }) : null,
2554
- action ? /* @__PURE__ */ jsx28("div", { className: "mt-1", children: action }) : null
2630
+ /* @__PURE__ */ jsx29("h3", { id: titleId, className: "text-base font-normal text-foreground", children: title }),
2631
+ description ? /* @__PURE__ */ jsx29("p", { className: "max-w-sm text-sm text-muted-foreground", children: description }) : null,
2632
+ action ? /* @__PURE__ */ jsx29("div", { className: "mt-1", children: action }) : null
2555
2633
  ]
2556
2634
  }
2557
2635
  );
2558
2636
  };
2559
2637
 
2560
2638
  // src/app/integrations/PlanBadge.tsx
2561
- import { jsx as jsx29 } from "react/jsx-runtime";
2639
+ import { jsx as jsx30 } from "react/jsx-runtime";
2562
2640
  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";
2563
- var PlanBadge = ({ children, className }) => /* @__PURE__ */ jsx29("span", { className: cn(planBadgeClass, className), children });
2641
+ var PlanBadge = ({ children, className }) => /* @__PURE__ */ jsx30("span", { className: cn(planBadgeClass, className), children });
2564
2642
 
2565
2643
  // src/app/integrations/ConnectionRow.tsx
2566
- import { Fragment as Fragment5, jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
2644
+ import { Fragment as Fragment5, jsx as jsx31, jsxs as jsxs25 } from "react/jsx-runtime";
2567
2645
  var logoShellClass2 = cn(
2568
2646
  "flex size-9 shrink-0 items-center justify-center overflow-hidden rounded-lg",
2569
2647
  TIMBAL_V2_LOGO_TILE
@@ -2579,13 +2657,13 @@ var ConnectionRow = ({
2579
2657
  className
2580
2658
  }) => {
2581
2659
  const inner = /* @__PURE__ */ jsxs25(Fragment5, { children: [
2582
- logo ? /* @__PURE__ */ jsx30("span", { className: logoShellClass2, children: logo }) : null,
2660
+ logo ? /* @__PURE__ */ jsx31("span", { className: logoShellClass2, children: logo }) : null,
2583
2661
  /* @__PURE__ */ jsxs25("div", { className: "min-w-0 flex-1", children: [
2584
- /* @__PURE__ */ jsx30("p", { className: "truncate text-sm font-normal text-foreground", children: name }),
2585
- meta ? /* @__PURE__ */ jsx30("p", { className: "truncate text-xs text-muted-foreground", children: meta }) : null
2662
+ /* @__PURE__ */ jsx31("p", { className: "truncate text-sm font-normal text-foreground", children: name }),
2663
+ meta ? /* @__PURE__ */ jsx31("p", { className: "truncate text-xs text-muted-foreground", children: meta }) : null
2586
2664
  ] }),
2587
- badge ? /* @__PURE__ */ jsx30("span", { className: "shrink-0", children: badge }) : null,
2588
- action ? /* @__PURE__ */ jsx30("span", { className: "shrink-0", children: action }) : null
2665
+ badge ? /* @__PURE__ */ jsx31("span", { className: "shrink-0", children: badge }) : null,
2666
+ action ? /* @__PURE__ */ jsx31("span", { className: "shrink-0", children: action }) : null
2589
2667
  ] });
2590
2668
  const rowClass2 = cn(
2591
2669
  "flex w-full items-center gap-3 px-4 py-3 text-left",
@@ -2593,7 +2671,7 @@ var ConnectionRow = ({
2593
2671
  className
2594
2672
  );
2595
2673
  if (onClick) {
2596
- return /* @__PURE__ */ jsx30(
2674
+ return /* @__PURE__ */ jsx31(
2597
2675
  "button",
2598
2676
  {
2599
2677
  type: "button",
@@ -2605,7 +2683,7 @@ var ConnectionRow = ({
2605
2683
  }
2606
2684
  );
2607
2685
  }
2608
- return /* @__PURE__ */ jsx30("div", { role: "listitem", className: rowClass2, children: inner });
2686
+ return /* @__PURE__ */ jsx31("div", { role: "listitem", className: rowClass2, children: inner });
2609
2687
  };
2610
2688
  var connectionRowListClass = cn(
2611
2689
  "overflow-hidden rounded-2xl",
@@ -2613,12 +2691,12 @@ var connectionRowListClass = cn(
2613
2691
  );
2614
2692
 
2615
2693
  // src/app/integrations/ConnectionRowList.tsx
2616
- import { jsx as jsx31 } from "react/jsx-runtime";
2694
+ import { jsx as jsx32 } from "react/jsx-runtime";
2617
2695
  var ConnectionRowList = ({
2618
2696
  children,
2619
2697
  "aria-label": ariaLabel = "Connected integrations",
2620
2698
  className
2621
- }) => /* @__PURE__ */ jsx31(
2699
+ }) => /* @__PURE__ */ jsx32(
2622
2700
  "div",
2623
2701
  {
2624
2702
  role: "list",
@@ -2629,7 +2707,7 @@ var ConnectionRowList = ({
2629
2707
  );
2630
2708
 
2631
2709
  // src/app/navigation/SubNav.tsx
2632
- import { jsx as jsx32 } from "react/jsx-runtime";
2710
+ import { jsx as jsx33 } from "react/jsx-runtime";
2633
2711
  var SubNav = ({
2634
2712
  items,
2635
2713
  activeId,
@@ -2638,7 +2716,7 @@ var SubNav = ({
2638
2716
  "aria-label": ariaLabel = "Section navigation",
2639
2717
  layoutId
2640
2718
  }) => {
2641
- return /* @__PURE__ */ jsx32("nav", { className: cn("aui-app-sub-nav", className), "aria-label": ariaLabel, children: /* @__PURE__ */ jsx32(
2719
+ return /* @__PURE__ */ jsx33("nav", { className: cn("aui-app-sub-nav", className), "aria-label": ariaLabel, children: /* @__PURE__ */ jsx33(
2642
2720
  PillSegmentedTabs,
2643
2721
  {
2644
2722
  value: activeId,
@@ -2652,13 +2730,13 @@ var SubNav = ({
2652
2730
  };
2653
2731
 
2654
2732
  // src/app/navigation/Breadcrumbs.tsx
2655
- import { jsx as jsx33, jsxs as jsxs26 } from "react/jsx-runtime";
2733
+ import { jsx as jsx34, jsxs as jsxs26 } from "react/jsx-runtime";
2656
2734
  var Breadcrumbs = ({ items, className }) => {
2657
- return /* @__PURE__ */ jsx33("nav", { className: cn("aui-app-breadcrumbs", appBreadcrumbsClass, className), "aria-label": "Breadcrumb", children: /* @__PURE__ */ jsx33("ol", { className: "flex flex-wrap items-center gap-1.5", children: items.map((item, index) => {
2735
+ return /* @__PURE__ */ jsx34("nav", { className: cn("aui-app-breadcrumbs", appBreadcrumbsClass, className), "aria-label": "Breadcrumb", children: /* @__PURE__ */ jsx34("ol", { className: "flex flex-wrap items-center gap-1.5", children: items.map((item, index) => {
2658
2736
  const isLast = index === items.length - 1;
2659
2737
  return /* @__PURE__ */ jsxs26("li", { className: "inline-flex items-center gap-1.5", children: [
2660
- index > 0 ? /* @__PURE__ */ jsx33("span", { className: "text-muted-foreground/50", "aria-hidden": true, children: "/" }) : null,
2661
- isLast ? /* @__PURE__ */ jsx33("span", { className: "text-foreground", "aria-current": "page", children: item.label }) : item.href ? /* @__PURE__ */ jsx33("a", { href: item.href, className: appBreadcrumbLinkClass, children: item.label }) : /* @__PURE__ */ jsx33(
2738
+ index > 0 ? /* @__PURE__ */ jsx34("span", { className: "text-muted-foreground/50", "aria-hidden": true, children: "/" }) : null,
2739
+ isLast ? /* @__PURE__ */ jsx34("span", { className: "text-foreground", "aria-current": "page", children: item.label }) : item.href ? /* @__PURE__ */ jsx34("a", { href: item.href, className: appBreadcrumbLinkClass, children: item.label }) : /* @__PURE__ */ jsx34(
2662
2740
  "button",
2663
2741
  {
2664
2742
  type: "button",
@@ -2672,7 +2750,7 @@ var Breadcrumbs = ({ items, className }) => {
2672
2750
  };
2673
2751
 
2674
2752
  // src/app/forms/Field.tsx
2675
- import { jsx as jsx34, jsxs as jsxs27 } from "react/jsx-runtime";
2753
+ import { jsx as jsx35, jsxs as jsxs27 } from "react/jsx-runtime";
2676
2754
  var Field = ({
2677
2755
  label,
2678
2756
  hint,
@@ -2682,10 +2760,10 @@ var Field = ({
2682
2760
  htmlFor
2683
2761
  }) => {
2684
2762
  return /* @__PURE__ */ jsxs27("div", { className: cn("aui-app-field", appFieldClass, className), children: [
2685
- /* @__PURE__ */ jsx34("label", { className: appFieldLabelClass, htmlFor, children: label }),
2763
+ /* @__PURE__ */ jsx35("label", { className: appFieldLabelClass, htmlFor, children: label }),
2686
2764
  children,
2687
- hint && !error ? /* @__PURE__ */ jsx34("p", { className: appFieldHintClass, children: hint }) : null,
2688
- error ? /* @__PURE__ */ jsx34("p", { className: "text-xs text-destructive", role: "alert", children: error }) : null
2765
+ hint && !error ? /* @__PURE__ */ jsx35("p", { className: appFieldHintClass, children: hint }) : null,
2766
+ error ? /* @__PURE__ */ jsx35("p", { className: "text-xs text-destructive", role: "alert", children: error }) : null
2689
2767
  ] });
2690
2768
  };
2691
2769
  var FieldInput = ({
@@ -2698,7 +2776,7 @@ var FieldInput = ({
2698
2776
  ...inputProps
2699
2777
  }) => {
2700
2778
  const inputId = id ?? inputProps.name;
2701
- return /* @__PURE__ */ jsx34(
2779
+ return /* @__PURE__ */ jsx35(
2702
2780
  Field,
2703
2781
  {
2704
2782
  label,
@@ -2706,7 +2784,7 @@ var FieldInput = ({
2706
2784
  error,
2707
2785
  htmlFor: inputId,
2708
2786
  className: fieldClassName,
2709
- children: /* @__PURE__ */ jsx34(
2787
+ children: /* @__PURE__ */ jsx35(
2710
2788
  "input",
2711
2789
  {
2712
2790
  id: inputId,
@@ -2720,7 +2798,7 @@ var FieldInput = ({
2720
2798
  };
2721
2799
 
2722
2800
  // src/app/forms/FieldTextarea.tsx
2723
- import { jsx as jsx35 } from "react/jsx-runtime";
2801
+ import { jsx as jsx36 } from "react/jsx-runtime";
2724
2802
  var textareaClass = cn(
2725
2803
  appInputClass,
2726
2804
  "min-h-[5.5rem] resize-y py-2.5 leading-relaxed"
@@ -2735,7 +2813,7 @@ var FieldTextarea = ({
2735
2813
  ...props
2736
2814
  }) => {
2737
2815
  const textareaId = id ?? props.name;
2738
- return /* @__PURE__ */ jsx35(
2816
+ return /* @__PURE__ */ jsx36(
2739
2817
  Field,
2740
2818
  {
2741
2819
  label,
@@ -2743,7 +2821,7 @@ var FieldTextarea = ({
2743
2821
  error,
2744
2822
  htmlFor: textareaId,
2745
2823
  className: fieldClassName,
2746
- children: /* @__PURE__ */ jsx35(
2824
+ children: /* @__PURE__ */ jsx36(
2747
2825
  "textarea",
2748
2826
  {
2749
2827
  id: textareaId,
@@ -2758,7 +2836,7 @@ var FieldTextarea = ({
2758
2836
 
2759
2837
  // src/app/forms/FieldSelect.tsx
2760
2838
  import { ChevronDownIcon } from "lucide-react";
2761
- import { jsx as jsx36, jsxs as jsxs28 } from "react/jsx-runtime";
2839
+ import { jsx as jsx37, jsxs as jsxs28 } from "react/jsx-runtime";
2762
2840
  var selectWrapClass = "relative";
2763
2841
  var selectClass = cn(
2764
2842
  appInputClass,
@@ -2775,7 +2853,7 @@ var FieldSelect = ({
2775
2853
  ...props
2776
2854
  }) => {
2777
2855
  const selectId = id ?? props.name;
2778
- return /* @__PURE__ */ jsx36(
2856
+ return /* @__PURE__ */ jsx37(
2779
2857
  Field,
2780
2858
  {
2781
2859
  label,
@@ -2784,7 +2862,7 @@ var FieldSelect = ({
2784
2862
  htmlFor: selectId,
2785
2863
  className: fieldClassName,
2786
2864
  children: /* @__PURE__ */ jsxs28("div", { className: selectWrapClass, children: [
2787
- /* @__PURE__ */ jsx36(
2865
+ /* @__PURE__ */ jsx37(
2788
2866
  "select",
2789
2867
  {
2790
2868
  id: selectId,
@@ -2794,7 +2872,7 @@ var FieldSelect = ({
2794
2872
  children
2795
2873
  }
2796
2874
  ),
2797
- /* @__PURE__ */ jsx36(
2875
+ /* @__PURE__ */ jsx37(
2798
2876
  ChevronDownIcon,
2799
2877
  {
2800
2878
  className: "pointer-events-none absolute top-1/2 right-3 size-4 -translate-y-1/2 text-muted-foreground",
@@ -2807,7 +2885,7 @@ var FieldSelect = ({
2807
2885
  };
2808
2886
 
2809
2887
  // src/app/forms/FieldSwitch.tsx
2810
- import { jsx as jsx37, jsxs as jsxs29 } from "react/jsx-runtime";
2888
+ import { jsx as jsx38, jsxs as jsxs29 } from "react/jsx-runtime";
2811
2889
  var trackClass = cn(
2812
2890
  "relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-[background,box-shadow,border-color] duration-200",
2813
2891
  "peer-focus-visible:ring-2 peer-focus-visible:ring-foreground/10",
@@ -2838,7 +2916,7 @@ var FieldSwitch = ({
2838
2916
  htmlFor: inputId,
2839
2917
  children: [
2840
2918
  /* @__PURE__ */ jsxs29("span", { className: "relative mt-0.5", children: [
2841
- /* @__PURE__ */ jsx37(
2919
+ /* @__PURE__ */ jsx38(
2842
2920
  "input",
2843
2921
  {
2844
2922
  id: inputId,
@@ -2848,11 +2926,11 @@ var FieldSwitch = ({
2848
2926
  ...props
2849
2927
  }
2850
2928
  ),
2851
- /* @__PURE__ */ jsx37("span", { className: trackClass, "aria-hidden": true, children: /* @__PURE__ */ jsx37("span", { className: thumbClass }) })
2929
+ /* @__PURE__ */ jsx38("span", { className: trackClass, "aria-hidden": true, children: /* @__PURE__ */ jsx38("span", { className: thumbClass }) })
2852
2930
  ] }),
2853
2931
  /* @__PURE__ */ jsxs29("span", { className: "flex min-w-0 flex-col gap-0.5", children: [
2854
- /* @__PURE__ */ jsx37("span", { className: "text-sm font-medium text-foreground", children: label }),
2855
- description ? /* @__PURE__ */ jsx37("span", { className: "text-xs text-muted-foreground", children: description }) : null
2932
+ /* @__PURE__ */ jsx38("span", { className: "text-sm font-medium text-foreground", children: label }),
2933
+ description ? /* @__PURE__ */ jsx38("span", { className: "text-xs text-muted-foreground", children: description }) : null
2856
2934
  ] })
2857
2935
  ]
2858
2936
  }
@@ -2861,7 +2939,7 @@ var FieldSwitch = ({
2861
2939
 
2862
2940
  // src/app/forms/SearchInput.tsx
2863
2941
  import { SearchIcon } from "lucide-react";
2864
- import { jsx as jsx38, jsxs as jsxs30 } from "react/jsx-runtime";
2942
+ import { jsx as jsx39, jsxs as jsxs30 } from "react/jsx-runtime";
2865
2943
  var SearchInput = ({
2866
2944
  className,
2867
2945
  placeholder = "Search\u2026",
@@ -2876,8 +2954,8 @@ var SearchInput = ({
2876
2954
  className
2877
2955
  ),
2878
2956
  children: [
2879
- /* @__PURE__ */ jsx38(SearchIcon, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": true }),
2880
- /* @__PURE__ */ jsx38(
2957
+ /* @__PURE__ */ jsx39(SearchIcon, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": true }),
2958
+ /* @__PURE__ */ jsx39(
2881
2959
  "input",
2882
2960
  {
2883
2961
  type: "search",
@@ -2892,18 +2970,18 @@ var SearchInput = ({
2892
2970
  };
2893
2971
 
2894
2972
  // src/app/forms/FormSection.tsx
2895
- import { jsx as jsx39, jsxs as jsxs31 } from "react/jsx-runtime";
2973
+ import { jsx as jsx40, jsxs as jsxs31 } from "react/jsx-runtime";
2896
2974
  var FormSection = ({ title, children, className }) => {
2897
2975
  return /* @__PURE__ */ jsxs31("fieldset", { className: cn("aui-app-form-section", appSectionClass, "border-0 p-0", className), children: [
2898
- title ? /* @__PURE__ */ jsx39("legend", { className: cn(appSectionTitleClass, "mb-3 px-0"), children: title }) : null,
2899
- /* @__PURE__ */ jsx39("div", { className: "flex flex-col gap-4", children })
2976
+ title ? /* @__PURE__ */ jsx40("legend", { className: cn(appSectionTitleClass, "mb-3 px-0"), children: title }) : null,
2977
+ /* @__PURE__ */ jsx40("div", { className: "flex flex-col gap-4", children })
2900
2978
  ] });
2901
2979
  };
2902
2980
 
2903
2981
  // src/app/data/FilterBar.tsx
2904
- import { jsx as jsx40 } from "react/jsx-runtime";
2982
+ import { jsx as jsx41 } from "react/jsx-runtime";
2905
2983
  var FilterBar = ({ children, className }) => {
2906
- return /* @__PURE__ */ jsx40(
2984
+ return /* @__PURE__ */ jsx41(
2907
2985
  "div",
2908
2986
  {
2909
2987
  className: cn("aui-app-filter-bar", appFilterBarClass, className),
@@ -2914,20 +2992,41 @@ var FilterBar = ({ children, className }) => {
2914
2992
  );
2915
2993
  };
2916
2994
 
2995
+ // src/app/data/FilterField.tsx
2996
+ import { jsx as jsx42, jsxs as jsxs32 } from "react/jsx-runtime";
2997
+ var FilterField = ({
2998
+ label,
2999
+ children,
3000
+ className
3001
+ }) => {
3002
+ return /* @__PURE__ */ jsxs32("div", { className: cn("aui-app-filter-field", appFieldClass, className), children: [
3003
+ label ? /* @__PURE__ */ jsx42("span", { className: appFieldLabelClass, children: label }) : null,
3004
+ children
3005
+ ] });
3006
+ };
3007
+
2917
3008
  // src/app/data/DataTable.tsx
2918
- import { useMemo, useState as useState4 } from "react";
2919
- import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon } from "lucide-react";
2920
- import { jsx as jsx41, jsxs as jsxs32 } from "react/jsx-runtime";
3009
+ import { useEffect as useEffect2, useMemo as useMemo2, useState as useState4 } from "react";
3010
+ import {
3011
+ ArrowDownIcon,
3012
+ ArrowUpDownIcon,
3013
+ ArrowUpIcon,
3014
+ ChevronLeftIcon,
3015
+ ChevronRightIcon
3016
+ } from "lucide-react";
3017
+ import { jsx as jsx43, jsxs as jsxs33 } from "react/jsx-runtime";
2921
3018
  var shellClass2 = "overflow-hidden rounded-xl border border-border bg-card shadow-card";
2922
3019
  var tableClass = "w-full border-collapse bg-transparent text-sm";
2923
3020
  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";
2924
3021
  var bodyCellClass = "border-b border-border/40 bg-transparent px-4 py-2.5 text-foreground";
2925
- var rowClass = "bg-transparent transition-colors hover:bg-foreground/[0.03] data-[clickable=true]:cursor-pointer";
3022
+ var rowClass = "bg-transparent transition-colors hover:bg-foreground/[0.03] data-[clickable=true]:cursor-pointer data-[selected=true]:bg-primary/[0.04]";
2926
3023
  var footCellClass = "border-t border-border/60 bg-transparent px-4 py-2.5 text-xs text-muted-foreground";
2927
3024
  var footInnerClass = "flex flex-wrap items-center gap-2";
2928
3025
  var emptyCellClass = "bg-transparent px-4 py-10 text-center text-sm text-muted-foreground";
2929
3026
  var sortButtonClass = "group inline-flex min-w-0 items-center gap-1.5 rounded-md -mx-1 px-1 py-0.5 text-left font-medium text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/10";
2930
3027
  var stickyHeadClass = "sticky top-0 z-[1] bg-card/95 shadow-[0_1px_0_0_hsl(var(--border)/0.5)] backdrop-blur-sm [&_th]:bg-card/95";
3028
+ var selectCellClass = "w-10 px-4 py-2.5 align-middle";
3029
+ var pagerButtonClass = "inline-flex size-7 items-center justify-center rounded-md border border-border bg-transparent text-muted-foreground transition-colors hover:bg-foreground/[0.04] hover:text-foreground disabled:pointer-events-none disabled:opacity-40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/10";
2931
3030
  var alignClass = {
2932
3031
  left: "text-left",
2933
3032
  center: "text-center",
@@ -2957,12 +3056,12 @@ function SortIndicator({
2957
3056
  }) {
2958
3057
  const iconClass = "size-3.5 shrink-0 opacity-60 group-hover:opacity-100";
2959
3058
  if (!active) {
2960
- return /* @__PURE__ */ jsx41(ArrowUpDownIcon, { className: iconClass, "aria-hidden": true });
3059
+ return /* @__PURE__ */ jsx43(ArrowUpDownIcon, { className: iconClass, "aria-hidden": true });
2961
3060
  }
2962
3061
  if (direction === "desc") {
2963
- return /* @__PURE__ */ jsx41(ArrowDownIcon, { className: iconClass, "aria-hidden": true });
3062
+ return /* @__PURE__ */ jsx43(ArrowDownIcon, { className: iconClass, "aria-hidden": true });
2964
3063
  }
2965
- return /* @__PURE__ */ jsx41(ArrowUpIcon, { className: iconClass, "aria-hidden": true });
3064
+ return /* @__PURE__ */ jsx43(ArrowUpIcon, { className: iconClass, "aria-hidden": true });
2966
3065
  }
2967
3066
  function DataTable({
2968
3067
  columns,
@@ -2981,7 +3080,18 @@ function DataTable({
2981
3080
  onRowClick,
2982
3081
  stickyHeader = false,
2983
3082
  dense = false,
2984
- caption
3083
+ caption,
3084
+ loading = false,
3085
+ loadingRows,
3086
+ selectable = false,
3087
+ selectedKeys: selectedKeysProp,
3088
+ defaultSelectedKeys,
3089
+ onSelectionChange,
3090
+ selectAllAriaLabel = "Select all rows",
3091
+ pageSize,
3092
+ pageIndex: pageIndexProp,
3093
+ defaultPageIndex = 0,
3094
+ onPageChange
2985
3095
  }) {
2986
3096
  const [uncontrolledSort, setUncontrolledSort] = useState4(
2987
3097
  defaultSort
@@ -2994,7 +3104,28 @@ function DataTable({
2994
3104
  }
2995
3105
  onSortChange?.(next);
2996
3106
  };
2997
- const sortedRows = useMemo(() => {
3107
+ const [uncontrolledSelected, setUncontrolledSelected] = useState4(
3108
+ defaultSelectedKeys ?? []
3109
+ );
3110
+ const isSelectionControlled = selectedKeysProp !== void 0;
3111
+ const selectedKeys = isSelectionControlled ? selectedKeysProp : uncontrolledSelected;
3112
+ const selectedSet = useMemo2(() => new Set(selectedKeys), [selectedKeys]);
3113
+ const setSelected = (next) => {
3114
+ if (!isSelectionControlled) {
3115
+ setUncontrolledSelected(next);
3116
+ }
3117
+ onSelectionChange?.(next);
3118
+ };
3119
+ const [uncontrolledPage, setUncontrolledPage] = useState4(defaultPageIndex);
3120
+ const isPageControlled = pageIndexProp !== void 0;
3121
+ const rawPageIndex = isPageControlled ? pageIndexProp : uncontrolledPage;
3122
+ const setPage = (next) => {
3123
+ if (!isPageControlled) {
3124
+ setUncontrolledPage(next);
3125
+ }
3126
+ onPageChange?.(next);
3127
+ };
3128
+ const sortedRows = useMemo2(() => {
2998
3129
  if (!sort) return rows;
2999
3130
  const column = columns.find((col) => col.id === sort.columnId);
3000
3131
  if (!column?.sortable) return rows;
@@ -3010,89 +3141,219 @@ function DataTable({
3010
3141
  return sort.direction === "asc" ? cmp : -cmp;
3011
3142
  });
3012
3143
  }, [columns, rows, sort]);
3144
+ const paginated = typeof pageSize === "number" && pageSize > 0;
3145
+ const pageCount = paginated ? Math.max(1, Math.ceil(sortedRows.length / pageSize)) : 1;
3146
+ const pageIndex = Math.min(Math.max(0, rawPageIndex), pageCount - 1);
3147
+ useEffect2(() => {
3148
+ if (!paginated || isPageControlled) return;
3149
+ if (uncontrolledPage > pageCount - 1) {
3150
+ setUncontrolledPage(pageCount - 1);
3151
+ }
3152
+ }, [paginated, isPageControlled, uncontrolledPage, pageCount]);
3153
+ const visibleRows = useMemo2(() => {
3154
+ if (!paginated) return sortedRows;
3155
+ const start = pageIndex * pageSize;
3156
+ return sortedRows.slice(start, start + pageSize);
3157
+ }, [paginated, sortedRows, pageIndex, pageSize]);
3013
3158
  const cellPad = dense ? "px-3 py-2" : void 0;
3014
3159
  const headPad = dense ? "px-3 py-2" : void 0;
3015
- if (rows.length === 0 && emptyMode === "replace") {
3016
- return /* @__PURE__ */ jsx41(EmptyState, { title: emptyTitle, description: emptyDescription, className });
3160
+ const colSpan = columns.length + (selectable ? 1 : 0);
3161
+ if (!loading && rows.length === 0 && emptyMode === "replace") {
3162
+ return /* @__PURE__ */ jsx43(EmptyState, { title: emptyTitle, description: emptyDescription, className });
3017
3163
  }
3164
+ const allKeys = sortedRows.map(getRowKey);
3165
+ const allSelected = allKeys.length > 0 && allKeys.every((k) => selectedSet.has(k));
3166
+ const headerCheckedState = allSelected ? true : selectedSet.size > 0 ? "indeterminate" : false;
3167
+ const toggleAll = () => {
3168
+ if (allSelected) {
3169
+ setSelected([]);
3170
+ } else {
3171
+ setSelected(allKeys);
3172
+ }
3173
+ };
3174
+ const toggleRow = (key) => {
3175
+ const next = new Set(selectedSet);
3176
+ if (next.has(key)) {
3177
+ next.delete(key);
3178
+ } else {
3179
+ next.add(key);
3180
+ }
3181
+ setSelected([...next]);
3182
+ };
3018
3183
  const rowCountText = rowCountLabel?.(sortedRows.length) ?? `${sortedRows.length} row${sortedRows.length === 1 ? "" : "s"}`;
3019
- const hasFoot = Boolean((showRowCount || footer) && sortedRows.length > 0);
3020
- return /* @__PURE__ */ jsx41("div", { className: cn("aui-app-data-table", shellClass2, className), children: /* @__PURE__ */ jsx41("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs32("table", { className: tableClass, children: [
3021
- caption ? /* @__PURE__ */ jsx41("caption", { className: "sr-only", children: caption }) : null,
3022
- /* @__PURE__ */ jsx41("thead", { className: cn(stickyHeader && stickyHeadClass), children: /* @__PURE__ */ jsx41("tr", { children: columns.map((col) => {
3023
- const isSorted = sort?.columnId === col.id;
3024
- const ariaSort = col.sortable ? isSorted ? sort.direction === "asc" ? "ascending" : "descending" : "none" : void 0;
3025
- const headerContent = col.sortable ? /* @__PURE__ */ jsxs32(
3026
- "button",
3184
+ const hasPager = paginated && !loading && sortedRows.length > 0;
3185
+ const hasFoot = (showRowCount || footer || hasPager) && (loading || sortedRows.length > 0);
3186
+ const skeletonCount = loadingRows ?? pageSize ?? 5;
3187
+ return /* @__PURE__ */ jsx43("div", { className: cn("aui-app-data-table", shellClass2, className), children: /* @__PURE__ */ jsx43("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs33("table", { className: tableClass, children: [
3188
+ caption ? /* @__PURE__ */ jsx43("caption", { className: "sr-only", children: caption }) : null,
3189
+ /* @__PURE__ */ jsx43("thead", { className: cn(stickyHeader && stickyHeadClass), children: /* @__PURE__ */ jsxs33("tr", { children: [
3190
+ selectable ? /* @__PURE__ */ jsx43("th", { scope: "col", className: cn(selectCellClass, headPad), children: /* @__PURE__ */ jsx43(
3191
+ Checkbox,
3027
3192
  {
3028
- type: "button",
3029
- className: sortButtonClass,
3030
- onClick: () => setSort(nextSort(sort, col.id)),
3031
- children: [
3032
- /* @__PURE__ */ jsx41("span", { className: "truncate", children: col.header }),
3033
- /* @__PURE__ */ jsx41(SortIndicator, { active: Boolean(isSorted), direction: sort?.direction })
3034
- ]
3193
+ checked: headerCheckedState,
3194
+ onCheckedChange: toggleAll,
3195
+ "aria-label": selectAllAriaLabel,
3196
+ disabled: loading || allKeys.length === 0
3035
3197
  }
3036
- ) : col.header;
3037
- return /* @__PURE__ */ jsx41(
3038
- "th",
3039
- {
3040
- scope: "col",
3041
- "aria-sort": ariaSort,
3042
- className: cn(
3043
- headCellClass,
3044
- headPad,
3045
- col.align && alignClass[col.align],
3046
- col.headerClassName
3047
- ),
3048
- children: headerContent
3049
- },
3050
- col.id
3051
- );
3052
- }) }) }),
3053
- /* @__PURE__ */ jsx41("tbody", { className: cn(!hasFoot && "[&_tr:last-child_td]:border-b-0"), children: sortedRows.length === 0 ? /* @__PURE__ */ jsx41("tr", { children: /* @__PURE__ */ jsx41("td", { colSpan: columns.length, className: emptyCellClass, children: /* @__PURE__ */ jsxs32("div", { className: "flex flex-col items-center gap-1", children: [
3054
- /* @__PURE__ */ jsx41("p", { className: "font-medium text-foreground", children: emptyTitle }),
3055
- emptyDescription ? /* @__PURE__ */ jsx41("p", { className: "max-w-sm text-muted-foreground", children: emptyDescription }) : null
3056
- ] }) }) }) : sortedRows.map((row) => /* @__PURE__ */ jsx41(
3057
- "tr",
3058
- {
3059
- className: rowClass,
3060
- "data-clickable": onRowClick ? "true" : void 0,
3061
- onClick: onRowClick ? () => onRowClick(row) : void 0,
3062
- onKeyDown: onRowClick ? (event) => {
3063
- if (event.key === "Enter" || event.key === " ") {
3064
- event.preventDefault();
3065
- onRowClick(row);
3198
+ ) }) : null,
3199
+ columns.map((col) => {
3200
+ const isSorted = sort?.columnId === col.id;
3201
+ const ariaSort = col.sortable ? isSorted ? sort.direction === "asc" ? "ascending" : "descending" : "none" : void 0;
3202
+ const headerContent = col.sortable ? /* @__PURE__ */ jsxs33(
3203
+ "button",
3204
+ {
3205
+ type: "button",
3206
+ className: sortButtonClass,
3207
+ onClick: () => setSort(nextSort(sort, col.id)),
3208
+ children: [
3209
+ /* @__PURE__ */ jsx43("span", { className: "truncate", children: col.header }),
3210
+ /* @__PURE__ */ jsx43(SortIndicator, { active: Boolean(isSorted), direction: sort?.direction })
3211
+ ]
3066
3212
  }
3067
- } : void 0,
3068
- tabIndex: onRowClick ? 0 : void 0,
3069
- role: onRowClick ? "button" : void 0,
3070
- children: columns.map((col) => /* @__PURE__ */ jsx41(
3071
- "td",
3213
+ ) : col.header;
3214
+ return /* @__PURE__ */ jsx43(
3215
+ "th",
3072
3216
  {
3217
+ scope: "col",
3218
+ "aria-sort": ariaSort,
3073
3219
  className: cn(
3074
- bodyCellClass,
3075
- cellPad,
3220
+ headCellClass,
3221
+ headPad,
3076
3222
  col.align && alignClass[col.align],
3077
- col.className
3223
+ col.headerClassName
3078
3224
  ),
3079
- children: col.cell(row)
3225
+ children: headerContent
3080
3226
  },
3081
3227
  col.id
3082
- ))
3083
- },
3084
- getRowKey(row)
3085
- )) }),
3086
- hasFoot ? /* @__PURE__ */ jsx41("tfoot", { children: /* @__PURE__ */ jsx41("tr", { children: /* @__PURE__ */ jsx41("td", { colSpan: columns.length, className: footCellClass, children: /* @__PURE__ */ jsxs32(
3228
+ );
3229
+ })
3230
+ ] }) }),
3231
+ /* @__PURE__ */ jsx43("tbody", { className: cn(!hasFoot && "[&_tr:last-child_td]:border-b-0"), children: loading ? Array.from({ length: skeletonCount }).map((_, rowIdx) => /* @__PURE__ */ jsxs33("tr", { className: rowClass, "aria-hidden": true, children: [
3232
+ selectable ? /* @__PURE__ */ jsx43("td", { className: cn(selectCellClass, cellPad), children: /* @__PURE__ */ jsx43(Skeleton, { className: "size-4 rounded-[4px]" }) }) : null,
3233
+ columns.map((col) => /* @__PURE__ */ jsx43(
3234
+ "td",
3235
+ {
3236
+ className: cn(
3237
+ bodyCellClass,
3238
+ cellPad,
3239
+ col.align && alignClass[col.align],
3240
+ col.className
3241
+ ),
3242
+ children: /* @__PURE__ */ jsx43(Skeleton, { className: "h-4 w-[60%]" })
3243
+ },
3244
+ col.id
3245
+ ))
3246
+ ] }, `skeleton-${rowIdx}`)) : visibleRows.length === 0 ? /* @__PURE__ */ jsx43("tr", { children: /* @__PURE__ */ jsx43("td", { colSpan, className: emptyCellClass, children: /* @__PURE__ */ jsxs33("div", { className: "flex flex-col items-center gap-1", children: [
3247
+ /* @__PURE__ */ jsx43("p", { className: "font-medium text-foreground", children: emptyTitle }),
3248
+ emptyDescription ? /* @__PURE__ */ jsx43("p", { className: "max-w-sm text-muted-foreground", children: emptyDescription }) : null
3249
+ ] }) }) }) : visibleRows.map((row) => {
3250
+ const key = getRowKey(row);
3251
+ const isSelected = selectedSet.has(key);
3252
+ return /* @__PURE__ */ jsxs33(
3253
+ "tr",
3254
+ {
3255
+ className: rowClass,
3256
+ "data-clickable": onRowClick ? "true" : void 0,
3257
+ "data-selected": isSelected ? "true" : void 0,
3258
+ onClick: onRowClick ? () => onRowClick(row) : void 0,
3259
+ onKeyDown: onRowClick ? (event) => {
3260
+ if (event.key === "Enter" || event.key === " ") {
3261
+ event.preventDefault();
3262
+ onRowClick(row);
3263
+ }
3264
+ } : void 0,
3265
+ tabIndex: onRowClick ? 0 : void 0,
3266
+ role: onRowClick ? "button" : void 0,
3267
+ children: [
3268
+ selectable ? /* @__PURE__ */ jsx43(
3269
+ "td",
3270
+ {
3271
+ className: cn(selectCellClass, cellPad),
3272
+ onClick: (event) => event.stopPropagation(),
3273
+ children: /* @__PURE__ */ jsx43(
3274
+ Checkbox,
3275
+ {
3276
+ checked: isSelected,
3277
+ onCheckedChange: () => toggleRow(key),
3278
+ "aria-label": `Select row`
3279
+ }
3280
+ )
3281
+ }
3282
+ ) : null,
3283
+ columns.map((col) => /* @__PURE__ */ jsx43(
3284
+ "td",
3285
+ {
3286
+ className: cn(
3287
+ bodyCellClass,
3288
+ cellPad,
3289
+ col.truncate && "max-w-0",
3290
+ col.align && alignClass[col.align],
3291
+ col.className
3292
+ ),
3293
+ children: col.truncate ? /* @__PURE__ */ jsx43("div", { className: "truncate", children: col.cell(row) }) : col.cell(row)
3294
+ },
3295
+ col.id
3296
+ ))
3297
+ ]
3298
+ },
3299
+ key
3300
+ );
3301
+ }) }),
3302
+ hasFoot ? /* @__PURE__ */ jsx43("tfoot", { children: /* @__PURE__ */ jsx43("tr", { children: /* @__PURE__ */ jsx43("td", { colSpan, className: footCellClass, children: /* @__PURE__ */ jsxs33(
3087
3303
  "div",
3088
3304
  {
3089
3305
  className: cn(
3090
3306
  footInnerClass,
3091
- showRowCount && footer ? "justify-between" : "justify-start"
3307
+ (showRowCount || footer || hasPager) && "justify-between"
3092
3308
  ),
3093
3309
  children: [
3094
- showRowCount ? /* @__PURE__ */ jsx41("span", { children: rowCountText }) : null,
3095
- footer
3310
+ /* @__PURE__ */ jsxs33("div", { className: footInnerClass, children: [
3311
+ showRowCount ? /* @__PURE__ */ jsxs33("span", { children: [
3312
+ rowCountText,
3313
+ selectable && selectedSet.size > 0 ? ` \xB7 ${selectedSet.size} selected` : null
3314
+ ] }) : selectable && selectedSet.size > 0 ? /* @__PURE__ */ jsxs33("span", { children: [
3315
+ selectedSet.size,
3316
+ " selected"
3317
+ ] }) : null,
3318
+ footer
3319
+ ] }),
3320
+ hasPager ? /* @__PURE__ */ jsxs33("div", { className: "flex items-center gap-2", children: [
3321
+ /* @__PURE__ */ jsxs33("span", { className: "tabular-nums", children: [
3322
+ pageIndex * pageSize + 1,
3323
+ "\u2013",
3324
+ Math.min(
3325
+ (pageIndex + 1) * pageSize,
3326
+ sortedRows.length
3327
+ ),
3328
+ " ",
3329
+ "of ",
3330
+ sortedRows.length
3331
+ ] }),
3332
+ /* @__PURE__ */ jsxs33("div", { className: "flex items-center gap-1", children: [
3333
+ /* @__PURE__ */ jsx43(
3334
+ "button",
3335
+ {
3336
+ type: "button",
3337
+ className: pagerButtonClass,
3338
+ onClick: () => setPage(pageIndex - 1),
3339
+ disabled: pageIndex <= 0,
3340
+ "aria-label": "Previous page",
3341
+ children: /* @__PURE__ */ jsx43(ChevronLeftIcon, { className: "size-4", "aria-hidden": true })
3342
+ }
3343
+ ),
3344
+ /* @__PURE__ */ jsx43(
3345
+ "button",
3346
+ {
3347
+ type: "button",
3348
+ className: pagerButtonClass,
3349
+ onClick: () => setPage(pageIndex + 1),
3350
+ disabled: pageIndex >= pageCount - 1,
3351
+ "aria-label": "Next page",
3352
+ children: /* @__PURE__ */ jsx43(ChevronRightIcon, { className: "size-4", "aria-hidden": true })
3353
+ }
3354
+ )
3355
+ ] })
3356
+ ] }) : null
3096
3357
  ]
3097
3358
  }
3098
3359
  ) }) }) }) : null
@@ -3101,7 +3362,7 @@ function DataTable({
3101
3362
 
3102
3363
  // src/app/data/ChartPanel.tsx
3103
3364
  import { useId as useId4 } from "react";
3104
- import { jsx as jsx42, jsxs as jsxs33 } from "react/jsx-runtime";
3365
+ import { jsx as jsx44, jsxs as jsxs34 } from "react/jsx-runtime";
3105
3366
  var ChartPanel = ({
3106
3367
  title,
3107
3368
  description,
@@ -3109,19 +3370,20 @@ var ChartPanel = ({
3109
3370
  children,
3110
3371
  actions,
3111
3372
  height = 300,
3373
+ loading = false,
3112
3374
  className
3113
3375
  }) => {
3114
3376
  const titleId = useId4();
3115
3377
  const resolvedTitle = title ?? artifact?.title;
3116
3378
  const hasHeader = Boolean(resolvedTitle || description || actions);
3117
- const body = children ?? (artifact ? /* @__PURE__ */ jsx42(ChartArtifactView, { artifact, embedded: true, height }) : null);
3118
- return /* @__PURE__ */ jsxs33(
3379
+ const body = loading ? /* @__PURE__ */ jsx44(Skeleton, { className: "w-full rounded-lg", style: { height }, "aria-hidden": true }) : children ?? (artifact ? /* @__PURE__ */ jsx44(ChartArtifactView, { artifact, embedded: true, height }) : null);
3380
+ return /* @__PURE__ */ jsxs34(
3119
3381
  "section",
3120
3382
  {
3121
3383
  className: cn(metricCardShellClass, "aui-app-chart-panel", className),
3122
3384
  "aria-labelledby": resolvedTitle ? titleId : void 0,
3123
3385
  children: [
3124
- /* @__PURE__ */ jsx42(
3386
+ /* @__PURE__ */ jsx44(
3125
3387
  MetricCardHeader,
3126
3388
  {
3127
3389
  title: resolvedTitle,
@@ -3130,14 +3392,14 @@ var ChartPanel = ({
3130
3392
  actions
3131
3393
  }
3132
3394
  ),
3133
- /* @__PURE__ */ jsx42(
3395
+ /* @__PURE__ */ jsx44(
3134
3396
  "div",
3135
3397
  {
3136
3398
  className: cn(
3137
3399
  "relative min-h-0 w-full",
3138
3400
  hasHeader ? metricChartPlotRegionClass : "pt-2 pb-3"
3139
3401
  ),
3140
- children: body ?? /* @__PURE__ */ jsx42(
3402
+ children: body ?? /* @__PURE__ */ jsx44(
3141
3403
  "div",
3142
3404
  {
3143
3405
  className: "flex items-center justify-center text-sm font-normal text-muted-foreground",
@@ -3155,7 +3417,7 @@ var ChartPanel = ({
3155
3417
 
3156
3418
  // src/app/data/MetricRow.tsx
3157
3419
  import { useId as useId5, useState as useState5 } from "react";
3158
- import { jsx as jsx43, jsxs as jsxs34 } from "react/jsx-runtime";
3420
+ import { jsx as jsx45, jsxs as jsxs35 } from "react/jsx-runtime";
3159
3421
  var MetricRow = ({
3160
3422
  title,
3161
3423
  description,
@@ -3165,6 +3427,7 @@ var MetricRow = ({
3165
3427
  defaultActiveMetricId,
3166
3428
  onMetricChange,
3167
3429
  metricsAriaLabel = "Metrics",
3430
+ loading = false,
3168
3431
  className
3169
3432
  }) => {
3170
3433
  const titleId = useId5();
@@ -3177,13 +3440,13 @@ var MetricRow = ({
3177
3440
  if (activeMetricId == null) setInternalId(id);
3178
3441
  onMetricChange?.(id);
3179
3442
  };
3180
- return /* @__PURE__ */ jsxs34(
3443
+ return /* @__PURE__ */ jsxs35(
3181
3444
  "section",
3182
3445
  {
3183
3446
  className: cn(metricCardShellClass, className),
3184
3447
  "aria-labelledby": title ? titleId : void 0,
3185
3448
  children: [
3186
- /* @__PURE__ */ jsx43(
3449
+ /* @__PURE__ */ jsx45(
3187
3450
  MetricCardHeader,
3188
3451
  {
3189
3452
  title,
@@ -3192,17 +3455,29 @@ var MetricRow = ({
3192
3455
  actions
3193
3456
  }
3194
3457
  ),
3195
- /* @__PURE__ */ jsx43(
3458
+ /* @__PURE__ */ jsx45(
3196
3459
  "div",
3197
3460
  {
3198
3461
  role: selectable ? "group" : void 0,
3199
3462
  "aria-label": selectable ? metricsAriaLabel : void 0,
3463
+ "aria-busy": loading || void 0,
3200
3464
  className: cn(
3201
3465
  metricTilesRowClass,
3202
- metricTilesGridColsClass(metrics.length),
3466
+ metricTilesGridColsClass(loading ? metrics.length || 4 : metrics.length),
3203
3467
  (title || description || actions) && "mt-3"
3204
3468
  ),
3205
- children: metrics.map((m, index) => /* @__PURE__ */ jsx43(
3469
+ children: loading ? Array.from({ length: metrics.length || 4 }).map((_, index) => /* @__PURE__ */ jsxs35(
3470
+ "div",
3471
+ {
3472
+ className: "flex min-w-0 flex-1 flex-col gap-2 px-4 py-3",
3473
+ "aria-hidden": true,
3474
+ children: [
3475
+ /* @__PURE__ */ jsx45(Skeleton, { className: "h-3 w-20" }),
3476
+ /* @__PURE__ */ jsx45(Skeleton, { className: "h-7 w-24" })
3477
+ ]
3478
+ },
3479
+ `skeleton-${index}`
3480
+ )) : metrics.map((m, index) => /* @__PURE__ */ jsx45(
3206
3481
  MetricTile,
3207
3482
  {
3208
3483
  label: m.label,
@@ -3225,7 +3500,7 @@ var MetricRow = ({
3225
3500
 
3226
3501
  // src/app/data/MetricChartCard.tsx
3227
3502
  import { useId as useId6, useState as useState6 } from "react";
3228
- import { jsx as jsx44, jsxs as jsxs35 } from "react/jsx-runtime";
3503
+ import { jsx as jsx46, jsxs as jsxs36 } from "react/jsx-runtime";
3229
3504
  var MetricChartCard = ({
3230
3505
  title,
3231
3506
  description,
@@ -3241,6 +3516,7 @@ var MetricChartCard = ({
3241
3516
  formatValue,
3242
3517
  emptyLabel = "No data yet",
3243
3518
  metricsAriaLabel = "Metrics",
3519
+ loading = false,
3244
3520
  className
3245
3521
  }) => {
3246
3522
  const titleId = useId6();
@@ -3255,13 +3531,13 @@ var MetricChartCard = ({
3255
3531
  };
3256
3532
  const hasHeader = Boolean(title || description || actions);
3257
3533
  const chartAriaLabel = typeof active?.label === "string" ? `${active.label} over time` : "Metric chart";
3258
- return /* @__PURE__ */ jsxs35(
3534
+ return /* @__PURE__ */ jsxs36(
3259
3535
  "section",
3260
3536
  {
3261
3537
  className: cn(metricCardShellClass, className),
3262
3538
  "aria-labelledby": title ? titleId : void 0,
3263
3539
  children: [
3264
- /* @__PURE__ */ jsx44(
3540
+ /* @__PURE__ */ jsx46(
3265
3541
  MetricCardHeader,
3266
3542
  {
3267
3543
  title,
@@ -3270,17 +3546,29 @@ var MetricChartCard = ({
3270
3546
  actions
3271
3547
  }
3272
3548
  ),
3273
- /* @__PURE__ */ jsx44(
3549
+ /* @__PURE__ */ jsx46(
3274
3550
  "div",
3275
3551
  {
3276
3552
  role: "group",
3277
3553
  "aria-label": metricsAriaLabel,
3554
+ "aria-busy": loading || void 0,
3278
3555
  className: cn(
3279
3556
  metricTilesRowClass,
3280
- metricTilesGridColsClass(metrics.length),
3557
+ metricTilesGridColsClass(loading ? metrics.length || 4 : metrics.length),
3281
3558
  hasHeader && "mt-3"
3282
3559
  ),
3283
- children: metrics.map((m, index) => /* @__PURE__ */ jsx44(
3560
+ children: loading ? Array.from({ length: metrics.length || 4 }).map((_, index) => /* @__PURE__ */ jsxs36(
3561
+ "div",
3562
+ {
3563
+ className: "flex min-w-0 flex-1 flex-col gap-2 px-4 py-3",
3564
+ "aria-hidden": true,
3565
+ children: [
3566
+ /* @__PURE__ */ jsx46(Skeleton, { className: "h-3 w-20" }),
3567
+ /* @__PURE__ */ jsx46(Skeleton, { className: "h-7 w-24" })
3568
+ ]
3569
+ },
3570
+ `skeleton-${index}`
3571
+ )) : metrics.map((m, index) => /* @__PURE__ */ jsx46(
3284
3572
  MetricTile,
3285
3573
  {
3286
3574
  label: m.label,
@@ -3296,7 +3584,14 @@ var MetricChartCard = ({
3296
3584
  ))
3297
3585
  }
3298
3586
  ),
3299
- /* @__PURE__ */ jsx44("div", { className: metricChartRegionClass, "aria-live": "polite", "aria-atomic": "true", children: active?.data && active.data.length > 0 ? /* @__PURE__ */ jsx44(
3587
+ /* @__PURE__ */ jsx46("div", { className: metricChartRegionClass, "aria-live": "polite", "aria-atomic": "true", children: loading ? /* @__PURE__ */ jsx46(
3588
+ Skeleton,
3589
+ {
3590
+ className: "w-full rounded-lg",
3591
+ style: { height },
3592
+ "aria-hidden": true
3593
+ }
3594
+ ) : active?.data && active.data.length > 0 ? /* @__PURE__ */ jsx46(
3300
3595
  LineAreaChart,
3301
3596
  {
3302
3597
  data: active.data,
@@ -3316,7 +3611,7 @@ var MetricChartCard = ({
3316
3611
  ariaLabel: chartAriaLabel
3317
3612
  },
3318
3613
  active.id
3319
- ) : /* @__PURE__ */ jsx44(
3614
+ ) : /* @__PURE__ */ jsx46(
3320
3615
  "div",
3321
3616
  {
3322
3617
  className: "flex w-full items-center justify-center text-sm font-normal text-muted-foreground",
@@ -3330,9 +3625,99 @@ var MetricChartCard = ({
3330
3625
  );
3331
3626
  };
3332
3627
 
3628
+ // src/hooks/use-live-query.ts
3629
+ import { useCallback as useCallback2, useEffect as useEffect3, useRef, useState as useState7 } from "react";
3630
+ function useInterval(callback, delayMs) {
3631
+ const saved = useRef(callback);
3632
+ useEffect3(() => {
3633
+ saved.current = callback;
3634
+ }, [callback]);
3635
+ useEffect3(() => {
3636
+ if (delayMs === null) return;
3637
+ const id = setInterval(() => saved.current(), delayMs);
3638
+ return () => clearInterval(id);
3639
+ }, [delayMs]);
3640
+ }
3641
+ function useLiveQuery(fetcher, options = {}) {
3642
+ const {
3643
+ intervalMs = null,
3644
+ enabled = true,
3645
+ immediate = true,
3646
+ refetchOnFocus = true
3647
+ } = options;
3648
+ const [data, setData] = useState7(void 0);
3649
+ const [error, setError] = useState7(void 0);
3650
+ const [loading, setLoading] = useState7(enabled);
3651
+ const [refreshing, setRefreshing] = useState7(false);
3652
+ const [lastUpdated, setLastUpdated] = useState7(null);
3653
+ const fetcherRef = useRef(fetcher);
3654
+ useEffect3(() => {
3655
+ fetcherRef.current = fetcher;
3656
+ }, [fetcher]);
3657
+ const mounted = useRef(true);
3658
+ const requestId = useRef(0);
3659
+ const hasData = useRef(false);
3660
+ useEffect3(() => {
3661
+ mounted.current = true;
3662
+ return () => {
3663
+ mounted.current = false;
3664
+ };
3665
+ }, []);
3666
+ const run = useCallback2(() => {
3667
+ const id = ++requestId.current;
3668
+ if (hasData.current) {
3669
+ setRefreshing(true);
3670
+ } else {
3671
+ setLoading(true);
3672
+ }
3673
+ fetcherRef.current().then((result) => {
3674
+ if (!mounted.current || id !== requestId.current) return;
3675
+ setData(result);
3676
+ setError(void 0);
3677
+ setLastUpdated(Date.now());
3678
+ hasData.current = true;
3679
+ }).catch((err) => {
3680
+ if (!mounted.current || id !== requestId.current) return;
3681
+ setError(err);
3682
+ }).finally(() => {
3683
+ if (!mounted.current || id !== requestId.current) return;
3684
+ setLoading(false);
3685
+ setRefreshing(false);
3686
+ });
3687
+ }, []);
3688
+ const refetch = useCallback2(() => {
3689
+ if (!enabled) return;
3690
+ run();
3691
+ }, [enabled, run]);
3692
+ useEffect3(() => {
3693
+ if (!enabled) return;
3694
+ if (immediate) run();
3695
+ }, [enabled, immediate, run]);
3696
+ useEffect3(() => {
3697
+ if (!enabled || intervalMs === null) return;
3698
+ const tick = () => {
3699
+ if (refetchOnFocus && typeof document !== "undefined" && document.visibilityState === "hidden") {
3700
+ return;
3701
+ }
3702
+ run();
3703
+ };
3704
+ const handle = setInterval(tick, intervalMs);
3705
+ return () => clearInterval(handle);
3706
+ }, [enabled, intervalMs, refetchOnFocus, run]);
3707
+ useEffect3(() => {
3708
+ if (!enabled || !refetchOnFocus || typeof document === "undefined") return;
3709
+ const onVisible = () => {
3710
+ if (document.visibilityState === "visible") run();
3711
+ };
3712
+ document.addEventListener("visibilitychange", onVisible);
3713
+ return () => document.removeEventListener("visibilitychange", onVisible);
3714
+ }, [enabled, refetchOnFocus, run]);
3715
+ return { data, error, loading, refreshing, lastUpdated, refetch };
3716
+ }
3717
+
3333
3718
  // src/charts/sparkline.tsx
3334
3719
  import { useId as useId7 } from "react";
3335
- import { Fragment as Fragment6, jsx as jsx45, jsxs as jsxs36 } from "react/jsx-runtime";
3720
+ import { Fragment as Fragment6, jsx as jsx47, jsxs as jsxs37 } from "react/jsx-runtime";
3336
3721
  var Sparkline = ({
3337
3722
  data,
3338
3723
  dataKey = "value",
@@ -3347,7 +3732,7 @@ var Sparkline = ({
3347
3732
  const uid = useId7();
3348
3733
  const values = data.map((d) => typeof d === "number" ? d : toNum(d[dataKey]));
3349
3734
  if (values.length === 0) {
3350
- return /* @__PURE__ */ jsx45("span", { className: cn("inline-block", className), style: { width, height } });
3735
+ return /* @__PURE__ */ jsx47("span", { className: cn("inline-block", className), style: { width, height } });
3351
3736
  }
3352
3737
  const pad = strokeWidth + 1;
3353
3738
  const min = Math.min(...values);
@@ -3359,7 +3744,7 @@ var Sparkline = ({
3359
3744
  x: pad + (values.length > 1 ? i / (values.length - 1) * innerW : innerW / 2),
3360
3745
  y: pad + innerH - (v - min) / range * innerH
3361
3746
  }));
3362
- return /* @__PURE__ */ jsxs36(
3747
+ return /* @__PURE__ */ jsxs37(
3363
3748
  "svg",
3364
3749
  {
3365
3750
  width,
@@ -3370,14 +3755,14 @@ var Sparkline = ({
3370
3755
  "aria-label": ariaLabel,
3371
3756
  preserveAspectRatio: "none",
3372
3757
  children: [
3373
- area && /* @__PURE__ */ jsxs36(Fragment6, { children: [
3374
- /* @__PURE__ */ jsx45("defs", { children: /* @__PURE__ */ jsxs36("linearGradient", { id: `${uid}-spark`, x1: "0", x2: "0", y1: "0", y2: "1", children: [
3375
- /* @__PURE__ */ jsx45("stop", { offset: "0%", style: { stopColor: color, stopOpacity: 0.25 } }),
3376
- /* @__PURE__ */ jsx45("stop", { offset: "100%", style: { stopColor: color, stopOpacity: 0 } })
3758
+ area && /* @__PURE__ */ jsxs37(Fragment6, { children: [
3759
+ /* @__PURE__ */ jsx47("defs", { children: /* @__PURE__ */ jsxs37("linearGradient", { id: `${uid}-spark`, x1: "0", x2: "0", y1: "0", y2: "1", children: [
3760
+ /* @__PURE__ */ jsx47("stop", { offset: "0%", style: { stopColor: color, stopOpacity: 0.25 } }),
3761
+ /* @__PURE__ */ jsx47("stop", { offset: "100%", style: { stopColor: color, stopOpacity: 0 } })
3377
3762
  ] }) }),
3378
- /* @__PURE__ */ jsx45("path", { d: monotoneAreaPath(points, height - pad), fill: `url(#${uid}-spark)` })
3763
+ /* @__PURE__ */ jsx47("path", { d: monotoneAreaPath(points, height - pad), fill: `url(#${uid}-spark)` })
3379
3764
  ] }),
3380
- /* @__PURE__ */ jsx45(
3765
+ /* @__PURE__ */ jsx47(
3381
3766
  "path",
3382
3767
  {
3383
3768
  d: monotoneLinePath(points),
@@ -3426,9 +3811,11 @@ export {
3426
3811
  appFilterBarClass,
3427
3812
  appSearchInputClass,
3428
3813
  useAppShellChat,
3814
+ useAppShellNav,
3429
3815
  AppShell,
3430
3816
  AppShellTopbar,
3431
3817
  AppShellChatTrigger,
3818
+ AppShellSidebarTrigger,
3432
3819
  PageHeader,
3433
3820
  Page,
3434
3821
  Section,
@@ -3468,9 +3855,12 @@ export {
3468
3855
  SearchInput,
3469
3856
  FormSection,
3470
3857
  FilterBar,
3858
+ FilterField,
3471
3859
  DataTable,
3472
3860
  ChartPanel,
3473
3861
  MetricRow,
3474
3862
  MetricChartCard,
3863
+ useInterval,
3864
+ useLiveQuery,
3475
3865
  Sparkline
3476
3866
  };