@timbal-ai/timbal-react 0.8.0 → 0.8.1
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 +15 -0
- package/README.md +51 -5
- package/dist/app.cjs +1750 -1157
- package/dist/app.d.cts +2 -2
- package/dist/app.d.ts +2 -2
- package/dist/app.esm.js +27 -5
- package/dist/{button-CIKzUrJI.d.cts → button-ClSgD6OF.d.cts} +1 -1
- package/dist/{button-CIKzUrJI.d.ts → button-ClSgD6OF.d.ts} +1 -1
- package/dist/{chart-artifact-C2m891nx.d.cts → chart-artifact-DWkqIAK5.d.cts} +165 -1
- package/dist/{chart-artifact-CqqhdSR9.d.ts → chart-artifact-DwfRtQWL.d.ts} +165 -1
- package/dist/chat.esm.js +3 -3
- package/dist/{chunk-VVTTLIGT.esm.js → chunk-5ZKLPWVN.esm.js} +1 -1
- package/dist/{chunk-ZG5NBHOS.esm.js → chunk-CFU3YDTV.esm.js} +2 -2
- package/dist/{chunk-ZEDE2TWQ.esm.js → chunk-GBBLAM3G.esm.js} +954 -378
- package/dist/{chunk-YNDXBN6C.esm.js → chunk-OISVICYF.esm.js} +1 -1
- package/dist/{chunk-LSEUKTU5.esm.js → chunk-P4SN7M67.esm.js} +1 -1
- package/dist/{chunk-Z27GBSOT.esm.js → chunk-QIABF4KB.esm.js} +53 -51
- package/dist/{chunk-QKO67F4V.esm.js → chunk-QVAUCVQA.esm.js} +93 -93
- package/dist/{chunk-4AO3HCAR.esm.js → chunk-VWHHKAHN.esm.js} +5 -5
- package/dist/index.cjs +1006 -418
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.esm.js +30 -8
- package/dist/studio.cjs +3 -1
- package/dist/studio.esm.js +6 -6
- package/dist/ui.d.cts +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/ui.esm.js +3 -3
- package/package.json +1 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SIDEBAR_INSET_PX_EXPANDED,
|
|
3
|
+
STORAGE_KEYS,
|
|
3
4
|
ShellInsetProvider,
|
|
4
5
|
studioChromeShellStyle,
|
|
5
6
|
studioSidebarWidthTransition
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-QIABF4KB.esm.js";
|
|
7
8
|
import {
|
|
8
9
|
ChartArtifactView,
|
|
9
10
|
LineAreaChart,
|
|
@@ -16,10 +17,10 @@ import {
|
|
|
16
17
|
studioSecondaryChromeClass,
|
|
17
18
|
studioTopbarPillHeightClass,
|
|
18
19
|
toNum
|
|
19
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-5ZKLPWVN.esm.js";
|
|
20
21
|
import {
|
|
21
22
|
PillSegmentedTabs
|
|
22
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-OISVICYF.esm.js";
|
|
23
24
|
import {
|
|
24
25
|
Button,
|
|
25
26
|
Dialog,
|
|
@@ -31,7 +32,7 @@ import {
|
|
|
31
32
|
TIMBAL_V2_SWITCH_TRACK_OFF,
|
|
32
33
|
TimbalV2Button,
|
|
33
34
|
cn
|
|
34
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-QVAUCVQA.esm.js";
|
|
35
36
|
|
|
36
37
|
// src/app/agent-instructions.ts
|
|
37
38
|
var APP_KIT_AGENT_INSTRUCTIONS = `
|
|
@@ -66,6 +67,8 @@ Presentational groups \u2014 import from the package root, not from these paths:
|
|
|
66
67
|
|
|
67
68
|
Also re-exported: \`Button\`, \`TimbalChat\`, \`ChartArtifactView\`, \`APP_KIT_AGENT_INSTRUCTIONS\`.
|
|
68
69
|
|
|
70
|
+
Theming helpers (import from the package root or \`/app\`): \`createTimbalTheme\`, \`themeToCss\`, \`applyTimbalTheme\`, \`TIMBAL_THEME_PRESETS\`, \`applyThemePreset\`, \`ThemePresetGallery\`, \`TimbalThemeStyle\`, \`THEME_AGENT_INSTRUCTIONS\`.
|
|
71
|
+
|
|
69
72
|
### Design guidelines (required)
|
|
70
73
|
|
|
71
74
|
| Area | Rule |
|
|
@@ -73,7 +76,7 @@ Also re-exported: \`Button\`, \`TimbalChat\`, \`ChartArtifactView\`, \`APP_KIT_A
|
|
|
73
76
|
| **Copilot** | Use \`AppCopilotProvider\` for page context (\`useAppCopilotContext\`). Copilot is a **floating overlay** via \`AppShell\` \`chat={<AppChatPanel />}\` \u2014 not a sidebar column that shrinks main content. |
|
|
74
77
|
| **Chat panel** | \`AppChatPanel\` only; \`Thread\` uses \`variant="panel"\` internally. Dismiss with **X**; trigger is a **text-only** pill (e.g. "Assistant") \u2014 **no** MessageSquare or chat icons on the shell trigger. |
|
|
75
78
|
| **Context** | Do not show raw JSON context in the panel header; keep context in \`AppCopilotProvider\` only. |
|
|
76
|
-
| **Theming** | Use semantic Tailwind tokens (\`bg-background\`, \`text-foreground\`, \`border-border\`, \`bg-elevated-from\`, etc.) from the host app's \`styles.css\`.
|
|
79
|
+
| **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\`. |
|
|
77
80
|
| **Layout chrome** | \`Page\` \u2192 \`Section\` for main content hierarchy. \`AppShellTopbar\` for global actions (auth, theme). |
|
|
78
81
|
| **Data** | Prefer \`DataTable\` with typed \`columns\` / \`rows\` / \`getRowKey\`; use \`ChartPanel\` with \`ChartArtifact\` for charts. |
|
|
79
82
|
| **Modals** | Use \`AppConfirmDialog\` for destructive/export confirmations. |
|
|
@@ -173,6 +176,7 @@ Studio chrome (\`StudioSidebar\`, \`ModeToggle\`, \u2026) lives in \`@timbal-ai/
|
|
|
173
176
|
| \`resource-gallery.tsx\` | \`ResourceCard\`, \`StatusDot\`, \`Sparkline\` |
|
|
174
177
|
| \`charts-panel.tsx\` | \`ChartPanel\`, \`ChartArtifact\` |
|
|
175
178
|
| \`copilot-overlay.tsx\` | \`AppShell\`, \`AppChatPanel\` |
|
|
179
|
+
| \`theme-presets.tsx\` | \`ThemePresetGallery\`, \`applyTimbalTheme\` |
|
|
176
180
|
|
|
177
181
|
### Typical compositions
|
|
178
182
|
|
|
@@ -218,6 +222,681 @@ import {
|
|
|
218
222
|
- For rich in-chat widgets, use **artifacts** (\`ARTIFACT_AGENT_INSTRUCTIONS\`) \u2014 app kit is for the **host application shell**.
|
|
219
223
|
`.trim();
|
|
220
224
|
|
|
225
|
+
// src/design/oklch.ts
|
|
226
|
+
var clamp = (n, min, max) => Math.min(max, Math.max(min, n));
|
|
227
|
+
var round = (n, digits) => {
|
|
228
|
+
const f = 10 ** digits;
|
|
229
|
+
return Math.round(n * f) / f;
|
|
230
|
+
};
|
|
231
|
+
function srgbToLinear(channel) {
|
|
232
|
+
const c = channel / 255;
|
|
233
|
+
return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
|
|
234
|
+
}
|
|
235
|
+
function linearRgbToOklch(r, g, b, alpha) {
|
|
236
|
+
const l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;
|
|
237
|
+
const m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b;
|
|
238
|
+
const s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b;
|
|
239
|
+
const l_ = Math.cbrt(l);
|
|
240
|
+
const m_ = Math.cbrt(m);
|
|
241
|
+
const s_ = Math.cbrt(s);
|
|
242
|
+
const labL = 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_;
|
|
243
|
+
const labA = 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_;
|
|
244
|
+
const labB = 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_;
|
|
245
|
+
const c = Math.sqrt(labA * labA + labB * labB);
|
|
246
|
+
let h = Math.atan2(labB, labA) * 180 / Math.PI;
|
|
247
|
+
if (h < 0) h += 360;
|
|
248
|
+
return { l: labL, c, h, alpha };
|
|
249
|
+
}
|
|
250
|
+
function oklchToLinearRgb(color) {
|
|
251
|
+
const hRad = color.h * Math.PI / 180;
|
|
252
|
+
const labA = color.c * Math.cos(hRad);
|
|
253
|
+
const labB = color.c * Math.sin(hRad);
|
|
254
|
+
const l_ = color.l + 0.3963377774 * labA + 0.2158037573 * labB;
|
|
255
|
+
const m_ = color.l - 0.1055613458 * labA - 0.0638541728 * labB;
|
|
256
|
+
const s_ = color.l - 0.0894841775 * labA - 1.291485548 * labB;
|
|
257
|
+
const l = l_ ** 3;
|
|
258
|
+
const m = m_ ** 3;
|
|
259
|
+
const s = s_ ** 3;
|
|
260
|
+
return {
|
|
261
|
+
r: 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
|
|
262
|
+
g: -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
|
|
263
|
+
b: -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
function parseHex(value) {
|
|
267
|
+
let hex = value.trim().replace(/^#/, "");
|
|
268
|
+
if (![3, 4, 6, 8].includes(hex.length)) return null;
|
|
269
|
+
if (hex.length === 3 || hex.length === 4) {
|
|
270
|
+
hex = hex.split("").map((ch) => ch + ch).join("");
|
|
271
|
+
}
|
|
272
|
+
const int = Number.parseInt(hex, 16);
|
|
273
|
+
if (Number.isNaN(int)) return null;
|
|
274
|
+
const hasAlpha = hex.length === 8;
|
|
275
|
+
const r = int >>> (hasAlpha ? 24 : 16) & 255;
|
|
276
|
+
const g = int >>> (hasAlpha ? 16 : 8) & 255;
|
|
277
|
+
const b = int >>> (hasAlpha ? 8 : 0) & 255;
|
|
278
|
+
const alpha = hasAlpha ? (int & 255) / 255 : 1;
|
|
279
|
+
return linearRgbToOklch(
|
|
280
|
+
srgbToLinear(r),
|
|
281
|
+
srgbToLinear(g),
|
|
282
|
+
srgbToLinear(b),
|
|
283
|
+
alpha
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
function parseRgb(value) {
|
|
287
|
+
const match = value.match(
|
|
288
|
+
/rgba?\(\s*([0-9.]+)[\s,]+([0-9.]+)[\s,]+([0-9.]+)(?:[\s,/]+([0-9.%]+))?\s*\)/i
|
|
289
|
+
);
|
|
290
|
+
if (!match) return null;
|
|
291
|
+
const r = Number.parseFloat(match[1]);
|
|
292
|
+
const g = Number.parseFloat(match[2]);
|
|
293
|
+
const b = Number.parseFloat(match[3]);
|
|
294
|
+
let alpha = 1;
|
|
295
|
+
if (match[4]) {
|
|
296
|
+
alpha = match[4].includes("%") ? Number.parseFloat(match[4]) / 100 : Number.parseFloat(match[4]);
|
|
297
|
+
}
|
|
298
|
+
if (![r, g, b].every(Number.isFinite)) return null;
|
|
299
|
+
return linearRgbToOklch(
|
|
300
|
+
srgbToLinear(r),
|
|
301
|
+
srgbToLinear(g),
|
|
302
|
+
srgbToLinear(b),
|
|
303
|
+
Number.isFinite(alpha) ? alpha : 1
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
function parseOklch(value) {
|
|
307
|
+
const match = value.match(
|
|
308
|
+
/oklch\(\s*([0-9.]+%?)\s+([0-9.]+%?)\s+([0-9.]+)(?:deg)?(?:\s*\/\s*([0-9.%]+))?\s*\)/i
|
|
309
|
+
);
|
|
310
|
+
if (!match) return null;
|
|
311
|
+
const l = match[1].includes("%") ? Number.parseFloat(match[1]) / 100 : Number.parseFloat(match[1]);
|
|
312
|
+
const c = match[2].includes("%") ? Number.parseFloat(match[2]) / 100 * 0.4 : Number.parseFloat(match[2]);
|
|
313
|
+
const h = Number.parseFloat(match[3]);
|
|
314
|
+
let alpha = 1;
|
|
315
|
+
if (match[4]) {
|
|
316
|
+
alpha = match[4].includes("%") ? Number.parseFloat(match[4]) / 100 : Number.parseFloat(match[4]);
|
|
317
|
+
}
|
|
318
|
+
if (![l, c, h].every(Number.isFinite)) return null;
|
|
319
|
+
return { l, c, h, alpha: Number.isFinite(alpha) ? alpha : 1 };
|
|
320
|
+
}
|
|
321
|
+
function parseColor(value) {
|
|
322
|
+
const parsed = parseOklch(value) ?? parseHex(value) ?? parseRgb(value);
|
|
323
|
+
if (!parsed) {
|
|
324
|
+
throw new Error(
|
|
325
|
+
`[@timbal-ai/timbal-react] Could not parse color "${value}". Use a hex (#1E40AF), rgb()/rgba(), or oklch() string.`
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
return parsed;
|
|
329
|
+
}
|
|
330
|
+
function lighten(color, delta) {
|
|
331
|
+
return { ...color, l: clamp(color.l + delta, 0, 1) };
|
|
332
|
+
}
|
|
333
|
+
function scaleChroma(color, factor) {
|
|
334
|
+
return { ...color, c: clamp(color.c * factor, 0, 0.4) };
|
|
335
|
+
}
|
|
336
|
+
function withAlpha(color, alpha) {
|
|
337
|
+
return { ...color, alpha: clamp(alpha, 0, 1) };
|
|
338
|
+
}
|
|
339
|
+
function oklchToString(color) {
|
|
340
|
+
const l = round(clamp(color.l, 0, 1), 4);
|
|
341
|
+
const c = round(clamp(color.c, 0, 0.4), 4);
|
|
342
|
+
const h = round((color.h % 360 + 360) % 360, 2);
|
|
343
|
+
const a = clamp(color.alpha, 0, 1);
|
|
344
|
+
const base = `oklch(${l} ${c} ${h}`;
|
|
345
|
+
return a >= 1 ? `${base})` : `${base} / ${round(a, 3)})`;
|
|
346
|
+
}
|
|
347
|
+
function readableForeground(bg, options) {
|
|
348
|
+
const threshold = options?.threshold ?? 0.62;
|
|
349
|
+
const lightText = options?.light ?? "oklch(0.985 0 0)";
|
|
350
|
+
const darkText = options?.dark ?? "oklch(0.205 0 0)";
|
|
351
|
+
return bg.l >= threshold ? darkText : lightText;
|
|
352
|
+
}
|
|
353
|
+
function relativeLuminance(color) {
|
|
354
|
+
const { r, g, b } = oklchToLinearRgb(color);
|
|
355
|
+
const lr = clamp(r, 0, 1);
|
|
356
|
+
const lg = clamp(g, 0, 1);
|
|
357
|
+
const lb = clamp(b, 0, 1);
|
|
358
|
+
return 0.2126 * lr + 0.7152 * lg + 0.0722 * lb;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// src/design/theme.ts
|
|
362
|
+
function primaryForMode(brand, mode) {
|
|
363
|
+
if (mode === "light") {
|
|
364
|
+
return { ...brand, l: Math.min(Math.max(brand.l, 0.42), 0.68) };
|
|
365
|
+
}
|
|
366
|
+
const lightened = lighten(brand, 0.06);
|
|
367
|
+
return {
|
|
368
|
+
...lightened,
|
|
369
|
+
l: Math.min(Math.max(lightened.l, 0.5), 0.78),
|
|
370
|
+
c: Math.min(brand.c, 0.22)
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
function brandGradient(primary) {
|
|
374
|
+
return {
|
|
375
|
+
from: lighten(primary, 0.03),
|
|
376
|
+
to: lighten(primary, -0.02),
|
|
377
|
+
hoverFrom: lighten(primary, 0.06),
|
|
378
|
+
hoverTo: lighten(primary, 0.01),
|
|
379
|
+
activeFrom: lighten(primary, -0.02),
|
|
380
|
+
activeTo: lighten(primary, -0.06)
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
function neutralTints(brand) {
|
|
384
|
+
return {
|
|
385
|
+
lightHue: brand.h,
|
|
386
|
+
darkHue: brand.h,
|
|
387
|
+
lightChroma: 6e-3,
|
|
388
|
+
darkChroma: 8e-3
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
function createTimbalTheme(intent) {
|
|
392
|
+
const brand = parseColor(intent.brand);
|
|
393
|
+
const accent = intent.accent ? parseColor(intent.accent) : null;
|
|
394
|
+
const light = {};
|
|
395
|
+
const dark = {};
|
|
396
|
+
const root = {};
|
|
397
|
+
if (typeof intent.radius === "number") {
|
|
398
|
+
root["--radius"] = `${intent.radius}rem`;
|
|
399
|
+
}
|
|
400
|
+
const primaryLight = primaryForMode(brand, "light");
|
|
401
|
+
const primaryDark = primaryForMode(brand, "dark");
|
|
402
|
+
light["--primary"] = oklchToString(primaryLight);
|
|
403
|
+
light["--primary-foreground"] = readableForeground(primaryLight);
|
|
404
|
+
light["--ring"] = oklchToString(
|
|
405
|
+
scaleChroma({ ...primaryLight, l: 0.6 }, 0.7)
|
|
406
|
+
);
|
|
407
|
+
dark["--primary"] = oklchToString(primaryDark);
|
|
408
|
+
dark["--primary-foreground"] = readableForeground(primaryDark);
|
|
409
|
+
dark["--ring"] = oklchToString(scaleChroma({ ...primaryDark, l: 0.62 }, 0.6));
|
|
410
|
+
const gLight = brandGradient(primaryLight);
|
|
411
|
+
light["--primary-fill-from"] = oklchToString(gLight.from);
|
|
412
|
+
light["--primary-fill-to"] = oklchToString(gLight.to);
|
|
413
|
+
light["--primary-fill-hover-from"] = oklchToString(gLight.hoverFrom);
|
|
414
|
+
light["--primary-fill-hover-to"] = oklchToString(gLight.hoverTo);
|
|
415
|
+
light["--primary-fill-active-from"] = oklchToString(gLight.activeFrom);
|
|
416
|
+
light["--primary-fill-active-to"] = oklchToString(gLight.activeTo);
|
|
417
|
+
const gDark = brandGradient(primaryDark);
|
|
418
|
+
dark["--primary-fill-from"] = oklchToString(gDark.from);
|
|
419
|
+
dark["--primary-fill-to"] = oklchToString(gDark.to);
|
|
420
|
+
dark["--primary-fill-hover-from"] = oklchToString(gDark.hoverFrom);
|
|
421
|
+
dark["--primary-fill-hover-to"] = oklchToString(gDark.hoverTo);
|
|
422
|
+
dark["--primary-fill-active-from"] = oklchToString(gDark.activeFrom);
|
|
423
|
+
dark["--primary-fill-active-to"] = oklchToString(gDark.activeTo);
|
|
424
|
+
if (accent) {
|
|
425
|
+
const accentLight = { ...accent, l: Math.min(Math.max(accent.l, 0.9), 0.97) };
|
|
426
|
+
const accentDark = { ...accent, l: 0.25, c: Math.min(accent.c, 0.04) };
|
|
427
|
+
light["--accent"] = oklchToString(accentLight);
|
|
428
|
+
light["--accent-foreground"] = readableForeground(accentLight);
|
|
429
|
+
dark["--accent"] = oklchToString(accentDark);
|
|
430
|
+
dark["--accent-foreground"] = readableForeground(accentDark);
|
|
431
|
+
}
|
|
432
|
+
light["--playground-from"] = oklchToString(
|
|
433
|
+
withAlpha({ l: 0.91, c: 0.03, h: brand.h, alpha: 0.6 }, 0.6)
|
|
434
|
+
);
|
|
435
|
+
light["--playground-via"] = oklchToString(
|
|
436
|
+
withAlpha({ l: 0.965, c: 0.015, h: brand.h, alpha: 0.3 }, 0.3)
|
|
437
|
+
);
|
|
438
|
+
dark["--playground-from"] = oklchToString({
|
|
439
|
+
l: 0.27,
|
|
440
|
+
c: 0.03,
|
|
441
|
+
h: brand.h,
|
|
442
|
+
alpha: 1
|
|
443
|
+
});
|
|
444
|
+
dark["--playground-via"] = oklchToString({
|
|
445
|
+
l: 0.19,
|
|
446
|
+
c: 0.02,
|
|
447
|
+
h: brand.h,
|
|
448
|
+
alpha: 1
|
|
449
|
+
});
|
|
450
|
+
if (intent.tintNeutrals) {
|
|
451
|
+
const t = neutralTints(brand);
|
|
452
|
+
light["--secondary"] = oklchToString({
|
|
453
|
+
l: 0.975,
|
|
454
|
+
c: t.lightChroma,
|
|
455
|
+
h: t.lightHue,
|
|
456
|
+
alpha: 1
|
|
457
|
+
});
|
|
458
|
+
light["--muted"] = light["--secondary"];
|
|
459
|
+
light["--accent"] ?? (light["--accent"] = oklchToString({
|
|
460
|
+
l: 0.965,
|
|
461
|
+
c: t.lightChroma,
|
|
462
|
+
h: t.lightHue,
|
|
463
|
+
alpha: 1
|
|
464
|
+
}));
|
|
465
|
+
light["--border"] = oklchToString({
|
|
466
|
+
l: 0.91,
|
|
467
|
+
c: t.lightChroma,
|
|
468
|
+
h: t.lightHue,
|
|
469
|
+
alpha: 1
|
|
470
|
+
});
|
|
471
|
+
dark["--secondary"] = oklchToString({
|
|
472
|
+
l: 0.22,
|
|
473
|
+
c: t.darkChroma,
|
|
474
|
+
h: t.darkHue,
|
|
475
|
+
alpha: 1
|
|
476
|
+
});
|
|
477
|
+
dark["--muted"] = dark["--secondary"];
|
|
478
|
+
dark["--border"] = oklchToString({
|
|
479
|
+
l: 1,
|
|
480
|
+
c: 0,
|
|
481
|
+
h: 0,
|
|
482
|
+
alpha: 0.1
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
if (isDev()) {
|
|
486
|
+
const lum = relativeLuminance(primaryLight);
|
|
487
|
+
const fgIsLight = light["--primary-foreground"].includes("0.985");
|
|
488
|
+
const fgLum = fgIsLight ? 1 : 0.05;
|
|
489
|
+
const ratio = (Math.max(lum, fgLum) + 0.05) / (Math.min(lum, fgLum) + 0.05);
|
|
490
|
+
if (ratio < 3.5) {
|
|
491
|
+
console.warn(
|
|
492
|
+
`[@timbal-ai/timbal-react] createTimbalTheme: brand "${intent.brand}" yields a low primary/foreground contrast (~${ratio.toFixed(2)}:1). Consider a darker or more saturated brand color for buttons/CTAs.`
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
return { light, dark, root };
|
|
497
|
+
}
|
|
498
|
+
function declarations(map, indent) {
|
|
499
|
+
return Object.entries(map).map(([name, value]) => `${indent}${name}: ${value};`).join("\n");
|
|
500
|
+
}
|
|
501
|
+
function themeToCss(theme, options = {}) {
|
|
502
|
+
const indent = options.indent ?? " ";
|
|
503
|
+
const blocks = [];
|
|
504
|
+
const lightVars = { ...theme.root ?? {}, ...theme.light };
|
|
505
|
+
if (options.scope) {
|
|
506
|
+
const sel = `[data-timbal-theme="${options.scope}"]`;
|
|
507
|
+
if (Object.keys(lightVars).length) {
|
|
508
|
+
blocks.push(`${sel} {
|
|
509
|
+
${declarations(lightVars, indent)}
|
|
510
|
+
}`);
|
|
511
|
+
}
|
|
512
|
+
if (Object.keys(theme.dark).length) {
|
|
513
|
+
blocks.push(
|
|
514
|
+
`.dark ${sel}, ${sel}.dark {
|
|
515
|
+
${declarations(theme.dark, indent)}
|
|
516
|
+
}`
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
} else {
|
|
520
|
+
if (Object.keys(lightVars).length) {
|
|
521
|
+
blocks.push(`:root {
|
|
522
|
+
${declarations(lightVars, indent)}
|
|
523
|
+
}`);
|
|
524
|
+
}
|
|
525
|
+
if (Object.keys(theme.dark).length) {
|
|
526
|
+
blocks.push(`.dark {
|
|
527
|
+
${declarations(theme.dark, indent)}
|
|
528
|
+
}`);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
return blocks.join("\n\n");
|
|
532
|
+
}
|
|
533
|
+
var RUNTIME_STYLE_ID = "timbal-theme-runtime";
|
|
534
|
+
function applyTimbalTheme(theme) {
|
|
535
|
+
if (typeof document === "undefined") return () => {
|
|
536
|
+
};
|
|
537
|
+
let el = document.getElementById(RUNTIME_STYLE_ID);
|
|
538
|
+
if (!el) {
|
|
539
|
+
el = document.createElement("style");
|
|
540
|
+
el.id = RUNTIME_STYLE_ID;
|
|
541
|
+
el.setAttribute("data-timbal-theme-runtime", "");
|
|
542
|
+
document.head.appendChild(el);
|
|
543
|
+
}
|
|
544
|
+
el.textContent = themeToCss(theme);
|
|
545
|
+
return () => {
|
|
546
|
+
el?.parentNode?.removeChild(el);
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
function clearTimbalTheme() {
|
|
550
|
+
if (typeof document === "undefined") return;
|
|
551
|
+
document.getElementById(RUNTIME_STYLE_ID)?.remove();
|
|
552
|
+
}
|
|
553
|
+
function isDev() {
|
|
554
|
+
if (typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
|
|
555
|
+
return false;
|
|
556
|
+
}
|
|
557
|
+
return true;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// src/design/theme-presets.ts
|
|
561
|
+
var EMPTY_TOKENS = { light: {}, dark: {}, root: {} };
|
|
562
|
+
var TIMBAL_THEME_PRESETS = [
|
|
563
|
+
{
|
|
564
|
+
id: "platform",
|
|
565
|
+
label: "Platform",
|
|
566
|
+
description: "Shipped neutral monochrome \u2014 the Timbal Platform default. Calm, brand-agnostic.",
|
|
567
|
+
swatch: "oklch(0.205 0 0)",
|
|
568
|
+
tokens: EMPTY_TOKENS
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
id: "indigo",
|
|
572
|
+
label: "Indigo",
|
|
573
|
+
description: "Cool, trustworthy blue-violet \u2014 good for analytics & ops dashboards.",
|
|
574
|
+
swatch: "#4f46e5",
|
|
575
|
+
tokens: createTimbalTheme({ brand: "#4f46e5" })
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
id: "violet",
|
|
579
|
+
label: "Violet",
|
|
580
|
+
description: "Vivid purple \u2014 expressive, product/marketing-leaning surfaces.",
|
|
581
|
+
swatch: "#7c3aed",
|
|
582
|
+
tokens: createTimbalTheme({ brand: "#7c3aed" })
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
id: "forest",
|
|
586
|
+
label: "Forest",
|
|
587
|
+
description: "Grounded green \u2014 finance, sustainability, status-positive apps.",
|
|
588
|
+
swatch: "#16a34a",
|
|
589
|
+
tokens: createTimbalTheme({ brand: "#16a34a" })
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
id: "warm",
|
|
593
|
+
label: "Warm",
|
|
594
|
+
description: "Energetic orange \u2014 consumer, creative, high-engagement tools.",
|
|
595
|
+
swatch: "#ea580c",
|
|
596
|
+
tokens: createTimbalTheme({ brand: "#ea580c" })
|
|
597
|
+
},
|
|
598
|
+
{
|
|
599
|
+
id: "slate",
|
|
600
|
+
label: "Slate",
|
|
601
|
+
description: "Muted cool gray-blue with a subtle tint \u2014 understated enterprise.",
|
|
602
|
+
swatch: "#475569",
|
|
603
|
+
tokens: createTimbalTheme({ brand: "#475569", tintNeutrals: true })
|
|
604
|
+
}
|
|
605
|
+
];
|
|
606
|
+
var PRESET_BY_ID = new Map(
|
|
607
|
+
TIMBAL_THEME_PRESETS.map((preset) => [preset.id, preset])
|
|
608
|
+
);
|
|
609
|
+
function getThemePreset(id) {
|
|
610
|
+
return PRESET_BY_ID.get(id);
|
|
611
|
+
}
|
|
612
|
+
function applyThemePreset(id) {
|
|
613
|
+
const preset = PRESET_BY_ID.get(id);
|
|
614
|
+
if (!preset) return () => {
|
|
615
|
+
};
|
|
616
|
+
if (typeof window !== "undefined") {
|
|
617
|
+
try {
|
|
618
|
+
window.localStorage.setItem(STORAGE_KEYS.themePreset, id);
|
|
619
|
+
} catch {
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
return applyTimbalTheme(preset.tokens);
|
|
623
|
+
}
|
|
624
|
+
function getStoredThemePreset() {
|
|
625
|
+
if (typeof window === "undefined") return null;
|
|
626
|
+
try {
|
|
627
|
+
const value = window.localStorage.getItem(STORAGE_KEYS.themePreset);
|
|
628
|
+
return value && PRESET_BY_ID.has(value) ? value : null;
|
|
629
|
+
} catch {
|
|
630
|
+
return null;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// src/design/theme-instructions.ts
|
|
635
|
+
var THEME_AGENT_INSTRUCTIONS = `
|
|
636
|
+
## Theming (@timbal-ai/timbal-react)
|
|
637
|
+
|
|
638
|
+
The package ships a complete light + dark token system (\`styles.css\`). Components are written against semantic Tailwind tokens (\`bg-background\`, \`text-primary\`, \`border-border\`, \`bg-elevated-from\`, \`bg-bubble-user\`, \u2026). To restyle, you change CSS variables \u2014 **never** hardcode colors in component code.
|
|
639
|
+
|
|
640
|
+
### Golden rule
|
|
641
|
+
|
|
642
|
+
**Never write \`oklch(...)\` / hex literals or hand-author paired \`:root\` + \`.dark\` blocks.** Express intent and let the package derive a complete, contrast-correct, paired palette.
|
|
643
|
+
|
|
644
|
+
### Pick a brand color (rebrand)
|
|
645
|
+
|
|
646
|
+
\`\`\`ts
|
|
647
|
+
import { createTimbalTheme, themeToCss } from "@timbal-ai/timbal-react";
|
|
648
|
+
|
|
649
|
+
const theme = createTimbalTheme({ brand: "#4f46e5" /* accent?, radius?, tintNeutrals? */ });
|
|
650
|
+
// Build-time: write once into your app CSS (paired light + dark, guaranteed in sync):
|
|
651
|
+
const css = themeToCss(theme);
|
|
652
|
+
\`\`\`
|
|
653
|
+
|
|
654
|
+
- For a real company, look up the actual brand hex first (brandfetch / "<company> brand color hex"), then pass it as \`brand\`.
|
|
655
|
+
- \`createTimbalTheme\` derives \`--primary\`, its foreground, ring, the full button gradient, and a soft playground tint. You only supply intent.
|
|
656
|
+
|
|
657
|
+
### Apply a theme
|
|
658
|
+
|
|
659
|
+
- **Build-time / SSR:** \`themeToCss(theme)\` \u2192 paste the returned CSS into your \`index.css\` (after the \`@import "@timbal-ai/timbal-react/styles.css"\`). One block, both modes.
|
|
660
|
+
- **Runtime / swappable:** \`applyTimbalTheme(theme)\` injects a managed \`<style>\` and returns a disposer. Works with the \`.dark\` toggle (next-themes / ModeToggle).
|
|
661
|
+
- **Component:** render \`<TimbalThemeStyle theme={theme} />\` (or \`preset="indigo"\`) once near the app root.
|
|
662
|
+
|
|
663
|
+
### Offer styles to the user ("show compatible styles, then apply")
|
|
664
|
+
|
|
665
|
+
Use the closed preset catalog \u2014 do not invent options:
|
|
666
|
+
|
|
667
|
+
\`\`\`ts
|
|
668
|
+
import { TIMBAL_THEME_PRESETS, applyThemePreset } from "@timbal-ai/timbal-react";
|
|
669
|
+
// TIMBAL_THEME_PRESETS: { id, label, description, swatch, tokens }[]
|
|
670
|
+
\`\`\`
|
|
671
|
+
|
|
672
|
+
| Preset id | Use when |
|
|
673
|
+
|-----------|----------|
|
|
674
|
+
| \`platform\` | Neutral monochrome default (no brand) |
|
|
675
|
+
| \`indigo\` | Cool, trustworthy \u2014 analytics / ops dashboards |
|
|
676
|
+
| \`violet\` | Expressive purple \u2014 product / marketing |
|
|
677
|
+
| \`forest\` | Green \u2014 finance, sustainability, positive status |
|
|
678
|
+
| \`warm\` | Orange \u2014 consumer / creative / high-engagement |
|
|
679
|
+
| \`slate\` | Muted enterprise gray-blue (tinted neutrals) |
|
|
680
|
+
|
|
681
|
+
- To present options visually, render \`<ThemePresetGallery value={id} onSelect={setId} />\` \u2014 each swatch previews real components (Button + metric tile) scoped via \`data-timbal-theme\`, so the live app doesn't change until the user picks.
|
|
682
|
+
- On selection, call \`applyThemePreset(id)\` (persists to \`localStorage\` and restores on reload).
|
|
683
|
+
|
|
684
|
+
### Rules
|
|
685
|
+
|
|
686
|
+
- Generated pages use **semantic Tailwind tokens only** \u2014 never literal colors or per-element \`style={{ color }}\`.
|
|
687
|
+
- Light/dark mode stays the \`.dark\` class (\`next-themes attribute="class"\` or \`ModeToggle\`). Presets are **brand**, not a second dark-mode system.
|
|
688
|
+
- Override individual tokens only for one-offs the generator doesn't cover; if you must, set the variable in **both** \`:root\` and \`.dark\` (a dev-only warning fires otherwise).
|
|
689
|
+
`.trim();
|
|
690
|
+
|
|
691
|
+
// src/app/theme/TimbalThemeStyle.tsx
|
|
692
|
+
import { jsx } from "react/jsx-runtime";
|
|
693
|
+
var TimbalThemeStyle = ({
|
|
694
|
+
theme,
|
|
695
|
+
preset,
|
|
696
|
+
scope,
|
|
697
|
+
nonce
|
|
698
|
+
}) => {
|
|
699
|
+
const tokens = theme ?? (preset ? getThemePreset(preset)?.tokens : void 0);
|
|
700
|
+
if (!tokens) return null;
|
|
701
|
+
const css = themeToCss(tokens, scope ? { scope } : void 0);
|
|
702
|
+
if (!css) return null;
|
|
703
|
+
return /* @__PURE__ */ jsx(
|
|
704
|
+
"style",
|
|
705
|
+
{
|
|
706
|
+
"data-timbal-theme-style": scope ?? "root",
|
|
707
|
+
nonce,
|
|
708
|
+
dangerouslySetInnerHTML: { __html: css }
|
|
709
|
+
}
|
|
710
|
+
);
|
|
711
|
+
};
|
|
712
|
+
|
|
713
|
+
// src/app/data/metrics-shared.tsx
|
|
714
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
715
|
+
var metricCardShellClass = cn(
|
|
716
|
+
studioIntegrationCardClass,
|
|
717
|
+
"aui-app-metric-card shadow-none",
|
|
718
|
+
"flex flex-col overflow-hidden"
|
|
719
|
+
);
|
|
720
|
+
var metricCardHeaderClass = "flex items-start justify-between gap-3 px-4 pb-1 pt-3";
|
|
721
|
+
var metricTilesRowClass = "grid w-full min-w-0";
|
|
722
|
+
var metricChartRegionClass = "relative min-h-0 w-full border-t border-border/40 pt-2";
|
|
723
|
+
var metricChartPlotRegionClass = "relative min-h-0 w-full border-t border-border/40 px-0 pt-5 pb-3";
|
|
724
|
+
var metricCellDividerClass = "border-r border-border/40";
|
|
725
|
+
var MetricCardHeader = ({
|
|
726
|
+
title,
|
|
727
|
+
titleId,
|
|
728
|
+
description,
|
|
729
|
+
actions
|
|
730
|
+
}) => {
|
|
731
|
+
if (!title && !description && !actions) return null;
|
|
732
|
+
return /* @__PURE__ */ jsxs("header", { className: metricCardHeaderClass, children: [
|
|
733
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
734
|
+
title ? /* @__PURE__ */ jsx2("h3", { id: titleId, className: "text-base font-normal text-foreground", children: title }) : null,
|
|
735
|
+
description ? /* @__PURE__ */ jsx2("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
|
|
736
|
+
] }),
|
|
737
|
+
actions ? /* @__PURE__ */ jsx2("div", { className: "shrink-0", children: actions }) : null
|
|
738
|
+
] });
|
|
739
|
+
};
|
|
740
|
+
function metricTilesGridColsClass(n) {
|
|
741
|
+
switch (n) {
|
|
742
|
+
case 1:
|
|
743
|
+
return "grid-cols-1";
|
|
744
|
+
case 2:
|
|
745
|
+
return "grid-cols-2";
|
|
746
|
+
case 3:
|
|
747
|
+
return "grid-cols-3";
|
|
748
|
+
case 5:
|
|
749
|
+
return "grid-cols-2 sm:grid-cols-5";
|
|
750
|
+
case 6:
|
|
751
|
+
return "grid-cols-2 sm:grid-cols-3 lg:grid-cols-6";
|
|
752
|
+
default:
|
|
753
|
+
return "grid-cols-2 md:grid-cols-4";
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// src/app/data/MetricTile.tsx
|
|
758
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
759
|
+
var trendToneClass = {
|
|
760
|
+
up: "border-border/80 bg-muted/40 text-muted-foreground",
|
|
761
|
+
down: "border-border/80 bg-muted/40 text-muted-foreground",
|
|
762
|
+
neutral: "border-border/80 bg-muted/30 text-muted-foreground"
|
|
763
|
+
};
|
|
764
|
+
var metricTileBaseClass = "relative flex min-w-0 flex-1 flex-col gap-1 px-4 py-3 text-left font-normal";
|
|
765
|
+
var metricTileInteractiveClass = cn(
|
|
766
|
+
metricTileBaseClass,
|
|
767
|
+
"bg-transparent hover:bg-transparent active:bg-transparent",
|
|
768
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-foreground/10"
|
|
769
|
+
);
|
|
770
|
+
var MetricTile = ({
|
|
771
|
+
label,
|
|
772
|
+
value,
|
|
773
|
+
unit,
|
|
774
|
+
trend,
|
|
775
|
+
trendTone = "neutral",
|
|
776
|
+
active = false,
|
|
777
|
+
showDivider = false,
|
|
778
|
+
onSelect,
|
|
779
|
+
ariaLabel,
|
|
780
|
+
className
|
|
781
|
+
}) => {
|
|
782
|
+
const content = /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
783
|
+
active ? /* @__PURE__ */ jsx3(
|
|
784
|
+
"span",
|
|
785
|
+
{
|
|
786
|
+
"aria-hidden": true,
|
|
787
|
+
className: "absolute inset-x-0 bottom-0 h-0.5 bg-foreground dark:bg-white"
|
|
788
|
+
}
|
|
789
|
+
) : null,
|
|
790
|
+
/* @__PURE__ */ jsx3("span", { className: "text-xs font-normal text-muted-foreground", children: label }),
|
|
791
|
+
/* @__PURE__ */ jsxs2("span", { className: "flex items-center gap-2", children: [
|
|
792
|
+
/* @__PURE__ */ jsxs2("span", { className: "flex items-baseline gap-1", children: [
|
|
793
|
+
/* @__PURE__ */ jsx3("span", { className: "text-2xl font-normal tracking-tight text-foreground tabular-nums", children: value }),
|
|
794
|
+
unit ? /* @__PURE__ */ jsx3("span", { className: "text-xs font-normal text-muted-foreground", children: unit }) : null
|
|
795
|
+
] }),
|
|
796
|
+
trend ? /* @__PURE__ */ jsx3(
|
|
797
|
+
"span",
|
|
798
|
+
{
|
|
799
|
+
className: cn(
|
|
800
|
+
"rounded-full border px-1.5 py-0.5 text-xs font-normal",
|
|
801
|
+
trendToneClass[trendTone]
|
|
802
|
+
),
|
|
803
|
+
children: trend
|
|
804
|
+
}
|
|
805
|
+
) : null
|
|
806
|
+
] })
|
|
807
|
+
] });
|
|
808
|
+
const divider = showDivider ? metricCellDividerClass : void 0;
|
|
809
|
+
if (onSelect) {
|
|
810
|
+
return /* @__PURE__ */ jsx3(
|
|
811
|
+
"button",
|
|
812
|
+
{
|
|
813
|
+
type: "button",
|
|
814
|
+
onClick: onSelect,
|
|
815
|
+
"aria-pressed": active,
|
|
816
|
+
"aria-label": ariaLabel,
|
|
817
|
+
className: cn(metricTileInteractiveClass, divider, className),
|
|
818
|
+
children: content
|
|
819
|
+
}
|
|
820
|
+
);
|
|
821
|
+
}
|
|
822
|
+
return /* @__PURE__ */ jsx3("div", { className: cn(metricTileBaseClass, divider, className), children: content });
|
|
823
|
+
};
|
|
824
|
+
|
|
825
|
+
// src/app/theme/ThemePresetGallery.tsx
|
|
826
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
827
|
+
var ThemePresetGallery = ({
|
|
828
|
+
value,
|
|
829
|
+
onSelect,
|
|
830
|
+
presets,
|
|
831
|
+
className
|
|
832
|
+
}) => {
|
|
833
|
+
const items = presets ? TIMBAL_THEME_PRESETS.filter((p) => presets.includes(p.id)) : TIMBAL_THEME_PRESETS;
|
|
834
|
+
return /* @__PURE__ */ jsx4(
|
|
835
|
+
"div",
|
|
836
|
+
{
|
|
837
|
+
role: "radiogroup",
|
|
838
|
+
"aria-label": "Theme presets",
|
|
839
|
+
className: cn(
|
|
840
|
+
"grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3",
|
|
841
|
+
className
|
|
842
|
+
),
|
|
843
|
+
children: items.map((preset) => {
|
|
844
|
+
const selected = value === preset.id;
|
|
845
|
+
return /* @__PURE__ */ jsxs3("div", { "data-timbal-theme": preset.id, children: [
|
|
846
|
+
/* @__PURE__ */ jsx4(TimbalThemeStyle, { preset: preset.id, scope: preset.id }),
|
|
847
|
+
/* @__PURE__ */ jsxs3(
|
|
848
|
+
"button",
|
|
849
|
+
{
|
|
850
|
+
type: "button",
|
|
851
|
+
role: "radio",
|
|
852
|
+
"aria-checked": selected,
|
|
853
|
+
"aria-label": `${preset.label} theme`,
|
|
854
|
+
onClick: () => onSelect?.(preset.id),
|
|
855
|
+
className: cn(
|
|
856
|
+
"group flex w-full flex-col gap-3 rounded-xl border bg-card p-3 text-left transition-colors",
|
|
857
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
858
|
+
selected ? "border-primary ring-2 ring-primary/30" : "border-border hover:border-foreground/30"
|
|
859
|
+
),
|
|
860
|
+
children: [
|
|
861
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between gap-2", children: [
|
|
862
|
+
/* @__PURE__ */ jsxs3("span", { className: "flex items-center gap-2", children: [
|
|
863
|
+
/* @__PURE__ */ jsx4(
|
|
864
|
+
"span",
|
|
865
|
+
{
|
|
866
|
+
"aria-hidden": true,
|
|
867
|
+
className: "size-4 shrink-0 rounded-full ring-1 ring-black/10",
|
|
868
|
+
style: { background: preset.swatch }
|
|
869
|
+
}
|
|
870
|
+
),
|
|
871
|
+
/* @__PURE__ */ jsx4("span", { className: "text-sm font-medium text-foreground", children: preset.label })
|
|
872
|
+
] }),
|
|
873
|
+
selected ? /* @__PURE__ */ jsx4("span", { className: "text-xs font-medium text-primary", children: "Selected" }) : null
|
|
874
|
+
] }),
|
|
875
|
+
/* @__PURE__ */ jsx4("p", { className: "text-xs leading-snug text-muted-foreground", children: preset.description }),
|
|
876
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-2 rounded-lg border border-border bg-background p-2", children: [
|
|
877
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
|
|
878
|
+
/* @__PURE__ */ jsx4(Button, { size: "xs", className: "pointer-events-none", children: "Primary" }),
|
|
879
|
+
/* @__PURE__ */ jsx4("span", { className: "size-5 rounded-md bg-primary", "aria-hidden": true }),
|
|
880
|
+
/* @__PURE__ */ jsx4("span", { className: "size-5 rounded-md bg-muted", "aria-hidden": true }),
|
|
881
|
+
/* @__PURE__ */ jsx4(
|
|
882
|
+
"span",
|
|
883
|
+
{
|
|
884
|
+
className: "size-5 rounded-md border border-border bg-accent",
|
|
885
|
+
"aria-hidden": true
|
|
886
|
+
}
|
|
887
|
+
)
|
|
888
|
+
] }),
|
|
889
|
+
/* @__PURE__ */ jsx4(MetricTile, { label: "Active users", value: "1,248", trend: "+8%" })
|
|
890
|
+
] })
|
|
891
|
+
]
|
|
892
|
+
}
|
|
893
|
+
)
|
|
894
|
+
] }, preset.id);
|
|
895
|
+
})
|
|
896
|
+
}
|
|
897
|
+
);
|
|
898
|
+
};
|
|
899
|
+
|
|
221
900
|
// src/design/app-classes.ts
|
|
222
901
|
var appPageColumnClass = "mx-auto w-full max-w-6xl px-4 md:px-6";
|
|
223
902
|
var appShellTopbarInsetClass = "w-full px-4 md:px-6";
|
|
@@ -282,7 +961,7 @@ function useAppShellChat() {
|
|
|
282
961
|
// src/app/layout/AppShell.tsx
|
|
283
962
|
import { motion, useReducedMotion } from "motion/react";
|
|
284
963
|
import { useCallback, useState } from "react";
|
|
285
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
964
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
286
965
|
var floatingTriggerClass = cn(
|
|
287
966
|
"aui-app-shell-chat-trigger-fixed fixed z-50 rounded-full px-5 py-2.5 text-sm font-medium shadow-card-elevated",
|
|
288
967
|
"bg-primary text-primary-foreground transition-colors hover:bg-primary/90",
|
|
@@ -311,14 +990,14 @@ var AppShellBody = ({
|
|
|
311
990
|
layoutDirection
|
|
312
991
|
);
|
|
313
992
|
const insetPadding = sidebar ? insetPaddingPx : 0;
|
|
314
|
-
return /* @__PURE__ */
|
|
993
|
+
return /* @__PURE__ */ jsx5(
|
|
315
994
|
motion.div,
|
|
316
995
|
{
|
|
317
996
|
className: "aui-app-shell-body relative z-10 flex min-h-0 min-w-0 flex-1 flex-col",
|
|
318
997
|
initial: false,
|
|
319
998
|
animate: { paddingLeft: insetPadding },
|
|
320
999
|
transition: layoutTransition,
|
|
321
|
-
children: /* @__PURE__ */
|
|
1000
|
+
children: /* @__PURE__ */ jsxs4(
|
|
322
1001
|
"div",
|
|
323
1002
|
{
|
|
324
1003
|
className: cn(
|
|
@@ -326,8 +1005,8 @@ var AppShellBody = ({
|
|
|
326
1005
|
!topbarContent && appShellInsetTopClass
|
|
327
1006
|
),
|
|
328
1007
|
children: [
|
|
329
|
-
topbarContent ? /* @__PURE__ */
|
|
330
|
-
/* @__PURE__ */
|
|
1008
|
+
topbarContent ? /* @__PURE__ */ jsx5("header", { className: cn("aui-app-shell-topbar-region", appShellTopbarStickyClass), children: /* @__PURE__ */ jsx5("div", { className: appShellTopbarInsetClass, children: topbarContent }) }) : null,
|
|
1009
|
+
/* @__PURE__ */ jsx5("main", { className: cn("aui-app-shell-main min-w-0 flex-1", mainClassName), children })
|
|
331
1010
|
]
|
|
332
1011
|
}
|
|
333
1012
|
)
|
|
@@ -375,7 +1054,7 @@ var AppShell = ({
|
|
|
375
1054
|
setInsetPaddingPx(insetPx);
|
|
376
1055
|
}, []);
|
|
377
1056
|
const insetExpanded = insetPaddingPx >= SIDEBAR_INSET_PX_EXPANDED;
|
|
378
|
-
const shellBody = /* @__PURE__ */
|
|
1057
|
+
const shellBody = /* @__PURE__ */ jsx5(
|
|
379
1058
|
AppShellBody,
|
|
380
1059
|
{
|
|
381
1060
|
sidebar,
|
|
@@ -386,7 +1065,7 @@ var AppShell = ({
|
|
|
386
1065
|
children
|
|
387
1066
|
}
|
|
388
1067
|
);
|
|
389
|
-
const tree = /* @__PURE__ */
|
|
1068
|
+
const tree = /* @__PURE__ */ jsx5(ShellInsetProvider, { value: sidebar ? reportShellInset : null, children: /* @__PURE__ */ jsxs4(
|
|
390
1069
|
"div",
|
|
391
1070
|
{
|
|
392
1071
|
className: cn(
|
|
@@ -397,7 +1076,7 @@ var AppShell = ({
|
|
|
397
1076
|
children: [
|
|
398
1077
|
sidebar,
|
|
399
1078
|
shellBody,
|
|
400
|
-
hasChat && chatOpen ? /* @__PURE__ */
|
|
1079
|
+
hasChat && chatOpen ? /* @__PURE__ */ jsx5(
|
|
401
1080
|
"div",
|
|
402
1081
|
{
|
|
403
1082
|
className: floatingPanelClass,
|
|
@@ -410,7 +1089,7 @@ var AppShell = ({
|
|
|
410
1089
|
children: chat
|
|
411
1090
|
}
|
|
412
1091
|
) : null,
|
|
413
|
-
hasChat && chatCollapsible && !chatOpen && !hideChatTrigger ? /* @__PURE__ */
|
|
1092
|
+
hasChat && chatCollapsible && !chatOpen && !hideChatTrigger ? /* @__PURE__ */ jsx5(
|
|
414
1093
|
"button",
|
|
415
1094
|
{
|
|
416
1095
|
type: "button",
|
|
@@ -426,7 +1105,7 @@ var AppShell = ({
|
|
|
426
1105
|
if (!hasChat) {
|
|
427
1106
|
return tree;
|
|
428
1107
|
}
|
|
429
|
-
return /* @__PURE__ */
|
|
1108
|
+
return /* @__PURE__ */ jsx5(
|
|
430
1109
|
AppShellChatProvider,
|
|
431
1110
|
{
|
|
432
1111
|
value: {
|
|
@@ -441,24 +1120,24 @@ var AppShell = ({
|
|
|
441
1120
|
};
|
|
442
1121
|
|
|
443
1122
|
// src/app/layout/AppShellTopbar.tsx
|
|
444
|
-
import { jsx as
|
|
1123
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
445
1124
|
var AppShellTopbar = ({
|
|
446
1125
|
start,
|
|
447
1126
|
actions,
|
|
448
1127
|
children,
|
|
449
1128
|
className
|
|
450
1129
|
}) => {
|
|
451
|
-
return /* @__PURE__ */
|
|
452
|
-
/* @__PURE__ */
|
|
1130
|
+
return /* @__PURE__ */ jsxs5("div", { className: cn("aui-app-shell-topbar", appShellTopbarRowClass, className), children: [
|
|
1131
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
|
|
453
1132
|
start,
|
|
454
1133
|
children
|
|
455
1134
|
] }),
|
|
456
|
-
actions ? /* @__PURE__ */
|
|
1135
|
+
actions ? /* @__PURE__ */ jsx6("div", { className: "aui-app-shell-topbar-actions flex shrink-0 items-center gap-2", children: actions }) : null
|
|
457
1136
|
] });
|
|
458
1137
|
};
|
|
459
1138
|
|
|
460
1139
|
// src/app/layout/AppShellChatTrigger.tsx
|
|
461
|
-
import { jsx as
|
|
1140
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
462
1141
|
var floatingPositionClass = "fixed bottom-6 right-6 z-50 max-sm:bottom-4 max-sm:right-4";
|
|
463
1142
|
var AppShellChatTrigger = ({
|
|
464
1143
|
className,
|
|
@@ -467,7 +1146,7 @@ var AppShellChatTrigger = ({
|
|
|
467
1146
|
}) => {
|
|
468
1147
|
const shellChat = useAppShellChat();
|
|
469
1148
|
if (!shellChat || shellChat.open) return null;
|
|
470
|
-
return /* @__PURE__ */
|
|
1149
|
+
return /* @__PURE__ */ jsx7(
|
|
471
1150
|
TimbalV2Button,
|
|
472
1151
|
{
|
|
473
1152
|
type: "button",
|
|
@@ -487,61 +1166,61 @@ var AppShellChatTrigger = ({
|
|
|
487
1166
|
};
|
|
488
1167
|
|
|
489
1168
|
// src/app/layout/PageHeader.tsx
|
|
490
|
-
import { jsx as
|
|
1169
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
491
1170
|
var PageHeader = ({
|
|
492
1171
|
title,
|
|
493
1172
|
description,
|
|
494
1173
|
actions,
|
|
495
1174
|
className
|
|
496
1175
|
}) => {
|
|
497
|
-
return /* @__PURE__ */
|
|
498
|
-
/* @__PURE__ */
|
|
499
|
-
/* @__PURE__ */
|
|
500
|
-
description ? /* @__PURE__ */
|
|
1176
|
+
return /* @__PURE__ */ jsxs6("header", { className: cn("aui-app-page-header", appPageHeaderClass, className), children: [
|
|
1177
|
+
/* @__PURE__ */ jsxs6("div", { className: "min-w-0", children: [
|
|
1178
|
+
/* @__PURE__ */ jsx8("h1", { className: "text-2xl font-semibold tracking-tight text-foreground", children: title }),
|
|
1179
|
+
description ? /* @__PURE__ */ jsx8("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null
|
|
501
1180
|
] }),
|
|
502
|
-
actions ? /* @__PURE__ */
|
|
1181
|
+
actions ? /* @__PURE__ */ jsx8("div", { className: "aui-app-page-header-actions flex shrink-0 flex-wrap items-center gap-2", children: actions }) : null
|
|
503
1182
|
] });
|
|
504
1183
|
};
|
|
505
1184
|
|
|
506
1185
|
// src/app/layout/Page.tsx
|
|
507
|
-
import { jsx as
|
|
1186
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
508
1187
|
var Page = ({
|
|
509
1188
|
children,
|
|
510
1189
|
breadcrumbs,
|
|
511
1190
|
className,
|
|
512
1191
|
...headerProps
|
|
513
1192
|
}) => {
|
|
514
|
-
return /* @__PURE__ */
|
|
1193
|
+
return /* @__PURE__ */ jsxs7("div", { className: cn("aui-app-page", appPageColumnClass, className), children: [
|
|
515
1194
|
breadcrumbs,
|
|
516
|
-
/* @__PURE__ */
|
|
1195
|
+
/* @__PURE__ */ jsx9(PageHeader, { ...headerProps }),
|
|
517
1196
|
children
|
|
518
1197
|
] });
|
|
519
1198
|
};
|
|
520
1199
|
|
|
521
1200
|
// src/app/layout/Section.tsx
|
|
522
|
-
import { jsx as
|
|
1201
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
523
1202
|
var Section = ({
|
|
524
1203
|
title,
|
|
525
1204
|
description,
|
|
526
1205
|
children,
|
|
527
1206
|
className
|
|
528
1207
|
}) => {
|
|
529
|
-
return /* @__PURE__ */
|
|
530
|
-
title ? /* @__PURE__ */
|
|
531
|
-
description ? /* @__PURE__ */
|
|
1208
|
+
return /* @__PURE__ */ jsxs8("section", { className: cn("aui-app-section", appSectionClass, className), children: [
|
|
1209
|
+
title ? /* @__PURE__ */ jsx10("h2", { className: appSectionTitleClass, children: title }) : null,
|
|
1210
|
+
description ? /* @__PURE__ */ jsx10("p", { className: appSectionDescriptionClass, children: description }) : null,
|
|
532
1211
|
children
|
|
533
1212
|
] });
|
|
534
1213
|
};
|
|
535
1214
|
|
|
536
1215
|
// src/app/copilot/app-copilot-context.tsx
|
|
537
1216
|
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
538
|
-
import { jsx as
|
|
1217
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
539
1218
|
var AppCopilotContext = createContext2(null);
|
|
540
1219
|
var AppCopilotProvider = ({
|
|
541
1220
|
value,
|
|
542
1221
|
children
|
|
543
1222
|
}) => {
|
|
544
|
-
return /* @__PURE__ */
|
|
1223
|
+
return /* @__PURE__ */ jsx11(AppCopilotContext.Provider, { value, children });
|
|
545
1224
|
};
|
|
546
1225
|
function useAppCopilotContext() {
|
|
547
1226
|
return useContext2(AppCopilotContext) ?? {};
|
|
@@ -549,7 +1228,7 @@ function useAppCopilotContext() {
|
|
|
549
1228
|
|
|
550
1229
|
// src/app/chat/AppChatPanel.tsx
|
|
551
1230
|
import { XIcon } from "lucide-react";
|
|
552
|
-
import { jsx as
|
|
1231
|
+
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
553
1232
|
var shellClass = "aui-app-chat-panel flex h-full min-h-0 flex-col overflow-hidden";
|
|
554
1233
|
var chromeClass = cn(
|
|
555
1234
|
"aui-app-chat-panel-chrome relative z-20 flex min-h-10 shrink-0 items-center justify-end px-2 pt-2"
|
|
@@ -594,18 +1273,18 @@ var AppChatPanel = ({
|
|
|
594
1273
|
...rest
|
|
595
1274
|
}) => {
|
|
596
1275
|
const shellChat = useAppShellChat();
|
|
597
|
-
return /* @__PURE__ */
|
|
598
|
-
shellChat?.collapsible ? /* @__PURE__ */
|
|
1276
|
+
return /* @__PURE__ */ jsxs9("div", { className: cn(shellClass, className), children: [
|
|
1277
|
+
shellChat?.collapsible ? /* @__PURE__ */ jsx12("div", { className: chromeClass, children: /* @__PURE__ */ jsx12(
|
|
599
1278
|
"button",
|
|
600
1279
|
{
|
|
601
1280
|
type: "button",
|
|
602
1281
|
className: closeButtonClass,
|
|
603
1282
|
onClick: () => shellChat.setOpen(false),
|
|
604
1283
|
"aria-label": "Close assistant",
|
|
605
|
-
children: /* @__PURE__ */
|
|
1284
|
+
children: /* @__PURE__ */ jsx12(XIcon, { className: "size-4", "aria-hidden": true })
|
|
606
1285
|
}
|
|
607
1286
|
) }) : null,
|
|
608
|
-
/* @__PURE__ */
|
|
1287
|
+
/* @__PURE__ */ jsx12("div", { className: bodyClass, children: /* @__PURE__ */ jsx12(
|
|
609
1288
|
TimbalRuntimeProvider,
|
|
610
1289
|
{
|
|
611
1290
|
workforceId,
|
|
@@ -615,7 +1294,7 @@ var AppChatPanel = ({
|
|
|
615
1294
|
attachmentsUploadUrl,
|
|
616
1295
|
attachmentsAccept,
|
|
617
1296
|
debug,
|
|
618
|
-
children: /* @__PURE__ */
|
|
1297
|
+
children: /* @__PURE__ */ jsx12(
|
|
619
1298
|
Thread,
|
|
620
1299
|
{
|
|
621
1300
|
variant: "panel",
|
|
@@ -636,38 +1315,38 @@ var AppChatPanel = ({
|
|
|
636
1315
|
};
|
|
637
1316
|
|
|
638
1317
|
// src/app/surfaces/SurfaceCard.tsx
|
|
639
|
-
import { jsx as
|
|
1318
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
640
1319
|
var SurfaceCard = ({ children, className }) => {
|
|
641
|
-
return /* @__PURE__ */
|
|
1320
|
+
return /* @__PURE__ */ jsx13("div", { className: cn("aui-app-surface-card", appSurfaceCardClass, className), children });
|
|
642
1321
|
};
|
|
643
1322
|
|
|
644
1323
|
// src/app/surfaces/StatTile.tsx
|
|
645
|
-
import { jsx as
|
|
1324
|
+
import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
646
1325
|
var StatTile = ({ label, value, hint, className }) => {
|
|
647
|
-
return /* @__PURE__ */
|
|
648
|
-
/* @__PURE__ */
|
|
649
|
-
/* @__PURE__ */
|
|
650
|
-
hint ? /* @__PURE__ */
|
|
1326
|
+
return /* @__PURE__ */ jsxs10("div", { className: cn("aui-app-stat-tile", appStatTileClass, className), children: [
|
|
1327
|
+
/* @__PURE__ */ jsx14("span", { className: appStatLabelClass, children: label }),
|
|
1328
|
+
/* @__PURE__ */ jsx14("span", { className: appStatValueClass, children: value }),
|
|
1329
|
+
hint ? /* @__PURE__ */ jsx14("span", { className: "text-xs text-muted-foreground", children: hint }) : null
|
|
651
1330
|
] });
|
|
652
1331
|
};
|
|
653
1332
|
|
|
654
1333
|
// src/app/surfaces/EmptyState.tsx
|
|
655
|
-
import { jsx as
|
|
1334
|
+
import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
656
1335
|
var EmptyState = ({
|
|
657
1336
|
title,
|
|
658
1337
|
description,
|
|
659
1338
|
action,
|
|
660
1339
|
className
|
|
661
1340
|
}) => {
|
|
662
|
-
return /* @__PURE__ */
|
|
663
|
-
/* @__PURE__ */
|
|
664
|
-
description ? /* @__PURE__ */
|
|
1341
|
+
return /* @__PURE__ */ jsxs11("div", { className: cn("aui-app-empty-state", appEmptyStateClass, className), children: [
|
|
1342
|
+
/* @__PURE__ */ jsx15("p", { className: appEmptyStateTitleClass, children: title }),
|
|
1343
|
+
description ? /* @__PURE__ */ jsx15("p", { className: appEmptyStateDescriptionClass, children: description }) : null,
|
|
665
1344
|
action
|
|
666
1345
|
] });
|
|
667
1346
|
};
|
|
668
1347
|
|
|
669
1348
|
// src/app/surfaces/StatusBadge.tsx
|
|
670
|
-
import { jsx as
|
|
1349
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
671
1350
|
var statusBadgeToneClass = {
|
|
672
1351
|
default: "bg-muted text-foreground",
|
|
673
1352
|
primary: "bg-primary/10 text-primary",
|
|
@@ -680,7 +1359,7 @@ var StatusBadge = ({
|
|
|
680
1359
|
tone = "default",
|
|
681
1360
|
className
|
|
682
1361
|
}) => {
|
|
683
|
-
return /* @__PURE__ */
|
|
1362
|
+
return /* @__PURE__ */ jsx16(
|
|
684
1363
|
"span",
|
|
685
1364
|
{
|
|
686
1365
|
className: cn(
|
|
@@ -694,7 +1373,7 @@ var StatusBadge = ({
|
|
|
694
1373
|
};
|
|
695
1374
|
|
|
696
1375
|
// src/app/surfaces/AppConfirmDialog.tsx
|
|
697
|
-
import { jsx as
|
|
1376
|
+
import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
698
1377
|
var bodyClass2 = "flex flex-col gap-4 p-6";
|
|
699
1378
|
var titleClass = "pr-8";
|
|
700
1379
|
var actionsClass = "flex flex-wrap justify-end gap-2";
|
|
@@ -709,15 +1388,15 @@ var AppConfirmDialog = ({
|
|
|
709
1388
|
destructive = false,
|
|
710
1389
|
className
|
|
711
1390
|
}) => {
|
|
712
|
-
return /* @__PURE__ */
|
|
1391
|
+
return /* @__PURE__ */ jsx17(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsx17(
|
|
713
1392
|
DialogContent,
|
|
714
1393
|
{
|
|
715
1394
|
className: cn("gap-0 p-0 sm:max-w-md", className),
|
|
716
|
-
children: /* @__PURE__ */
|
|
717
|
-
/* @__PURE__ */
|
|
718
|
-
description ? /* @__PURE__ */
|
|
719
|
-
/* @__PURE__ */
|
|
720
|
-
/* @__PURE__ */
|
|
1395
|
+
children: /* @__PURE__ */ jsxs12("div", { className: bodyClass2, children: [
|
|
1396
|
+
/* @__PURE__ */ jsx17(DialogTitle, { className: titleClass, children: title }),
|
|
1397
|
+
description ? /* @__PURE__ */ jsx17("p", { className: "text-sm text-muted-foreground", children: description }) : null,
|
|
1398
|
+
/* @__PURE__ */ jsxs12("div", { className: actionsClass, children: [
|
|
1399
|
+
/* @__PURE__ */ jsx17(
|
|
721
1400
|
TimbalV2Button,
|
|
722
1401
|
{
|
|
723
1402
|
type: "button",
|
|
@@ -727,7 +1406,7 @@ var AppConfirmDialog = ({
|
|
|
727
1406
|
children: cancelLabel
|
|
728
1407
|
}
|
|
729
1408
|
),
|
|
730
|
-
/* @__PURE__ */
|
|
1409
|
+
/* @__PURE__ */ jsx17(
|
|
731
1410
|
TimbalV2Button,
|
|
732
1411
|
{
|
|
733
1412
|
type: "button",
|
|
@@ -747,7 +1426,7 @@ var AppConfirmDialog = ({
|
|
|
747
1426
|
};
|
|
748
1427
|
|
|
749
1428
|
// src/app/surfaces/InfoCard.tsx
|
|
750
|
-
import { jsx as
|
|
1429
|
+
import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
751
1430
|
var toneClass = {
|
|
752
1431
|
neutral: "border-border bg-muted/40",
|
|
753
1432
|
info: "border-primary/25 bg-primary/5",
|
|
@@ -762,7 +1441,7 @@ var InfoCard = ({
|
|
|
762
1441
|
action,
|
|
763
1442
|
tone = "neutral",
|
|
764
1443
|
className
|
|
765
|
-
}) => /* @__PURE__ */
|
|
1444
|
+
}) => /* @__PURE__ */ jsxs13(
|
|
766
1445
|
"div",
|
|
767
1446
|
{
|
|
768
1447
|
className: cn(
|
|
@@ -771,18 +1450,18 @@ var InfoCard = ({
|
|
|
771
1450
|
className
|
|
772
1451
|
),
|
|
773
1452
|
children: [
|
|
774
|
-
icon ? /* @__PURE__ */
|
|
775
|
-
/* @__PURE__ */
|
|
776
|
-
title ? /* @__PURE__ */
|
|
777
|
-
children ? /* @__PURE__ */
|
|
1453
|
+
icon ? /* @__PURE__ */ jsx18("span", { className: "mt-0.5 shrink-0 text-muted-foreground", children: icon }) : null,
|
|
1454
|
+
/* @__PURE__ */ jsxs13("div", { className: "min-w-0 flex-1", children: [
|
|
1455
|
+
title ? /* @__PURE__ */ jsx18("p", { className: "text-sm font-medium text-foreground", children: title }) : null,
|
|
1456
|
+
children ? /* @__PURE__ */ jsx18("div", { className: cn("text-sm text-muted-foreground", title && "mt-1"), children }) : null
|
|
778
1457
|
] }),
|
|
779
|
-
action ? /* @__PURE__ */
|
|
1458
|
+
action ? /* @__PURE__ */ jsx18("div", { className: "shrink-0", children: action }) : null
|
|
780
1459
|
]
|
|
781
1460
|
}
|
|
782
1461
|
);
|
|
783
1462
|
|
|
784
1463
|
// src/app/surfaces/StatusDot.tsx
|
|
785
|
-
import { jsx as
|
|
1464
|
+
import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
786
1465
|
var dotClass = {
|
|
787
1466
|
online: "bg-emerald-500",
|
|
788
1467
|
busy: "bg-amber-500",
|
|
@@ -795,9 +1474,9 @@ var StatusDot = ({
|
|
|
795
1474
|
label,
|
|
796
1475
|
pulse = false,
|
|
797
1476
|
className
|
|
798
|
-
}) => /* @__PURE__ */
|
|
799
|
-
/* @__PURE__ */
|
|
800
|
-
pulse ? /* @__PURE__ */
|
|
1477
|
+
}) => /* @__PURE__ */ jsxs14("span", { className: cn("inline-flex items-center gap-1.5", className), children: [
|
|
1478
|
+
/* @__PURE__ */ jsxs14("span", { className: "relative flex size-2", children: [
|
|
1479
|
+
pulse ? /* @__PURE__ */ jsx19(
|
|
801
1480
|
"span",
|
|
802
1481
|
{
|
|
803
1482
|
className: cn(
|
|
@@ -806,25 +1485,25 @@ var StatusDot = ({
|
|
|
806
1485
|
)
|
|
807
1486
|
}
|
|
808
1487
|
) : null,
|
|
809
|
-
/* @__PURE__ */
|
|
1488
|
+
/* @__PURE__ */ jsx19("span", { className: cn("relative inline-flex size-2 rounded-full", dotClass[tone]) })
|
|
810
1489
|
] }),
|
|
811
|
-
label ? /* @__PURE__ */
|
|
1490
|
+
label ? /* @__PURE__ */ jsx19("span", { className: "text-xs text-muted-foreground", children: label }) : null
|
|
812
1491
|
] });
|
|
813
1492
|
|
|
814
1493
|
// src/app/surfaces/DescriptionList.tsx
|
|
815
|
-
import { jsx as
|
|
1494
|
+
import { jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
816
1495
|
var DescriptionList = ({
|
|
817
1496
|
items,
|
|
818
1497
|
stacked = false,
|
|
819
1498
|
className
|
|
820
|
-
}) => /* @__PURE__ */
|
|
1499
|
+
}) => /* @__PURE__ */ jsx20(
|
|
821
1500
|
"dl",
|
|
822
1501
|
{
|
|
823
1502
|
className: cn(
|
|
824
1503
|
"divide-y divide-border rounded-xl border border-border bg-card",
|
|
825
1504
|
className
|
|
826
1505
|
),
|
|
827
|
-
children: items.map((item, i) => /* @__PURE__ */
|
|
1506
|
+
children: items.map((item, i) => /* @__PURE__ */ jsxs15(
|
|
828
1507
|
"div",
|
|
829
1508
|
{
|
|
830
1509
|
className: cn(
|
|
@@ -832,8 +1511,8 @@ var DescriptionList = ({
|
|
|
832
1511
|
stacked ? "flex flex-col gap-0.5" : "flex items-center justify-between gap-4"
|
|
833
1512
|
),
|
|
834
1513
|
children: [
|
|
835
|
-
/* @__PURE__ */
|
|
836
|
-
/* @__PURE__ */
|
|
1514
|
+
/* @__PURE__ */ jsx20("dt", { className: "text-sm text-muted-foreground", children: item.label }),
|
|
1515
|
+
/* @__PURE__ */ jsx20(
|
|
837
1516
|
"dd",
|
|
838
1517
|
{
|
|
839
1518
|
className: cn(
|
|
@@ -853,8 +1532,8 @@ var DescriptionList = ({
|
|
|
853
1532
|
// src/app/surfaces/ExpandableSection.tsx
|
|
854
1533
|
import { useId, useState as useState2 } from "react";
|
|
855
1534
|
import { AnimatePresence, motion as motion2, useReducedMotion as useReducedMotion2 } from "motion/react";
|
|
856
|
-
import { jsx as
|
|
857
|
-
var Chevron = ({ open }) => /* @__PURE__ */
|
|
1535
|
+
import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1536
|
+
var Chevron = ({ open }) => /* @__PURE__ */ jsx21(
|
|
858
1537
|
"svg",
|
|
859
1538
|
{
|
|
860
1539
|
viewBox: "0 0 24 24",
|
|
@@ -868,7 +1547,7 @@ var Chevron = ({ open }) => /* @__PURE__ */ jsx17(
|
|
|
868
1547
|
strokeLinecap: "round",
|
|
869
1548
|
strokeLinejoin: "round",
|
|
870
1549
|
"aria-hidden": true,
|
|
871
|
-
children: /* @__PURE__ */
|
|
1550
|
+
children: /* @__PURE__ */ jsx21("path", { d: "m6 9 6 6 6-6" })
|
|
872
1551
|
}
|
|
873
1552
|
);
|
|
874
1553
|
var ExpandableSection = ({
|
|
@@ -889,8 +1568,8 @@ var ExpandableSection = ({
|
|
|
889
1568
|
if (openProp == null) setInternalOpen((o) => !o);
|
|
890
1569
|
onOpenChange?.(!open);
|
|
891
1570
|
};
|
|
892
|
-
return /* @__PURE__ */
|
|
893
|
-
/* @__PURE__ */
|
|
1571
|
+
return /* @__PURE__ */ jsxs16("div", { className: cn("border-b border-border last:border-0", className), children: [
|
|
1572
|
+
/* @__PURE__ */ jsxs16(
|
|
894
1573
|
"button",
|
|
895
1574
|
{
|
|
896
1575
|
type: "button",
|
|
@@ -899,16 +1578,16 @@ var ExpandableSection = ({
|
|
|
899
1578
|
"aria-controls": panelId,
|
|
900
1579
|
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",
|
|
901
1580
|
children: [
|
|
902
|
-
/* @__PURE__ */
|
|
903
|
-
icon ? /* @__PURE__ */
|
|
904
|
-
/* @__PURE__ */
|
|
905
|
-
count != null ? /* @__PURE__ */
|
|
1581
|
+
/* @__PURE__ */ jsxs16("span", { className: "flex min-w-0 items-center gap-3", children: [
|
|
1582
|
+
icon ? /* @__PURE__ */ jsx21("span", { className: "flex size-8 items-center justify-center rounded-lg border border-border bg-muted text-muted-foreground", children: icon }) : null,
|
|
1583
|
+
/* @__PURE__ */ jsx21("span", { className: "truncate text-sm font-medium text-foreground", children: title }),
|
|
1584
|
+
count != null ? /* @__PURE__ */ jsx21("span", { className: "rounded-full border border-border bg-muted px-2 py-0.5 text-xs text-muted-foreground", children: count }) : null
|
|
906
1585
|
] }),
|
|
907
|
-
/* @__PURE__ */
|
|
1586
|
+
/* @__PURE__ */ jsx21(Chevron, { open })
|
|
908
1587
|
]
|
|
909
1588
|
}
|
|
910
1589
|
),
|
|
911
|
-
/* @__PURE__ */
|
|
1590
|
+
/* @__PURE__ */ jsx21(AnimatePresence, { initial: false, children: open ? /* @__PURE__ */ jsx21(
|
|
912
1591
|
motion2.div,
|
|
913
1592
|
{
|
|
914
1593
|
id: panelId,
|
|
@@ -917,7 +1596,7 @@ var ExpandableSection = ({
|
|
|
917
1596
|
exit: reduceMotion ? void 0 : { height: 0, opacity: 0 },
|
|
918
1597
|
transition: { duration: 0.2, ease: "easeOut" },
|
|
919
1598
|
className: "overflow-hidden",
|
|
920
|
-
children: /* @__PURE__ */
|
|
1599
|
+
children: /* @__PURE__ */ jsx21("div", { className: "bg-muted/20", children })
|
|
921
1600
|
},
|
|
922
1601
|
"body"
|
|
923
1602
|
) : null })
|
|
@@ -925,7 +1604,7 @@ var ExpandableSection = ({
|
|
|
925
1604
|
};
|
|
926
1605
|
|
|
927
1606
|
// src/app/surfaces/ResourceCard.tsx
|
|
928
|
-
import { Fragment, jsx as
|
|
1607
|
+
import { Fragment as Fragment2, jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
929
1608
|
var resourceCardShellClass = cn(
|
|
930
1609
|
"flex min-h-[8.5rem] flex-col rounded-2xl p-4 text-left font-normal",
|
|
931
1610
|
TIMBAL_V2_ELEVATED_SURFACE
|
|
@@ -950,35 +1629,35 @@ var ResourceCard = ({
|
|
|
950
1629
|
ariaLabel,
|
|
951
1630
|
className
|
|
952
1631
|
}) => {
|
|
953
|
-
const body = /* @__PURE__ */
|
|
954
|
-
/* @__PURE__ */
|
|
955
|
-
media ? /* @__PURE__ */
|
|
956
|
-
/* @__PURE__ */
|
|
957
|
-
/* @__PURE__ */
|
|
958
|
-
subtitle ? /* @__PURE__ */
|
|
1632
|
+
const body = /* @__PURE__ */ jsxs17(Fragment2, { children: [
|
|
1633
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex items-start gap-3", children: [
|
|
1634
|
+
media ? /* @__PURE__ */ jsx22("span", { className: mediaShellClass, children: media }) : null,
|
|
1635
|
+
/* @__PURE__ */ jsxs17("div", { className: "min-w-0 flex-1 pt-0.5", children: [
|
|
1636
|
+
/* @__PURE__ */ jsx22("p", { className: "truncate text-sm font-normal leading-snug text-foreground", children: title }),
|
|
1637
|
+
subtitle ? /* @__PURE__ */ jsx22("p", { className: "mt-1 line-clamp-2 text-xs font-normal text-muted-foreground", children: subtitle }) : null
|
|
959
1638
|
] }),
|
|
960
|
-
badge ? /* @__PURE__ */
|
|
1639
|
+
badge ? /* @__PURE__ */ jsx22("span", { className: "shrink-0 pt-0.5", children: badge }) : null
|
|
961
1640
|
] }),
|
|
962
|
-
footer || action ? /* @__PURE__ */
|
|
963
|
-
/* @__PURE__ */
|
|
964
|
-
action ? /* @__PURE__ */
|
|
1641
|
+
footer || action ? /* @__PURE__ */ jsxs17("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: [
|
|
1642
|
+
/* @__PURE__ */ jsx22("span", { className: "min-w-0 truncate", children: footer }),
|
|
1643
|
+
action ? /* @__PURE__ */ jsx22("span", { className: "shrink-0 opacity-80", children: action }) : null
|
|
965
1644
|
] }) : null
|
|
966
1645
|
] });
|
|
967
1646
|
if (onClick) {
|
|
968
|
-
return /* @__PURE__ */
|
|
1647
|
+
return /* @__PURE__ */ jsx22("button", { type: "button", onClick, "aria-label": ariaLabel, className: cn(resourceCardInteractiveClass, className), children: body });
|
|
969
1648
|
}
|
|
970
|
-
return /* @__PURE__ */
|
|
1649
|
+
return /* @__PURE__ */ jsx22("article", { className: cn(resourceCardShellClass, className), children: body });
|
|
971
1650
|
};
|
|
972
1651
|
|
|
973
1652
|
// src/app/settings/SettingsSection.tsx
|
|
974
|
-
import { jsx as
|
|
1653
|
+
import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
975
1654
|
var SettingsSectionHeader = ({
|
|
976
1655
|
title,
|
|
977
1656
|
description,
|
|
978
1657
|
className
|
|
979
|
-
}) => /* @__PURE__ */
|
|
980
|
-
/* @__PURE__ */
|
|
981
|
-
description ? /* @__PURE__ */
|
|
1658
|
+
}) => /* @__PURE__ */ jsxs18("div", { className: cn("flex flex-col", className), children: [
|
|
1659
|
+
/* @__PURE__ */ jsx23("h3", { className: "text-[17px] font-medium leading-tight text-foreground", children: title }),
|
|
1660
|
+
description ? /* @__PURE__ */ jsx23("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null
|
|
982
1661
|
] });
|
|
983
1662
|
var SettingsSection = ({
|
|
984
1663
|
title,
|
|
@@ -987,7 +1666,7 @@ var SettingsSection = ({
|
|
|
987
1666
|
children,
|
|
988
1667
|
noBorderTop = false,
|
|
989
1668
|
className
|
|
990
|
-
}) => /* @__PURE__ */
|
|
1669
|
+
}) => /* @__PURE__ */ jsxs18(
|
|
991
1670
|
"section",
|
|
992
1671
|
{
|
|
993
1672
|
className: cn(
|
|
@@ -996,18 +1675,18 @@ var SettingsSection = ({
|
|
|
996
1675
|
className
|
|
997
1676
|
),
|
|
998
1677
|
children: [
|
|
999
|
-
/* @__PURE__ */
|
|
1000
|
-
/* @__PURE__ */
|
|
1001
|
-
description ? /* @__PURE__ */
|
|
1002
|
-
descriptionFooter ? /* @__PURE__ */
|
|
1678
|
+
/* @__PURE__ */ jsxs18("div", { className: "min-w-0", children: [
|
|
1679
|
+
/* @__PURE__ */ jsx23("h2", { className: "text-sm font-medium text-foreground", children: title }),
|
|
1680
|
+
description ? /* @__PURE__ */ jsx23("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null,
|
|
1681
|
+
descriptionFooter ? /* @__PURE__ */ jsx23("div", { className: "mt-3 min-w-0", children: descriptionFooter }) : null
|
|
1003
1682
|
] }),
|
|
1004
|
-
/* @__PURE__ */
|
|
1683
|
+
/* @__PURE__ */ jsx23("div", { className: "min-w-0 space-y-3", children })
|
|
1005
1684
|
]
|
|
1006
1685
|
}
|
|
1007
1686
|
);
|
|
1008
1687
|
|
|
1009
1688
|
// src/app/settings/FieldRow.tsx
|
|
1010
|
-
import { jsx as
|
|
1689
|
+
import { jsx as jsx24, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1011
1690
|
var FieldRow = ({
|
|
1012
1691
|
label,
|
|
1013
1692
|
children,
|
|
@@ -1017,7 +1696,7 @@ var FieldRow = ({
|
|
|
1017
1696
|
className
|
|
1018
1697
|
}) => {
|
|
1019
1698
|
if (inline) {
|
|
1020
|
-
return /* @__PURE__ */
|
|
1699
|
+
return /* @__PURE__ */ jsxs19(
|
|
1021
1700
|
"div",
|
|
1022
1701
|
{
|
|
1023
1702
|
className: cn(
|
|
@@ -1025,8 +1704,8 @@ var FieldRow = ({
|
|
|
1025
1704
|
className
|
|
1026
1705
|
),
|
|
1027
1706
|
children: [
|
|
1028
|
-
/* @__PURE__ */
|
|
1029
|
-
/* @__PURE__ */
|
|
1707
|
+
/* @__PURE__ */ jsxs19("div", { className: "min-w-0", children: [
|
|
1708
|
+
/* @__PURE__ */ jsx24(
|
|
1030
1709
|
"label",
|
|
1031
1710
|
{
|
|
1032
1711
|
htmlFor,
|
|
@@ -1034,17 +1713,17 @@ var FieldRow = ({
|
|
|
1034
1713
|
children: label
|
|
1035
1714
|
}
|
|
1036
1715
|
),
|
|
1037
|
-
description ? /* @__PURE__ */
|
|
1716
|
+
description ? /* @__PURE__ */ jsx24("p", { className: "mt-0.5 text-xs text-muted-foreground", children: description }) : null
|
|
1038
1717
|
] }),
|
|
1039
|
-
/* @__PURE__ */
|
|
1718
|
+
/* @__PURE__ */ jsx24("div", { className: "shrink-0", children })
|
|
1040
1719
|
]
|
|
1041
1720
|
}
|
|
1042
1721
|
);
|
|
1043
1722
|
}
|
|
1044
|
-
return /* @__PURE__ */
|
|
1045
|
-
/* @__PURE__ */
|
|
1723
|
+
return /* @__PURE__ */ jsxs19("div", { className: cn("flex flex-col gap-1.5", className), children: [
|
|
1724
|
+
/* @__PURE__ */ jsx24("label", { htmlFor, className: "text-sm font-medium text-foreground", children: label }),
|
|
1046
1725
|
children,
|
|
1047
|
-
description ? /* @__PURE__ */
|
|
1726
|
+
description ? /* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground", children: description }) : null
|
|
1048
1727
|
] });
|
|
1049
1728
|
};
|
|
1050
1729
|
|
|
@@ -1052,7 +1731,7 @@ var FieldRow = ({
|
|
|
1052
1731
|
import { useEffect, useState as useState3 } from "react";
|
|
1053
1732
|
import { createPortal } from "react-dom";
|
|
1054
1733
|
import { AnimatePresence as AnimatePresence2, motion as motion3, useReducedMotion as useReducedMotion3 } from "motion/react";
|
|
1055
|
-
import { jsx as
|
|
1734
|
+
import { jsx as jsx25, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1056
1735
|
var FloatingUnsavedChangesBar = ({
|
|
1057
1736
|
visible,
|
|
1058
1737
|
message = "Unsaved changes",
|
|
@@ -1070,7 +1749,7 @@ var FloatingUnsavedChangesBar = ({
|
|
|
1070
1749
|
useEffect(() => setMounted(true), []);
|
|
1071
1750
|
if (!mounted || typeof document === "undefined") return null;
|
|
1072
1751
|
return createPortal(
|
|
1073
|
-
/* @__PURE__ */
|
|
1752
|
+
/* @__PURE__ */ jsx25(AnimatePresence2, { children: visible ? /* @__PURE__ */ jsx25("div", { className: "pointer-events-none fixed inset-x-0 bottom-5 z-50 flex justify-center px-4", children: /* @__PURE__ */ jsxs20(
|
|
1074
1753
|
motion3.div,
|
|
1075
1754
|
{
|
|
1076
1755
|
role: "region",
|
|
@@ -1084,10 +1763,10 @@ var FloatingUnsavedChangesBar = ({
|
|
|
1084
1763
|
className
|
|
1085
1764
|
),
|
|
1086
1765
|
children: [
|
|
1087
|
-
/* @__PURE__ */
|
|
1088
|
-
/* @__PURE__ */
|
|
1089
|
-
/* @__PURE__ */
|
|
1090
|
-
/* @__PURE__ */
|
|
1766
|
+
/* @__PURE__ */ jsx25("span", { className: "text-sm text-muted-foreground", children: message }),
|
|
1767
|
+
/* @__PURE__ */ jsxs20("span", { className: "flex items-center gap-1.5", children: [
|
|
1768
|
+
/* @__PURE__ */ jsx25(Button, { variant: "ghost", size: "sm", onClick: onDiscard, disabled: isSaving, children: discardLabel }),
|
|
1769
|
+
/* @__PURE__ */ jsx25(Button, { size: "sm", onClick: onSave, disabled: saveDisabled || isSaving, children: isSaving ? "Saving\u2026" : saveLabel })
|
|
1091
1770
|
] })
|
|
1092
1771
|
]
|
|
1093
1772
|
}
|
|
@@ -1097,13 +1776,13 @@ var FloatingUnsavedChangesBar = ({
|
|
|
1097
1776
|
};
|
|
1098
1777
|
|
|
1099
1778
|
// src/app/settings/DangerZone.tsx
|
|
1100
|
-
import { jsx as
|
|
1779
|
+
import { jsx as jsx26, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1101
1780
|
var DangerZoneAction = ({
|
|
1102
1781
|
title,
|
|
1103
1782
|
description,
|
|
1104
1783
|
action,
|
|
1105
1784
|
className
|
|
1106
|
-
}) => /* @__PURE__ */
|
|
1785
|
+
}) => /* @__PURE__ */ jsxs21(
|
|
1107
1786
|
"div",
|
|
1108
1787
|
{
|
|
1109
1788
|
className: cn(
|
|
@@ -1111,11 +1790,11 @@ var DangerZoneAction = ({
|
|
|
1111
1790
|
className
|
|
1112
1791
|
),
|
|
1113
1792
|
children: [
|
|
1114
|
-
/* @__PURE__ */
|
|
1115
|
-
/* @__PURE__ */
|
|
1116
|
-
description ? /* @__PURE__ */
|
|
1793
|
+
/* @__PURE__ */ jsxs21("div", { className: "min-w-0", children: [
|
|
1794
|
+
/* @__PURE__ */ jsx26("p", { className: "text-sm font-medium text-foreground", children: title }),
|
|
1795
|
+
description ? /* @__PURE__ */ jsx26("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
|
|
1117
1796
|
] }),
|
|
1118
|
-
/* @__PURE__ */
|
|
1797
|
+
/* @__PURE__ */ jsx26("div", { className: "shrink-0", children: action })
|
|
1119
1798
|
]
|
|
1120
1799
|
}
|
|
1121
1800
|
);
|
|
@@ -1124,7 +1803,7 @@ var DangerZone = ({
|
|
|
1124
1803
|
description,
|
|
1125
1804
|
children,
|
|
1126
1805
|
className
|
|
1127
|
-
}) => /* @__PURE__ */
|
|
1806
|
+
}) => /* @__PURE__ */ jsxs21(
|
|
1128
1807
|
"section",
|
|
1129
1808
|
{
|
|
1130
1809
|
className: cn(
|
|
@@ -1132,18 +1811,18 @@ var DangerZone = ({
|
|
|
1132
1811
|
className
|
|
1133
1812
|
),
|
|
1134
1813
|
children: [
|
|
1135
|
-
(title || description) && /* @__PURE__ */
|
|
1136
|
-
title ? /* @__PURE__ */
|
|
1137
|
-
description ? /* @__PURE__ */
|
|
1814
|
+
(title || description) && /* @__PURE__ */ jsxs21("header", { className: "border-b border-destructive/20 bg-destructive/5 px-4 py-3", children: [
|
|
1815
|
+
title ? /* @__PURE__ */ jsx26("h3", { className: "text-sm font-semibold text-destructive", children: title }) : null,
|
|
1816
|
+
description ? /* @__PURE__ */ jsx26("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
|
|
1138
1817
|
] }),
|
|
1139
|
-
/* @__PURE__ */
|
|
1818
|
+
/* @__PURE__ */ jsx26("div", { className: "divide-y divide-border bg-card", children })
|
|
1140
1819
|
]
|
|
1141
1820
|
}
|
|
1142
1821
|
);
|
|
1143
1822
|
|
|
1144
1823
|
// src/app/integrations/IntegrationCard.tsx
|
|
1145
1824
|
import { useId as useId2 } from "react";
|
|
1146
|
-
import { Fragment as
|
|
1825
|
+
import { Fragment as Fragment3, jsx as jsx27, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1147
1826
|
var INTEGRATION_CATALOG_CARD_HEIGHT_CLASS = "h-[12.25rem] min-h-[12.25rem] max-h-[12.25rem]";
|
|
1148
1827
|
var statusLabel = {
|
|
1149
1828
|
available: null,
|
|
@@ -1184,12 +1863,12 @@ var IntegrationCard = ({
|
|
|
1184
1863
|
const titleId = useId2();
|
|
1185
1864
|
const locked = status === "locked";
|
|
1186
1865
|
const dimmed = status === "disabled" || locked;
|
|
1187
|
-
const body = /* @__PURE__ */
|
|
1188
|
-
/* @__PURE__ */
|
|
1189
|
-
logo ? /* @__PURE__ */
|
|
1190
|
-
/* @__PURE__ */
|
|
1191
|
-
/* @__PURE__ */
|
|
1192
|
-
/* @__PURE__ */
|
|
1866
|
+
const body = /* @__PURE__ */ jsxs22("div", { className: "flex h-full min-h-0 flex-col", children: [
|
|
1867
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex shrink-0 items-start gap-3 pr-2", children: [
|
|
1868
|
+
logo ? /* @__PURE__ */ jsx27("span", { className: logoShellClass, "aria-hidden": Boolean(ariaLabel), children: logo }) : null,
|
|
1869
|
+
/* @__PURE__ */ jsx27("div", { className: "min-w-0 flex-1 pt-0.5", children: /* @__PURE__ */ jsxs22("div", { className: "flex items-start justify-between gap-2", children: [
|
|
1870
|
+
/* @__PURE__ */ jsxs22("div", { className: "min-w-0", children: [
|
|
1871
|
+
/* @__PURE__ */ jsx27(
|
|
1193
1872
|
"h4",
|
|
1194
1873
|
{
|
|
1195
1874
|
id: onClick && !action ? void 0 : titleId,
|
|
@@ -1197,12 +1876,12 @@ var IntegrationCard = ({
|
|
|
1197
1876
|
children: name
|
|
1198
1877
|
}
|
|
1199
1878
|
),
|
|
1200
|
-
statusLabel[status] ? /* @__PURE__ */
|
|
1879
|
+
statusLabel[status] ? /* @__PURE__ */ jsx27("p", { className: "mt-0.5 text-xs text-muted-foreground", children: statusLabel[status] }) : null
|
|
1201
1880
|
] }),
|
|
1202
|
-
badge ? /* @__PURE__ */
|
|
1881
|
+
badge ? /* @__PURE__ */ jsx27("span", { className: "shrink-0", children: badge }) : null
|
|
1203
1882
|
] }) })
|
|
1204
1883
|
] }),
|
|
1205
|
-
description ? /* @__PURE__ */
|
|
1884
|
+
description ? /* @__PURE__ */ jsx27(
|
|
1206
1885
|
"p",
|
|
1207
1886
|
{
|
|
1208
1887
|
className: cn(
|
|
@@ -1212,9 +1891,9 @@ var IntegrationCard = ({
|
|
|
1212
1891
|
children: description
|
|
1213
1892
|
}
|
|
1214
1893
|
) : null,
|
|
1215
|
-
action ? /* @__PURE__ */
|
|
1216
|
-
/* @__PURE__ */
|
|
1217
|
-
/* @__PURE__ */
|
|
1894
|
+
action ? /* @__PURE__ */ jsxs22(Fragment3, { children: [
|
|
1895
|
+
/* @__PURE__ */ jsx27("div", { className: "min-h-0 flex-1", "aria-hidden": true }),
|
|
1896
|
+
/* @__PURE__ */ jsx27("div", { className: "relative mt-3 shrink-0", children: action })
|
|
1218
1897
|
] }) : null
|
|
1219
1898
|
] });
|
|
1220
1899
|
const shellClass3 = cn(
|
|
@@ -1224,7 +1903,7 @@ var IntegrationCard = ({
|
|
|
1224
1903
|
className
|
|
1225
1904
|
);
|
|
1226
1905
|
if (onClick && !action) {
|
|
1227
|
-
return /* @__PURE__ */
|
|
1906
|
+
return /* @__PURE__ */ jsx27(
|
|
1228
1907
|
"button",
|
|
1229
1908
|
{
|
|
1230
1909
|
type: "button",
|
|
@@ -1241,12 +1920,12 @@ var IntegrationCard = ({
|
|
|
1241
1920
|
}
|
|
1242
1921
|
);
|
|
1243
1922
|
}
|
|
1244
|
-
return /* @__PURE__ */
|
|
1923
|
+
return /* @__PURE__ */ jsx27("article", { className: shellClass3, "aria-labelledby": titleId, children: body });
|
|
1245
1924
|
};
|
|
1246
1925
|
|
|
1247
1926
|
// src/app/integrations/IntegrationsEmptyState.tsx
|
|
1248
1927
|
import { useId as useId3 } from "react";
|
|
1249
|
-
import { jsx as
|
|
1928
|
+
import { jsx as jsx28, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1250
1929
|
var IntegrationsEmptyState = ({
|
|
1251
1930
|
title = "No integrations yet",
|
|
1252
1931
|
description = "Connect a provider to start syncing data and powering your workforce.",
|
|
@@ -1255,7 +1934,7 @@ var IntegrationsEmptyState = ({
|
|
|
1255
1934
|
className
|
|
1256
1935
|
}) => {
|
|
1257
1936
|
const titleId = useId3();
|
|
1258
|
-
return /* @__PURE__ */
|
|
1937
|
+
return /* @__PURE__ */ jsxs23(
|
|
1259
1938
|
"section",
|
|
1260
1939
|
{
|
|
1261
1940
|
className: cn(
|
|
@@ -1265,7 +1944,7 @@ var IntegrationsEmptyState = ({
|
|
|
1265
1944
|
),
|
|
1266
1945
|
"aria-labelledby": titleId,
|
|
1267
1946
|
children: [
|
|
1268
|
-
icon ? /* @__PURE__ */
|
|
1947
|
+
icon ? /* @__PURE__ */ jsx28(
|
|
1269
1948
|
"span",
|
|
1270
1949
|
{
|
|
1271
1950
|
className: cn(
|
|
@@ -1277,21 +1956,21 @@ var IntegrationsEmptyState = ({
|
|
|
1277
1956
|
children: icon
|
|
1278
1957
|
}
|
|
1279
1958
|
) : null,
|
|
1280
|
-
/* @__PURE__ */
|
|
1281
|
-
description ? /* @__PURE__ */
|
|
1282
|
-
action ? /* @__PURE__ */
|
|
1959
|
+
/* @__PURE__ */ jsx28("h3", { id: titleId, className: "text-base font-normal text-foreground", children: title }),
|
|
1960
|
+
description ? /* @__PURE__ */ jsx28("p", { className: "max-w-sm text-sm text-muted-foreground", children: description }) : null,
|
|
1961
|
+
action ? /* @__PURE__ */ jsx28("div", { className: "mt-1", children: action }) : null
|
|
1283
1962
|
]
|
|
1284
1963
|
}
|
|
1285
1964
|
);
|
|
1286
1965
|
};
|
|
1287
1966
|
|
|
1288
1967
|
// src/app/integrations/PlanBadge.tsx
|
|
1289
|
-
import { jsx as
|
|
1968
|
+
import { jsx as jsx29 } from "react/jsx-runtime";
|
|
1290
1969
|
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";
|
|
1291
|
-
var PlanBadge = ({ children, className }) => /* @__PURE__ */
|
|
1970
|
+
var PlanBadge = ({ children, className }) => /* @__PURE__ */ jsx29("span", { className: cn(planBadgeClass, className), children });
|
|
1292
1971
|
|
|
1293
1972
|
// src/app/integrations/ConnectionRow.tsx
|
|
1294
|
-
import { Fragment as
|
|
1973
|
+
import { Fragment as Fragment4, jsx as jsx30, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1295
1974
|
var logoShellClass2 = cn(
|
|
1296
1975
|
"flex size-9 shrink-0 items-center justify-center overflow-hidden rounded-lg",
|
|
1297
1976
|
TIMBAL_V2_LOGO_TILE
|
|
@@ -1306,14 +1985,14 @@ var ConnectionRow = ({
|
|
|
1306
1985
|
ariaLabel,
|
|
1307
1986
|
className
|
|
1308
1987
|
}) => {
|
|
1309
|
-
const inner = /* @__PURE__ */
|
|
1310
|
-
logo ? /* @__PURE__ */
|
|
1311
|
-
/* @__PURE__ */
|
|
1312
|
-
/* @__PURE__ */
|
|
1313
|
-
meta ? /* @__PURE__ */
|
|
1988
|
+
const inner = /* @__PURE__ */ jsxs24(Fragment4, { children: [
|
|
1989
|
+
logo ? /* @__PURE__ */ jsx30("span", { className: logoShellClass2, children: logo }) : null,
|
|
1990
|
+
/* @__PURE__ */ jsxs24("div", { className: "min-w-0 flex-1", children: [
|
|
1991
|
+
/* @__PURE__ */ jsx30("p", { className: "truncate text-sm font-normal text-foreground", children: name }),
|
|
1992
|
+
meta ? /* @__PURE__ */ jsx30("p", { className: "truncate text-xs text-muted-foreground", children: meta }) : null
|
|
1314
1993
|
] }),
|
|
1315
|
-
badge ? /* @__PURE__ */
|
|
1316
|
-
action ? /* @__PURE__ */
|
|
1994
|
+
badge ? /* @__PURE__ */ jsx30("span", { className: "shrink-0", children: badge }) : null,
|
|
1995
|
+
action ? /* @__PURE__ */ jsx30("span", { className: "shrink-0", children: action }) : null
|
|
1317
1996
|
] });
|
|
1318
1997
|
const rowClass2 = cn(
|
|
1319
1998
|
"flex w-full items-center gap-3 px-4 py-3 text-left",
|
|
@@ -1321,7 +2000,7 @@ var ConnectionRow = ({
|
|
|
1321
2000
|
className
|
|
1322
2001
|
);
|
|
1323
2002
|
if (onClick) {
|
|
1324
|
-
return /* @__PURE__ */
|
|
2003
|
+
return /* @__PURE__ */ jsx30(
|
|
1325
2004
|
"button",
|
|
1326
2005
|
{
|
|
1327
2006
|
type: "button",
|
|
@@ -1333,7 +2012,7 @@ var ConnectionRow = ({
|
|
|
1333
2012
|
}
|
|
1334
2013
|
);
|
|
1335
2014
|
}
|
|
1336
|
-
return /* @__PURE__ */
|
|
2015
|
+
return /* @__PURE__ */ jsx30("div", { role: "listitem", className: rowClass2, children: inner });
|
|
1337
2016
|
};
|
|
1338
2017
|
var connectionRowListClass = cn(
|
|
1339
2018
|
"overflow-hidden rounded-2xl",
|
|
@@ -1341,12 +2020,12 @@ var connectionRowListClass = cn(
|
|
|
1341
2020
|
);
|
|
1342
2021
|
|
|
1343
2022
|
// src/app/integrations/ConnectionRowList.tsx
|
|
1344
|
-
import { jsx as
|
|
2023
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
1345
2024
|
var ConnectionRowList = ({
|
|
1346
2025
|
children,
|
|
1347
2026
|
"aria-label": ariaLabel = "Connected integrations",
|
|
1348
2027
|
className
|
|
1349
|
-
}) => /* @__PURE__ */
|
|
2028
|
+
}) => /* @__PURE__ */ jsx31(
|
|
1350
2029
|
"div",
|
|
1351
2030
|
{
|
|
1352
2031
|
role: "list",
|
|
@@ -1357,7 +2036,7 @@ var ConnectionRowList = ({
|
|
|
1357
2036
|
);
|
|
1358
2037
|
|
|
1359
2038
|
// src/app/navigation/SubNav.tsx
|
|
1360
|
-
import { jsx as
|
|
2039
|
+
import { jsx as jsx32 } from "react/jsx-runtime";
|
|
1361
2040
|
var SubNav = ({
|
|
1362
2041
|
items,
|
|
1363
2042
|
activeId,
|
|
@@ -1366,7 +2045,7 @@ var SubNav = ({
|
|
|
1366
2045
|
"aria-label": ariaLabel = "Section navigation",
|
|
1367
2046
|
layoutId
|
|
1368
2047
|
}) => {
|
|
1369
|
-
return /* @__PURE__ */
|
|
2048
|
+
return /* @__PURE__ */ jsx32("nav", { className: cn("aui-app-sub-nav", className), "aria-label": ariaLabel, children: /* @__PURE__ */ jsx32(
|
|
1370
2049
|
PillSegmentedTabs,
|
|
1371
2050
|
{
|
|
1372
2051
|
value: activeId,
|
|
@@ -1380,13 +2059,13 @@ var SubNav = ({
|
|
|
1380
2059
|
};
|
|
1381
2060
|
|
|
1382
2061
|
// src/app/navigation/Breadcrumbs.tsx
|
|
1383
|
-
import { jsx as
|
|
2062
|
+
import { jsx as jsx33, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1384
2063
|
var Breadcrumbs = ({ items, className }) => {
|
|
1385
|
-
return /* @__PURE__ */
|
|
2064
|
+
return /* @__PURE__ */ jsx33("nav", { className: cn("aui-app-breadcrumbs", appBreadcrumbsClass, className), "aria-label": "Breadcrumb", children: /* @__PURE__ */ jsx33("ol", { className: "flex flex-wrap items-center gap-1.5", children: items.map((item, index) => {
|
|
1386
2065
|
const isLast = index === items.length - 1;
|
|
1387
|
-
return /* @__PURE__ */
|
|
1388
|
-
index > 0 ? /* @__PURE__ */
|
|
1389
|
-
isLast ? /* @__PURE__ */
|
|
2066
|
+
return /* @__PURE__ */ jsxs25("li", { className: "inline-flex items-center gap-1.5", children: [
|
|
2067
|
+
index > 0 ? /* @__PURE__ */ jsx33("span", { className: "text-muted-foreground/50", "aria-hidden": true, children: "/" }) : null,
|
|
2068
|
+
isLast ? /* @__PURE__ */ jsx33("span", { className: "text-foreground", "aria-current": "page", children: item.label }) : item.href ? /* @__PURE__ */ jsx33("a", { href: item.href, className: appBreadcrumbLinkClass, children: item.label }) : /* @__PURE__ */ jsx33(
|
|
1390
2069
|
"button",
|
|
1391
2070
|
{
|
|
1392
2071
|
type: "button",
|
|
@@ -1400,7 +2079,7 @@ var Breadcrumbs = ({ items, className }) => {
|
|
|
1400
2079
|
};
|
|
1401
2080
|
|
|
1402
2081
|
// src/app/forms/Field.tsx
|
|
1403
|
-
import { jsx as
|
|
2082
|
+
import { jsx as jsx34, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
1404
2083
|
var Field = ({
|
|
1405
2084
|
label,
|
|
1406
2085
|
hint,
|
|
@@ -1409,11 +2088,11 @@ var Field = ({
|
|
|
1409
2088
|
className,
|
|
1410
2089
|
htmlFor
|
|
1411
2090
|
}) => {
|
|
1412
|
-
return /* @__PURE__ */
|
|
1413
|
-
/* @__PURE__ */
|
|
2091
|
+
return /* @__PURE__ */ jsxs26("div", { className: cn("aui-app-field", appFieldClass, className), children: [
|
|
2092
|
+
/* @__PURE__ */ jsx34("label", { className: appFieldLabelClass, htmlFor, children: label }),
|
|
1414
2093
|
children,
|
|
1415
|
-
hint && !error ? /* @__PURE__ */
|
|
1416
|
-
error ? /* @__PURE__ */
|
|
2094
|
+
hint && !error ? /* @__PURE__ */ jsx34("p", { className: appFieldHintClass, children: hint }) : null,
|
|
2095
|
+
error ? /* @__PURE__ */ jsx34("p", { className: "text-xs text-destructive", role: "alert", children: error }) : null
|
|
1417
2096
|
] });
|
|
1418
2097
|
};
|
|
1419
2098
|
var FieldInput = ({
|
|
@@ -1426,7 +2105,7 @@ var FieldInput = ({
|
|
|
1426
2105
|
...inputProps
|
|
1427
2106
|
}) => {
|
|
1428
2107
|
const inputId = id ?? inputProps.name;
|
|
1429
|
-
return /* @__PURE__ */
|
|
2108
|
+
return /* @__PURE__ */ jsx34(
|
|
1430
2109
|
Field,
|
|
1431
2110
|
{
|
|
1432
2111
|
label,
|
|
@@ -1434,7 +2113,7 @@ var FieldInput = ({
|
|
|
1434
2113
|
error,
|
|
1435
2114
|
htmlFor: inputId,
|
|
1436
2115
|
className: fieldClassName,
|
|
1437
|
-
children: /* @__PURE__ */
|
|
2116
|
+
children: /* @__PURE__ */ jsx34(
|
|
1438
2117
|
"input",
|
|
1439
2118
|
{
|
|
1440
2119
|
id: inputId,
|
|
@@ -1448,7 +2127,7 @@ var FieldInput = ({
|
|
|
1448
2127
|
};
|
|
1449
2128
|
|
|
1450
2129
|
// src/app/forms/FieldTextarea.tsx
|
|
1451
|
-
import { jsx as
|
|
2130
|
+
import { jsx as jsx35 } from "react/jsx-runtime";
|
|
1452
2131
|
var textareaClass = cn(
|
|
1453
2132
|
appInputClass,
|
|
1454
2133
|
"min-h-[5.5rem] resize-y py-2.5 leading-relaxed"
|
|
@@ -1463,7 +2142,7 @@ var FieldTextarea = ({
|
|
|
1463
2142
|
...props
|
|
1464
2143
|
}) => {
|
|
1465
2144
|
const textareaId = id ?? props.name;
|
|
1466
|
-
return /* @__PURE__ */
|
|
2145
|
+
return /* @__PURE__ */ jsx35(
|
|
1467
2146
|
Field,
|
|
1468
2147
|
{
|
|
1469
2148
|
label,
|
|
@@ -1471,7 +2150,7 @@ var FieldTextarea = ({
|
|
|
1471
2150
|
error,
|
|
1472
2151
|
htmlFor: textareaId,
|
|
1473
2152
|
className: fieldClassName,
|
|
1474
|
-
children: /* @__PURE__ */
|
|
2153
|
+
children: /* @__PURE__ */ jsx35(
|
|
1475
2154
|
"textarea",
|
|
1476
2155
|
{
|
|
1477
2156
|
id: textareaId,
|
|
@@ -1486,7 +2165,7 @@ var FieldTextarea = ({
|
|
|
1486
2165
|
|
|
1487
2166
|
// src/app/forms/FieldSelect.tsx
|
|
1488
2167
|
import { ChevronDownIcon } from "lucide-react";
|
|
1489
|
-
import { jsx as
|
|
2168
|
+
import { jsx as jsx36, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
1490
2169
|
var selectWrapClass = "relative";
|
|
1491
2170
|
var selectClass = cn(
|
|
1492
2171
|
appInputClass,
|
|
@@ -1503,7 +2182,7 @@ var FieldSelect = ({
|
|
|
1503
2182
|
...props
|
|
1504
2183
|
}) => {
|
|
1505
2184
|
const selectId = id ?? props.name;
|
|
1506
|
-
return /* @__PURE__ */
|
|
2185
|
+
return /* @__PURE__ */ jsx36(
|
|
1507
2186
|
Field,
|
|
1508
2187
|
{
|
|
1509
2188
|
label,
|
|
@@ -1511,8 +2190,8 @@ var FieldSelect = ({
|
|
|
1511
2190
|
error,
|
|
1512
2191
|
htmlFor: selectId,
|
|
1513
2192
|
className: fieldClassName,
|
|
1514
|
-
children: /* @__PURE__ */
|
|
1515
|
-
/* @__PURE__ */
|
|
2193
|
+
children: /* @__PURE__ */ jsxs27("div", { className: selectWrapClass, children: [
|
|
2194
|
+
/* @__PURE__ */ jsx36(
|
|
1516
2195
|
"select",
|
|
1517
2196
|
{
|
|
1518
2197
|
id: selectId,
|
|
@@ -1522,7 +2201,7 @@ var FieldSelect = ({
|
|
|
1522
2201
|
children
|
|
1523
2202
|
}
|
|
1524
2203
|
),
|
|
1525
|
-
/* @__PURE__ */
|
|
2204
|
+
/* @__PURE__ */ jsx36(
|
|
1526
2205
|
ChevronDownIcon,
|
|
1527
2206
|
{
|
|
1528
2207
|
className: "pointer-events-none absolute top-1/2 right-3 size-4 -translate-y-1/2 text-muted-foreground",
|
|
@@ -1535,7 +2214,7 @@ var FieldSelect = ({
|
|
|
1535
2214
|
};
|
|
1536
2215
|
|
|
1537
2216
|
// src/app/forms/FieldSwitch.tsx
|
|
1538
|
-
import { jsx as
|
|
2217
|
+
import { jsx as jsx37, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
1539
2218
|
var trackClass = cn(
|
|
1540
2219
|
"relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-[background,box-shadow,border-color] duration-200",
|
|
1541
2220
|
"peer-focus-visible:ring-2 peer-focus-visible:ring-foreground/10",
|
|
@@ -1556,7 +2235,7 @@ var FieldSwitch = ({
|
|
|
1556
2235
|
...props
|
|
1557
2236
|
}) => {
|
|
1558
2237
|
const inputId = id ?? props.name ?? "switch";
|
|
1559
|
-
return /* @__PURE__ */
|
|
2238
|
+
return /* @__PURE__ */ jsxs28(
|
|
1560
2239
|
"label",
|
|
1561
2240
|
{
|
|
1562
2241
|
className: cn(
|
|
@@ -1565,8 +2244,8 @@ var FieldSwitch = ({
|
|
|
1565
2244
|
),
|
|
1566
2245
|
htmlFor: inputId,
|
|
1567
2246
|
children: [
|
|
1568
|
-
/* @__PURE__ */
|
|
1569
|
-
/* @__PURE__ */
|
|
2247
|
+
/* @__PURE__ */ jsxs28("span", { className: "relative mt-0.5", children: [
|
|
2248
|
+
/* @__PURE__ */ jsx37(
|
|
1570
2249
|
"input",
|
|
1571
2250
|
{
|
|
1572
2251
|
id: inputId,
|
|
@@ -1576,11 +2255,11 @@ var FieldSwitch = ({
|
|
|
1576
2255
|
...props
|
|
1577
2256
|
}
|
|
1578
2257
|
),
|
|
1579
|
-
/* @__PURE__ */
|
|
2258
|
+
/* @__PURE__ */ jsx37("span", { className: trackClass, "aria-hidden": true, children: /* @__PURE__ */ jsx37("span", { className: thumbClass }) })
|
|
1580
2259
|
] }),
|
|
1581
|
-
/* @__PURE__ */
|
|
1582
|
-
/* @__PURE__ */
|
|
1583
|
-
description ? /* @__PURE__ */
|
|
2260
|
+
/* @__PURE__ */ jsxs28("span", { className: "flex min-w-0 flex-col gap-0.5", children: [
|
|
2261
|
+
/* @__PURE__ */ jsx37("span", { className: "text-sm font-medium text-foreground", children: label }),
|
|
2262
|
+
description ? /* @__PURE__ */ jsx37("span", { className: "text-xs text-muted-foreground", children: description }) : null
|
|
1584
2263
|
] })
|
|
1585
2264
|
]
|
|
1586
2265
|
}
|
|
@@ -1589,13 +2268,13 @@ var FieldSwitch = ({
|
|
|
1589
2268
|
|
|
1590
2269
|
// src/app/forms/SearchInput.tsx
|
|
1591
2270
|
import { SearchIcon } from "lucide-react";
|
|
1592
|
-
import { jsx as
|
|
2271
|
+
import { jsx as jsx38, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
1593
2272
|
var SearchInput = ({
|
|
1594
2273
|
className,
|
|
1595
2274
|
placeholder = "Search\u2026",
|
|
1596
2275
|
...props
|
|
1597
2276
|
}) => {
|
|
1598
|
-
return /* @__PURE__ */
|
|
2277
|
+
return /* @__PURE__ */ jsxs29(
|
|
1599
2278
|
"label",
|
|
1600
2279
|
{
|
|
1601
2280
|
className: cn(
|
|
@@ -1604,8 +2283,8 @@ var SearchInput = ({
|
|
|
1604
2283
|
className
|
|
1605
2284
|
),
|
|
1606
2285
|
children: [
|
|
1607
|
-
/* @__PURE__ */
|
|
1608
|
-
/* @__PURE__ */
|
|
2286
|
+
/* @__PURE__ */ jsx38(SearchIcon, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": true }),
|
|
2287
|
+
/* @__PURE__ */ jsx38(
|
|
1609
2288
|
"input",
|
|
1610
2289
|
{
|
|
1611
2290
|
type: "search",
|
|
@@ -1620,18 +2299,18 @@ var SearchInput = ({
|
|
|
1620
2299
|
};
|
|
1621
2300
|
|
|
1622
2301
|
// src/app/forms/FormSection.tsx
|
|
1623
|
-
import { jsx as
|
|
2302
|
+
import { jsx as jsx39, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
1624
2303
|
var FormSection = ({ title, children, className }) => {
|
|
1625
|
-
return /* @__PURE__ */
|
|
1626
|
-
title ? /* @__PURE__ */
|
|
1627
|
-
/* @__PURE__ */
|
|
2304
|
+
return /* @__PURE__ */ jsxs30("fieldset", { className: cn("aui-app-form-section", appSectionClass, "border-0 p-0", className), children: [
|
|
2305
|
+
title ? /* @__PURE__ */ jsx39("legend", { className: cn(appSectionTitleClass, "mb-3 px-0"), children: title }) : null,
|
|
2306
|
+
/* @__PURE__ */ jsx39("div", { className: "flex flex-col gap-4", children })
|
|
1628
2307
|
] });
|
|
1629
2308
|
};
|
|
1630
2309
|
|
|
1631
2310
|
// src/app/data/FilterBar.tsx
|
|
1632
|
-
import { jsx as
|
|
2311
|
+
import { jsx as jsx40 } from "react/jsx-runtime";
|
|
1633
2312
|
var FilterBar = ({ children, className }) => {
|
|
1634
|
-
return /* @__PURE__ */
|
|
2313
|
+
return /* @__PURE__ */ jsx40(
|
|
1635
2314
|
"div",
|
|
1636
2315
|
{
|
|
1637
2316
|
className: cn("aui-app-filter-bar", appFilterBarClass, className),
|
|
@@ -1645,7 +2324,7 @@ var FilterBar = ({ children, className }) => {
|
|
|
1645
2324
|
// src/app/data/DataTable.tsx
|
|
1646
2325
|
import { useMemo, useState as useState4 } from "react";
|
|
1647
2326
|
import { ArrowDownIcon, ArrowUpDownIcon, ArrowUpIcon } from "lucide-react";
|
|
1648
|
-
import { jsx as
|
|
2327
|
+
import { jsx as jsx41, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
1649
2328
|
var shellClass2 = "overflow-hidden rounded-xl border border-border bg-card shadow-card";
|
|
1650
2329
|
var tableClass = "w-full border-collapse bg-transparent text-sm";
|
|
1651
2330
|
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";
|
|
@@ -1685,12 +2364,12 @@ function SortIndicator({
|
|
|
1685
2364
|
}) {
|
|
1686
2365
|
const iconClass = "size-3.5 shrink-0 opacity-60 group-hover:opacity-100";
|
|
1687
2366
|
if (!active) {
|
|
1688
|
-
return /* @__PURE__ */
|
|
2367
|
+
return /* @__PURE__ */ jsx41(ArrowUpDownIcon, { className: iconClass, "aria-hidden": true });
|
|
1689
2368
|
}
|
|
1690
2369
|
if (direction === "desc") {
|
|
1691
|
-
return /* @__PURE__ */
|
|
2370
|
+
return /* @__PURE__ */ jsx41(ArrowDownIcon, { className: iconClass, "aria-hidden": true });
|
|
1692
2371
|
}
|
|
1693
|
-
return /* @__PURE__ */
|
|
2372
|
+
return /* @__PURE__ */ jsx41(ArrowUpIcon, { className: iconClass, "aria-hidden": true });
|
|
1694
2373
|
}
|
|
1695
2374
|
function DataTable({
|
|
1696
2375
|
columns,
|
|
@@ -1741,28 +2420,28 @@ function DataTable({
|
|
|
1741
2420
|
const cellPad = dense ? "px-3 py-2" : void 0;
|
|
1742
2421
|
const headPad = dense ? "px-3 py-2" : void 0;
|
|
1743
2422
|
if (rows.length === 0 && emptyMode === "replace") {
|
|
1744
|
-
return /* @__PURE__ */
|
|
2423
|
+
return /* @__PURE__ */ jsx41(EmptyState, { title: emptyTitle, description: emptyDescription, className });
|
|
1745
2424
|
}
|
|
1746
2425
|
const rowCountText = rowCountLabel?.(sortedRows.length) ?? `${sortedRows.length} row${sortedRows.length === 1 ? "" : "s"}`;
|
|
1747
2426
|
const hasFoot = Boolean((showRowCount || footer) && sortedRows.length > 0);
|
|
1748
|
-
return /* @__PURE__ */
|
|
1749
|
-
caption ? /* @__PURE__ */
|
|
1750
|
-
/* @__PURE__ */
|
|
2427
|
+
return /* @__PURE__ */ jsx41("div", { className: cn("aui-app-data-table", shellClass2, className), children: /* @__PURE__ */ jsx41("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs31("table", { className: tableClass, children: [
|
|
2428
|
+
caption ? /* @__PURE__ */ jsx41("caption", { className: "sr-only", children: caption }) : null,
|
|
2429
|
+
/* @__PURE__ */ jsx41("thead", { className: cn(stickyHeader && stickyHeadClass), children: /* @__PURE__ */ jsx41("tr", { children: columns.map((col) => {
|
|
1751
2430
|
const isSorted = sort?.columnId === col.id;
|
|
1752
2431
|
const ariaSort = col.sortable ? isSorted ? sort.direction === "asc" ? "ascending" : "descending" : "none" : void 0;
|
|
1753
|
-
const headerContent = col.sortable ? /* @__PURE__ */
|
|
2432
|
+
const headerContent = col.sortable ? /* @__PURE__ */ jsxs31(
|
|
1754
2433
|
"button",
|
|
1755
2434
|
{
|
|
1756
2435
|
type: "button",
|
|
1757
2436
|
className: sortButtonClass,
|
|
1758
2437
|
onClick: () => setSort(nextSort(sort, col.id)),
|
|
1759
2438
|
children: [
|
|
1760
|
-
/* @__PURE__ */
|
|
1761
|
-
/* @__PURE__ */
|
|
2439
|
+
/* @__PURE__ */ jsx41("span", { className: "truncate", children: col.header }),
|
|
2440
|
+
/* @__PURE__ */ jsx41(SortIndicator, { active: Boolean(isSorted), direction: sort?.direction })
|
|
1762
2441
|
]
|
|
1763
2442
|
}
|
|
1764
2443
|
) : col.header;
|
|
1765
|
-
return /* @__PURE__ */
|
|
2444
|
+
return /* @__PURE__ */ jsx41(
|
|
1766
2445
|
"th",
|
|
1767
2446
|
{
|
|
1768
2447
|
scope: "col",
|
|
@@ -1778,10 +2457,10 @@ function DataTable({
|
|
|
1778
2457
|
col.id
|
|
1779
2458
|
);
|
|
1780
2459
|
}) }) }),
|
|
1781
|
-
/* @__PURE__ */
|
|
1782
|
-
/* @__PURE__ */
|
|
1783
|
-
emptyDescription ? /* @__PURE__ */
|
|
1784
|
-
] }) }) }) : sortedRows.map((row) => /* @__PURE__ */
|
|
2460
|
+
/* @__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__ */ jsxs31("div", { className: "flex flex-col items-center gap-1", children: [
|
|
2461
|
+
/* @__PURE__ */ jsx41("p", { className: "font-medium text-foreground", children: emptyTitle }),
|
|
2462
|
+
emptyDescription ? /* @__PURE__ */ jsx41("p", { className: "max-w-sm text-muted-foreground", children: emptyDescription }) : null
|
|
2463
|
+
] }) }) }) : sortedRows.map((row) => /* @__PURE__ */ jsx41(
|
|
1785
2464
|
"tr",
|
|
1786
2465
|
{
|
|
1787
2466
|
className: rowClass,
|
|
@@ -1795,7 +2474,7 @@ function DataTable({
|
|
|
1795
2474
|
} : void 0,
|
|
1796
2475
|
tabIndex: onRowClick ? 0 : void 0,
|
|
1797
2476
|
role: onRowClick ? "button" : void 0,
|
|
1798
|
-
children: columns.map((col) => /* @__PURE__ */
|
|
2477
|
+
children: columns.map((col) => /* @__PURE__ */ jsx41(
|
|
1799
2478
|
"td",
|
|
1800
2479
|
{
|
|
1801
2480
|
className: cn(
|
|
@@ -1811,7 +2490,7 @@ function DataTable({
|
|
|
1811
2490
|
},
|
|
1812
2491
|
getRowKey(row)
|
|
1813
2492
|
)) }),
|
|
1814
|
-
hasFoot ? /* @__PURE__ */
|
|
2493
|
+
hasFoot ? /* @__PURE__ */ jsx41("tfoot", { children: /* @__PURE__ */ jsx41("tr", { children: /* @__PURE__ */ jsx41("td", { colSpan: columns.length, className: footCellClass, children: /* @__PURE__ */ jsxs31(
|
|
1815
2494
|
"div",
|
|
1816
2495
|
{
|
|
1817
2496
|
className: cn(
|
|
@@ -1819,7 +2498,7 @@ function DataTable({
|
|
|
1819
2498
|
showRowCount && footer ? "justify-between" : "justify-start"
|
|
1820
2499
|
),
|
|
1821
2500
|
children: [
|
|
1822
|
-
showRowCount ? /* @__PURE__ */
|
|
2501
|
+
showRowCount ? /* @__PURE__ */ jsx41("span", { children: rowCountText }) : null,
|
|
1823
2502
|
footer
|
|
1824
2503
|
]
|
|
1825
2504
|
}
|
|
@@ -1829,53 +2508,7 @@ function DataTable({
|
|
|
1829
2508
|
|
|
1830
2509
|
// src/app/data/ChartPanel.tsx
|
|
1831
2510
|
import { useId as useId4 } from "react";
|
|
1832
|
-
|
|
1833
|
-
// src/app/data/metrics-shared.tsx
|
|
1834
|
-
import { jsx as jsx38, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
1835
|
-
var metricCardShellClass = cn(
|
|
1836
|
-
studioIntegrationCardClass,
|
|
1837
|
-
"aui-app-metric-card shadow-none",
|
|
1838
|
-
"flex flex-col overflow-hidden"
|
|
1839
|
-
);
|
|
1840
|
-
var metricCardHeaderClass = "flex items-start justify-between gap-3 px-4 pb-1 pt-3";
|
|
1841
|
-
var metricTilesRowClass = "grid w-full min-w-0";
|
|
1842
|
-
var metricChartRegionClass = "relative min-h-0 w-full border-t border-border/40 pt-2";
|
|
1843
|
-
var metricChartPlotRegionClass = "relative min-h-0 w-full border-t border-border/40 px-0 pt-5 pb-3";
|
|
1844
|
-
var metricCellDividerClass = "border-r border-border/40";
|
|
1845
|
-
var MetricCardHeader = ({
|
|
1846
|
-
title,
|
|
1847
|
-
titleId,
|
|
1848
|
-
description,
|
|
1849
|
-
actions
|
|
1850
|
-
}) => {
|
|
1851
|
-
if (!title && !description && !actions) return null;
|
|
1852
|
-
return /* @__PURE__ */ jsxs29("header", { className: metricCardHeaderClass, children: [
|
|
1853
|
-
/* @__PURE__ */ jsxs29("div", { className: "min-w-0", children: [
|
|
1854
|
-
title ? /* @__PURE__ */ jsx38("h3", { id: titleId, className: "text-base font-normal text-foreground", children: title }) : null,
|
|
1855
|
-
description ? /* @__PURE__ */ jsx38("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
|
|
1856
|
-
] }),
|
|
1857
|
-
actions ? /* @__PURE__ */ jsx38("div", { className: "shrink-0", children: actions }) : null
|
|
1858
|
-
] });
|
|
1859
|
-
};
|
|
1860
|
-
function metricTilesGridColsClass(n) {
|
|
1861
|
-
switch (n) {
|
|
1862
|
-
case 1:
|
|
1863
|
-
return "grid-cols-1";
|
|
1864
|
-
case 2:
|
|
1865
|
-
return "grid-cols-2";
|
|
1866
|
-
case 3:
|
|
1867
|
-
return "grid-cols-3";
|
|
1868
|
-
case 5:
|
|
1869
|
-
return "grid-cols-2 sm:grid-cols-5";
|
|
1870
|
-
case 6:
|
|
1871
|
-
return "grid-cols-2 sm:grid-cols-3 lg:grid-cols-6";
|
|
1872
|
-
default:
|
|
1873
|
-
return "grid-cols-2 md:grid-cols-4";
|
|
1874
|
-
}
|
|
1875
|
-
}
|
|
1876
|
-
|
|
1877
|
-
// src/app/data/ChartPanel.tsx
|
|
1878
|
-
import { jsx as jsx39, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2511
|
+
import { jsx as jsx42, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
1879
2512
|
var ChartPanel = ({
|
|
1880
2513
|
title,
|
|
1881
2514
|
description,
|
|
@@ -1888,14 +2521,14 @@ var ChartPanel = ({
|
|
|
1888
2521
|
const titleId = useId4();
|
|
1889
2522
|
const resolvedTitle = title ?? artifact?.title;
|
|
1890
2523
|
const hasHeader = Boolean(resolvedTitle || description || actions);
|
|
1891
|
-
const body = children ?? (artifact ? /* @__PURE__ */
|
|
1892
|
-
return /* @__PURE__ */
|
|
2524
|
+
const body = children ?? (artifact ? /* @__PURE__ */ jsx42(ChartArtifactView, { artifact, embedded: true, height }) : null);
|
|
2525
|
+
return /* @__PURE__ */ jsxs32(
|
|
1893
2526
|
"section",
|
|
1894
2527
|
{
|
|
1895
2528
|
className: cn(metricCardShellClass, "aui-app-chart-panel", className),
|
|
1896
2529
|
"aria-labelledby": resolvedTitle ? titleId : void 0,
|
|
1897
2530
|
children: [
|
|
1898
|
-
/* @__PURE__ */
|
|
2531
|
+
/* @__PURE__ */ jsx42(
|
|
1899
2532
|
MetricCardHeader,
|
|
1900
2533
|
{
|
|
1901
2534
|
title: resolvedTitle,
|
|
@@ -1904,14 +2537,14 @@ var ChartPanel = ({
|
|
|
1904
2537
|
actions
|
|
1905
2538
|
}
|
|
1906
2539
|
),
|
|
1907
|
-
/* @__PURE__ */
|
|
2540
|
+
/* @__PURE__ */ jsx42(
|
|
1908
2541
|
"div",
|
|
1909
2542
|
{
|
|
1910
2543
|
className: cn(
|
|
1911
2544
|
"relative min-h-0 w-full",
|
|
1912
2545
|
hasHeader ? metricChartPlotRegionClass : "pt-2 pb-3"
|
|
1913
2546
|
),
|
|
1914
|
-
children: body ?? /* @__PURE__ */
|
|
2547
|
+
children: body ?? /* @__PURE__ */ jsx42(
|
|
1915
2548
|
"div",
|
|
1916
2549
|
{
|
|
1917
2550
|
className: "flex items-center justify-center text-sm font-normal text-muted-foreground",
|
|
@@ -1927,77 +2560,9 @@ var ChartPanel = ({
|
|
|
1927
2560
|
);
|
|
1928
2561
|
};
|
|
1929
2562
|
|
|
1930
|
-
// src/app/data/MetricTile.tsx
|
|
1931
|
-
import { Fragment as Fragment4, jsx as jsx40, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
1932
|
-
var trendToneClass = {
|
|
1933
|
-
up: "border-border/80 bg-muted/40 text-muted-foreground",
|
|
1934
|
-
down: "border-border/80 bg-muted/40 text-muted-foreground",
|
|
1935
|
-
neutral: "border-border/80 bg-muted/30 text-muted-foreground"
|
|
1936
|
-
};
|
|
1937
|
-
var metricTileBaseClass = "relative flex min-w-0 flex-1 flex-col gap-1 px-4 py-3 text-left font-normal";
|
|
1938
|
-
var metricTileInteractiveClass = cn(
|
|
1939
|
-
metricTileBaseClass,
|
|
1940
|
-
"bg-transparent hover:bg-transparent active:bg-transparent",
|
|
1941
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-foreground/10"
|
|
1942
|
-
);
|
|
1943
|
-
var MetricTile = ({
|
|
1944
|
-
label,
|
|
1945
|
-
value,
|
|
1946
|
-
unit,
|
|
1947
|
-
trend,
|
|
1948
|
-
trendTone = "neutral",
|
|
1949
|
-
active = false,
|
|
1950
|
-
showDivider = false,
|
|
1951
|
-
onSelect,
|
|
1952
|
-
ariaLabel,
|
|
1953
|
-
className
|
|
1954
|
-
}) => {
|
|
1955
|
-
const content = /* @__PURE__ */ jsxs31(Fragment4, { children: [
|
|
1956
|
-
active ? /* @__PURE__ */ jsx40(
|
|
1957
|
-
"span",
|
|
1958
|
-
{
|
|
1959
|
-
"aria-hidden": true,
|
|
1960
|
-
className: "absolute inset-x-0 bottom-0 h-0.5 bg-foreground dark:bg-white"
|
|
1961
|
-
}
|
|
1962
|
-
) : null,
|
|
1963
|
-
/* @__PURE__ */ jsx40("span", { className: "text-xs font-normal text-muted-foreground", children: label }),
|
|
1964
|
-
/* @__PURE__ */ jsxs31("span", { className: "flex items-center gap-2", children: [
|
|
1965
|
-
/* @__PURE__ */ jsxs31("span", { className: "flex items-baseline gap-1", children: [
|
|
1966
|
-
/* @__PURE__ */ jsx40("span", { className: "text-2xl font-normal tracking-tight text-foreground tabular-nums", children: value }),
|
|
1967
|
-
unit ? /* @__PURE__ */ jsx40("span", { className: "text-xs font-normal text-muted-foreground", children: unit }) : null
|
|
1968
|
-
] }),
|
|
1969
|
-
trend ? /* @__PURE__ */ jsx40(
|
|
1970
|
-
"span",
|
|
1971
|
-
{
|
|
1972
|
-
className: cn(
|
|
1973
|
-
"rounded-full border px-1.5 py-0.5 text-xs font-normal",
|
|
1974
|
-
trendToneClass[trendTone]
|
|
1975
|
-
),
|
|
1976
|
-
children: trend
|
|
1977
|
-
}
|
|
1978
|
-
) : null
|
|
1979
|
-
] })
|
|
1980
|
-
] });
|
|
1981
|
-
const divider = showDivider ? metricCellDividerClass : void 0;
|
|
1982
|
-
if (onSelect) {
|
|
1983
|
-
return /* @__PURE__ */ jsx40(
|
|
1984
|
-
"button",
|
|
1985
|
-
{
|
|
1986
|
-
type: "button",
|
|
1987
|
-
onClick: onSelect,
|
|
1988
|
-
"aria-pressed": active,
|
|
1989
|
-
"aria-label": ariaLabel,
|
|
1990
|
-
className: cn(metricTileInteractiveClass, divider, className),
|
|
1991
|
-
children: content
|
|
1992
|
-
}
|
|
1993
|
-
);
|
|
1994
|
-
}
|
|
1995
|
-
return /* @__PURE__ */ jsx40("div", { className: cn(metricTileBaseClass, divider, className), children: content });
|
|
1996
|
-
};
|
|
1997
|
-
|
|
1998
2563
|
// src/app/data/MetricRow.tsx
|
|
1999
2564
|
import { useId as useId5, useState as useState5 } from "react";
|
|
2000
|
-
import { jsx as
|
|
2565
|
+
import { jsx as jsx43, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2001
2566
|
var MetricRow = ({
|
|
2002
2567
|
title,
|
|
2003
2568
|
description,
|
|
@@ -2019,13 +2584,13 @@ var MetricRow = ({
|
|
|
2019
2584
|
if (activeMetricId == null) setInternalId(id);
|
|
2020
2585
|
onMetricChange?.(id);
|
|
2021
2586
|
};
|
|
2022
|
-
return /* @__PURE__ */
|
|
2587
|
+
return /* @__PURE__ */ jsxs33(
|
|
2023
2588
|
"section",
|
|
2024
2589
|
{
|
|
2025
2590
|
className: cn(metricCardShellClass, className),
|
|
2026
2591
|
"aria-labelledby": title ? titleId : void 0,
|
|
2027
2592
|
children: [
|
|
2028
|
-
/* @__PURE__ */
|
|
2593
|
+
/* @__PURE__ */ jsx43(
|
|
2029
2594
|
MetricCardHeader,
|
|
2030
2595
|
{
|
|
2031
2596
|
title,
|
|
@@ -2034,7 +2599,7 @@ var MetricRow = ({
|
|
|
2034
2599
|
actions
|
|
2035
2600
|
}
|
|
2036
2601
|
),
|
|
2037
|
-
/* @__PURE__ */
|
|
2602
|
+
/* @__PURE__ */ jsx43(
|
|
2038
2603
|
"div",
|
|
2039
2604
|
{
|
|
2040
2605
|
role: selectable ? "group" : void 0,
|
|
@@ -2044,7 +2609,7 @@ var MetricRow = ({
|
|
|
2044
2609
|
metricTilesGridColsClass(metrics.length),
|
|
2045
2610
|
(title || description || actions) && "mt-3"
|
|
2046
2611
|
),
|
|
2047
|
-
children: metrics.map((m, index) => /* @__PURE__ */
|
|
2612
|
+
children: metrics.map((m, index) => /* @__PURE__ */ jsx43(
|
|
2048
2613
|
MetricTile,
|
|
2049
2614
|
{
|
|
2050
2615
|
label: m.label,
|
|
@@ -2067,7 +2632,7 @@ var MetricRow = ({
|
|
|
2067
2632
|
|
|
2068
2633
|
// src/app/data/MetricChartCard.tsx
|
|
2069
2634
|
import { useId as useId6, useState as useState6 } from "react";
|
|
2070
|
-
import { jsx as
|
|
2635
|
+
import { jsx as jsx44, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2071
2636
|
var MetricChartCard = ({
|
|
2072
2637
|
title,
|
|
2073
2638
|
description,
|
|
@@ -2097,13 +2662,13 @@ var MetricChartCard = ({
|
|
|
2097
2662
|
};
|
|
2098
2663
|
const hasHeader = Boolean(title || description || actions);
|
|
2099
2664
|
const chartAriaLabel = typeof active?.label === "string" ? `${active.label} over time` : "Metric chart";
|
|
2100
|
-
return /* @__PURE__ */
|
|
2665
|
+
return /* @__PURE__ */ jsxs34(
|
|
2101
2666
|
"section",
|
|
2102
2667
|
{
|
|
2103
2668
|
className: cn(metricCardShellClass, className),
|
|
2104
2669
|
"aria-labelledby": title ? titleId : void 0,
|
|
2105
2670
|
children: [
|
|
2106
|
-
/* @__PURE__ */
|
|
2671
|
+
/* @__PURE__ */ jsx44(
|
|
2107
2672
|
MetricCardHeader,
|
|
2108
2673
|
{
|
|
2109
2674
|
title,
|
|
@@ -2112,7 +2677,7 @@ var MetricChartCard = ({
|
|
|
2112
2677
|
actions
|
|
2113
2678
|
}
|
|
2114
2679
|
),
|
|
2115
|
-
/* @__PURE__ */
|
|
2680
|
+
/* @__PURE__ */ jsx44(
|
|
2116
2681
|
"div",
|
|
2117
2682
|
{
|
|
2118
2683
|
role: "group",
|
|
@@ -2122,7 +2687,7 @@ var MetricChartCard = ({
|
|
|
2122
2687
|
metricTilesGridColsClass(metrics.length),
|
|
2123
2688
|
hasHeader && "mt-3"
|
|
2124
2689
|
),
|
|
2125
|
-
children: metrics.map((m, index) => /* @__PURE__ */
|
|
2690
|
+
children: metrics.map((m, index) => /* @__PURE__ */ jsx44(
|
|
2126
2691
|
MetricTile,
|
|
2127
2692
|
{
|
|
2128
2693
|
label: m.label,
|
|
@@ -2138,7 +2703,7 @@ var MetricChartCard = ({
|
|
|
2138
2703
|
))
|
|
2139
2704
|
}
|
|
2140
2705
|
),
|
|
2141
|
-
/* @__PURE__ */
|
|
2706
|
+
/* @__PURE__ */ jsx44("div", { className: metricChartRegionClass, "aria-live": "polite", "aria-atomic": "true", children: active?.data && active.data.length > 0 ? /* @__PURE__ */ jsx44(
|
|
2142
2707
|
LineAreaChart,
|
|
2143
2708
|
{
|
|
2144
2709
|
data: active.data,
|
|
@@ -2158,7 +2723,7 @@ var MetricChartCard = ({
|
|
|
2158
2723
|
ariaLabel: chartAriaLabel
|
|
2159
2724
|
},
|
|
2160
2725
|
active.id
|
|
2161
|
-
) : /* @__PURE__ */
|
|
2726
|
+
) : /* @__PURE__ */ jsx44(
|
|
2162
2727
|
"div",
|
|
2163
2728
|
{
|
|
2164
2729
|
className: "flex w-full items-center justify-center text-sm font-normal text-muted-foreground",
|
|
@@ -2174,7 +2739,7 @@ var MetricChartCard = ({
|
|
|
2174
2739
|
|
|
2175
2740
|
// src/charts/sparkline.tsx
|
|
2176
2741
|
import { useId as useId7 } from "react";
|
|
2177
|
-
import { Fragment as Fragment5, jsx as
|
|
2742
|
+
import { Fragment as Fragment5, jsx as jsx45, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2178
2743
|
var Sparkline = ({
|
|
2179
2744
|
data,
|
|
2180
2745
|
dataKey = "value",
|
|
@@ -2189,7 +2754,7 @@ var Sparkline = ({
|
|
|
2189
2754
|
const uid = useId7();
|
|
2190
2755
|
const values = data.map((d) => typeof d === "number" ? d : toNum(d[dataKey]));
|
|
2191
2756
|
if (values.length === 0) {
|
|
2192
|
-
return /* @__PURE__ */
|
|
2757
|
+
return /* @__PURE__ */ jsx45("span", { className: cn("inline-block", className), style: { width, height } });
|
|
2193
2758
|
}
|
|
2194
2759
|
const pad = strokeWidth + 1;
|
|
2195
2760
|
const min = Math.min(...values);
|
|
@@ -2201,7 +2766,7 @@ var Sparkline = ({
|
|
|
2201
2766
|
x: pad + (values.length > 1 ? i / (values.length - 1) * innerW : innerW / 2),
|
|
2202
2767
|
y: pad + innerH - (v - min) / range * innerH
|
|
2203
2768
|
}));
|
|
2204
|
-
return /* @__PURE__ */
|
|
2769
|
+
return /* @__PURE__ */ jsxs35(
|
|
2205
2770
|
"svg",
|
|
2206
2771
|
{
|
|
2207
2772
|
width,
|
|
@@ -2212,14 +2777,14 @@ var Sparkline = ({
|
|
|
2212
2777
|
"aria-label": ariaLabel,
|
|
2213
2778
|
preserveAspectRatio: "none",
|
|
2214
2779
|
children: [
|
|
2215
|
-
area && /* @__PURE__ */
|
|
2216
|
-
/* @__PURE__ */
|
|
2217
|
-
/* @__PURE__ */
|
|
2218
|
-
/* @__PURE__ */
|
|
2780
|
+
area && /* @__PURE__ */ jsxs35(Fragment5, { children: [
|
|
2781
|
+
/* @__PURE__ */ jsx45("defs", { children: /* @__PURE__ */ jsxs35("linearGradient", { id: `${uid}-spark`, x1: "0", x2: "0", y1: "0", y2: "1", children: [
|
|
2782
|
+
/* @__PURE__ */ jsx45("stop", { offset: "0%", style: { stopColor: color, stopOpacity: 0.25 } }),
|
|
2783
|
+
/* @__PURE__ */ jsx45("stop", { offset: "100%", style: { stopColor: color, stopOpacity: 0 } })
|
|
2219
2784
|
] }) }),
|
|
2220
|
-
/* @__PURE__ */
|
|
2785
|
+
/* @__PURE__ */ jsx45("path", { d: monotoneAreaPath(points, height - pad), fill: `url(#${uid}-spark)` })
|
|
2221
2786
|
] }),
|
|
2222
|
-
/* @__PURE__ */
|
|
2787
|
+
/* @__PURE__ */ jsx45(
|
|
2223
2788
|
"path",
|
|
2224
2789
|
{
|
|
2225
2790
|
d: monotoneLinePath(points),
|
|
@@ -2237,6 +2802,18 @@ var Sparkline = ({
|
|
|
2237
2802
|
|
|
2238
2803
|
export {
|
|
2239
2804
|
APP_KIT_AGENT_INSTRUCTIONS,
|
|
2805
|
+
createTimbalTheme,
|
|
2806
|
+
themeToCss,
|
|
2807
|
+
applyTimbalTheme,
|
|
2808
|
+
clearTimbalTheme,
|
|
2809
|
+
TIMBAL_THEME_PRESETS,
|
|
2810
|
+
getThemePreset,
|
|
2811
|
+
applyThemePreset,
|
|
2812
|
+
getStoredThemePreset,
|
|
2813
|
+
THEME_AGENT_INSTRUCTIONS,
|
|
2814
|
+
TimbalThemeStyle,
|
|
2815
|
+
MetricTile,
|
|
2816
|
+
ThemePresetGallery,
|
|
2240
2817
|
appPageColumnClass,
|
|
2241
2818
|
appShellTopbarInsetClass,
|
|
2242
2819
|
appShellInsetTopClass,
|
|
@@ -2289,7 +2866,6 @@ export {
|
|
|
2289
2866
|
FilterBar,
|
|
2290
2867
|
DataTable,
|
|
2291
2868
|
ChartPanel,
|
|
2292
|
-
MetricTile,
|
|
2293
2869
|
MetricRow,
|
|
2294
2870
|
MetricChartCard,
|
|
2295
2871
|
Sparkline
|