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