@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.
- package/CHANGELOG.md +28 -0
- package/README.md +45 -4
- package/dist/app.cjs +1996 -1183
- package/dist/app.d.cts +8 -4
- package/dist/app.d.ts +8 -4
- package/dist/app.esm.js +23 -6
- package/dist/{chart-artifact-CBo9x8Ch.d.ts → chart-artifact-BZp7nmaf.d.ts} +253 -12
- package/dist/{chart-artifact-DOkwSTjQ.d.cts → chart-artifact-CX-rh9nq.d.cts} +253 -12
- package/dist/{chat-Bed4FQSl.d.cts → chat-DCms8pJ_.d.cts} +31 -4
- package/dist/{chat-Bed4FQSl.d.ts → chat-DCms8pJ_.d.ts} +31 -4
- package/dist/chat.cjs +1088 -775
- package/dist/chat.d.cts +1 -1
- package/dist/chat.d.ts +1 -1
- package/dist/chat.esm.js +3 -3
- package/dist/{chunk-FOD67Z6G.esm.js → chunk-4AKJ6FKE.esm.js} +235 -4
- package/dist/{chunk-YEFBANNF.esm.js → chunk-6HWMJNZT.esm.js} +242 -288
- package/dist/{chunk-C6IXFM4T.esm.js → chunk-FRZOEYBO.esm.js} +4 -4
- package/dist/chunk-JEAUF54A.esm.js +52 -0
- package/dist/{chunk-AYHOVAMI.esm.js → chunk-P3KDAYX6.esm.js} +1 -1
- package/dist/{chunk-GLPOVYEA.esm.js → chunk-TK2AGIME.esm.js} +662 -274
- package/dist/{chunk-RZ6QC6RG.esm.js → chunk-XCM3V6RK.esm.js} +2 -2
- package/dist/{chunk-SNLXVG7H.esm.js → chunk-YXZ22OJN.esm.js} +849 -665
- package/dist/index.cjs +2558 -1789
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.esm.js +29 -11
- package/dist/pill-segmented-tabs-Ba5q0feL.d.cts +500 -0
- package/dist/pill-segmented-tabs-Ba5q0feL.d.ts +500 -0
- package/dist/studio.cjs +1310 -997
- package/dist/studio.d.cts +2 -2
- package/dist/studio.d.ts +2 -2
- package/dist/studio.esm.js +5 -5
- package/dist/styles.css +26 -0
- package/dist/ui.cjs +275 -37
- package/dist/ui.d.cts +71 -491
- package/dist/ui.d.ts +71 -491
- package/dist/ui.esm.js +22 -6
- package/dist/{welcome-COOb05a5.d.cts → welcome-CRqOPKMp.d.cts} +1 -1
- package/dist/{welcome-DE08m9ca.d.ts → welcome-DlHUa3OL.d.ts} +1 -1
- package/package.json +7 -3
|
@@ -15,10 +15,14 @@ import {
|
|
|
15
15
|
studioIntegrationCardClass,
|
|
16
16
|
studioTopbarPillHeightClass,
|
|
17
17
|
toNum
|
|
18
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
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
|
|
308
|
-
| \`FilterBar\` | Horizontal filter row
|
|
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
|
|
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\` |
|
|
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 =
|
|
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
|
|
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:
|
|
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
|
|
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__ */
|
|
1772
|
-
description ? /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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
|
|
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__ */
|
|
1803
|
-
description ? /* @__PURE__ */
|
|
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
|
|
1810
|
-
import { jsx as
|
|
1811
|
-
var AppCopilotContext =
|
|
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__ */
|
|
1892
|
+
return /* @__PURE__ */ jsx12(AppCopilotContext.Provider, { value, children });
|
|
1817
1893
|
};
|
|
1818
1894
|
function useAppCopilotContext() {
|
|
1819
|
-
return
|
|
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
|
|
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__ */
|
|
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__ */
|
|
1953
|
+
children: /* @__PURE__ */ jsx13(XIcon, { className: "size-4", "aria-hidden": true })
|
|
1878
1954
|
}
|
|
1879
1955
|
) }) : null,
|
|
1880
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
1987
|
+
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
1912
1988
|
var SurfaceCard = ({ children, className }) => {
|
|
1913
|
-
return /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
1921
|
-
/* @__PURE__ */
|
|
1922
|
-
hint ? /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
1936
|
-
description ? /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
1990
|
-
description ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
2049
|
-
children ? /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
2158
|
+
/* @__PURE__ */ jsx20("span", { className: cn("relative inline-flex size-2 rounded-full", dotClass[tone]) })
|
|
2082
2159
|
] }),
|
|
2083
|
-
label ? /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
2108
|
-
/* @__PURE__ */
|
|
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
|
|
2129
|
-
var Chevron = ({ open }) => /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2176
|
-
/* @__PURE__ */
|
|
2177
|
-
count != null ? /* @__PURE__ */
|
|
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__ */
|
|
2256
|
+
/* @__PURE__ */ jsx22(Chevron, { open })
|
|
2180
2257
|
]
|
|
2181
2258
|
}
|
|
2182
2259
|
),
|
|
2183
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
2230
|
-
subtitle ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2236
|
-
action ? /* @__PURE__ */
|
|
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__ */
|
|
2317
|
+
return /* @__PURE__ */ jsx23("button", { type: "button", onClick, "aria-label": ariaLabel, className: cn(resourceCardInteractiveClass, className), children: body });
|
|
2241
2318
|
}
|
|
2242
|
-
return /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
2253
|
-
description ? /* @__PURE__ */
|
|
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__ */
|
|
2273
|
-
description ? /* @__PURE__ */
|
|
2274
|
-
descriptionFooter ? /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
2386
|
+
description ? /* @__PURE__ */ jsx25("p", { className: "mt-0.5 text-xs text-muted-foreground", children: description }) : null
|
|
2310
2387
|
] }),
|
|
2311
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2394
|
+
/* @__PURE__ */ jsx25("label", { htmlFor, className: "text-sm font-medium text-foreground", children: label }),
|
|
2318
2395
|
children,
|
|
2319
|
-
description ? /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2362
|
-
/* @__PURE__ */
|
|
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
|
|
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__ */
|
|
2388
|
-
description ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2409
|
-
description ? /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
2462
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2549
|
+
statusLabel[status] ? /* @__PURE__ */ jsx28("p", { className: "mt-0.5 text-xs text-muted-foreground", children: statusLabel[status] }) : null
|
|
2473
2550
|
] }),
|
|
2474
|
-
badge ? /* @__PURE__ */
|
|
2551
|
+
badge ? /* @__PURE__ */ jsx28("span", { className: "shrink-0", children: badge }) : null
|
|
2475
2552
|
] }) })
|
|
2476
2553
|
] }),
|
|
2477
|
-
description ? /* @__PURE__ */
|
|
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__ */
|
|
2489
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
2553
|
-
description ? /* @__PURE__ */
|
|
2554
|
-
action ? /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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
|
|
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__ */
|
|
2659
|
+
logo ? /* @__PURE__ */ jsx31("span", { className: logoShellClass2, children: logo }) : null,
|
|
2583
2660
|
/* @__PURE__ */ jsxs25("div", { className: "min-w-0 flex-1", children: [
|
|
2584
|
-
/* @__PURE__ */
|
|
2585
|
-
meta ? /* @__PURE__ */
|
|
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__ */
|
|
2588
|
-
action ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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
|
|
2732
|
+
import { jsx as jsx34, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
2656
2733
|
var Breadcrumbs = ({ items, className }) => {
|
|
2657
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
2661
|
-
isLast ? /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
2762
|
+
/* @__PURE__ */ jsx35("label", { className: appFieldLabelClass, htmlFor, children: label }),
|
|
2686
2763
|
children,
|
|
2687
|
-
hint && !error ? /* @__PURE__ */
|
|
2688
|
-
error ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2855
|
-
description ? /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
2880
|
-
/* @__PURE__ */
|
|
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
|
|
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__ */
|
|
2899
|
-
/* @__PURE__ */
|
|
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
|
|
2981
|
+
import { jsx as jsx41 } from "react/jsx-runtime";
|
|
2905
2982
|
var FilterBar = ({ children, className }) => {
|
|
2906
|
-
return /* @__PURE__ */
|
|
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 {
|
|
2920
|
-
|
|
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__ */
|
|
3058
|
+
return /* @__PURE__ */ jsx43(ArrowUpDownIcon, { className: iconClass, "aria-hidden": true });
|
|
2961
3059
|
}
|
|
2962
3060
|
if (direction === "desc") {
|
|
2963
|
-
return /* @__PURE__ */
|
|
3061
|
+
return /* @__PURE__ */ jsx43(ArrowDownIcon, { className: iconClass, "aria-hidden": true });
|
|
2964
3062
|
}
|
|
2965
|
-
return /* @__PURE__ */
|
|
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
|
|
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
|
-
|
|
3016
|
-
|
|
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
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
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
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
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
|
-
) :
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
"
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
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
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
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
|
-
|
|
3075
|
-
|
|
3219
|
+
headCellClass,
|
|
3220
|
+
headPad,
|
|
3076
3221
|
col.align && alignClass[col.align],
|
|
3077
|
-
col.
|
|
3222
|
+
col.headerClassName
|
|
3078
3223
|
),
|
|
3079
|
-
children:
|
|
3224
|
+
children: headerContent
|
|
3080
3225
|
},
|
|
3081
3226
|
col.id
|
|
3082
|
-
)
|
|
3083
|
-
}
|
|
3084
|
-
|
|
3085
|
-
)
|
|
3086
|
-
|
|
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
|
|
3305
|
+
(showRowCount || footer || hasPager) && "justify-between"
|
|
3092
3306
|
),
|
|
3093
3307
|
children: [
|
|
3094
|
-
|
|
3095
|
-
|
|
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
|
|
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__ */
|
|
3118
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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((
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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((
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3374
|
-
/* @__PURE__ */
|
|
3375
|
-
/* @__PURE__ */
|
|
3376
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3761
|
+
/* @__PURE__ */ jsx47("path", { d: monotoneAreaPath(points, height - pad), fill: `url(#${uid}-spark)` })
|
|
3379
3762
|
] }),
|
|
3380
|
-
/* @__PURE__ */
|
|
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
|
};
|