@camstack/ui-library 0.1.26 → 0.1.28

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/dist/index.js CHANGED
@@ -1273,8 +1273,30 @@ function ProviderBadge({
1273
1273
  ] });
1274
1274
  }
1275
1275
 
1276
+ // src/composites/version-badge.tsx
1277
+ import { jsx as jsx22 } from "react/jsx-runtime";
1278
+ var VARIANT_STYLES = {
1279
+ success: "bg-emerald-400 text-emerald-950",
1280
+ warning: "bg-amber-400 text-amber-950",
1281
+ danger: "bg-red-400 text-red-950",
1282
+ info: "bg-blue-400 text-blue-950",
1283
+ neutral: "bg-foreground-subtle/20 text-foreground"
1284
+ };
1285
+ function SemanticBadge({ children, variant = "neutral", mono, className }) {
1286
+ return /* @__PURE__ */ jsx22("span", { className: cn(
1287
+ "inline-flex items-center rounded-md px-2 py-0.5 text-[11px] font-bold leading-tight",
1288
+ mono && "font-mono",
1289
+ VARIANT_STYLES[variant],
1290
+ className
1291
+ ), children });
1292
+ }
1293
+ function VersionBadge({ version, preRelease, className }) {
1294
+ const isPreRelease = preRelease ?? /-(alpha|beta|rc|dev|canary|next)/i.test(version);
1295
+ return /* @__PURE__ */ jsx22(SemanticBadge, { variant: isPreRelease ? "warning" : "success", mono: true, className, children: version });
1296
+ }
1297
+
1276
1298
  // src/composites/form-field.tsx
1277
- import { jsx as jsx22, jsxs as jsxs8 } from "react/jsx-runtime";
1299
+ import { jsx as jsx23, jsxs as jsxs8 } from "react/jsx-runtime";
1278
1300
  function FormField({
1279
1301
  label,
1280
1302
  description,
@@ -1297,31 +1319,31 @@ function FormField({
1297
1319
  /* @__PURE__ */ jsxs8("div", { className: cn(isHorizontal ? "flex-1" : ""), children: [
1298
1320
  /* @__PURE__ */ jsxs8(Label, { children: [
1299
1321
  label,
1300
- required && /* @__PURE__ */ jsx22("span", { className: "text-danger ml-0.5", children: "*" })
1322
+ required && /* @__PURE__ */ jsx23("span", { className: "text-danger ml-0.5", children: "*" })
1301
1323
  ] }),
1302
- description && /* @__PURE__ */ jsx22("p", { className: "text-foreground-subtle text-xs mt-0.5", children: description })
1324
+ description && /* @__PURE__ */ jsx23("p", { className: "text-foreground-subtle text-xs mt-0.5", children: description })
1303
1325
  ] }),
1304
- /* @__PURE__ */ jsx22("div", { className: cn(isHorizontal ? "shrink-0" : ""), children }),
1305
- error && /* @__PURE__ */ jsx22("p", { className: "text-danger text-xs", children: error })
1326
+ /* @__PURE__ */ jsx23("div", { className: cn(isHorizontal ? "shrink-0" : ""), children }),
1327
+ error && /* @__PURE__ */ jsx23("p", { className: "text-danger text-xs", children: error })
1306
1328
  ]
1307
1329
  }
1308
1330
  );
1309
1331
  }
1310
1332
 
1311
1333
  // src/composites/page-header.tsx
1312
- import { jsx as jsx23, jsxs as jsxs9 } from "react/jsx-runtime";
1334
+ import { jsx as jsx24, jsxs as jsxs9 } from "react/jsx-runtime";
1313
1335
  function PageHeader({ title, subtitle, actions, className }) {
1314
1336
  return /* @__PURE__ */ jsxs9("div", { className: cn("flex items-center justify-between mb-3", className), children: [
1315
1337
  /* @__PURE__ */ jsxs9("div", { children: [
1316
- /* @__PURE__ */ jsx23("h1", { className: "text-sm font-semibold text-foreground", children: title }),
1317
- subtitle && /* @__PURE__ */ jsx23("p", { className: "text-foreground-subtle text-xs", children: subtitle })
1338
+ /* @__PURE__ */ jsx24("h1", { className: "text-sm font-semibold text-foreground", children: title }),
1339
+ subtitle && /* @__PURE__ */ jsx24("p", { className: "text-foreground-subtle text-xs", children: subtitle })
1318
1340
  ] }),
1319
- actions && /* @__PURE__ */ jsx23("div", { className: "flex items-center gap-2", children: actions })
1341
+ actions && /* @__PURE__ */ jsx24("div", { className: "flex items-center gap-2", children: actions })
1320
1342
  ] });
1321
1343
  }
1322
1344
 
1323
1345
  // src/composites/empty-state.tsx
1324
- import { jsx as jsx24, jsxs as jsxs10 } from "react/jsx-runtime";
1346
+ import { jsx as jsx25, jsxs as jsxs10 } from "react/jsx-runtime";
1325
1347
  function EmptyState({
1326
1348
  icon: Icon,
1327
1349
  title,
@@ -1330,17 +1352,17 @@ function EmptyState({
1330
1352
  className
1331
1353
  }) {
1332
1354
  return /* @__PURE__ */ jsxs10("div", { className: cn("flex flex-col items-center justify-center gap-3 py-12", className), children: [
1333
- Icon && /* @__PURE__ */ jsx24(Icon, { className: "h-12 w-12 text-foreground-subtle", "aria-hidden": "true" }),
1355
+ Icon && /* @__PURE__ */ jsx25(Icon, { className: "h-12 w-12 text-foreground-subtle", "aria-hidden": "true" }),
1334
1356
  /* @__PURE__ */ jsxs10("div", { className: "flex flex-col items-center gap-1 text-center", children: [
1335
- /* @__PURE__ */ jsx24("p", { className: "text-foreground-muted text-sm font-medium", children: title }),
1336
- description && /* @__PURE__ */ jsx24("p", { className: "text-foreground-subtle text-xs max-w-xs", children: description })
1357
+ /* @__PURE__ */ jsx25("p", { className: "text-foreground-muted text-sm font-medium", children: title }),
1358
+ description && /* @__PURE__ */ jsx25("p", { className: "text-foreground-subtle text-xs max-w-xs", children: description })
1337
1359
  ] }),
1338
- action && /* @__PURE__ */ jsx24("div", { className: "mt-1", children: action })
1360
+ action && /* @__PURE__ */ jsx25("div", { className: "mt-1", children: action })
1339
1361
  ] });
1340
1362
  }
1341
1363
 
1342
1364
  // src/composites/confirm-dialog.tsx
1343
- import { jsx as jsx25, jsxs as jsxs11 } from "react/jsx-runtime";
1365
+ import { jsx as jsx26, jsxs as jsxs11 } from "react/jsx-runtime";
1344
1366
  function ConfirmDialog({
1345
1367
  title,
1346
1368
  message,
@@ -1352,14 +1374,14 @@ function ConfirmDialog({
1352
1374
  open,
1353
1375
  onOpenChange
1354
1376
  }) {
1355
- return /* @__PURE__ */ jsx25(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs11(DialogContent, { children: [
1377
+ return /* @__PURE__ */ jsx26(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs11(DialogContent, { children: [
1356
1378
  /* @__PURE__ */ jsxs11(DialogHeader, { children: [
1357
- /* @__PURE__ */ jsx25(DialogTitle, { children: title }),
1358
- /* @__PURE__ */ jsx25(DialogDescription, { children: message })
1379
+ /* @__PURE__ */ jsx26(DialogTitle, { children: title }),
1380
+ /* @__PURE__ */ jsx26(DialogDescription, { children: message })
1359
1381
  ] }),
1360
1382
  /* @__PURE__ */ jsxs11(DialogFooter, { children: [
1361
- /* @__PURE__ */ jsx25(Button, { variant: "ghost", onClick: onCancel, children: cancelLabel }),
1362
- /* @__PURE__ */ jsx25(
1383
+ /* @__PURE__ */ jsx26(Button, { variant: "ghost", onClick: onCancel, children: cancelLabel }),
1384
+ /* @__PURE__ */ jsx26(
1363
1385
  Button,
1364
1386
  {
1365
1387
  variant: variant === "danger" ? "danger" : "primary",
@@ -1373,11 +1395,11 @@ function ConfirmDialog({
1373
1395
 
1374
1396
  // src/composites/stat-card.tsx
1375
1397
  import { TrendingUp, TrendingDown } from "lucide-react";
1376
- import { jsx as jsx26, jsxs as jsxs12 } from "react/jsx-runtime";
1398
+ import { jsx as jsx27, jsxs as jsxs12 } from "react/jsx-runtime";
1377
1399
  function StatCard({ value, label, trend, className }) {
1378
1400
  return /* @__PURE__ */ jsxs12(Card, { className: cn("flex flex-col gap-1", className), children: [
1379
1401
  /* @__PURE__ */ jsxs12("div", { className: "flex items-baseline gap-2", children: [
1380
- /* @__PURE__ */ jsx26("span", { className: "text-2xl font-semibold text-foreground", children: value }),
1402
+ /* @__PURE__ */ jsx27("span", { className: "text-2xl font-semibold text-foreground", children: value }),
1381
1403
  trend && /* @__PURE__ */ jsxs12(
1382
1404
  "span",
1383
1405
  {
@@ -1386,27 +1408,27 @@ function StatCard({ value, label, trend, className }) {
1386
1408
  trend.direction === "up" ? "text-success" : "text-danger"
1387
1409
  ),
1388
1410
  children: [
1389
- trend.direction === "up" ? /* @__PURE__ */ jsx26(TrendingUp, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx26(TrendingDown, { className: "h-3 w-3" }),
1411
+ trend.direction === "up" ? /* @__PURE__ */ jsx27(TrendingUp, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx27(TrendingDown, { className: "h-3 w-3" }),
1390
1412
  trend.value,
1391
1413
  "%"
1392
1414
  ]
1393
1415
  }
1394
1416
  )
1395
1417
  ] }),
1396
- /* @__PURE__ */ jsx26("span", { className: "text-xs text-foreground-muted", children: label })
1418
+ /* @__PURE__ */ jsx27("span", { className: "text-xs text-foreground-muted", children: label })
1397
1419
  ] });
1398
1420
  }
1399
1421
 
1400
1422
  // src/composites/key-value-list.tsx
1401
- import { jsx as jsx27, jsxs as jsxs13 } from "react/jsx-runtime";
1423
+ import { jsx as jsx28, jsxs as jsxs13 } from "react/jsx-runtime";
1402
1424
  function KeyValueList({ items, className }) {
1403
- return /* @__PURE__ */ jsx27("dl", { className: cn("flex flex-col", className), children: items.map((item) => /* @__PURE__ */ jsxs13(
1425
+ return /* @__PURE__ */ jsx28("dl", { className: cn("flex flex-col", className), children: items.map((item) => /* @__PURE__ */ jsxs13(
1404
1426
  "div",
1405
1427
  {
1406
1428
  className: "flex items-center h-7",
1407
1429
  children: [
1408
- /* @__PURE__ */ jsx27("dt", { className: "text-foreground-subtle text-xs w-1/3 shrink-0", children: item.key }),
1409
- /* @__PURE__ */ jsx27("dd", { className: "text-foreground text-xs", children: item.value })
1430
+ /* @__PURE__ */ jsx28("dt", { className: "text-foreground-subtle text-xs w-1/3 shrink-0", children: item.key }),
1431
+ /* @__PURE__ */ jsx28("dd", { className: "text-foreground text-xs", children: item.value })
1410
1432
  ]
1411
1433
  },
1412
1434
  item.key
@@ -1416,7 +1438,7 @@ function KeyValueList({ items, className }) {
1416
1438
  // src/composites/code-block.tsx
1417
1439
  import { useCallback as useCallback7, useState as useState8 } from "react";
1418
1440
  import { Copy, Check } from "lucide-react";
1419
- import { jsx as jsx28, jsxs as jsxs14 } from "react/jsx-runtime";
1441
+ import { jsx as jsx29, jsxs as jsxs14 } from "react/jsx-runtime";
1420
1442
  function CodeBlock({ children, maxHeight = 300, className }) {
1421
1443
  const [copied, setCopied] = useState8(false);
1422
1444
  const handleCopy = useCallback7(() => {
@@ -1426,8 +1448,8 @@ function CodeBlock({ children, maxHeight = 300, className }) {
1426
1448
  });
1427
1449
  }, [children]);
1428
1450
  return /* @__PURE__ */ jsxs14("div", { className: cn("relative group", className), children: [
1429
- /* @__PURE__ */ jsx28(ScrollArea, { style: { maxHeight }, children: /* @__PURE__ */ jsx28("pre", { className: "font-mono text-xs bg-surface p-3 rounded-md border border-border-subtle", children: /* @__PURE__ */ jsx28("code", { children }) }) }),
1430
- /* @__PURE__ */ jsx28("div", { className: "absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity", children: /* @__PURE__ */ jsx28(
1451
+ /* @__PURE__ */ jsx29(ScrollArea, { style: { maxHeight }, children: /* @__PURE__ */ jsx29("pre", { className: "font-mono text-xs bg-surface p-3 rounded-md border border-border-subtle", children: /* @__PURE__ */ jsx29("code", { children }) }) }),
1452
+ /* @__PURE__ */ jsx29("div", { className: "absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity", children: /* @__PURE__ */ jsx29(
1431
1453
  IconButton,
1432
1454
  {
1433
1455
  icon: copied ? Check : Copy,
@@ -1442,27 +1464,27 @@ function CodeBlock({ children, maxHeight = 300, className }) {
1442
1464
 
1443
1465
  // src/composites/filter-bar.tsx
1444
1466
  import { Search } from "lucide-react";
1445
- import { jsx as jsx29 } from "react/jsx-runtime";
1467
+ import { jsx as jsx30 } from "react/jsx-runtime";
1446
1468
  function FilterBar({ filters, values, onChange, className }) {
1447
1469
  const handleChange = (key, value) => {
1448
1470
  onChange({ ...values, [key]: value });
1449
1471
  };
1450
- return /* @__PURE__ */ jsx29("div", { className: cn("flex items-center gap-2 flex-wrap", className), children: filters.map((filter) => {
1472
+ return /* @__PURE__ */ jsx30("div", { className: cn("flex items-center gap-2 flex-wrap", className), children: filters.map((filter) => {
1451
1473
  switch (filter.type) {
1452
1474
  case "search":
1453
- return /* @__PURE__ */ jsx29(
1475
+ return /* @__PURE__ */ jsx30(
1454
1476
  Input,
1455
1477
  {
1456
1478
  placeholder: filter.placeholder ?? "Search...",
1457
1479
  value: values[filter.key] ?? "",
1458
1480
  onChange: (e) => handleChange(filter.key, e.target.value),
1459
- leftSlot: /* @__PURE__ */ jsx29(Search, { className: "h-3 w-3 text-foreground-subtle" }),
1481
+ leftSlot: /* @__PURE__ */ jsx30(Search, { className: "h-3 w-3 text-foreground-subtle" }),
1460
1482
  className: "w-48"
1461
1483
  },
1462
1484
  filter.key
1463
1485
  );
1464
1486
  case "select":
1465
- return /* @__PURE__ */ jsx29(
1487
+ return /* @__PURE__ */ jsx30(
1466
1488
  Select,
1467
1489
  {
1468
1490
  options: filter.options,
@@ -1473,10 +1495,10 @@ function FilterBar({ filters, values, onChange, className }) {
1473
1495
  filter.key
1474
1496
  );
1475
1497
  case "badge-toggle":
1476
- return /* @__PURE__ */ jsx29("div", { className: "flex items-center gap-1", children: filter.options.map((option) => {
1498
+ return /* @__PURE__ */ jsx30("div", { className: "flex items-center gap-1", children: filter.options.map((option) => {
1477
1499
  const currentValue = values[filter.key];
1478
1500
  const isActive = currentValue === option.value;
1479
- return /* @__PURE__ */ jsx29(
1501
+ return /* @__PURE__ */ jsx30(
1480
1502
  "button",
1481
1503
  {
1482
1504
  type: "button",
@@ -1484,7 +1506,7 @@ function FilterBar({ filters, values, onChange, className }) {
1484
1506
  filter.key,
1485
1507
  isActive ? void 0 : option.value
1486
1508
  ),
1487
- children: /* @__PURE__ */ jsx29(
1509
+ children: /* @__PURE__ */ jsx30(
1488
1510
  Badge,
1489
1511
  {
1490
1512
  variant: isActive ? "info" : "default",
@@ -1503,7 +1525,7 @@ function FilterBar({ filters, values, onChange, className }) {
1503
1525
  }
1504
1526
 
1505
1527
  // src/composites/app-shell/sidebar-item.tsx
1506
- import { jsx as jsx30, jsxs as jsxs15 } from "react/jsx-runtime";
1528
+ import { jsx as jsx31, jsxs as jsxs15 } from "react/jsx-runtime";
1507
1529
  function SidebarItem({
1508
1530
  label,
1509
1531
  icon: Icon,
@@ -1522,16 +1544,16 @@ function SidebarItem({
1522
1544
  className
1523
1545
  ),
1524
1546
  children: [
1525
- /* @__PURE__ */ jsx30(Icon, { className: "h-3.5 w-3.5 shrink-0" }),
1526
- /* @__PURE__ */ jsx30("span", { className: "truncate flex-1", children: label }),
1527
- badge !== void 0 && /* @__PURE__ */ jsx30(Badge, { className: "ml-auto text-[10px] px-1.5 py-0", children: badge })
1547
+ /* @__PURE__ */ jsx31(Icon, { className: "h-3.5 w-3.5 shrink-0" }),
1548
+ /* @__PURE__ */ jsx31("span", { className: "truncate flex-1", children: label }),
1549
+ badge !== void 0 && /* @__PURE__ */ jsx31(Badge, { className: "ml-auto text-[10px] px-1.5 py-0", children: badge })
1528
1550
  ]
1529
1551
  }
1530
1552
  );
1531
1553
  }
1532
1554
 
1533
1555
  // src/composites/app-shell/sidebar.tsx
1534
- import { jsx as jsx31, jsxs as jsxs16 } from "react/jsx-runtime";
1556
+ import { jsx as jsx32, jsxs as jsxs16 } from "react/jsx-runtime";
1535
1557
  function Sidebar({ logo, sections, footer, className }) {
1536
1558
  return /* @__PURE__ */ jsxs16(
1537
1559
  "nav",
@@ -1541,14 +1563,14 @@ function Sidebar({ logo, sections, footer, className }) {
1541
1563
  className
1542
1564
  ),
1543
1565
  children: [
1544
- logo && /* @__PURE__ */ jsx31("div", { className: "px-3 py-2 shrink-0", children: logo }),
1545
- /* @__PURE__ */ jsx31("div", { className: "flex-1 overflow-auto px-1 py-1", children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs16("div", { className: cn(sectionIndex > 0 ? "mt-3" : ""), children: [
1546
- section.label && /* @__PURE__ */ jsx31("span", { className: "text-[10px] text-foreground-disabled uppercase tracking-wider px-2 mb-1 block", children: section.label }),
1547
- /* @__PURE__ */ jsx31("div", { className: "flex flex-col gap-0.5", children: section.items.map((item) => /* @__PURE__ */ jsx31(SidebarItem, { ...item }, item.href)) })
1566
+ logo && /* @__PURE__ */ jsx32("div", { className: "px-3 py-2 shrink-0", children: logo }),
1567
+ /* @__PURE__ */ jsx32("div", { className: "flex-1 overflow-auto px-1 py-1", children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs16("div", { className: cn(sectionIndex > 0 ? "mt-3" : ""), children: [
1568
+ section.label && /* @__PURE__ */ jsx32("span", { className: "text-[10px] text-foreground-disabled uppercase tracking-wider px-2 mb-1 block", children: section.label }),
1569
+ /* @__PURE__ */ jsx32("div", { className: "flex flex-col gap-0.5", children: section.items.map((item) => /* @__PURE__ */ jsx32(SidebarItem, { ...item }, item.href)) })
1548
1570
  ] }, sectionIndex)) }),
1549
1571
  footer && footer.length > 0 && /* @__PURE__ */ jsxs16("div", { className: "shrink-0 px-1 pb-1", children: [
1550
- /* @__PURE__ */ jsx31(Separator, { className: "mb-1" }),
1551
- /* @__PURE__ */ jsx31("div", { className: "flex flex-col gap-0.5", children: footer.map((item) => /* @__PURE__ */ jsx31(SidebarItem, { ...item }, item.href)) })
1572
+ /* @__PURE__ */ jsx32(Separator, { className: "mb-1" }),
1573
+ /* @__PURE__ */ jsx32("div", { className: "flex flex-col gap-0.5", children: footer.map((item) => /* @__PURE__ */ jsx32(SidebarItem, { ...item }, item.href)) })
1552
1574
  ] })
1553
1575
  ]
1554
1576
  }
@@ -1557,29 +1579,29 @@ function Sidebar({ logo, sections, footer, className }) {
1557
1579
 
1558
1580
  // src/composites/app-shell/app-shell.tsx
1559
1581
  import { ChevronRight } from "lucide-react";
1560
- import { jsx as jsx32, jsxs as jsxs17 } from "react/jsx-runtime";
1582
+ import { jsx as jsx33, jsxs as jsxs17 } from "react/jsx-runtime";
1561
1583
  function AppShell({ sidebar, header, children, className }) {
1562
1584
  return /* @__PURE__ */ jsxs17("div", { className: cn("flex h-screen", className), children: [
1563
- /* @__PURE__ */ jsx32(Sidebar, { ...sidebar }),
1585
+ /* @__PURE__ */ jsx33(Sidebar, { ...sidebar }),
1564
1586
  /* @__PURE__ */ jsxs17("div", { className: "flex flex-1 flex-col min-w-0", children: [
1565
1587
  header && /* @__PURE__ */ jsxs17("header", { className: "flex items-center h-10 border-b border-border px-4 shrink-0", children: [
1566
- header.breadcrumbs && header.breadcrumbs.length > 0 && /* @__PURE__ */ jsx32("nav", { className: "flex items-center gap-1 text-xs flex-1 min-w-0", children: header.breadcrumbs.map((crumb, index) => {
1588
+ header.breadcrumbs && header.breadcrumbs.length > 0 && /* @__PURE__ */ jsx33("nav", { className: "flex items-center gap-1 text-xs flex-1 min-w-0", children: header.breadcrumbs.map((crumb, index) => {
1567
1589
  const isLast = index === header.breadcrumbs.length - 1;
1568
1590
  return /* @__PURE__ */ jsxs17("span", { className: "flex items-center gap-1", children: [
1569
- index > 0 && /* @__PURE__ */ jsx32(ChevronRight, { className: "h-3 w-3 text-foreground-subtle shrink-0" }),
1570
- crumb.href && !isLast ? /* @__PURE__ */ jsx32(
1591
+ index > 0 && /* @__PURE__ */ jsx33(ChevronRight, { className: "h-3 w-3 text-foreground-subtle shrink-0" }),
1592
+ crumb.href && !isLast ? /* @__PURE__ */ jsx33(
1571
1593
  "a",
1572
1594
  {
1573
1595
  href: crumb.href,
1574
1596
  className: "text-foreground-subtle hover:text-foreground transition-colors truncate",
1575
1597
  children: crumb.label
1576
1598
  }
1577
- ) : /* @__PURE__ */ jsx32("span", { className: "text-foreground truncate", children: crumb.label })
1599
+ ) : /* @__PURE__ */ jsx33("span", { className: "text-foreground truncate", children: crumb.label })
1578
1600
  ] }, index);
1579
1601
  }) }),
1580
- header.actions && /* @__PURE__ */ jsx32("div", { className: "flex items-center gap-2 ml-auto shrink-0", children: header.actions })
1602
+ header.actions && /* @__PURE__ */ jsx33("div", { className: "flex items-center gap-2 ml-auto shrink-0", children: header.actions })
1581
1603
  ] }),
1582
- /* @__PURE__ */ jsx32("main", { className: "flex-1 overflow-auto p-4", children })
1604
+ /* @__PURE__ */ jsx33("main", { className: "flex-1 overflow-auto p-4", children })
1583
1605
  ] })
1584
1606
  ] });
1585
1607
  }
@@ -1597,20 +1619,20 @@ import {
1597
1619
 
1598
1620
  // src/composites/data-table/data-table-header.tsx
1599
1621
  import { ArrowUpDown, ArrowUp, ArrowDown } from "lucide-react";
1600
- import { jsx as jsx33, jsxs as jsxs18 } from "react/jsx-runtime";
1622
+ import { jsx as jsx34, jsxs as jsxs18 } from "react/jsx-runtime";
1601
1623
  function DataTableHeader({
1602
1624
  headerGroups,
1603
1625
  onSortingChange,
1604
1626
  stickyHeader,
1605
1627
  flexRender: render
1606
1628
  }) {
1607
- return /* @__PURE__ */ jsx33(
1629
+ return /* @__PURE__ */ jsx34(
1608
1630
  "thead",
1609
1631
  {
1610
1632
  className: cn(
1611
1633
  stickyHeader && "sticky top-0 z-10 bg-background"
1612
1634
  ),
1613
- children: headerGroups.map((headerGroup) => /* @__PURE__ */ jsx33("tr", { className: "h-6", children: headerGroup.headers.map((header) => /* @__PURE__ */ jsx33(
1635
+ children: headerGroups.map((headerGroup) => /* @__PURE__ */ jsx34("tr", { className: "h-6", children: headerGroup.headers.map((header) => /* @__PURE__ */ jsx34(
1614
1636
  HeaderCell,
1615
1637
  {
1616
1638
  header,
@@ -1625,7 +1647,7 @@ function DataTableHeader({
1625
1647
  function HeaderCell({ header, sortable, flexRender: render }) {
1626
1648
  const sorted = header.column.getIsSorted();
1627
1649
  const SortIcon = sorted === "asc" ? ArrowUp : sorted === "desc" ? ArrowDown : ArrowUpDown;
1628
- return /* @__PURE__ */ jsx33(
1650
+ return /* @__PURE__ */ jsx34(
1629
1651
  "th",
1630
1652
  {
1631
1653
  className: cn(
@@ -1635,7 +1657,7 @@ function HeaderCell({ header, sortable, flexRender: render }) {
1635
1657
  onClick: sortable ? header.column.getToggleSortingHandler() : void 0,
1636
1658
  children: /* @__PURE__ */ jsxs18("span", { className: "inline-flex items-center gap-1", children: [
1637
1659
  header.isPlaceholder ? null : render(header.column.columnDef.header, header.getContext()),
1638
- sortable && /* @__PURE__ */ jsx33(SortIcon, { className: "h-3 w-3" })
1660
+ sortable && /* @__PURE__ */ jsx34(SortIcon, { className: "h-3 w-3" })
1639
1661
  ] })
1640
1662
  }
1641
1663
  );
@@ -1643,7 +1665,7 @@ function HeaderCell({ header, sortable, flexRender: render }) {
1643
1665
 
1644
1666
  // src/composites/data-table/data-table-row.tsx
1645
1667
  import { MoreHorizontal } from "lucide-react";
1646
- import { jsx as jsx34, jsxs as jsxs19 } from "react/jsx-runtime";
1668
+ import { jsx as jsx35, jsxs as jsxs19 } from "react/jsx-runtime";
1647
1669
  function DataTableRow({
1648
1670
  row,
1649
1671
  onRowClick,
@@ -1661,17 +1683,17 @@ function DataTableRow({
1661
1683
  ),
1662
1684
  onClick: onRowClick ? () => onRowClick(row.original) : void 0,
1663
1685
  children: [
1664
- row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx34(DataTableCell, { cell, flexRender: render }, cell.id)),
1665
- actions.length > 0 && /* @__PURE__ */ jsx34("td", { className: "px-2 py-1.5 w-8", children: /* @__PURE__ */ jsxs19(Dropdown, { children: [
1666
- /* @__PURE__ */ jsx34(
1686
+ row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx35(DataTableCell, { cell, flexRender: render }, cell.id)),
1687
+ actions.length > 0 && /* @__PURE__ */ jsx35("td", { className: "px-2 py-1.5 w-8", children: /* @__PURE__ */ jsxs19(Dropdown, { children: [
1688
+ /* @__PURE__ */ jsx35(
1667
1689
  DropdownTrigger,
1668
1690
  {
1669
1691
  className: "p-0.5 rounded hover:bg-surface-hover",
1670
1692
  onClick: (e) => e.stopPropagation(),
1671
- children: /* @__PURE__ */ jsx34(MoreHorizontal, { className: "h-3.5 w-3.5 text-foreground-muted" })
1693
+ children: /* @__PURE__ */ jsx35(MoreHorizontal, { className: "h-3.5 w-3.5 text-foreground-muted" })
1672
1694
  }
1673
1695
  ),
1674
- /* @__PURE__ */ jsx34(DropdownContent, { className: "right-0 left-auto", children: actions.map((action) => /* @__PURE__ */ jsx34(
1696
+ /* @__PURE__ */ jsx35(DropdownContent, { className: "right-0 left-auto", children: actions.map((action) => /* @__PURE__ */ jsx35(
1675
1697
  DropdownItem,
1676
1698
  {
1677
1699
  icon: action.icon,
@@ -1690,12 +1712,12 @@ function DataTableRow({
1690
1712
  );
1691
1713
  }
1692
1714
  function DataTableCell({ cell, flexRender: render }) {
1693
- return /* @__PURE__ */ jsx34("td", { className: "px-2 py-1.5 text-xs text-foreground", children: render(cell.column.columnDef.cell, cell.getContext()) });
1715
+ return /* @__PURE__ */ jsx35("td", { className: "px-2 py-1.5 text-xs text-foreground", children: render(cell.column.columnDef.cell, cell.getContext()) });
1694
1716
  }
1695
1717
 
1696
1718
  // src/composites/data-table/data-table-pagination.tsx
1697
1719
  import { ChevronLeft, ChevronRight as ChevronRight2 } from "lucide-react";
1698
- import { jsx as jsx35, jsxs as jsxs20 } from "react/jsx-runtime";
1720
+ import { jsx as jsx36, jsxs as jsxs20 } from "react/jsx-runtime";
1699
1721
  var PAGE_SIZE_OPTIONS = [
1700
1722
  { value: "10", label: "10" },
1701
1723
  { value: "25", label: "25" },
@@ -1712,8 +1734,8 @@ function DataTablePagination({
1712
1734
  const currentPage = page + 1;
1713
1735
  return /* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-between px-2 py-2 text-xs text-foreground-muted", children: [
1714
1736
  /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2", children: [
1715
- /* @__PURE__ */ jsx35("span", { children: "Rows per page" }),
1716
- /* @__PURE__ */ jsx35("div", { className: "w-16", children: /* @__PURE__ */ jsx35(
1737
+ /* @__PURE__ */ jsx36("span", { children: "Rows per page" }),
1738
+ /* @__PURE__ */ jsx36("div", { className: "w-16", children: /* @__PURE__ */ jsx36(
1717
1739
  Select,
1718
1740
  {
1719
1741
  options: PAGE_SIZE_OPTIONS,
@@ -1732,7 +1754,7 @@ function DataTablePagination({
1732
1754
  " of ",
1733
1755
  totalPages
1734
1756
  ] }),
1735
- /* @__PURE__ */ jsx35(
1757
+ /* @__PURE__ */ jsx36(
1736
1758
  IconButton,
1737
1759
  {
1738
1760
  icon: ChevronLeft,
@@ -1743,7 +1765,7 @@ function DataTablePagination({
1743
1765
  onClick: () => onPaginationChange?.({ pageIndex: page - 1, pageSize })
1744
1766
  }
1745
1767
  ),
1746
- /* @__PURE__ */ jsx35(
1768
+ /* @__PURE__ */ jsx36(
1747
1769
  IconButton,
1748
1770
  {
1749
1771
  icon: ChevronRight2,
@@ -1759,7 +1781,7 @@ function DataTablePagination({
1759
1781
  }
1760
1782
 
1761
1783
  // src/composites/data-table/data-table.tsx
1762
- import { Fragment, jsx as jsx36, jsxs as jsxs21 } from "react/jsx-runtime";
1784
+ import { Fragment, jsx as jsx37, jsxs as jsxs21 } from "react/jsx-runtime";
1763
1785
  function DataTable({
1764
1786
  data,
1765
1787
  columns: userColumns,
@@ -1782,7 +1804,7 @@ function DataTable({
1782
1804
  if (!selectable) return userColumns;
1783
1805
  const selectColumn = {
1784
1806
  id: "__select",
1785
- header: ({ table: table2 }) => /* @__PURE__ */ jsx36(
1807
+ header: ({ table: table2 }) => /* @__PURE__ */ jsx37(
1786
1808
  Checkbox,
1787
1809
  {
1788
1810
  checked: table2.getIsAllPageRowsSelected(),
@@ -1790,7 +1812,7 @@ function DataTable({
1790
1812
  "aria-label": "Select all"
1791
1813
  }
1792
1814
  ),
1793
- cell: ({ row }) => /* @__PURE__ */ jsx36(
1815
+ cell: ({ row }) => /* @__PURE__ */ jsx37(
1794
1816
  Checkbox,
1795
1817
  {
1796
1818
  checked: row.getIsSelected(),
@@ -1830,7 +1852,7 @@ function DataTable({
1830
1852
  const hasActions = !!rowActions;
1831
1853
  return /* @__PURE__ */ jsxs21("div", { className: cn("overflow-auto", className), children: [
1832
1854
  /* @__PURE__ */ jsxs21("table", { className: "w-full border-collapse", children: [
1833
- /* @__PURE__ */ jsx36(
1855
+ /* @__PURE__ */ jsx37(
1834
1856
  DataTableHeader,
1835
1857
  {
1836
1858
  headerGroups: table.getHeaderGroups(),
@@ -1839,14 +1861,14 @@ function DataTable({
1839
1861
  flexRender
1840
1862
  }
1841
1863
  ),
1842
- /* @__PURE__ */ jsx36("tbody", { children: loading ? /* @__PURE__ */ jsx36(LoadingRows, { colSpan: columns.length + (hasActions ? 1 : 0), compact }) : table.getRowModel().rows.length === 0 ? /* @__PURE__ */ jsx36("tr", { children: /* @__PURE__ */ jsx36(
1864
+ /* @__PURE__ */ jsx37("tbody", { children: loading ? /* @__PURE__ */ jsx37(LoadingRows, { colSpan: columns.length + (hasActions ? 1 : 0), compact }) : table.getRowModel().rows.length === 0 ? /* @__PURE__ */ jsx37("tr", { children: /* @__PURE__ */ jsx37(
1843
1865
  "td",
1844
1866
  {
1845
1867
  colSpan: columns.length + (hasActions ? 1 : 0),
1846
1868
  className: "text-center py-8 text-xs text-foreground-muted",
1847
1869
  children: emptyState ?? "No data"
1848
1870
  }
1849
- ) }) : table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx36(
1871
+ ) }) : table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx37(
1850
1872
  DataTableRow,
1851
1873
  {
1852
1874
  row,
@@ -1857,7 +1879,7 @@ function DataTable({
1857
1879
  row.id
1858
1880
  )) })
1859
1881
  ] }),
1860
- pagination && /* @__PURE__ */ jsx36(
1882
+ pagination && /* @__PURE__ */ jsx37(
1861
1883
  DataTablePagination,
1862
1884
  {
1863
1885
  page: pagination.page,
@@ -1869,11 +1891,11 @@ function DataTable({
1869
1891
  ] });
1870
1892
  }
1871
1893
  function LoadingRows({ colSpan, compact }) {
1872
- return /* @__PURE__ */ jsx36(Fragment, { children: Array.from({ length: 5 }).map((_, rowIdx) => /* @__PURE__ */ jsx36("tr", { className: compact ? "h-7" : "h-9", children: Array.from({ length: colSpan }).map((_2, colIdx) => /* @__PURE__ */ jsx36("td", { className: "px-2 py-1.5", children: /* @__PURE__ */ jsx36(Skeleton, { className: "h-3 w-full" }) }, colIdx)) }, rowIdx)) });
1894
+ return /* @__PURE__ */ jsx37(Fragment, { children: Array.from({ length: 5 }).map((_, rowIdx) => /* @__PURE__ */ jsx37("tr", { className: compact ? "h-7" : "h-9", children: Array.from({ length: colSpan }).map((_2, colIdx) => /* @__PURE__ */ jsx37("td", { className: "px-2 py-1.5", children: /* @__PURE__ */ jsx37(Skeleton, { className: "h-3 w-full" }) }, colIdx)) }, rowIdx)) });
1873
1895
  }
1874
1896
 
1875
1897
  // src/composites/device-card.tsx
1876
- import { jsx as jsx37, jsxs as jsxs22 } from "react/jsx-runtime";
1898
+ import { jsx as jsx38, jsxs as jsxs22 } from "react/jsx-runtime";
1877
1899
  var STATUS_COLORS = {
1878
1900
  online: "bg-success",
1879
1901
  offline: "bg-danger",
@@ -1905,11 +1927,11 @@ function DeviceCard({
1905
1927
  ),
1906
1928
  children: [
1907
1929
  /* @__PURE__ */ jsxs22("div", { className: "flex items-center justify-between mb-2", children: [
1908
- /* @__PURE__ */ jsx37("span", { className: "text-sm font-medium truncate", children: title }),
1909
- status && /* @__PURE__ */ jsx37("span", { className: cn("h-2 w-2 rounded-full shrink-0", STATUS_COLORS[status]) })
1930
+ /* @__PURE__ */ jsx38("span", { className: "text-sm font-medium truncate", children: title }),
1931
+ status && /* @__PURE__ */ jsx38("span", { className: cn("h-2 w-2 rounded-full shrink-0", STATUS_COLORS[status]) })
1910
1932
  ] }),
1911
- subtitle && /* @__PURE__ */ jsx37("div", { className: "text-[11px] text-foreground-muted", children: subtitle }),
1912
- badges && badges.length > 0 && /* @__PURE__ */ jsx37("div", { className: "flex flex-wrap gap-1 mt-2", children: badges.map((badge, i) => {
1933
+ subtitle && /* @__PURE__ */ jsx38("div", { className: "text-[11px] text-foreground-muted", children: subtitle }),
1934
+ badges && badges.length > 0 && /* @__PURE__ */ jsx38("div", { className: "flex flex-wrap gap-1 mt-2", children: badges.map((badge, i) => {
1913
1935
  const cls = cn(
1914
1936
  "rounded px-1.5 py-0.5 text-[10px] flex items-center gap-0.5",
1915
1937
  selected ? "bg-primary/20" : "bg-surface-hover",
@@ -1934,7 +1956,7 @@ function DeviceCard({
1934
1956
  badge.label
1935
1957
  ] }, i);
1936
1958
  }) }),
1937
- !isOffline && actions && actions.length > 0 && /* @__PURE__ */ jsx37("div", { className: "flex items-center gap-0.5 mt-2 -mb-1", children: actions.map((action, i) => /* @__PURE__ */ jsx37(
1959
+ !isOffline && actions && actions.length > 0 && /* @__PURE__ */ jsx38("div", { className: "flex items-center gap-0.5 mt-2 -mb-1", children: actions.map((action, i) => /* @__PURE__ */ jsx38(
1938
1960
  "button",
1939
1961
  {
1940
1962
  onClick: (e) => {
@@ -1948,21 +1970,21 @@ function DeviceCard({
1948
1970
  },
1949
1971
  i
1950
1972
  )) }),
1951
- isOffline && offlineAction && /* @__PURE__ */ jsx37("div", { className: "mt-2", onClick: (e) => e.stopPropagation(), children: offlineAction })
1973
+ isOffline && offlineAction && /* @__PURE__ */ jsx38("div", { className: "mt-2", onClick: (e) => e.stopPropagation(), children: offlineAction })
1952
1974
  ]
1953
1975
  }
1954
1976
  );
1955
1977
  }
1956
1978
 
1957
1979
  // src/composites/device-grid.tsx
1958
- import { jsx as jsx38 } from "react/jsx-runtime";
1980
+ import { jsx as jsx39 } from "react/jsx-runtime";
1959
1981
  function DeviceGrid({
1960
1982
  children,
1961
1983
  minCardWidth = 220,
1962
1984
  gap = 3,
1963
1985
  className
1964
1986
  }) {
1965
- return /* @__PURE__ */ jsx38(
1987
+ return /* @__PURE__ */ jsx39(
1966
1988
  "div",
1967
1989
  {
1968
1990
  className: cn(
@@ -1982,7 +2004,7 @@ function DeviceGrid({
1982
2004
  // src/composites/pipeline-step.tsx
1983
2005
  import { useState as useState9 } from "react";
1984
2006
  import { ChevronRight as ChevronRight3, ChevronDown as ChevronDown2 } from "lucide-react";
1985
- import { jsx as jsx39, jsxs as jsxs23 } from "react/jsx-runtime";
2007
+ import { jsx as jsx40, jsxs as jsxs23 } from "react/jsx-runtime";
1986
2008
  var ADDON_COLORS = {
1987
2009
  "object-detection": "border-l-blue-500",
1988
2010
  "motion-detection": "border-l-amber-500",
@@ -2081,7 +2103,7 @@ function PipelineStep({
2081
2103
  if (e.target.closest(".step-config")) return;
2082
2104
  setExpanded((v) => !v);
2083
2105
  }
2084
- return /* @__PURE__ */ jsx39("div", { className: "space-y-2", children: /* @__PURE__ */ jsxs23(
2106
+ return /* @__PURE__ */ jsx40("div", { className: "space-y-2", children: /* @__PURE__ */ jsxs23(
2085
2107
  "div",
2086
2108
  {
2087
2109
  className: cn(
@@ -2091,17 +2113,17 @@ function PipelineStep({
2091
2113
  ),
2092
2114
  children: [
2093
2115
  /* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-2.5 px-3 py-2.5 cursor-pointer select-none", onClick: handleClick, children: [
2094
- /* @__PURE__ */ jsx39("span", { className: "text-foreground-subtle", children: expanded ? /* @__PURE__ */ jsx39(ChevronDown2, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx39(ChevronRight3, { className: "h-4 w-4" }) }),
2116
+ /* @__PURE__ */ jsx40("span", { className: "text-foreground-subtle", children: expanded ? /* @__PURE__ */ jsx40(ChevronDown2, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx40(ChevronRight3, { className: "h-4 w-4" }) }),
2095
2117
  /* @__PURE__ */ jsxs23("div", { className: "flex-1 min-w-0", children: [
2096
- /* @__PURE__ */ jsx39("span", { className: "text-[10px] uppercase tracking-wider font-medium text-foreground-subtle/60 block leading-none", children: step.slot }),
2097
- /* @__PURE__ */ jsx39("span", { className: "text-sm font-semibold text-foreground truncate block leading-tight", children: step.addonName }),
2118
+ /* @__PURE__ */ jsx40("span", { className: "text-[10px] uppercase tracking-wider font-medium text-foreground-subtle/60 block leading-none", children: step.slot }),
2119
+ /* @__PURE__ */ jsx40("span", { className: "text-sm font-semibold text-foreground truncate block leading-tight", children: step.addonName }),
2098
2120
  /* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-1 mt-0.5 flex-wrap", children: [
2099
- step.inputClasses.map((c) => /* @__PURE__ */ jsx39("span", { className: "text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-blue-500/12 text-blue-400", children: c }, c)),
2100
- step.inputClasses.length > 0 && step.outputClasses.length > 0 && /* @__PURE__ */ jsx39("span", { className: "text-foreground-subtle/40 text-[10px]", children: "\u2192" }),
2101
- step.outputClasses.map((c) => /* @__PURE__ */ jsx39("span", { className: "text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-green-500/12 text-green-400", children: c }, c))
2121
+ step.inputClasses.map((c) => /* @__PURE__ */ jsx40("span", { className: "text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-blue-500/12 text-blue-400", children: c }, c)),
2122
+ step.inputClasses.length > 0 && step.outputClasses.length > 0 && /* @__PURE__ */ jsx40("span", { className: "text-foreground-subtle/40 text-[10px]", children: "\u2192" }),
2123
+ step.outputClasses.map((c) => /* @__PURE__ */ jsx40("span", { className: "text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-green-500/12 text-green-400", children: c }, c))
2102
2124
  ] })
2103
2125
  ] }),
2104
- /* @__PURE__ */ jsx39(
2126
+ /* @__PURE__ */ jsx40(
2105
2127
  "button",
2106
2128
  {
2107
2129
  onClick: (e) => {
@@ -2112,7 +2134,7 @@ function PipelineStep({
2112
2134
  "relative inline-flex h-6 w-11 shrink-0 items-center rounded-full transition-colors",
2113
2135
  step.enabled ? "bg-success" : "bg-foreground-subtle/30"
2114
2136
  ),
2115
- children: /* @__PURE__ */ jsx39("span", { className: cn(
2137
+ children: /* @__PURE__ */ jsx40("span", { className: cn(
2116
2138
  "inline-block h-4 w-4 rounded-full bg-white shadow transition-transform",
2117
2139
  step.enabled ? "translate-x-6" : "translate-x-1"
2118
2140
  ) })
@@ -2121,7 +2143,7 @@ function PipelineStep({
2121
2143
  ] }),
2122
2144
  expanded && /* @__PURE__ */ jsxs23("div", { className: "step-config border-t border-border bg-background px-4 py-4 space-y-3", children: [
2123
2145
  /* @__PURE__ */ jsxs23("div", { className: "grid grid-cols-2 gap-3", children: [
2124
- /* @__PURE__ */ jsx39(
2146
+ /* @__PURE__ */ jsx40(
2125
2147
  ConfigSelect,
2126
2148
  {
2127
2149
  label: "Agent",
@@ -2131,7 +2153,7 @@ function PipelineStep({
2131
2153
  onChange: (v) => onChange({ ...step, agentId: v })
2132
2154
  }
2133
2155
  ),
2134
- /* @__PURE__ */ jsx39(
2156
+ /* @__PURE__ */ jsx40(
2135
2157
  ConfigSelect,
2136
2158
  {
2137
2159
  label: "Runtime",
@@ -2141,7 +2163,7 @@ function PipelineStep({
2141
2163
  onChange: (v) => onChange({ ...step, runtime: v })
2142
2164
  }
2143
2165
  ),
2144
- /* @__PURE__ */ jsx39(
2166
+ /* @__PURE__ */ jsx40(
2145
2167
  ConfigSelect,
2146
2168
  {
2147
2169
  label: "Backend",
@@ -2151,7 +2173,7 @@ function PipelineStep({
2151
2173
  onChange: (v) => onChange({ ...step, backend: v })
2152
2174
  }
2153
2175
  ),
2154
- /* @__PURE__ */ jsx39(
2176
+ /* @__PURE__ */ jsx40(
2155
2177
  ConfigSelect,
2156
2178
  {
2157
2179
  label: "Model",
@@ -2164,13 +2186,13 @@ function PipelineStep({
2164
2186
  ] }),
2165
2187
  /* @__PURE__ */ jsxs23("div", { children: [
2166
2188
  /* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-between mb-1", children: [
2167
- /* @__PURE__ */ jsx39("span", { className: "text-[10px] font-medium text-foreground-subtle uppercase tracking-wide", children: "Confidence" }),
2189
+ /* @__PURE__ */ jsx40("span", { className: "text-[10px] font-medium text-foreground-subtle uppercase tracking-wide", children: "Confidence" }),
2168
2190
  /* @__PURE__ */ jsxs23("span", { className: "text-xs font-medium text-foreground tabular-nums", children: [
2169
2191
  (step.confidence * 100).toFixed(0),
2170
2192
  "%"
2171
2193
  ] })
2172
2194
  ] }),
2173
- /* @__PURE__ */ jsx39(
2195
+ /* @__PURE__ */ jsx40(
2174
2196
  "input",
2175
2197
  {
2176
2198
  type: "range",
@@ -2191,7 +2213,7 @@ function PipelineStep({
2191
2213
  }
2192
2214
  function ConfigSelect({ label, value, options, disabled, onChange }) {
2193
2215
  return /* @__PURE__ */ jsxs23("div", { children: [
2194
- /* @__PURE__ */ jsx39("label", { className: "block text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-1.5", children: label }),
2216
+ /* @__PURE__ */ jsx40("label", { className: "block text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-1.5", children: label }),
2195
2217
  /* @__PURE__ */ jsxs23(
2196
2218
  "select",
2197
2219
  {
@@ -2200,8 +2222,8 @@ function ConfigSelect({ label, value, options, disabled, onChange }) {
2200
2222
  disabled,
2201
2223
  className: "w-full rounded-lg border border-border bg-surface px-3 py-2 text-xs text-foreground focus:outline-none focus:border-primary/50",
2202
2224
  children: [
2203
- options.length === 0 && /* @__PURE__ */ jsx39("option", { value, children: value || "default" }),
2204
- options.map((o) => /* @__PURE__ */ jsx39("option", { value: o.value, disabled: o.disabled, children: o.label }, o.value))
2225
+ options.length === 0 && /* @__PURE__ */ jsx40("option", { value, children: value || "default" }),
2226
+ options.map((o) => /* @__PURE__ */ jsx40("option", { value: o.value, disabled: o.disabled, children: o.label }, o.value))
2205
2227
  ]
2206
2228
  }
2207
2229
  )
@@ -2210,9 +2232,9 @@ function ConfigSelect({ label, value, options, disabled, onChange }) {
2210
2232
 
2211
2233
  // src/composites/pipeline-runtime-selector.tsx
2212
2234
  import { Cpu, Star } from "lucide-react";
2213
- import { jsx as jsx40, jsxs as jsxs24 } from "react/jsx-runtime";
2235
+ import { jsx as jsx41, jsxs as jsxs24 } from "react/jsx-runtime";
2214
2236
  function PipelineRuntimeSelector({ options, value, onChange }) {
2215
- return /* @__PURE__ */ jsx40("div", { className: "flex flex-wrap gap-2", children: options.map((opt) => {
2237
+ return /* @__PURE__ */ jsx41("div", { className: "flex flex-wrap gap-2", children: options.map((opt) => {
2216
2238
  const active = opt.id === value;
2217
2239
  return /* @__PURE__ */ jsxs24(
2218
2240
  "button",
@@ -2221,10 +2243,10 @@ function PipelineRuntimeSelector({ options, value, onChange }) {
2221
2243
  disabled: !opt.available,
2222
2244
  className: `flex items-center gap-2 rounded-lg border px-3 py-2 text-xs font-medium transition-all ${active ? "border-primary/40 bg-primary/10 text-primary" : opt.available ? "border-border bg-surface text-foreground-subtle hover:bg-surface-hover hover:text-foreground" : "border-border/40 bg-surface/40 text-foreground-subtle/40 cursor-not-allowed"}`,
2223
2245
  children: [
2224
- /* @__PURE__ */ jsx40(Cpu, { className: "h-3.5 w-3.5 shrink-0" }),
2246
+ /* @__PURE__ */ jsx41(Cpu, { className: "h-3.5 w-3.5 shrink-0" }),
2225
2247
  opt.label,
2226
2248
  opt.isBest && /* @__PURE__ */ jsxs24("span", { className: "inline-flex items-center gap-0.5 rounded-full bg-amber-500/15 px-1.5 py-0.5 text-[10px] font-semibold text-amber-400", children: [
2227
- /* @__PURE__ */ jsx40(Star, { className: "h-2.5 w-2.5" }),
2249
+ /* @__PURE__ */ jsx41(Star, { className: "h-2.5 w-2.5" }),
2228
2250
  "Best"
2229
2251
  ] }),
2230
2252
  opt.platformScore != null && /* @__PURE__ */ jsxs24("span", { className: "text-[10px] text-foreground-subtle/60", children: [
@@ -2232,7 +2254,7 @@ function PipelineRuntimeSelector({ options, value, onChange }) {
2232
2254
  opt.platformScore,
2233
2255
  ")"
2234
2256
  ] }),
2235
- /* @__PURE__ */ jsx40(
2257
+ /* @__PURE__ */ jsx41(
2236
2258
  "span",
2237
2259
  {
2238
2260
  className: `h-1.5 w-1.5 rounded-full ${opt.available ? "bg-success" : "bg-danger"}`
@@ -2279,7 +2301,7 @@ function validateTemplate(steps, schema) {
2279
2301
  }
2280
2302
 
2281
2303
  // src/composites/pipeline-builder.tsx
2282
- import { jsx as jsx41, jsxs as jsxs25 } from "react/jsx-runtime";
2304
+ import { jsx as jsx42, jsxs as jsxs25 } from "react/jsx-runtime";
2283
2305
  function buildSchemaMap(schema) {
2284
2306
  const map = /* @__PURE__ */ new Map();
2285
2307
  for (const slot of schema.slots) {
@@ -2308,20 +2330,20 @@ function createDefaultStep(addon, fallbackRuntime, fallbackBackend) {
2308
2330
  };
2309
2331
  }
2310
2332
  function PlaceholderStep({ addon, onClick }) {
2311
- return /* @__PURE__ */ jsx41(
2333
+ return /* @__PURE__ */ jsx42(
2312
2334
  "button",
2313
2335
  {
2314
2336
  type: "button",
2315
2337
  onClick,
2316
2338
  className: "w-full rounded-xl border-2 border-dashed border-border/60 px-4 py-3 text-left transition-all hover:border-primary/30 hover:bg-surface/60 group",
2317
2339
  children: /* @__PURE__ */ jsxs25("div", { className: "flex items-center gap-3", children: [
2318
- /* @__PURE__ */ jsx41(PlusCircle, { className: "h-[18px] w-[18px] text-foreground-subtle/30 group-hover:text-primary/60 shrink-0" }),
2340
+ /* @__PURE__ */ jsx42(PlusCircle, { className: "h-[18px] w-[18px] text-foreground-subtle/30 group-hover:text-primary/60 shrink-0" }),
2319
2341
  /* @__PURE__ */ jsxs25("div", { className: "flex-1 min-w-0", children: [
2320
- /* @__PURE__ */ jsx41("span", { className: "text-[13px] font-medium text-foreground-subtle/50 group-hover:text-foreground-subtle block truncate", children: addon.name }),
2342
+ /* @__PURE__ */ jsx42("span", { className: "text-[13px] font-medium text-foreground-subtle/50 group-hover:text-foreground-subtle block truncate", children: addon.name }),
2321
2343
  /* @__PURE__ */ jsxs25("div", { className: "flex items-center gap-1 mt-0.5 flex-wrap", children: [
2322
- addon.inputClasses.map((c) => /* @__PURE__ */ jsx41("span", { className: "text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-blue-500/8 text-blue-400/50", children: c }, c)),
2323
- addon.inputClasses.length > 0 && addon.outputClasses.length > 0 && /* @__PURE__ */ jsx41("span", { className: "text-foreground-subtle/25 text-[10px]", children: "\u2192" }),
2324
- addon.outputClasses.map((c) => /* @__PURE__ */ jsx41("span", { className: "text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-green-500/8 text-green-400/50", children: c }, c))
2344
+ addon.inputClasses.map((c) => /* @__PURE__ */ jsx42("span", { className: "text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-blue-500/8 text-blue-400/50", children: c }, c)),
2345
+ addon.inputClasses.length > 0 && addon.outputClasses.length > 0 && /* @__PURE__ */ jsx42("span", { className: "text-foreground-subtle/25 text-[10px]", children: "\u2192" }),
2346
+ addon.outputClasses.map((c) => /* @__PURE__ */ jsx42("span", { className: "text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-green-500/8 text-green-400/50", children: c }, c))
2325
2347
  ] })
2326
2348
  ] })
2327
2349
  ] })
@@ -2434,7 +2456,7 @@ function PipelineBuilder({
2434
2456
  function renderStep(step) {
2435
2457
  const childPlaceholders = getChildPlaceholders(step);
2436
2458
  return /* @__PURE__ */ jsxs25("div", { className: "space-y-1.5", children: [
2437
- /* @__PURE__ */ jsx41(
2459
+ /* @__PURE__ */ jsx42(
2438
2460
  PipelineStep,
2439
2461
  {
2440
2462
  step,
@@ -2447,11 +2469,11 @@ function PipelineBuilder({
2447
2469
  }
2448
2470
  ),
2449
2471
  (step.children.length > 0 || childPlaceholders.length > 0) && /* @__PURE__ */ jsxs25("div", { className: "ml-6 pl-4 border-l-2 border-dashed border-border/40 space-y-1.5", children: [
2450
- /* @__PURE__ */ jsx41("span", { className: "text-[10px] font-semibold uppercase tracking-widest text-foreground-subtle/40", children: "Slot: Cropper / Classifier" }),
2472
+ /* @__PURE__ */ jsx42("span", { className: "text-[10px] font-semibold uppercase tracking-widest text-foreground-subtle/40", children: "Slot: Cropper / Classifier" }),
2451
2473
  step.children.map((child) => {
2452
2474
  const childChildPlaceholders = getChildPlaceholders(child);
2453
2475
  return /* @__PURE__ */ jsxs25("div", { className: "space-y-1.5", children: [
2454
- /* @__PURE__ */ jsx41(
2476
+ /* @__PURE__ */ jsx42(
2455
2477
  PipelineStep,
2456
2478
  {
2457
2479
  step: child,
@@ -2475,8 +2497,8 @@ function PipelineBuilder({
2475
2497
  }
2476
2498
  ),
2477
2499
  (child.children.length > 0 || childChildPlaceholders.length > 0) && /* @__PURE__ */ jsxs25("div", { className: "ml-6 pl-4 border-l-2 border-dashed border-border/30 space-y-1.5", children: [
2478
- /* @__PURE__ */ jsx41("span", { className: "text-[10px] font-semibold uppercase tracking-widest text-foreground-subtle/30", children: "Slot: Recognizer" }),
2479
- child.children.map((grandchild) => /* @__PURE__ */ jsx41(
2500
+ /* @__PURE__ */ jsx42("span", { className: "text-[10px] font-semibold uppercase tracking-widest text-foreground-subtle/30", children: "Slot: Recognizer" }),
2501
+ child.children.map((grandchild) => /* @__PURE__ */ jsx42(
2480
2502
  PipelineStep,
2481
2503
  {
2482
2504
  step: grandchild,
@@ -2504,7 +2526,7 @@ function PipelineBuilder({
2504
2526
  },
2505
2527
  grandchild.addonId
2506
2528
  )),
2507
- !readOnly && childChildPlaceholders.map((addon) => /* @__PURE__ */ jsx41(
2529
+ !readOnly && childChildPlaceholders.map((addon) => /* @__PURE__ */ jsx42(
2508
2530
  PlaceholderStep,
2509
2531
  {
2510
2532
  addon,
@@ -2523,7 +2545,7 @@ function PipelineBuilder({
2523
2545
  ] })
2524
2546
  ] }, child.addonId);
2525
2547
  }),
2526
- !readOnly && childPlaceholders.map((addon) => /* @__PURE__ */ jsx41(
2548
+ !readOnly && childPlaceholders.map((addon) => /* @__PURE__ */ jsx42(
2527
2549
  PlaceholderStep,
2528
2550
  {
2529
2551
  addon,
@@ -2536,21 +2558,21 @@ function PipelineBuilder({
2536
2558
  }
2537
2559
  const rootSlots = schema.slots.filter((s) => s.parentSlot === null).sort((a, b) => a.priority - b.priority);
2538
2560
  return /* @__PURE__ */ jsxs25("div", { className: "space-y-4", children: [
2539
- /* @__PURE__ */ jsx41("div", { className: "rounded-xl border border-border bg-surface p-3", children: /* @__PURE__ */ jsxs25("div", { className: "flex items-center gap-2", children: [
2540
- /* @__PURE__ */ jsx41("div", { className: "relative flex-1 min-w-0", children: /* @__PURE__ */ jsxs25(
2561
+ /* @__PURE__ */ jsx42("div", { className: "rounded-xl border border-border bg-surface p-3", children: /* @__PURE__ */ jsxs25("div", { className: "flex items-center gap-2", children: [
2562
+ /* @__PURE__ */ jsx42("div", { className: "relative flex-1 min-w-0", children: /* @__PURE__ */ jsxs25(
2541
2563
  "select",
2542
2564
  {
2543
2565
  value: selectedTemplateId ?? "",
2544
2566
  onChange: handleSelectTemplate,
2545
2567
  className: "w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-foreground focus:outline-none focus:border-primary/50",
2546
2568
  children: [
2547
- /* @__PURE__ */ jsx41("option", { value: "", children: "No template" }),
2548
- templates.map((t) => /* @__PURE__ */ jsx41("option", { value: t.id, children: t.name }, t.id))
2569
+ /* @__PURE__ */ jsx42("option", { value: "", children: "No template" }),
2570
+ templates.map((t) => /* @__PURE__ */ jsx42("option", { value: t.id, children: t.name }, t.id))
2549
2571
  ]
2550
2572
  }
2551
2573
  ) }),
2552
- dirty && /* @__PURE__ */ jsx41("span", { className: "h-1.5 w-1.5 rounded-full bg-amber-500 shrink-0" }),
2553
- /* @__PURE__ */ jsx41(
2574
+ dirty && /* @__PURE__ */ jsx42("span", { className: "h-1.5 w-1.5 rounded-full bg-amber-500 shrink-0" }),
2575
+ /* @__PURE__ */ jsx42(
2554
2576
  "button",
2555
2577
  {
2556
2578
  onClick: handleSave,
@@ -2560,10 +2582,10 @@ function PipelineBuilder({
2560
2582
  "p-2 rounded-lg border border-border transition-colors",
2561
2583
  selectedTemplateId && !readOnly ? "text-foreground-subtle hover:bg-surface-hover" : "text-foreground-subtle/30 cursor-not-allowed"
2562
2584
  ),
2563
- children: /* @__PURE__ */ jsx41(Save, { className: "h-4 w-4" })
2585
+ children: /* @__PURE__ */ jsx42(Save, { className: "h-4 w-4" })
2564
2586
  }
2565
2587
  ),
2566
- /* @__PURE__ */ jsx41(
2588
+ /* @__PURE__ */ jsx42(
2567
2589
  "button",
2568
2590
  {
2569
2591
  onClick: handleSaveAs,
@@ -2573,10 +2595,10 @@ function PipelineBuilder({
2573
2595
  "p-2 rounded-lg border border-border transition-colors",
2574
2596
  !readOnly ? "text-foreground-subtle hover:bg-surface-hover" : "text-foreground-subtle/30 cursor-not-allowed"
2575
2597
  ),
2576
- children: /* @__PURE__ */ jsx41(CopyPlus, { className: "h-4 w-4" })
2598
+ children: /* @__PURE__ */ jsx42(CopyPlus, { className: "h-4 w-4" })
2577
2599
  }
2578
2600
  ),
2579
- /* @__PURE__ */ jsx41(
2601
+ /* @__PURE__ */ jsx42(
2580
2602
  "button",
2581
2603
  {
2582
2604
  onClick: handleDelete,
@@ -2586,14 +2608,14 @@ function PipelineBuilder({
2586
2608
  "p-2 rounded-lg border border-border transition-colors",
2587
2609
  selectedTemplateId && !readOnly ? "text-foreground-subtle hover:text-danger" : "text-foreground-subtle/30 cursor-not-allowed"
2588
2610
  ),
2589
- children: /* @__PURE__ */ jsx41(Trash2, { className: "h-4 w-4" })
2611
+ children: /* @__PURE__ */ jsx42(Trash2, { className: "h-4 w-4" })
2590
2612
  }
2591
2613
  )
2592
2614
  ] }) }),
2593
2615
  warnings.length > 0 && /* @__PURE__ */ jsxs25("div", { className: "rounded-lg border border-amber-500/30 bg-amber-500/5 p-3 text-xs text-amber-400 space-y-1", children: [
2594
2616
  /* @__PURE__ */ jsxs25("div", { className: "flex items-center justify-between", children: [
2595
- /* @__PURE__ */ jsx41("span", { className: "font-medium", children: "Template loaded with warnings:" }),
2596
- /* @__PURE__ */ jsx41("button", { onClick: () => setWarnings([]), className: "text-amber-400/60 hover:text-amber-400", children: /* @__PURE__ */ jsx41(X2, { className: "h-3.5 w-3.5" }) })
2617
+ /* @__PURE__ */ jsx42("span", { className: "font-medium", children: "Template loaded with warnings:" }),
2618
+ /* @__PURE__ */ jsx42("button", { onClick: () => setWarnings([]), className: "text-amber-400/60 hover:text-amber-400", children: /* @__PURE__ */ jsx42(X2, { className: "h-3.5 w-3.5" }) })
2597
2619
  ] }),
2598
2620
  warnings.map((w, i) => /* @__PURE__ */ jsxs25("div", { children: [
2599
2621
  "\u2022 ",
@@ -2609,7 +2631,7 @@ function PipelineBuilder({
2609
2631
  slot.label
2610
2632
  ] }),
2611
2633
  slotSteps.map((step) => renderStep(step)),
2612
- !readOnly && missingRootAddons.map((addon) => /* @__PURE__ */ jsx41(PlaceholderStep, { addon, onClick: () => {
2634
+ !readOnly && missingRootAddons.map((addon) => /* @__PURE__ */ jsx42(PlaceholderStep, { addon, onClick: () => {
2613
2635
  onChange([...steps, createDefaultStep(addon, defaultRuntime, defaultBackend)]);
2614
2636
  } }, addon.id))
2615
2637
  ] }, slot.id);
@@ -2690,7 +2712,7 @@ function getClassColor(className, customColors) {
2690
2712
 
2691
2713
  // src/composites/detection-canvas.tsx
2692
2714
  import { useRef as useRef6, useEffect as useEffect6 } from "react";
2693
- import { Fragment as Fragment2, jsx as jsx42, jsxs as jsxs26 } from "react/jsx-runtime";
2715
+ import { Fragment as Fragment2, jsx as jsx43, jsxs as jsxs26 } from "react/jsx-runtime";
2694
2716
  var DEFAULT_CLASS_COLORS = CLASS_COLORS;
2695
2717
  function DetectionCanvas({
2696
2718
  src,
@@ -2710,7 +2732,7 @@ function DetectionCanvas({
2710
2732
  }
2711
2733
  const ratio = aspectRatio ?? (imageWidth && imageHeight ? `${imageWidth}/${imageHeight}` : "16/9");
2712
2734
  const filteredDetections = detections.filter((d) => d.confidence >= minConfidence);
2713
- return /* @__PURE__ */ jsx42(
2735
+ return /* @__PURE__ */ jsx43(
2714
2736
  "div",
2715
2737
  {
2716
2738
  className: cn(
@@ -2719,9 +2741,9 @@ function DetectionCanvas({
2719
2741
  ),
2720
2742
  style: { aspectRatio: ratio },
2721
2743
  children: src ? /* @__PURE__ */ jsxs26(Fragment2, { children: [
2722
- /* @__PURE__ */ jsx42("img", { src, className: "absolute inset-0 w-full h-full object-fill", alt: "" }),
2744
+ /* @__PURE__ */ jsx43("img", { src, className: "absolute inset-0 w-full h-full object-fill", alt: "" }),
2723
2745
  filteredDetections.map(
2724
- (d, i) => d.mask && d.maskWidth && d.maskHeight ? /* @__PURE__ */ jsx42(
2746
+ (d, i) => d.mask && d.maskWidth && d.maskHeight ? /* @__PURE__ */ jsx43(
2725
2747
  MaskOverlay,
2726
2748
  {
2727
2749
  mask: d.mask,
@@ -2735,7 +2757,7 @@ function DetectionCanvas({
2735
2757
  `mask-${i}`
2736
2758
  ) : null
2737
2759
  ),
2738
- filteredDetections.map((d, i) => /* @__PURE__ */ jsx42(
2760
+ filteredDetections.map((d, i) => /* @__PURE__ */ jsx43(
2739
2761
  BoundingBox,
2740
2762
  {
2741
2763
  detection: d,
@@ -2755,7 +2777,7 @@ function DetectionCanvas({
2755
2777
  const ph = py2 - py1;
2756
2778
  if (pw > 0 && ph > 0 && cw * ch / (pw * ph) > 0.8) return false;
2757
2779
  return true;
2758
- }).map((child, j) => /* @__PURE__ */ jsx42(
2780
+ }).map((child, j) => /* @__PURE__ */ jsx43(
2759
2781
  ChildBoundingBox,
2760
2782
  {
2761
2783
  child,
@@ -2768,7 +2790,7 @@ function DetectionCanvas({
2768
2790
  },
2769
2791
  `det-${i}`
2770
2792
  ))
2771
- ] }) : /* @__PURE__ */ jsx42("div", { className: "w-full h-full flex items-center justify-center text-foreground-subtle text-sm", children: placeholder ?? "No image loaded" })
2793
+ ] }) : /* @__PURE__ */ jsx43("div", { className: "w-full h-full flex items-center justify-center text-foreground-subtle text-sm", children: placeholder ?? "No image loaded" })
2772
2794
  }
2773
2795
  );
2774
2796
  }
@@ -2880,7 +2902,7 @@ function MaskOverlay({
2880
2902
  ctx.putImageData(imageData, 0, 0);
2881
2903
  }, [mask, maskWidth, maskHeight, color]);
2882
2904
  const [x1, y1, x2, y2] = bbox;
2883
- return /* @__PURE__ */ jsx42(
2905
+ return /* @__PURE__ */ jsx43(
2884
2906
  "canvas",
2885
2907
  {
2886
2908
  ref: canvasRef,
@@ -2906,7 +2928,7 @@ function ChildBoundingBox({
2906
2928
  const pw = px2 - px1;
2907
2929
  const ph = py2 - py1;
2908
2930
  if (pw <= 0 || ph <= 0) return null;
2909
- return /* @__PURE__ */ jsx42(
2931
+ return /* @__PURE__ */ jsx43(
2910
2932
  "div",
2911
2933
  {
2912
2934
  className: "absolute rounded-sm",
@@ -2963,7 +2985,7 @@ function ChildBoundingBox({
2963
2985
  }
2964
2986
 
2965
2987
  // src/composites/detection-result-tree.tsx
2966
- import { jsx as jsx43, jsxs as jsxs27 } from "react/jsx-runtime";
2988
+ import { jsx as jsx44, jsxs as jsxs27 } from "react/jsx-runtime";
2967
2989
  function DetectionResultTree({
2968
2990
  detections,
2969
2991
  classColors,
@@ -2973,7 +2995,7 @@ function DetectionResultTree({
2973
2995
  }) {
2974
2996
  const colors = classColors;
2975
2997
  if (detections.length === 0) {
2976
- return /* @__PURE__ */ jsx43("div", { className: "text-sm text-foreground-subtle italic text-center py-4", children: "No detections" });
2998
+ return /* @__PURE__ */ jsx44("div", { className: "text-sm text-foreground-subtle italic text-center py-4", children: "No detections" });
2977
2999
  }
2978
3000
  return /* @__PURE__ */ jsxs27("div", { className, children: [
2979
3001
  /* @__PURE__ */ jsxs27("div", { className: "text-xs font-medium text-foreground-subtle uppercase tracking-wide mb-2", children: [
@@ -2981,7 +3003,7 @@ function DetectionResultTree({
2981
3003
  detections.length,
2982
3004
  ")"
2983
3005
  ] }),
2984
- /* @__PURE__ */ jsx43("div", { className: "space-y-2", children: detections.map((d, i) => /* @__PURE__ */ jsx43(
3006
+ /* @__PURE__ */ jsx44("div", { className: "space-y-2", children: detections.map((d, i) => /* @__PURE__ */ jsx44(
2985
3007
  DetectionNode,
2986
3008
  {
2987
3009
  detection: d,
@@ -3006,7 +3028,7 @@ function DetectionNode({
3006
3028
  return /* @__PURE__ */ jsxs27("div", { className: `rounded-md border border-border bg-surface p-3 space-y-1 ${isVisible ? "" : "opacity-40"}`, children: [
3007
3029
  /* @__PURE__ */ jsxs27("div", { className: "flex justify-between items-center", children: [
3008
3030
  /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2", children: [
3009
- onToggleVisibility && /* @__PURE__ */ jsx43(
3031
+ onToggleVisibility && /* @__PURE__ */ jsx44(
3010
3032
  "input",
3011
3033
  {
3012
3034
  type: "checkbox",
@@ -3015,14 +3037,14 @@ function DetectionNode({
3015
3037
  className: "h-3.5 w-3.5 rounded border-border accent-primary cursor-pointer shrink-0"
3016
3038
  }
3017
3039
  ),
3018
- /* @__PURE__ */ jsx43(
3040
+ /* @__PURE__ */ jsx44(
3019
3041
  "span",
3020
3042
  {
3021
3043
  className: "h-2.5 w-2.5 rounded-full shrink-0",
3022
3044
  style: { backgroundColor: color }
3023
3045
  }
3024
3046
  ),
3025
- /* @__PURE__ */ jsx43("span", { className: "text-sm font-medium text-foreground", children: detection.className }),
3047
+ /* @__PURE__ */ jsx44("span", { className: "text-sm font-medium text-foreground", children: detection.className }),
3026
3048
  detection.mask && detection.maskWidth && detection.maskHeight && /* @__PURE__ */ jsxs27("span", { className: "text-[9px] font-mono px-1 py-0.5 rounded bg-primary/10 text-primary", children: [
3027
3049
  "mask ",
3028
3050
  detection.maskWidth,
@@ -3030,14 +3052,14 @@ function DetectionNode({
3030
3052
  detection.maskHeight
3031
3053
  ] })
3032
3054
  ] }),
3033
- /* @__PURE__ */ jsx43(ConfidenceBadge, { confidence: detection.confidence })
3055
+ /* @__PURE__ */ jsx44(ConfidenceBadge, { confidence: detection.confidence })
3034
3056
  ] }),
3035
3057
  /* @__PURE__ */ jsxs27("div", { className: "text-[10px] text-foreground-subtle font-mono", children: [
3036
3058
  "bbox: [",
3037
3059
  detection.bbox.map((v) => Math.round(v)).join(", "),
3038
3060
  "]"
3039
3061
  ] }),
3040
- detection.labelsData && detection.labelsData.length > 0 && /* @__PURE__ */ jsx43("div", { className: "flex flex-wrap gap-1 mt-1", children: detection.labelsData.map((l, k) => /* @__PURE__ */ jsxs27(
3062
+ detection.labelsData && detection.labelsData.length > 0 && /* @__PURE__ */ jsx44("div", { className: "flex flex-wrap gap-1 mt-1", children: detection.labelsData.map((l, k) => /* @__PURE__ */ jsxs27(
3041
3063
  "span",
3042
3064
  {
3043
3065
  className: "inline-flex items-center gap-1 text-[10px] font-medium px-1.5 py-0.5 rounded-full",
@@ -3048,12 +3070,12 @@ function DetectionNode({
3048
3070
  (l.score * 100).toFixed(0),
3049
3071
  "%"
3050
3072
  ] }),
3051
- l.addonId && /* @__PURE__ */ jsx43("span", { className: "opacity-40 text-[8px]", children: l.addonId })
3073
+ l.addonId && /* @__PURE__ */ jsx44("span", { className: "opacity-40 text-[8px]", children: l.addonId })
3052
3074
  ]
3053
3075
  },
3054
3076
  k
3055
3077
  )) }),
3056
- detection.children && detection.children.length > 0 && /* @__PURE__ */ jsx43(
3078
+ detection.children && detection.children.length > 0 && /* @__PURE__ */ jsx44(
3057
3079
  ChildrenTree,
3058
3080
  {
3059
3081
  children: detection.children,
@@ -3072,13 +3094,13 @@ function ChildrenTree({
3072
3094
  hiddenKeys,
3073
3095
  onToggleVisibility
3074
3096
  }) {
3075
- return /* @__PURE__ */ jsx43("div", { className: "ml-4 mt-1.5 space-y-1.5 border-l-2 border-border pl-3", children: children.map((child, j) => {
3097
+ return /* @__PURE__ */ jsx44("div", { className: "ml-4 mt-1.5 space-y-1.5 border-l-2 border-border pl-3", children: children.map((child, j) => {
3076
3098
  const childPath = `${parentPath}.${j}`;
3077
3099
  const childColor = getClassColor(child.className, colors);
3078
3100
  const isVisible = !hiddenKeys?.has(childPath);
3079
3101
  return /* @__PURE__ */ jsxs27("div", { className: `text-xs space-y-0.5 ${isVisible ? "" : "opacity-40"}`, children: [
3080
3102
  /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-1.5", children: [
3081
- onToggleVisibility && /* @__PURE__ */ jsx43(
3103
+ onToggleVisibility && /* @__PURE__ */ jsx44(
3082
3104
  "input",
3083
3105
  {
3084
3106
  type: "checkbox",
@@ -3087,14 +3109,14 @@ function ChildrenTree({
3087
3109
  className: "h-3 w-3 rounded border-border accent-primary cursor-pointer shrink-0"
3088
3110
  }
3089
3111
  ),
3090
- /* @__PURE__ */ jsx43(
3112
+ /* @__PURE__ */ jsx44(
3091
3113
  "span",
3092
3114
  {
3093
3115
  className: "h-1.5 w-1.5 rounded-full shrink-0",
3094
3116
  style: { backgroundColor: childColor }
3095
3117
  }
3096
3118
  ),
3097
- /* @__PURE__ */ jsx43("span", { className: "font-medium", style: { color: childColor }, children: child.className }),
3119
+ /* @__PURE__ */ jsx44("span", { className: "font-medium", style: { color: childColor }, children: child.className }),
3098
3120
  /* @__PURE__ */ jsxs27("span", { className: "text-foreground-subtle", children: [
3099
3121
  (child.confidence * 100).toFixed(0),
3100
3122
  "%"
@@ -3106,7 +3128,7 @@ function ChildrenTree({
3106
3128
  child.maskHeight
3107
3129
  ] })
3108
3130
  ] }),
3109
- child.labelsData && child.labelsData.length > 0 && /* @__PURE__ */ jsx43("div", { className: "flex flex-wrap gap-1 ml-5 mt-0.5", children: child.labelsData.map((l, k) => /* @__PURE__ */ jsxs27(
3131
+ child.labelsData && child.labelsData.length > 0 && /* @__PURE__ */ jsx44("div", { className: "flex flex-wrap gap-1 ml-5 mt-0.5", children: child.labelsData.map((l, k) => /* @__PURE__ */ jsxs27(
3110
3132
  "span",
3111
3133
  {
3112
3134
  className: "inline-flex items-center gap-0.5 text-[9px] font-medium px-1 py-0.5 rounded-full",
@@ -3122,7 +3144,7 @@ function ChildrenTree({
3122
3144
  },
3123
3145
  k
3124
3146
  )) }),
3125
- child.children && child.children.length > 0 && /* @__PURE__ */ jsx43(
3147
+ child.children && child.children.length > 0 && /* @__PURE__ */ jsx44(
3126
3148
  ChildrenTree,
3127
3149
  {
3128
3150
  children: child.children,
@@ -3144,22 +3166,22 @@ function ConfidenceBadge({ confidence }) {
3144
3166
  }
3145
3167
 
3146
3168
  // src/composites/step-timings.tsx
3147
- import { jsx as jsx44, jsxs as jsxs28 } from "react/jsx-runtime";
3169
+ import { jsx as jsx45, jsxs as jsxs28 } from "react/jsx-runtime";
3148
3170
  function StepTimings({ timings, totalMs, className }) {
3149
3171
  const entries = Object.entries(timings);
3150
3172
  if (entries.length === 0 && totalMs === void 0) return null;
3151
3173
  return /* @__PURE__ */ jsxs28("div", { className: `rounded-lg border border-border bg-surface p-3 space-y-2 ${className ?? ""}`, children: [
3152
- /* @__PURE__ */ jsx44("div", { className: "text-xs font-medium text-foreground-subtle uppercase tracking-wide", children: "Timings" }),
3174
+ /* @__PURE__ */ jsx45("div", { className: "text-xs font-medium text-foreground-subtle uppercase tracking-wide", children: "Timings" }),
3153
3175
  /* @__PURE__ */ jsxs28("div", { className: "space-y-1 text-xs", children: [
3154
3176
  entries.map(([step, ms]) => /* @__PURE__ */ jsxs28("div", { className: "flex justify-between", children: [
3155
- /* @__PURE__ */ jsx44("span", { className: "text-foreground-subtle", children: step }),
3177
+ /* @__PURE__ */ jsx45("span", { className: "text-foreground-subtle", children: step }),
3156
3178
  /* @__PURE__ */ jsxs28("span", { className: "font-mono text-foreground", children: [
3157
3179
  ms.toFixed(1),
3158
3180
  "ms"
3159
3181
  ] })
3160
3182
  ] }, step)),
3161
3183
  totalMs !== void 0 && /* @__PURE__ */ jsxs28("div", { className: "flex justify-between pt-1 border-t border-border font-medium text-foreground", children: [
3162
- /* @__PURE__ */ jsx44("span", { children: "Total" }),
3184
+ /* @__PURE__ */ jsx45("span", { children: "Total" }),
3163
3185
  /* @__PURE__ */ jsxs28("span", { className: "font-mono", children: [
3164
3186
  totalMs.toFixed(1),
3165
3187
  "ms"
@@ -3170,7 +3192,7 @@ function StepTimings({ timings, totalMs, className }) {
3170
3192
  }
3171
3193
 
3172
3194
  // src/composites/image-selector.tsx
3173
- import { jsx as jsx45, jsxs as jsxs29 } from "react/jsx-runtime";
3195
+ import { jsx as jsx46, jsxs as jsxs29 } from "react/jsx-runtime";
3174
3196
  function ImageSelector({
3175
3197
  images,
3176
3198
  selectedFilename,
@@ -3197,7 +3219,7 @@ function ImageSelector({
3197
3219
  input.click();
3198
3220
  };
3199
3221
  return /* @__PURE__ */ jsxs29("div", { className: `flex flex-wrap items-center gap-2 ${className ?? ""}`, children: [
3200
- images.map((img) => /* @__PURE__ */ jsx45(
3222
+ images.map((img) => /* @__PURE__ */ jsx46(
3201
3223
  "button",
3202
3224
  {
3203
3225
  onClick: () => onSelect(img.filename),
@@ -3206,7 +3228,7 @@ function ImageSelector({
3206
3228
  },
3207
3229
  img.filename
3208
3230
  )),
3209
- /* @__PURE__ */ jsx45(
3231
+ /* @__PURE__ */ jsx46(
3210
3232
  "button",
3211
3233
  {
3212
3234
  onClick: handleUploadClick,
@@ -3214,12 +3236,12 @@ function ImageSelector({
3214
3236
  children: "Upload..."
3215
3237
  }
3216
3238
  ),
3217
- uploadedName && /* @__PURE__ */ jsx45("span", { className: "text-xs text-foreground-subtle", children: uploadedName })
3239
+ uploadedName && /* @__PURE__ */ jsx46("span", { className: "text-xs text-foreground-subtle", children: uploadedName })
3218
3240
  ] });
3219
3241
  }
3220
3242
 
3221
3243
  // src/composites/inference-config-selector.tsx
3222
- import { jsx as jsx46, jsxs as jsxs30 } from "react/jsx-runtime";
3244
+ import { jsx as jsx47, jsxs as jsxs30 } from "react/jsx-runtime";
3223
3245
  var SELECT_CLASS = "w-full px-3 py-2 text-sm rounded-md border border-border bg-surface text-foreground focus:outline-none focus:ring-2 focus:ring-primary/50";
3224
3246
  function InferenceConfigSelector({
3225
3247
  runtime,
@@ -3241,8 +3263,8 @@ function InferenceConfigSelector({
3241
3263
  const containerClass = layout === "grid" ? "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4" : layout === "horizontal" ? "flex flex-wrap items-end gap-4" : "space-y-3";
3242
3264
  return /* @__PURE__ */ jsxs30("div", { className: `${containerClass} ${className ?? ""}`, children: [
3243
3265
  showAgent && agents.length > 0 && /* @__PURE__ */ jsxs30("label", { className: "space-y-1", children: [
3244
- /* @__PURE__ */ jsx46("span", { className: "text-xs font-medium text-foreground-subtle", children: "Agent" }),
3245
- /* @__PURE__ */ jsx46(
3266
+ /* @__PURE__ */ jsx47("span", { className: "text-xs font-medium text-foreground-subtle", children: "Agent" }),
3267
+ /* @__PURE__ */ jsx47(
3246
3268
  "select",
3247
3269
  {
3248
3270
  value: agentId,
@@ -3258,8 +3280,8 @@ function InferenceConfigSelector({
3258
3280
  )
3259
3281
  ] }),
3260
3282
  /* @__PURE__ */ jsxs30("label", { className: "space-y-1", children: [
3261
- /* @__PURE__ */ jsx46("span", { className: "text-xs font-medium text-foreground-subtle", children: "Runtime" }),
3262
- /* @__PURE__ */ jsx46(
3283
+ /* @__PURE__ */ jsx47("span", { className: "text-xs font-medium text-foreground-subtle", children: "Runtime" }),
3284
+ /* @__PURE__ */ jsx47(
3263
3285
  "select",
3264
3286
  {
3265
3287
  value: runtime,
@@ -3273,8 +3295,8 @@ function InferenceConfigSelector({
3273
3295
  )
3274
3296
  ] }),
3275
3297
  /* @__PURE__ */ jsxs30("label", { className: "space-y-1", children: [
3276
- /* @__PURE__ */ jsx46("span", { className: "text-xs font-medium text-foreground-subtle", children: "Backend" }),
3277
- /* @__PURE__ */ jsx46(
3298
+ /* @__PURE__ */ jsx47("span", { className: "text-xs font-medium text-foreground-subtle", children: "Backend" }),
3299
+ /* @__PURE__ */ jsx47(
3278
3300
  "select",
3279
3301
  {
3280
3302
  value: backend,
@@ -3288,14 +3310,14 @@ function InferenceConfigSelector({
3288
3310
  )
3289
3311
  ] }),
3290
3312
  /* @__PURE__ */ jsxs30("label", { className: "space-y-1", children: [
3291
- /* @__PURE__ */ jsx46("span", { className: "text-xs font-medium text-foreground-subtle", children: "Model" }),
3292
- /* @__PURE__ */ jsx46(
3313
+ /* @__PURE__ */ jsx47("span", { className: "text-xs font-medium text-foreground-subtle", children: "Model" }),
3314
+ /* @__PURE__ */ jsx47(
3293
3315
  "select",
3294
3316
  {
3295
3317
  value: modelId,
3296
3318
  onChange: (e) => onModelChange(e.target.value),
3297
3319
  className: SELECT_CLASS,
3298
- children: models.length === 0 ? /* @__PURE__ */ jsx46("option", { value: "", children: "No compatible models" }) : models.map((m) => /* @__PURE__ */ jsxs30("option", { value: m.id, children: [
3320
+ children: models.length === 0 ? /* @__PURE__ */ jsx47("option", { value: "", children: "No compatible models" }) : models.map((m) => /* @__PURE__ */ jsxs30("option", { value: m.id, children: [
3299
3321
  m.name,
3300
3322
  m.downloaded ? " \u2713" : ""
3301
3323
  ] }, m.id))
@@ -3316,7 +3338,7 @@ import superjson from "superjson";
3316
3338
 
3317
3339
  // src/composites/login-form.tsx
3318
3340
  import { useState as useState11 } from "react";
3319
- import { jsx as jsx47, jsxs as jsxs31 } from "react/jsx-runtime";
3341
+ import { jsx as jsx48, jsxs as jsxs31 } from "react/jsx-runtime";
3320
3342
  function EyeIcon({ className }) {
3321
3343
  return /* @__PURE__ */ jsxs31(
3322
3344
  "svg",
@@ -3330,8 +3352,8 @@ function EyeIcon({ className }) {
3330
3352
  strokeLinejoin: "round",
3331
3353
  className,
3332
3354
  children: [
3333
- /* @__PURE__ */ jsx47("path", { d: "M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0" }),
3334
- /* @__PURE__ */ jsx47("circle", { cx: "12", cy: "12", r: "3" })
3355
+ /* @__PURE__ */ jsx48("path", { d: "M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0" }),
3356
+ /* @__PURE__ */ jsx48("circle", { cx: "12", cy: "12", r: "3" })
3335
3357
  ]
3336
3358
  }
3337
3359
  );
@@ -3349,16 +3371,16 @@ function EyeOffIcon({ className }) {
3349
3371
  strokeLinejoin: "round",
3350
3372
  className,
3351
3373
  children: [
3352
- /* @__PURE__ */ jsx47("path", { d: "M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49" }),
3353
- /* @__PURE__ */ jsx47("path", { d: "M14.084 14.158a3 3 0 0 1-4.242-4.242" }),
3354
- /* @__PURE__ */ jsx47("path", { d: "M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143" }),
3355
- /* @__PURE__ */ jsx47("path", { d: "m2 2 20 20" })
3374
+ /* @__PURE__ */ jsx48("path", { d: "M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49" }),
3375
+ /* @__PURE__ */ jsx48("path", { d: "M14.084 14.158a3 3 0 0 1-4.242-4.242" }),
3376
+ /* @__PURE__ */ jsx48("path", { d: "M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143" }),
3377
+ /* @__PURE__ */ jsx48("path", { d: "m2 2 20 20" })
3356
3378
  ]
3357
3379
  }
3358
3380
  );
3359
3381
  }
3360
3382
  function SpinnerIcon({ className }) {
3361
- return /* @__PURE__ */ jsx47(
3383
+ return /* @__PURE__ */ jsx48(
3362
3384
  "svg",
3363
3385
  {
3364
3386
  xmlns: "http://www.w3.org/2000/svg",
@@ -3369,7 +3391,7 @@ function SpinnerIcon({ className }) {
3369
3391
  strokeLinecap: "round",
3370
3392
  strokeLinejoin: "round",
3371
3393
  className,
3372
- children: /* @__PURE__ */ jsx47("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
3394
+ children: /* @__PURE__ */ jsx48("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
3373
3395
  }
3374
3396
  );
3375
3397
  }
@@ -3400,7 +3422,7 @@ function LoginForm({
3400
3422
  setSubmitting(false);
3401
3423
  }
3402
3424
  };
3403
- return /* @__PURE__ */ jsx47(
3425
+ return /* @__PURE__ */ jsx48(
3404
3426
  "div",
3405
3427
  {
3406
3428
  className: cn(
@@ -3408,18 +3430,18 @@ function LoginForm({
3408
3430
  className
3409
3431
  ),
3410
3432
  children: /* @__PURE__ */ jsxs31("div", { className: "w-full max-w-sm", children: [
3411
- logoSrc && /* @__PURE__ */ jsx47("div", { className: "flex justify-center mb-8", children: /* @__PURE__ */ jsx47("img", { src: logoSrc, alt: "Logo", className: "h-12" }) }),
3412
- serverUrl && /* @__PURE__ */ jsx47("p", { className: "mb-4 text-center text-xs text-foreground-subtle truncate", children: serverUrl }),
3433
+ logoSrc && /* @__PURE__ */ jsx48("div", { className: "flex justify-center mb-8", children: /* @__PURE__ */ jsx48("img", { src: logoSrc, alt: "Logo", className: "h-12" }) }),
3434
+ serverUrl && /* @__PURE__ */ jsx48("p", { className: "mb-4 text-center text-xs text-foreground-subtle truncate", children: serverUrl }),
3413
3435
  /* @__PURE__ */ jsxs31(
3414
3436
  "form",
3415
3437
  {
3416
3438
  onSubmit: handleSubmit,
3417
3439
  className: "space-y-4 rounded-xl border border-border bg-surface p-6 shadow-xl shadow-black/10",
3418
3440
  children: [
3419
- error && /* @__PURE__ */ jsx47("div", { className: "rounded-md bg-danger/10 border border-danger/20 px-3 py-2 text-xs text-danger", children: error }),
3441
+ error && /* @__PURE__ */ jsx48("div", { className: "rounded-md bg-danger/10 border border-danger/20 px-3 py-2 text-xs text-danger", children: error }),
3420
3442
  /* @__PURE__ */ jsxs31("div", { className: "space-y-1.5", children: [
3421
- /* @__PURE__ */ jsx47("label", { className: "text-xs font-medium text-foreground-subtle", children: "Username" }),
3422
- /* @__PURE__ */ jsx47(
3443
+ /* @__PURE__ */ jsx48("label", { className: "text-xs font-medium text-foreground-subtle", children: "Username" }),
3444
+ /* @__PURE__ */ jsx48(
3423
3445
  "input",
3424
3446
  {
3425
3447
  type: "text",
@@ -3432,9 +3454,9 @@ function LoginForm({
3432
3454
  )
3433
3455
  ] }),
3434
3456
  /* @__PURE__ */ jsxs31("div", { className: "space-y-1.5", children: [
3435
- /* @__PURE__ */ jsx47("label", { className: "text-xs font-medium text-foreground-subtle", children: "Password" }),
3457
+ /* @__PURE__ */ jsx48("label", { className: "text-xs font-medium text-foreground-subtle", children: "Password" }),
3436
3458
  /* @__PURE__ */ jsxs31("div", { className: "relative", children: [
3437
- /* @__PURE__ */ jsx47(
3459
+ /* @__PURE__ */ jsx48(
3438
3460
  "input",
3439
3461
  {
3440
3462
  type: showPassword ? "text" : "password",
@@ -3445,14 +3467,14 @@ function LoginForm({
3445
3467
  className: "w-full rounded-lg border border-border bg-background px-3 py-2.5 pr-10 text-sm text-foreground placeholder:text-foreground-subtle focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary"
3446
3468
  }
3447
3469
  ),
3448
- /* @__PURE__ */ jsx47(
3470
+ /* @__PURE__ */ jsx48(
3449
3471
  "button",
3450
3472
  {
3451
3473
  type: "button",
3452
3474
  onClick: () => setShowPassword((prev) => !prev),
3453
3475
  className: "absolute right-2.5 top-1/2 -translate-y-1/2 text-foreground-subtle hover:text-foreground",
3454
3476
  tabIndex: -1,
3455
- children: showPassword ? /* @__PURE__ */ jsx47(EyeOffIcon, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx47(EyeIcon, { className: "h-4 w-4" })
3477
+ children: showPassword ? /* @__PURE__ */ jsx48(EyeOffIcon, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx48(EyeIcon, { className: "h-4 w-4" })
3456
3478
  }
3457
3479
  )
3458
3480
  ] })
@@ -3464,7 +3486,7 @@ function LoginForm({
3464
3486
  disabled: submitting,
3465
3487
  className: "w-full rounded-lg bg-primary px-4 py-2.5 text-sm font-semibold text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors flex items-center justify-center gap-2",
3466
3488
  children: [
3467
- submitting && /* @__PURE__ */ jsx47(SpinnerIcon, { className: "h-4 w-4 animate-spin" }),
3489
+ submitting && /* @__PURE__ */ jsx48(SpinnerIcon, { className: "h-4 w-4 animate-spin" }),
3468
3490
  submitting ? "Logging in..." : "Log in"
3469
3491
  ]
3470
3492
  }
@@ -3478,7 +3500,7 @@ function LoginForm({
3478
3500
  }
3479
3501
 
3480
3502
  // src/composites/dev-shell.tsx
3481
- import { jsx as jsx48, jsxs as jsxs32 } from "react/jsx-runtime";
3503
+ import { jsx as jsx49, jsxs as jsxs32 } from "react/jsx-runtime";
3482
3504
  var STORAGE_KEY = "camstack_dev_token";
3483
3505
  var DevShellContext = createContext7(null);
3484
3506
  function useDevShell() {
@@ -3505,21 +3527,21 @@ function SunIcon({ className }) {
3505
3527
  strokeLinejoin: "round",
3506
3528
  className,
3507
3529
  children: [
3508
- /* @__PURE__ */ jsx48("circle", { cx: "12", cy: "12", r: "4" }),
3509
- /* @__PURE__ */ jsx48("path", { d: "M12 2v2" }),
3510
- /* @__PURE__ */ jsx48("path", { d: "M12 20v2" }),
3511
- /* @__PURE__ */ jsx48("path", { d: "m4.93 4.93 1.41 1.41" }),
3512
- /* @__PURE__ */ jsx48("path", { d: "m17.66 17.66 1.41 1.41" }),
3513
- /* @__PURE__ */ jsx48("path", { d: "M2 12h2" }),
3514
- /* @__PURE__ */ jsx48("path", { d: "M20 12h2" }),
3515
- /* @__PURE__ */ jsx48("path", { d: "m6.34 17.66-1.41 1.41" }),
3516
- /* @__PURE__ */ jsx48("path", { d: "m19.07 4.93-1.41 1.41" })
3530
+ /* @__PURE__ */ jsx49("circle", { cx: "12", cy: "12", r: "4" }),
3531
+ /* @__PURE__ */ jsx49("path", { d: "M12 2v2" }),
3532
+ /* @__PURE__ */ jsx49("path", { d: "M12 20v2" }),
3533
+ /* @__PURE__ */ jsx49("path", { d: "m4.93 4.93 1.41 1.41" }),
3534
+ /* @__PURE__ */ jsx49("path", { d: "m17.66 17.66 1.41 1.41" }),
3535
+ /* @__PURE__ */ jsx49("path", { d: "M2 12h2" }),
3536
+ /* @__PURE__ */ jsx49("path", { d: "M20 12h2" }),
3537
+ /* @__PURE__ */ jsx49("path", { d: "m6.34 17.66-1.41 1.41" }),
3538
+ /* @__PURE__ */ jsx49("path", { d: "m19.07 4.93-1.41 1.41" })
3517
3539
  ]
3518
3540
  }
3519
3541
  );
3520
3542
  }
3521
3543
  function MoonIcon({ className }) {
3522
- return /* @__PURE__ */ jsx48(
3544
+ return /* @__PURE__ */ jsx49(
3523
3545
  "svg",
3524
3546
  {
3525
3547
  xmlns: "http://www.w3.org/2000/svg",
@@ -3530,7 +3552,7 @@ function MoonIcon({ className }) {
3530
3552
  strokeLinecap: "round",
3531
3553
  strokeLinejoin: "round",
3532
3554
  className,
3533
- children: /* @__PURE__ */ jsx48("path", { d: "M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" })
3555
+ children: /* @__PURE__ */ jsx49("path", { d: "M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" })
3534
3556
  }
3535
3557
  );
3536
3558
  }
@@ -3569,12 +3591,12 @@ function DevShellInner({
3569
3591
  () => ({ trpc, token, logout: onLogout }),
3570
3592
  [trpc, token, onLogout]
3571
3593
  );
3572
- return /* @__PURE__ */ jsx48(DevShellContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs32("div", { className: "min-h-screen bg-background text-foreground", children: [
3594
+ return /* @__PURE__ */ jsx49(DevShellContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs32("div", { className: "min-h-screen bg-background text-foreground", children: [
3573
3595
  /* @__PURE__ */ jsxs32("div", { className: "flex items-center justify-between border-b border-border bg-surface px-4 py-2", children: [
3574
3596
  /* @__PURE__ */ jsxs32("div", { className: "flex items-center gap-2", children: [
3575
- /* @__PURE__ */ jsx48("span", { className: "rounded bg-warning/20 px-2 py-0.5 text-xs font-bold text-warning", children: "DEV MODE" }),
3576
- title && /* @__PURE__ */ jsx48("span", { className: "text-sm font-medium text-foreground", children: title }),
3577
- /* @__PURE__ */ jsx48("span", { className: "text-xs text-foreground-subtle", children: serverUrl })
3597
+ /* @__PURE__ */ jsx49("span", { className: "rounded bg-warning/20 px-2 py-0.5 text-xs font-bold text-warning", children: "DEV MODE" }),
3598
+ title && /* @__PURE__ */ jsx49("span", { className: "text-sm font-medium text-foreground", children: title }),
3599
+ /* @__PURE__ */ jsx49("span", { className: "text-xs text-foreground-subtle", children: serverUrl })
3578
3600
  ] }),
3579
3601
  /* @__PURE__ */ jsxs32("div", { className: "flex items-center gap-2", children: [
3580
3602
  /* @__PURE__ */ jsxs32(
@@ -3585,12 +3607,12 @@ function DevShellInner({
3585
3607
  className: "flex items-center gap-1.5 rounded-md px-2 py-1 text-xs font-medium text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors",
3586
3608
  title: `Theme: ${theme.mode}`,
3587
3609
  children: [
3588
- theme.resolvedMode === "dark" ? /* @__PURE__ */ jsx48(SunIcon, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx48(MoonIcon, { className: "h-3.5 w-3.5" }),
3610
+ theme.resolvedMode === "dark" ? /* @__PURE__ */ jsx49(SunIcon, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx49(MoonIcon, { className: "h-3.5 w-3.5" }),
3589
3611
  theme.mode === "dark" ? "Dark" : theme.mode === "light" ? "Light" : "System"
3590
3612
  ]
3591
3613
  }
3592
3614
  ),
3593
- /* @__PURE__ */ jsx48(
3615
+ /* @__PURE__ */ jsx49(
3594
3616
  "button",
3595
3617
  {
3596
3618
  type: "button",
@@ -3601,7 +3623,7 @@ function DevShellInner({
3601
3623
  )
3602
3624
  ] })
3603
3625
  ] }),
3604
- /* @__PURE__ */ jsx48("div", { className: "p-4", children: children({ trpc, theme }) })
3626
+ /* @__PURE__ */ jsx49("div", { className: "p-4", children: children({ trpc, theme }) })
3605
3627
  ] }) });
3606
3628
  }
3607
3629
  function DevShell({
@@ -3632,9 +3654,9 @@ function DevShell({
3632
3654
  setToken(null);
3633
3655
  }, []);
3634
3656
  if (!token) {
3635
- return /* @__PURE__ */ jsx48(ThemeProvider, { children: /* @__PURE__ */ jsx48(LoginForm, { onLogin: handleLogin, serverUrl }) });
3657
+ return /* @__PURE__ */ jsx49(ThemeProvider, { children: /* @__PURE__ */ jsx49(LoginForm, { onLogin: handleLogin, serverUrl }) });
3636
3658
  }
3637
- return /* @__PURE__ */ jsx48(ThemeProvider, { children: /* @__PURE__ */ jsx48(
3659
+ return /* @__PURE__ */ jsx49(ThemeProvider, { children: /* @__PURE__ */ jsx49(
3638
3660
  DevShellInner,
3639
3661
  {
3640
3662
  serverUrl,
@@ -3721,6 +3743,7 @@ export {
3721
3743
  ProviderBadge,
3722
3744
  ScrollArea,
3723
3745
  Select,
3746
+ SemanticBadge,
3724
3747
  Separator,
3725
3748
  Sidebar,
3726
3749
  SidebarItem,
@@ -3737,6 +3760,7 @@ export {
3737
3760
  Tooltip,
3738
3761
  TooltipContent,
3739
3762
  TooltipTrigger,
3763
+ VersionBadge,
3740
3764
  cn,
3741
3765
  createTheme,
3742
3766
  darkColors,