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