@cytario/design 2.3.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -136,7 +136,7 @@ function Spinner({
136
136
  );
137
137
  }
138
138
 
139
- // src/components/InputGroup/InputGroupContext.ts
139
+ // src/components/Form/InputGroup/InputGroupContext.ts
140
140
  import { createContext, useContext } from "react";
141
141
  var InputGroupContext = createContext({
142
142
  inGroup: false,
@@ -325,7 +325,7 @@ function IconButton({
325
325
  return button;
326
326
  }
327
327
 
328
- // src/components/Input/Input.tsx
328
+ // src/components/Form/Input/Input.tsx
329
329
  import {
330
330
  TextField,
331
331
  Label,
@@ -501,7 +501,8 @@ function Input({
501
501
  );
502
502
  }
503
503
 
504
- // src/components/Select/Select.tsx
504
+ // src/components/Form/Select/Select.tsx
505
+ import { Check, ChevronDown } from "lucide-react";
505
506
  import {
506
507
  Button as Button2,
507
508
  Label as Label2,
@@ -511,48 +512,17 @@ import {
511
512
  Select as AriaSelect,
512
513
  SelectValue
513
514
  } from "react-aria-components";
515
+ import { twMerge as twMerge2 } from "tailwind-merge";
514
516
  import { Fragment, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
515
- function ChevronDown() {
516
- return /* @__PURE__ */ jsx7(
517
- "svg",
518
- {
519
- "aria-hidden": "true",
520
- className: "h-4 w-4 text-(--color-text-secondary)",
521
- viewBox: "0 0 16 16",
522
- fill: "none",
523
- stroke: "currentColor",
524
- strokeWidth: "2",
525
- strokeLinecap: "round",
526
- strokeLinejoin: "round",
527
- children: /* @__PURE__ */ jsx7("path", { d: "M4 6l4 4 4-4" })
528
- }
529
- );
530
- }
531
- function CheckIcon() {
532
- return /* @__PURE__ */ jsx7(
533
- "svg",
534
- {
535
- "aria-hidden": "true",
536
- className: "h-4 w-4 text-(--color-action-primary)",
537
- viewBox: "0 0 16 16",
538
- fill: "none",
539
- stroke: "currentColor",
540
- strokeWidth: "2",
541
- strokeLinecap: "round",
542
- strokeLinejoin: "round",
543
- children: /* @__PURE__ */ jsx7("path", { d: "M3 8.5l3.5 3.5 6.5-7" })
544
- }
545
- );
546
- }
547
517
  function Select({
548
518
  label,
549
519
  items,
550
520
  placeholder = "Select an option",
551
521
  errorMessage,
552
- hideLabel = false,
553
522
  isDisabled,
554
523
  isRequired,
555
524
  className,
525
+ renderItem,
556
526
  ...props
557
527
  }) {
558
528
  const hasError = Boolean(errorMessage);
@@ -563,44 +533,54 @@ function Select({
563
533
  isDisabled,
564
534
  isRequired,
565
535
  isInvalid: hasError,
566
- className: ["flex flex-col gap-1", className].filter(Boolean).join(" "),
536
+ className: twMerge2("flex flex-col gap-1", className),
567
537
  children: [
568
- /* @__PURE__ */ jsxs5(
569
- Label2,
570
- {
571
- className: [
572
- "text-sm font-medium text-(--color-text-primary)",
573
- hideLabel && "sr-only"
574
- ].filter(Boolean).join(" "),
575
- children: [
576
- label,
577
- isRequired && /* @__PURE__ */ jsx7(
578
- "span",
579
- {
580
- "aria-hidden": "true",
581
- className: "ml-0.5 text-(--color-text-danger)",
582
- children: "*"
583
- }
584
- )
585
- ]
586
- }
587
- ),
538
+ label && /* @__PURE__ */ jsxs5(Label2, { className: "text-sm font-medium text-(--color-text-primary)", children: [
539
+ label,
540
+ isRequired && /* @__PURE__ */ jsx7(
541
+ "span",
542
+ {
543
+ "aria-hidden": "true",
544
+ className: "ml-0.5 text-(--color-text-danger)",
545
+ children: "*"
546
+ }
547
+ )
548
+ ] }),
588
549
  /* @__PURE__ */ jsxs5(
589
550
  Button2,
590
551
  {
591
- className: [
552
+ className: twMerge2(
592
553
  "inline-flex items-center justify-between",
593
554
  "w-full rounded-md px-4 py-2",
594
555
  "text-base text-left",
595
556
  "border outline-none transition-colors",
596
557
  hasError ? "border-(--color-border-danger)" : "border-(--color-border-default)",
597
558
  "focus-visible:ring-2 focus-visible:ring-(--color-border-focus) focus-visible:ring-offset-2",
598
- "disabled:opacity-50 disabled:pointer-events-none",
559
+ "cursor-pointer disabled:opacity-50 disabled:pointer-events-none",
599
560
  "bg-(--color-surface-default)"
600
- ].join(" "),
561
+ ),
601
562
  children: [
602
- /* @__PURE__ */ jsx7(SelectValue, { className: "truncate data-[placeholder]:text-(--color-text-tertiary)", children: ({ selectedText }) => selectedText || placeholder }),
603
- /* @__PURE__ */ jsx7(ChevronDown, {})
563
+ /* @__PURE__ */ jsx7(
564
+ SelectValue,
565
+ {
566
+ className: twMerge2(
567
+ renderItem ? "min-w-0" : "truncate",
568
+ "data-placeholder:text-(--color-text-tertiary)"
569
+ ),
570
+ children: ({ selectedItem, isPlaceholder }) => {
571
+ if (isPlaceholder) return placeholder;
572
+ const item = selectedItem;
573
+ return renderItem ? renderItem(item) : item?.name ?? placeholder;
574
+ }
575
+ }
576
+ ),
577
+ /* @__PURE__ */ jsx7(
578
+ ChevronDown,
579
+ {
580
+ "aria-hidden": true,
581
+ className: "h-4 w-4 shrink-0 text-(--color-text-secondary)"
582
+ }
583
+ )
604
584
  ]
605
585
  }
606
586
  ),
@@ -608,33 +588,33 @@ function Select({
608
588
  /* @__PURE__ */ jsx7(
609
589
  Popover,
610
590
  {
611
- className: [
591
+ className: twMerge2(
612
592
  "w-(--trigger-width)",
613
593
  "rounded-md",
614
594
  "border border-(--color-border-default)",
615
595
  "bg-(--color-surface-default)",
616
596
  "shadow-lg",
617
597
  "overflow-auto",
618
- "entering:animate-in entering:fade-in entering:slide-in-from-top-1",
619
- "exiting:animate-out exiting:fade-out exiting:slide-out-to-top-1"
620
- ].join(" "),
598
+ "entering:animate-in entering:fade-in",
599
+ "exiting:animate-out exiting:fade-out"
600
+ ),
621
601
  children: /* @__PURE__ */ jsx7(ListBox, { className: "p-1 outline-none", items, children: (item) => /* @__PURE__ */ jsx7(
622
602
  ListBoxItem,
623
603
  {
624
604
  id: item.id,
625
605
  textValue: item.name,
626
- className: [
606
+ className: twMerge2(
627
607
  "flex items-center justify-between gap-2",
628
608
  "px-4 py-2 rounded-sm",
629
609
  "text-base text-(--color-text-primary)",
630
610
  "cursor-pointer outline-none",
631
611
  "hover:bg-(--color-surface-muted)",
632
- "focus:bg-(--color-surface-muted)",
612
+ "focus-visible:bg-(--color-surface-muted)",
633
613
  "selected:text-(--color-action-primary) selected:font-medium"
634
- ].join(" "),
614
+ ),
635
615
  children: ({ isSelected }) => /* @__PURE__ */ jsxs5(Fragment, { children: [
636
- /* @__PURE__ */ jsx7("span", { className: "truncate", children: item.name }),
637
- isSelected && /* @__PURE__ */ jsx7(CheckIcon, {})
616
+ /* @__PURE__ */ jsx7("span", { className: "truncate", children: renderItem ? renderItem(item) : item.name }),
617
+ isSelected && /* @__PURE__ */ jsx7(Check, { className: "h-4 w-4 shrink-0 text-(--color-action-primary)" })
638
618
  ] })
639
619
  }
640
620
  ) })
@@ -996,11 +976,11 @@ function EmptyState({
996
976
  );
997
977
  }
998
978
 
999
- // src/components/Checkbox/Checkbox.tsx
979
+ // src/components/Form/Checkbox/Checkbox.tsx
1000
980
  import {
1001
981
  Checkbox as AriaCheckbox
1002
982
  } from "react-aria-components";
1003
- import { Check } from "lucide-react";
983
+ import { Check as Check2 } from "lucide-react";
1004
984
  import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
1005
985
  function Checkbox({ children, className, ...props }) {
1006
986
  return /* @__PURE__ */ jsx13(
@@ -1023,7 +1003,7 @@ function Checkbox({ children, className, ...props }) {
1023
1003
  isSelected || isIndeterminate ? "bg-(--color-action-primary) border-(--color-action-primary)" : "bg-(--color-surface-default) border-(--color-border-default) group-hover:border-(--color-border-strong)"
1024
1004
  ].join(" "),
1025
1005
  children: [
1026
- isSelected && /* @__PURE__ */ jsx13(Check, { className: "w-4 h-4 text-(--color-text-inverse)", strokeWidth: 3 }),
1006
+ isSelected && /* @__PURE__ */ jsx13(Check2, { className: "w-4 h-4 text-(--color-text-inverse)", strokeWidth: 3 }),
1027
1007
  isIndeterminate && /* @__PURE__ */ jsx13("div", { className: "w-3 h-0.5 bg-(--color-text-inverse) rounded-full" })
1028
1008
  ]
1029
1009
  }
@@ -1034,7 +1014,7 @@ function Checkbox({ children, className, ...props }) {
1034
1014
  );
1035
1015
  }
1036
1016
 
1037
- // src/components/Switch/Switch.tsx
1017
+ // src/components/Form/Switch/Switch.tsx
1038
1018
  import {
1039
1019
  Switch as AriaSwitch
1040
1020
  } from "react-aria-components";
@@ -1091,7 +1071,7 @@ function Switch({
1091
1071
  );
1092
1072
  }
1093
1073
 
1094
- // src/components/Radio/Radio.tsx
1074
+ // src/components/Form/Radio/Radio.tsx
1095
1075
  import {
1096
1076
  RadioGroup as AriaRadioGroup,
1097
1077
  Radio as AriaRadio
@@ -1165,7 +1145,7 @@ function RadioButton({ children, className, ...props }) {
1165
1145
  );
1166
1146
  }
1167
1147
 
1168
- // src/components/Label/Label.tsx
1148
+ // src/components/Form/Label/Label.tsx
1169
1149
  import {
1170
1150
  Label as AriaLabel
1171
1151
  } from "react-aria-components";
@@ -1196,7 +1176,7 @@ function Label3({ isRequired, children, className, ...props }) {
1196
1176
  );
1197
1177
  }
1198
1178
 
1199
- // src/components/Field/Field.tsx
1179
+ // src/components/Form/Field/Field.tsx
1200
1180
  import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
1201
1181
  function getErrorMessage(error) {
1202
1182
  if (!error) return void 0;
@@ -1226,7 +1206,7 @@ function Field({
1226
1206
  );
1227
1207
  }
1228
1208
 
1229
- // src/components/Fieldset/Fieldset.tsx
1209
+ // src/components/Form/Fieldset/Fieldset.tsx
1230
1210
  import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
1231
1211
  function Fieldset({ legend, children, className }) {
1232
1212
  return /* @__PURE__ */ jsxs15(
@@ -1256,7 +1236,7 @@ function Fieldset({ legend, children, className }) {
1256
1236
  );
1257
1237
  }
1258
1238
 
1259
- // src/components/InputGroup/InputGroup.tsx
1239
+ // src/components/Form/InputGroup/InputGroup.tsx
1260
1240
  import React from "react";
1261
1241
  import { jsx as jsx19 } from "react/jsx-runtime";
1262
1242
  function InputGroup({ children, className }) {
@@ -1282,7 +1262,7 @@ function InputGroup({ children, className }) {
1282
1262
  );
1283
1263
  }
1284
1264
 
1285
- // src/components/InputAddon/InputAddon.tsx
1265
+ // src/components/Form/InputAddon/InputAddon.tsx
1286
1266
  import { jsx as jsx20 } from "react/jsx-runtime";
1287
1267
  function groupRadiusClass3(position) {
1288
1268
  switch (position) {
@@ -1319,7 +1299,7 @@ function InputAddon({ children, className }) {
1319
1299
  }
1320
1300
 
1321
1301
  // src/components/Heading/Heading.tsx
1322
- import { twMerge as twMerge2 } from "tailwind-merge";
1302
+ import { twMerge as twMerge3 } from "tailwind-merge";
1323
1303
  import { jsx as jsx21 } from "react/jsx-runtime";
1324
1304
  var defaultSizeMap = {
1325
1305
  h1: "2xl",
@@ -1353,7 +1333,7 @@ function Heading2({
1353
1333
  return /* @__PURE__ */ jsx21(
1354
1334
  Tag,
1355
1335
  {
1356
- className: twMerge2(
1336
+ className: twMerge3(
1357
1337
  weightStyles[weight],
1358
1338
  "text-(--color-text-primary)",
1359
1339
  sizeStyles3[resolvedSize],
@@ -1475,7 +1455,7 @@ function Breadcrumbs({ items, className }) {
1475
1455
  import {
1476
1456
  Link as AriaLink2
1477
1457
  } from "react-aria-components";
1478
- import { twMerge as twMerge3 } from "tailwind-merge";
1458
+ import { twMerge as twMerge4 } from "tailwind-merge";
1479
1459
  import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
1480
1460
  var iconSizeMap3 = {
1481
1461
  sm: "sm",
@@ -1495,7 +1475,7 @@ function ButtonLink({
1495
1475
  AriaLink2,
1496
1476
  {
1497
1477
  ...props,
1498
- className: twMerge3(
1478
+ className: twMerge4(
1499
1479
  "inline-flex items-center justify-center gap-2",
1500
1480
  "rounded-md",
1501
1481
  "font-medium",
@@ -1534,7 +1514,7 @@ function IconButtonLink({
1534
1514
  {
1535
1515
  ...props,
1536
1516
  "aria-label": ariaLabel,
1537
- className: twMerge3(
1517
+ className: twMerge4(
1538
1518
  "inline-flex items-center justify-center",
1539
1519
  "rounded-md",
1540
1520
  "outline-none transition-colors no-underline",
@@ -1556,7 +1536,7 @@ function IconButtonLink({
1556
1536
  import {
1557
1537
  ToggleButton as AriaToggleButton
1558
1538
  } from "react-aria-components";
1559
- import { twMerge as twMerge4 } from "tailwind-merge";
1539
+ import { twMerge as twMerge5 } from "tailwind-merge";
1560
1540
  import { jsx as jsx25 } from "react/jsx-runtime";
1561
1541
  var sizeStyles4 = {
1562
1542
  sm: "px-3 py-1.5 text-sm",
@@ -1610,7 +1590,7 @@ function ToggleButton({
1610
1590
  AriaToggleButton,
1611
1591
  {
1612
1592
  ...props,
1613
- className: ({ isSelected }) => twMerge4(
1593
+ className: ({ isSelected }) => twMerge5(
1614
1594
  "inline-flex items-center justify-center gap-2",
1615
1595
  isSquare ? "rounded-none" : "rounded-md",
1616
1596
  "font-medium",
@@ -1628,7 +1608,7 @@ function ToggleButton({
1628
1608
 
1629
1609
  // src/components/ToggleButtonGroup/ToggleButtonGroup.tsx
1630
1610
  import { createContext as createContext3, useContext as useContext3 } from "react";
1631
- import { twMerge as twMerge5 } from "tailwind-merge";
1611
+ import { twMerge as twMerge6 } from "tailwind-merge";
1632
1612
  import {
1633
1613
  RadioGroup as AriaRadioGroup2,
1634
1614
  Radio as AriaRadio2
@@ -1658,7 +1638,7 @@ function ToggleButtonGroup({
1658
1638
  {
1659
1639
  ...props,
1660
1640
  orientation: "horizontal",
1661
- className: twMerge5(
1641
+ className: twMerge6(
1662
1642
  "inline-flex items-center rounded-lg border border-(--color-border-default) bg-(--color-surface-muted) p-0.5 gap-0.5",
1663
1643
  className
1664
1644
  ),
@@ -1677,7 +1657,7 @@ function ToggleButtonGroupItem({
1677
1657
  AriaRadio2,
1678
1658
  {
1679
1659
  ...props,
1680
- className: ({ isSelected, isHovered, isPressed, isDisabled }) => twMerge5(
1660
+ className: ({ isSelected, isHovered, isPressed, isDisabled }) => twMerge6(
1681
1661
  // Base layout
1682
1662
  "inline-flex items-center justify-center",
1683
1663
  "rounded-md",
@@ -1824,7 +1804,7 @@ function MenuItem({
1824
1804
 
1825
1805
  // src/components/Menu/MenuCheckboxItem.tsx
1826
1806
  import { MenuItem as AriaMenuItem3 } from "react-aria-components";
1827
- import { Check as Check2 } from "lucide-react";
1807
+ import { Check as Check3 } from "lucide-react";
1828
1808
  import { Fragment as Fragment7, jsx as jsx29, jsxs as jsxs20 } from "react/jsx-runtime";
1829
1809
  function MenuCheckboxItem({
1830
1810
  id,
@@ -1850,7 +1830,7 @@ function MenuCheckboxItem({
1850
1830
  className
1851
1831
  ].filter(Boolean).join(" "),
1852
1832
  children: ({ isSelected }) => /* @__PURE__ */ jsxs20(Fragment7, { children: [
1853
- /* @__PURE__ */ jsx29("span", { className: "flex items-center justify-center w-4 h-4 shrink-0", children: isSelected && /* @__PURE__ */ jsx29(Check2, { size: 14, className: "text-(--color-action-primary)", "aria-hidden": "true" }) }),
1833
+ /* @__PURE__ */ jsx29("span", { className: "flex items-center justify-center w-4 h-4 shrink-0", children: isSelected && /* @__PURE__ */ jsx29(Check3, { size: 14, className: "text-(--color-action-primary)", "aria-hidden": "true" }) }),
1854
1834
  /* @__PURE__ */ jsx29("span", { className: "flex-1", children })
1855
1835
  ] })
1856
1836
  }
@@ -1963,7 +1943,7 @@ function PopoverContent({
1963
1943
 
1964
1944
  // src/components/Tabs/Tabs.tsx
1965
1945
  import { createContext as createContext4, useContext as useContext4 } from "react";
1966
- import { twMerge as twMerge6 } from "tailwind-merge";
1946
+ import { twMerge as twMerge7 } from "tailwind-merge";
1967
1947
  import {
1968
1948
  Tabs as AriaTabs,
1969
1949
  TabList as AriaTabList,
@@ -1993,7 +1973,7 @@ function Tabs({
1993
1973
  {
1994
1974
  ...props,
1995
1975
  orientation,
1996
- className: twMerge6(
1976
+ className: twMerge7(
1997
1977
  orientation === "vertical" ? "flex" : "",
1998
1978
  className
1999
1979
  ),
@@ -2012,7 +1992,7 @@ function TabList({
2012
1992
  AriaTabList,
2013
1993
  {
2014
1994
  ...props,
2015
- className: ({ orientation }) => twMerge6(
1995
+ className: ({ orientation }) => twMerge7(
2016
1996
  baseStyles,
2017
1997
  orientation === "vertical" ? verticalStyles : "",
2018
1998
  className
@@ -2028,14 +2008,14 @@ function Tab({ className, ...props }) {
2028
2008
  ...props,
2029
2009
  className: ({ isSelected, isDisabled, isHovered, isPressed }) => {
2030
2010
  if (variant === "unstyled") {
2031
- return twMerge6(
2011
+ return twMerge7(
2032
2012
  "cursor-pointer outline-none",
2033
2013
  "focus-visible:ring-2 focus-visible:ring-(--color-border-focus) focus-visible:ring-offset-2",
2034
2014
  isDisabled ? "opacity-50 pointer-events-none" : "",
2035
2015
  className
2036
2016
  );
2037
2017
  }
2038
- return twMerge6(
2018
+ return twMerge7(
2039
2019
  // Base
2040
2020
  "cursor-pointer outline-none transition-colors",
2041
2021
  "font-medium",
@@ -2083,7 +2063,7 @@ function TabPanel({ className, ...props }) {
2083
2063
  AriaTabPanel,
2084
2064
  {
2085
2065
  ...props,
2086
- className: twMerge6(
2066
+ className: twMerge7(
2087
2067
  variant === "unstyled" ? "outline-none" : "mt-4 outline-none",
2088
2068
  className
2089
2069
  )
@@ -2103,7 +2083,7 @@ import {
2103
2083
  import { useCallback as useCallback2, useImperativeHandle, useRef as useRef2, useState as useState2 } from "react";
2104
2084
  import { Tree as ArboristTree } from "react-arborist";
2105
2085
  import { ChevronRight as ChevronRight2, Folder, File } from "lucide-react";
2106
- import { Check as Check3 } from "lucide-react";
2086
+ import { Check as Check4 } from "lucide-react";
2107
2087
  import { jsx as jsx35, jsxs as jsxs22 } from "react/jsx-runtime";
2108
2088
  var rowHeightMap = {
2109
2089
  compact: 32,
@@ -2206,7 +2186,7 @@ function NodeRenderer({
2206
2186
  "aria-checked": isChecked,
2207
2187
  "aria-label": `Select ${data.name}`,
2208
2188
  children: isChecked && /* @__PURE__ */ jsx35(
2209
- Check3,
2189
+ Check4,
2210
2190
  {
2211
2191
  className: "w-3 h-3 text-(--color-text-inverse)",
2212
2192
  strokeWidth: 3
@@ -2335,7 +2315,7 @@ function Tree({
2335
2315
 
2336
2316
  // src/components/SegmentedControl/SegmentedControl.tsx
2337
2317
  import { createContext as createContext5, useContext as useContext5 } from "react";
2338
- import { twMerge as twMerge7 } from "tailwind-merge";
2318
+ import { twMerge as twMerge8 } from "tailwind-merge";
2339
2319
  import {
2340
2320
  ToggleButtonGroup as AriaToggleButtonGroup,
2341
2321
  ToggleButton as AriaToggleButton2
@@ -2368,7 +2348,7 @@ function SegmentedControl({
2368
2348
  selectedKeys: isNoneMode ? /* @__PURE__ */ new Set() : selectedKeys,
2369
2349
  defaultSelectedKeys: isNoneMode ? void 0 : defaultSelectedKeys,
2370
2350
  onSelectionChange: isNoneMode ? void 0 : onSelectionChange,
2371
- className: twMerge7(
2351
+ className: twMerge8(
2372
2352
  "inline-flex items-center rounded-lg border border-(--color-border-default) bg-(--color-surface-muted) p-0.5 gap-0.5",
2373
2353
  className
2374
2354
  ),
@@ -2385,7 +2365,7 @@ function SegmentedControlItem({
2385
2365
  AriaToggleButton2,
2386
2366
  {
2387
2367
  ...props,
2388
- className: ({ isSelected, isHovered, isPressed, isDisabled }) => twMerge7(
2368
+ className: ({ isSelected, isHovered, isPressed, isDisabled }) => twMerge8(
2389
2369
  // Base layout
2390
2370
  "inline-flex items-center justify-center",
2391
2371
  "rounded-md",
@@ -2407,65 +2387,21 @@ function SegmentedControlItem({
2407
2387
 
2408
2388
  // src/components/FileCard/FileCard.tsx
2409
2389
  import { useCallback as useCallback3 } from "react";
2410
- import {
2411
- File as File2,
2412
- FileSpreadsheet,
2413
- Folder as Folder2,
2414
- Image,
2415
- Info as Info2,
2416
- Microscope
2417
- } from "lucide-react";
2390
+ import { File as File2, Info as Info2 } from "lucide-react";
2418
2391
  import { Fragment as Fragment9, jsx as jsx37, jsxs as jsxs23 } from "react/jsx-runtime";
2419
- function getFileIcon(type, extension) {
2420
- if (type === "directory") return Folder2;
2421
- const ext = (extension ?? "").toLowerCase();
2422
- if (ext === "ome.tif" || ext === "ome.tiff") return Microscope;
2423
- if (/^(tiff?|png|jpe?g)$/.test(ext)) return Image;
2424
- if (/^(csv|parquet)$/.test(ext)) return FileSpreadsheet;
2425
- return File2;
2426
- }
2427
- function getTypeLabel(type, extension) {
2428
- if (type === "directory") return "Folder";
2429
- const ext = (extension ?? "").toLowerCase();
2430
- if (ext === "ome.tif" || ext === "ome.tiff") return "OME-TIFF";
2431
- if (/^tiff?$/.test(ext)) return "TIFF";
2432
- if (ext === "csv") return "CSV";
2433
- if (ext === "parquet") return "Parquet";
2434
- if (ext === "png") return "PNG";
2435
- if (/^jpe?g$/.test(ext)) return "JPEG";
2436
- return ext.toUpperCase() || "File";
2437
- }
2438
- function FileIcon({
2439
- type,
2440
- extension,
2441
- size = 16
2442
- }) {
2443
- const IconComponent = getFileIcon(type, extension);
2444
- return /* @__PURE__ */ jsx37(
2445
- IconComponent,
2446
- {
2447
- size,
2448
- className: "shrink-0 text-(--color-text-secondary)"
2449
- }
2450
- );
2451
- }
2452
2392
  function FileCard({
2453
2393
  name,
2454
- type,
2394
+ icon: IconComponent = File2,
2455
2395
  size,
2456
- extension,
2457
2396
  compact = false,
2458
2397
  children,
2459
2398
  onInfo,
2460
- href,
2461
2399
  onPress,
2462
2400
  className
2463
2401
  }) {
2464
- const isInteractive = !!href || !!onPress;
2402
+ const isInteractive = !!onPress;
2465
2403
  const radius = compact ? "rounded-md" : "rounded-lg";
2466
- const IconComponent = getFileIcon(type, extension);
2467
2404
  const iconSize = compact ? 24 : 32;
2468
- const iconColor = type === "directory" ? "text-(--color-text-tertiary)" : "text-(--color-text-secondary)";
2469
2405
  const thumbnailClass = compact ? "aspect-square rounded-t-(--border-radius-md)" : "aspect-[4/3] rounded-t-(--border-radius-lg)";
2470
2406
  const handleInfoClick = useCallback3(
2471
2407
  (e) => {
@@ -2491,7 +2427,7 @@ function FileCard({
2491
2427
  "div",
2492
2428
  {
2493
2429
  className: `shrink-0 overflow-hidden bg-neutral-900 ${thumbnailClass}`,
2494
- children: children ? /* @__PURE__ */ jsx37("div", { className: "h-full w-full overflow-hidden", children }) : /* @__PURE__ */ jsx37("div", { className: "flex h-full w-full items-center justify-center", children: /* @__PURE__ */ jsx37(IconComponent, { size: iconSize, className: iconColor }) })
2430
+ children: children ? /* @__PURE__ */ jsx37("div", { className: "h-full w-full overflow-hidden", children }) : /* @__PURE__ */ jsx37("div", { className: "flex h-full w-full items-center justify-center", children: /* @__PURE__ */ jsx37(IconComponent, { size: iconSize, className: "text-(--color-text-secondary)" }) })
2495
2431
  }
2496
2432
  ),
2497
2433
  /* @__PURE__ */ jsx37(
@@ -2504,7 +2440,13 @@ function FileCard({
2504
2440
  ].join(" "),
2505
2441
  children: compact ? /* @__PURE__ */ jsx37("span", { className: "text-xs font-medium text-(--color-text-primary) truncate", children: name }) : /* @__PURE__ */ jsxs23(Fragment9, { children: [
2506
2442
  /* @__PURE__ */ jsxs23("span", { className: "flex items-center gap-1.5", children: [
2507
- /* @__PURE__ */ jsx37(FileIcon, { type, extension, size: 16 }),
2443
+ /* @__PURE__ */ jsx37(
2444
+ IconComponent,
2445
+ {
2446
+ size: 16,
2447
+ className: "shrink-0 text-(--color-text-secondary)"
2448
+ }
2449
+ ),
2508
2450
  /* @__PURE__ */ jsx37("span", { className: "min-w-0 flex-1 text-sm font-medium text-(--color-text-primary) truncate", children: name }),
2509
2451
  onInfo && /* @__PURE__ */ jsx37(
2510
2452
  "span",
@@ -2545,17 +2487,6 @@ function FileCard({
2545
2487
  isInteractive && "focus-visible:ring-2 focus-visible:ring-(--color-border-focus) focus-visible:ring-offset-2 outline-none",
2546
2488
  className
2547
2489
  ].filter(Boolean).join(" ");
2548
- if (href) {
2549
- return /* @__PURE__ */ jsx37(
2550
- "a",
2551
- {
2552
- href,
2553
- "aria-label": name,
2554
- className: [baseStyles, "no-underline"].join(" "),
2555
- children: cardContent
2556
- }
2557
- );
2558
- }
2559
2490
  if (onPress) {
2560
2491
  return /* @__PURE__ */ jsx37(
2561
2492
  "div",
@@ -2575,150 +2506,25 @@ function FileCard({
2575
2506
 
2576
2507
  // src/components/StorageConnectionCard/StorageConnectionCard.tsx
2577
2508
  import { useCallback as useCallback4 } from "react";
2578
- import { AlertCircle, Database, Info as Info3 } from "lucide-react";
2579
- import { twMerge as twMerge10 } from "tailwind-merge";
2580
-
2581
- // src/components/Pill/Pill.tsx
2582
- import { twMerge as twMerge8 } from "tailwind-merge";
2583
- import { jsx as jsx38 } from "react/jsx-runtime";
2584
- var HASH_PALETTE = [
2585
- "teal",
2586
- // sky
2587
- "amber",
2588
- // amber
2589
- "green",
2590
- // emerald
2591
- "rose",
2592
- // rose
2593
- "purple",
2594
- // violet
2595
- "amber",
2596
- // orange (mapped to amber -- closest warm token)
2597
- "teal",
2598
- // teal
2599
- "rose"
2600
- // fuchsia (mapped to rose -- closest pink token)
2601
- ];
2602
- function pillColorFromName(name) {
2603
- let hash = 0;
2604
- for (let i = 0; i < name.length; i++) {
2605
- hash = name.charCodeAt(i) + ((hash << 5) - hash);
2606
- }
2607
- return HASH_PALETTE[Math.abs(hash) % HASH_PALETTE.length];
2608
- }
2609
- var colorStyles = {
2610
- neutral: "bg-(--color-badge-neutral-bg) text-(--color-badge-neutral-text)",
2611
- purple: "bg-(--color-badge-purple-bg) text-(--color-badge-purple-text)",
2612
- teal: "bg-(--color-badge-teal-bg) text-(--color-badge-teal-text)",
2613
- rose: "bg-(--color-badge-rose-bg) text-(--color-badge-rose-text)",
2614
- slate: "bg-(--color-badge-slate-bg) text-(--color-badge-slate-text)",
2615
- green: "bg-(--color-badge-green-bg) text-(--color-badge-green-text)",
2616
- amber: "bg-(--color-badge-amber-bg) text-(--color-badge-amber-text)"
2617
- };
2618
- var dotColorStyles = {
2619
- neutral: "bg-(--color-badge-neutral-text)",
2620
- purple: "bg-(--color-badge-purple-text)",
2621
- teal: "bg-(--color-badge-teal-text)",
2622
- rose: "bg-(--color-badge-rose-text)",
2623
- slate: "bg-(--color-badge-slate-text)",
2624
- green: "bg-(--color-badge-green-text)",
2625
- amber: "bg-(--color-badge-amber-text)"
2626
- };
2627
- function resolveColor(color, name) {
2628
- if (color && color !== "auto") return color;
2629
- if (name) return pillColorFromName(name);
2630
- return "neutral";
2631
- }
2632
- function Pill({ children, color, name, className }) {
2633
- const resolved = resolveColor(color, name);
2634
- return /* @__PURE__ */ jsx38(
2635
- "span",
2636
- {
2637
- className: twMerge8(
2638
- "inline-flex items-center rounded-full",
2639
- "px-2 py-0.5",
2640
- "text-xs font-medium leading-tight",
2641
- colorStyles[resolved],
2642
- className
2643
- ),
2644
- children
2645
- }
2646
- );
2647
- }
2648
-
2649
- // src/components/Pill/GroupPill.tsx
2509
+ import { AlertCircle, Database } from "lucide-react";
2650
2510
  import { twMerge as twMerge9 } from "tailwind-merge";
2651
- import { jsx as jsx39, jsxs as jsxs24 } from "react/jsx-runtime";
2652
- function GroupPill({
2653
- path,
2654
- visibleCount = 3,
2655
- className
2656
- }) {
2657
- const segments = path.replace(/^\/+|\/+$/g, "").split("/").filter(Boolean);
2658
- if (segments.length === 0) return null;
2659
- const hiddenCount = Math.max(0, segments.length - visibleCount);
2660
- const hiddenSegments = segments.slice(0, hiddenCount);
2661
- const visibleSegments = segments.slice(hiddenCount);
2662
- return /* @__PURE__ */ jsxs24(
2663
- "span",
2664
- {
2665
- className: twMerge9(
2666
- "inline-flex items-center gap-1",
2667
- className
2668
- ),
2669
- "aria-label": `Group: ${segments.join(" / ")}`,
2670
- children: [
2671
- hiddenSegments.map((segment, index) => {
2672
- const color = pillColorFromName(segment);
2673
- return /* @__PURE__ */ jsx39(
2674
- "span",
2675
- {
2676
- className: twMerge9(
2677
- "inline-block size-2 shrink-0 rounded-full",
2678
- dotColorStyles[color]
2679
- ),
2680
- "aria-hidden": "true",
2681
- title: segment
2682
- },
2683
- `dot-${index}-${segment}`
2684
- );
2685
- }),
2686
- visibleSegments.map((segment, index) => /* @__PURE__ */ jsx39(Pill, { name: segment, children: segment }, `pill-${index}-${segment}`))
2687
- ]
2688
- }
2689
- );
2690
- }
2691
-
2692
- // src/components/StorageConnectionCard/StorageConnectionCard.tsx
2693
- import { Fragment as Fragment10, jsx as jsx40, jsxs as jsxs25 } from "react/jsx-runtime";
2511
+ import { Fragment as Fragment10, jsx as jsx38, jsxs as jsxs24 } from "react/jsx-runtime";
2694
2512
  var statusDotStyles = {
2695
2513
  connected: "bg-(--color-status-success)",
2696
2514
  error: "border-2 border-(--color-status-danger) bg-transparent",
2697
2515
  loading: "bg-(--color-status-warning) animate-pulse"
2698
2516
  };
2699
- var providerConfig = {
2700
- aws: { label: "AWS", color: "purple" },
2701
- azure: { label: "Azure", color: "teal" },
2702
- gcp: { label: "GCP", color: "slate" },
2703
- minio: { label: "MinIO", color: "rose" }
2704
- };
2705
- function ProviderBadge({ provider }) {
2706
- const config = providerConfig[provider.toLowerCase()];
2707
- const label = config?.label ?? provider;
2708
- const color = config?.color ?? "neutral";
2709
- return /* @__PURE__ */ jsx40(Pill, { color, children: label });
2710
- }
2711
2517
  function PreviewArea({
2712
2518
  status = "connected",
2713
2519
  errorMessage,
2714
2520
  children
2715
2521
  }) {
2716
2522
  if (status === "loading") {
2717
- return /* @__PURE__ */ jsx40("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx40(Spinner, { size: "lg", "aria-label": "Loading connection" }) });
2523
+ return /* @__PURE__ */ jsx38("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx38(Spinner, { size: "lg", "aria-label": "Loading connection" }) });
2718
2524
  }
2719
2525
  if (status === "error") {
2720
- return /* @__PURE__ */ jsxs25("div", { className: "flex h-full flex-col items-center justify-center gap-2 bg-(--color-surface-danger) px-4", children: [
2721
- /* @__PURE__ */ jsx40(
2526
+ return /* @__PURE__ */ jsxs24("div", { className: "flex h-full flex-col items-center justify-center gap-2 bg-(--color-surface-danger) px-4", children: [
2527
+ /* @__PURE__ */ jsx38(
2722
2528
  Icon,
2723
2529
  {
2724
2530
  icon: AlertCircle,
@@ -2726,13 +2532,13 @@ function PreviewArea({
2726
2532
  className: "text-(--color-text-danger)"
2727
2533
  }
2728
2534
  ),
2729
- errorMessage && /* @__PURE__ */ jsx40("p", { className: "text-center text-xs text-(--color-text-danger)", children: errorMessage })
2535
+ errorMessage && /* @__PURE__ */ jsx38("p", { className: "text-center text-xs text-(--color-text-danger)", children: errorMessage })
2730
2536
  ] });
2731
2537
  }
2732
2538
  if (children) {
2733
- return /* @__PURE__ */ jsx40("div", { className: "h-full w-full overflow-hidden", children });
2539
+ return /* @__PURE__ */ jsx38("div", { className: "h-full w-full overflow-hidden", children });
2734
2540
  }
2735
- return /* @__PURE__ */ jsx40("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx40(
2541
+ return /* @__PURE__ */ jsx38("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx38(
2736
2542
  Icon,
2737
2543
  {
2738
2544
  icon: Database,
@@ -2743,28 +2549,16 @@ function PreviewArea({
2743
2549
  }
2744
2550
  function StorageConnectionCard({
2745
2551
  name,
2746
- provider,
2747
- region,
2748
2552
  status,
2749
2553
  errorMessage,
2750
- imageCount,
2554
+ meta,
2751
2555
  children,
2752
2556
  href,
2753
2557
  onPress,
2754
- onInfo,
2558
+ actions,
2755
2559
  className
2756
2560
  }) {
2757
2561
  const isInteractive = !!href || !!onPress;
2758
- const handleInfoPress = useCallback4(
2759
- (e) => {
2760
- if (isInteractive) {
2761
- e.stopPropagation();
2762
- e.preventDefault();
2763
- }
2764
- onInfo?.();
2765
- },
2766
- [onInfo, isInteractive]
2767
- );
2768
2562
  const handleKeyDown = useCallback4(
2769
2563
  (e) => {
2770
2564
  if (onPress && (e.key === "Enter" || e.key === " ")) {
@@ -2774,57 +2568,45 @@ function StorageConnectionCard({
2774
2568
  },
2775
2569
  [onPress]
2776
2570
  );
2777
- const cardContent = /* @__PURE__ */ jsxs25(Fragment10, { children: [
2778
- /* @__PURE__ */ jsx40("div", { className: "aspect-[4/3] bg-neutral-900 overflow-hidden rounded-t-(--border-radius-lg)", children: /* @__PURE__ */ jsx40(PreviewArea, { status, errorMessage, children }) }),
2779
- /* @__PURE__ */ jsxs25("div", { className: "flex flex-col gap-1.5 border-t border-(--color-border-default) bg-(--color-surface-default) px-3 py-2.5 rounded-b-(--border-radius-lg)", children: [
2780
- /* @__PURE__ */ jsxs25("div", { className: "flex items-start gap-2", children: [
2781
- status && /* @__PURE__ */ jsx40(
2571
+ const cardContent = /* @__PURE__ */ jsxs24(Fragment10, { children: [
2572
+ /* @__PURE__ */ jsx38("div", { className: "aspect-[4/3] bg-neutral-900 overflow-hidden rounded-t-(--border-radius-lg)", children: /* @__PURE__ */ jsx38(PreviewArea, { status, errorMessage, children }) }),
2573
+ /* @__PURE__ */ jsxs24("div", { className: "flex flex-col gap-1.5 border-t border-(--color-border-default) bg-(--color-surface-default) px-3 py-2.5 rounded-b-(--border-radius-lg)", children: [
2574
+ /* @__PURE__ */ jsxs24("div", { className: "flex items-start gap-2", children: [
2575
+ status && /* @__PURE__ */ jsx38(
2782
2576
  "span",
2783
2577
  {
2784
- className: twMerge10(
2578
+ className: twMerge9(
2785
2579
  "mt-1.5 h-2 w-2 shrink-0 rounded-full",
2786
2580
  statusDotStyles[status]
2787
2581
  ),
2788
2582
  "aria-label": `Status: ${status}`
2789
2583
  }
2790
2584
  ),
2791
- /* @__PURE__ */ jsx40("span", { className: "min-w-0 flex-1 line-clamp-2 text-sm font-medium text-(--color-text-primary)", children: name }),
2792
- onInfo && /* @__PURE__ */ jsx40(
2585
+ /* @__PURE__ */ jsx38("span", { className: "min-w-0 flex-1 line-clamp-2 text-sm font-medium text-(--color-text-primary)", children: name }),
2586
+ actions && /* @__PURE__ */ jsx38(
2793
2587
  "span",
2794
2588
  {
2795
- onClick: handleInfoPress,
2589
+ onClick: (e) => {
2590
+ if (isInteractive) {
2591
+ e.stopPropagation();
2592
+ e.preventDefault();
2593
+ }
2594
+ },
2796
2595
  onKeyDown: (e) => {
2797
- if (e.key === "Enter" || e.key === " ") {
2798
- handleInfoPress(e);
2596
+ if (isInteractive) {
2597
+ e.stopPropagation();
2799
2598
  }
2800
2599
  },
2801
2600
  role: "presentation",
2802
- children: /* @__PURE__ */ jsx40(
2803
- IconButton,
2804
- {
2805
- icon: Info3,
2806
- "aria-label": "Connection info",
2807
- variant: "ghost",
2808
- size: "sm",
2809
- className: "shrink-0 -mt-1 -mr-1",
2810
- onPress: onInfo
2811
- }
2812
- )
2601
+ className: "shrink-0 -mt-1 -mr-1",
2602
+ children: actions
2813
2603
  }
2814
2604
  )
2815
2605
  ] }),
2816
- (provider || imageCount != null && (!status || status === "connected")) && /* @__PURE__ */ jsxs25("div", { className: twMerge10("flex items-center gap-2", status && "pl-4"), children: [
2817
- provider && /* @__PURE__ */ jsx40(ProviderBadge, { provider }),
2818
- provider && region && /* @__PURE__ */ jsx40("span", { className: "shrink-0 text-xs text-(--color-text-secondary)", children: region }),
2819
- imageCount != null && (!status || status === "connected") && /* @__PURE__ */ jsxs25("span", { className: "ml-auto shrink-0 text-xs tabular-nums text-(--color-text-secondary)", children: [
2820
- imageCount,
2821
- " ",
2822
- imageCount === 1 ? "image" : "images"
2823
- ] })
2824
- ] })
2606
+ meta && /* @__PURE__ */ jsx38("div", { className: twMerge9("flex items-center gap-2", status && "pl-4"), children: meta })
2825
2607
  ] })
2826
2608
  ] });
2827
- const baseStyles = twMerge10(
2609
+ const baseStyles = twMerge9(
2828
2610
  "flex flex-col overflow-hidden rounded-lg",
2829
2611
  "border border-(--color-border-default)",
2830
2612
  "shadow-sm transition-all",
@@ -2833,10 +2615,10 @@ function StorageConnectionCard({
2833
2615
  className
2834
2616
  );
2835
2617
  if (href) {
2836
- return /* @__PURE__ */ jsx40("a", { href, className: twMerge10(baseStyles, "no-underline"), children: cardContent });
2618
+ return /* @__PURE__ */ jsx38("a", { href, className: twMerge9(baseStyles, "no-underline"), children: cardContent });
2837
2619
  }
2838
2620
  if (onPress) {
2839
- return /* @__PURE__ */ jsx40(
2621
+ return /* @__PURE__ */ jsx38(
2840
2622
  "div",
2841
2623
  {
2842
2624
  role: "button",
@@ -2848,12 +2630,12 @@ function StorageConnectionCard({
2848
2630
  }
2849
2631
  );
2850
2632
  }
2851
- return /* @__PURE__ */ jsx40("div", { className: baseStyles, children: cardContent });
2633
+ return /* @__PURE__ */ jsx38("div", { className: baseStyles, children: cardContent });
2852
2634
  }
2853
2635
 
2854
2636
  // src/components/Badge/Badge.tsx
2855
- import { twMerge as twMerge11 } from "tailwind-merge";
2856
- import { jsx as jsx41, jsxs as jsxs26 } from "react/jsx-runtime";
2637
+ import { twMerge as twMerge10 } from "tailwind-merge";
2638
+ import { jsx as jsx39, jsxs as jsxs25 } from "react/jsx-runtime";
2857
2639
  var variantStyles4 = {
2858
2640
  neutral: "bg-(--color-badge-neutral-bg) text-(--color-badge-neutral-text)",
2859
2641
  purple: "bg-(--color-badge-purple-bg) text-(--color-badge-purple-text)",
@@ -2878,10 +2660,10 @@ function Badge({
2878
2660
  icon: IconComponent,
2879
2661
  className
2880
2662
  }) {
2881
- return /* @__PURE__ */ jsxs26(
2663
+ return /* @__PURE__ */ jsxs25(
2882
2664
  "span",
2883
2665
  {
2884
- className: twMerge11(
2666
+ className: twMerge10(
2885
2667
  "inline-flex items-center gap-1 rounded-full",
2886
2668
  "text-xs font-medium leading-tight",
2887
2669
  variantStyles4[variant],
@@ -2889,7 +2671,7 @@ function Badge({
2889
2671
  className
2890
2672
  ),
2891
2673
  children: [
2892
- IconComponent && /* @__PURE__ */ jsx41(IconComponent, { size: iconSizeMap4[size], "aria-hidden": "true" }),
2674
+ IconComponent && /* @__PURE__ */ jsx39(IconComponent, { size: iconSizeMap4[size], "aria-hidden": "true" }),
2893
2675
  children
2894
2676
  ]
2895
2677
  }
@@ -2898,8 +2680,8 @@ function Badge({
2898
2680
 
2899
2681
  // src/components/Card/Card.tsx
2900
2682
  import { useCallback as useCallback5 } from "react";
2901
- import { twMerge as twMerge12 } from "tailwind-merge";
2902
- import { Fragment as Fragment11, jsx as jsx42, jsxs as jsxs27 } from "react/jsx-runtime";
2683
+ import { twMerge as twMerge11 } from "tailwind-merge";
2684
+ import { Fragment as Fragment11, jsx as jsx40, jsxs as jsxs26 } from "react/jsx-runtime";
2903
2685
  var paddingStyles = {
2904
2686
  none: "p-0",
2905
2687
  sm: "p-3",
@@ -2917,7 +2699,7 @@ function Card({
2917
2699
  className
2918
2700
  }) {
2919
2701
  const isInteractive = interactive || !!href || !!onPress;
2920
- const containerClass = twMerge12(
2702
+ const containerClass = twMerge11(
2921
2703
  "bg-(--color-surface-default) border border-(--color-border-default) rounded-lg overflow-hidden shadow-sm",
2922
2704
  isInteractive && "transition-all hover:shadow-md hover:border-(--color-border-focus) cursor-pointer",
2923
2705
  (href || onPress) && "block focus-visible:ring-2 focus-visible:ring-(--color-border-focus) focus-visible:ring-offset-2 outline-none",
@@ -2932,22 +2714,22 @@ function Card({
2932
2714
  },
2933
2715
  [onPress]
2934
2716
  );
2935
- const content = /* @__PURE__ */ jsxs27(Fragment11, { children: [
2936
- header && /* @__PURE__ */ jsx42(
2717
+ const content = /* @__PURE__ */ jsxs26(Fragment11, { children: [
2718
+ header && /* @__PURE__ */ jsx40(
2937
2719
  "div",
2938
2720
  {
2939
- className: twMerge12(
2721
+ className: twMerge11(
2940
2722
  "border-b border-(--color-border-default)",
2941
2723
  paddingStyles[padding]
2942
2724
  ),
2943
2725
  children: header
2944
2726
  }
2945
2727
  ),
2946
- /* @__PURE__ */ jsx42("div", { className: paddingStyles[padding], children }),
2947
- footer && /* @__PURE__ */ jsx42(
2728
+ /* @__PURE__ */ jsx40("div", { className: paddingStyles[padding], children }),
2729
+ footer && /* @__PURE__ */ jsx40(
2948
2730
  "div",
2949
2731
  {
2950
- className: twMerge12(
2732
+ className: twMerge11(
2951
2733
  "border-t border-(--color-border-default)",
2952
2734
  paddingStyles[padding]
2953
2735
  ),
@@ -2956,10 +2738,10 @@ function Card({
2956
2738
  )
2957
2739
  ] });
2958
2740
  if (href) {
2959
- return /* @__PURE__ */ jsx42("a", { href, className: containerClass, children: content });
2741
+ return /* @__PURE__ */ jsx40("a", { href, className: containerClass, children: content });
2960
2742
  }
2961
2743
  if (onPress) {
2962
- return /* @__PURE__ */ jsx42(
2744
+ return /* @__PURE__ */ jsx40(
2963
2745
  "div",
2964
2746
  {
2965
2747
  role: "button",
@@ -2971,13 +2753,13 @@ function Card({
2971
2753
  }
2972
2754
  );
2973
2755
  }
2974
- return /* @__PURE__ */ jsx42("div", { className: containerClass, children: content });
2756
+ return /* @__PURE__ */ jsx40("div", { className: containerClass, children: content });
2975
2757
  }
2976
2758
 
2977
2759
  // src/components/DeltaIndicator/DeltaIndicator.tsx
2978
2760
  import { ArrowUp, ArrowDown, Minus } from "lucide-react";
2979
- import { twMerge as twMerge13 } from "tailwind-merge";
2980
- import { jsx as jsx43, jsxs as jsxs28 } from "react/jsx-runtime";
2761
+ import { twMerge as twMerge12 } from "tailwind-merge";
2762
+ import { jsx as jsx41, jsxs as jsxs27 } from "react/jsx-runtime";
2981
2763
  function getDirection(current, previous) {
2982
2764
  const diff = current - previous;
2983
2765
  if (diff > 0) return "increase";
@@ -3030,16 +2812,16 @@ function DeltaIndicator({
3030
2812
  className
3031
2813
  }) {
3032
2814
  if (unavailable) {
3033
- return /* @__PURE__ */ jsxs28(
2815
+ return /* @__PURE__ */ jsxs27(
3034
2816
  "span",
3035
2817
  {
3036
- className: twMerge13(
2818
+ className: twMerge12(
3037
2819
  "inline-flex items-center gap-1 font-medium",
3038
2820
  "text-(--color-text-tertiary)",
3039
2821
  className
3040
2822
  ),
3041
2823
  children: [
3042
- label && /* @__PURE__ */ jsx43("span", { className: "text-sm text-(--color-text-secondary) mr-1", children: label }),
2824
+ label && /* @__PURE__ */ jsx41("span", { className: "text-sm text-(--color-text-secondary) mr-1", children: label }),
3043
2825
  unavailableText
3044
2826
  ]
3045
2827
  }
@@ -3069,10 +2851,10 @@ function DeltaIndicator({
3069
2851
  }
3070
2852
  }
3071
2853
  const isPill = mode === "pill";
3072
- return /* @__PURE__ */ jsxs28(
2854
+ return /* @__PURE__ */ jsxs27(
3073
2855
  "span",
3074
2856
  {
3075
- className: twMerge13(
2857
+ className: twMerge12(
3076
2858
  "inline-flex items-center gap-1 font-medium",
3077
2859
  colorStyles2,
3078
2860
  isPill && [
@@ -3083,8 +2865,8 @@ function DeltaIndicator({
3083
2865
  className
3084
2866
  ),
3085
2867
  children: [
3086
- label && /* @__PURE__ */ jsx43("span", { className: "text-sm text-(--color-text-secondary) mr-1", children: label }),
3087
- /* @__PURE__ */ jsx43(IconComponent, { size: 14, "aria-hidden": true }),
2868
+ label && /* @__PURE__ */ jsx41("span", { className: "text-sm text-(--color-text-secondary) mr-1", children: label }),
2869
+ /* @__PURE__ */ jsx41(IconComponent, { size: 14, "aria-hidden": true }),
3088
2870
  valueText
3089
2871
  ]
3090
2872
  }
@@ -3092,8 +2874,8 @@ function DeltaIndicator({
3092
2874
  }
3093
2875
 
3094
2876
  // src/components/ProgressBar/ProgressBar.tsx
3095
- import { twMerge as twMerge14 } from "tailwind-merge";
3096
- import { jsx as jsx44, jsxs as jsxs29 } from "react/jsx-runtime";
2877
+ import { twMerge as twMerge13 } from "tailwind-merge";
2878
+ import { jsx as jsx42, jsxs as jsxs28 } from "react/jsx-runtime";
3097
2879
  var fillStyles = {
3098
2880
  brand: "bg-(--color-progress-fill)",
3099
2881
  success: "bg-(--color-progress-fill-success)",
@@ -3116,12 +2898,12 @@ function ProgressBar({
3116
2898
  className
3117
2899
  }) {
3118
2900
  const clampedValue = Math.min(100, Math.max(0, value));
3119
- return /* @__PURE__ */ jsxs29("div", { className: twMerge14("w-full", className), children: [
3120
- (label || description || showValue) && /* @__PURE__ */ jsxs29("div", { className: "flex items-center justify-between mb-2", children: [
3121
- /* @__PURE__ */ jsx44("span", { className: "text-sm font-medium text-(--color-text-primary)", children: label }),
3122
- /* @__PURE__ */ jsx44("span", { className: "text-sm text-(--color-text-secondary)", children: description ?? (showValue ? `${clampedValue}%` : null) })
2901
+ return /* @__PURE__ */ jsxs28("div", { className: twMerge13("w-full", className), children: [
2902
+ (label || description || showValue) && /* @__PURE__ */ jsxs28("div", { className: "flex items-center justify-between mb-2", children: [
2903
+ /* @__PURE__ */ jsx42("span", { className: "text-sm font-medium text-(--color-text-primary)", children: label }),
2904
+ /* @__PURE__ */ jsx42("span", { className: "text-sm text-(--color-text-secondary)", children: description ?? (showValue ? `${clampedValue}%` : null) })
3123
2905
  ] }),
3124
- /* @__PURE__ */ jsx44(
2906
+ /* @__PURE__ */ jsx42(
3125
2907
  "div",
3126
2908
  {
3127
2909
  role: "progressbar",
@@ -3129,14 +2911,14 @@ function ProgressBar({
3129
2911
  "aria-valuemin": 0,
3130
2912
  "aria-valuemax": 100,
3131
2913
  "aria-label": label ?? "Progress",
3132
- className: twMerge14(
2914
+ className: twMerge13(
3133
2915
  "w-full rounded-full bg-(--color-progress-track)",
3134
2916
  sizeStyles9[size]
3135
2917
  ),
3136
- children: /* @__PURE__ */ jsx44(
2918
+ children: /* @__PURE__ */ jsx42(
3137
2919
  "div",
3138
2920
  {
3139
- className: twMerge14(
2921
+ className: twMerge13(
3140
2922
  "h-full rounded-full transition-all duration-300",
3141
2923
  fillStyles[variant]
3142
2924
  ),
@@ -3151,17 +2933,17 @@ function ProgressBar({
3151
2933
  // src/components/Banner/Banner.tsx
3152
2934
  import { useState as useState3 } from "react";
3153
2935
  import {
3154
- Info as Info4,
2936
+ Info as Info3,
3155
2937
  AlertTriangle,
3156
2938
  AlertCircle as AlertCircle2,
3157
2939
  CheckCircle2,
3158
2940
  X as X3
3159
2941
  } from "lucide-react";
3160
- import { twMerge as twMerge15 } from "tailwind-merge";
3161
- import { jsx as jsx45, jsxs as jsxs30 } from "react/jsx-runtime";
2942
+ import { twMerge as twMerge14 } from "tailwind-merge";
2943
+ import { jsx as jsx43, jsxs as jsxs29 } from "react/jsx-runtime";
3162
2944
  var variantConfig2 = {
3163
2945
  info: {
3164
- icon: Info4,
2946
+ icon: Info3,
3165
2947
  containerClass: "bg-(--color-banner-info-bg) border-(--color-banner-info-border) text-(--color-banner-info-text)",
3166
2948
  iconClass: "text-(--color-banner-info-icon)",
3167
2949
  role: "status"
@@ -3202,40 +2984,40 @@ function Banner({
3202
2984
  setDismissed(true);
3203
2985
  onDismiss?.();
3204
2986
  };
3205
- return /* @__PURE__ */ jsxs30(
2987
+ return /* @__PURE__ */ jsxs29(
3206
2988
  "div",
3207
2989
  {
3208
2990
  role: config.role,
3209
- className: twMerge15(
2991
+ className: twMerge14(
3210
2992
  "flex items-start gap-3 rounded-lg border px-4 py-3",
3211
2993
  "text-sm",
3212
2994
  config.containerClass,
3213
2995
  className
3214
2996
  ),
3215
2997
  children: [
3216
- /* @__PURE__ */ jsx45(
2998
+ /* @__PURE__ */ jsx43(
3217
2999
  IconComponent,
3218
3000
  {
3219
3001
  size: 20,
3220
- className: twMerge15("shrink-0 mt-0.5", config.iconClass),
3002
+ className: twMerge14("shrink-0 mt-0.5", config.iconClass),
3221
3003
  "aria-hidden": "true"
3222
3004
  }
3223
3005
  ),
3224
- /* @__PURE__ */ jsxs30("div", { className: "flex-1", children: [
3225
- title && /* @__PURE__ */ jsxs30("span", { className: "font-medium", children: [
3006
+ /* @__PURE__ */ jsxs29("div", { className: "flex-1", children: [
3007
+ title && /* @__PURE__ */ jsxs29("span", { className: "font-medium", children: [
3226
3008
  title,
3227
3009
  " \u2014 "
3228
3010
  ] }),
3229
3011
  children
3230
3012
  ] }),
3231
- dismissible && /* @__PURE__ */ jsx45(
3013
+ dismissible && /* @__PURE__ */ jsx43(
3232
3014
  "button",
3233
3015
  {
3234
3016
  type: "button",
3235
3017
  onClick: handleDismiss,
3236
3018
  className: "shrink-0 rounded-sm p-0.5 opacity-70 hover:opacity-100 transition-opacity outline-none focus-visible:ring-2 focus-visible:ring-current",
3237
3019
  "aria-label": "Dismiss",
3238
- children: /* @__PURE__ */ jsx45(X3, { size: 16, "aria-hidden": "true" })
3020
+ children: /* @__PURE__ */ jsx43(X3, { size: 16, "aria-hidden": "true" })
3239
3021
  }
3240
3022
  )
3241
3023
  ]
@@ -3244,8 +3026,8 @@ function Banner({
3244
3026
  }
3245
3027
 
3246
3028
  // src/components/MetricCard/MetricCard.tsx
3247
- import { twMerge as twMerge16 } from "tailwind-merge";
3248
- import { Fragment as Fragment12, jsx as jsx46, jsxs as jsxs31 } from "react/jsx-runtime";
3029
+ import { twMerge as twMerge15 } from "tailwind-merge";
3030
+ import { Fragment as Fragment12, jsx as jsx44, jsxs as jsxs30 } from "react/jsx-runtime";
3249
3031
  var sizeConfig = {
3250
3032
  sm: {
3251
3033
  padding: "p-3",
@@ -3267,55 +3049,135 @@ function MetricCard({
3267
3049
  className
3268
3050
  }) {
3269
3051
  const config = sizeConfig[size];
3270
- const containerClass = twMerge16(
3052
+ const containerClass = twMerge15(
3271
3053
  "bg-(--color-surface-default) border border-(--color-border-default) rounded-lg shadow-sm",
3272
3054
  config.padding,
3273
3055
  href && "block transition-shadow hover:shadow-md hover:border-(--color-border-focus) focus-visible:ring-2 focus-visible:ring-(--color-border-focus) focus-visible:ring-offset-2 outline-none",
3274
3056
  className
3275
3057
  );
3276
- const content = /* @__PURE__ */ jsxs31(Fragment12, { children: [
3277
- /* @__PURE__ */ jsx46("div", { className: twMerge16(config.labelClass, "text-(--color-text-secondary)"), children: label }),
3278
- /* @__PURE__ */ jsx46(
3058
+ const content = /* @__PURE__ */ jsxs30(Fragment12, { children: [
3059
+ /* @__PURE__ */ jsx44("div", { className: twMerge15(config.labelClass, "text-(--color-text-secondary)"), children: label }),
3060
+ /* @__PURE__ */ jsx44(
3279
3061
  "div",
3280
3062
  {
3281
- className: twMerge16(
3063
+ className: twMerge15(
3282
3064
  config.valueClass,
3283
3065
  "font-semibold text-(--color-text-primary) mt-1 tabular-nums"
3284
3066
  ),
3285
3067
  children: value
3286
3068
  }
3287
3069
  ),
3288
- secondary && /* @__PURE__ */ jsx46("div", { className: "mt-1 text-sm", children: secondary })
3070
+ secondary && /* @__PURE__ */ jsx44("div", { className: "mt-1 text-sm", children: secondary })
3289
3071
  ] });
3290
3072
  if (href) {
3291
- return /* @__PURE__ */ jsx46("a", { href, className: containerClass, children: content });
3073
+ return /* @__PURE__ */ jsx44("a", { href, className: containerClass, children: content });
3292
3074
  }
3293
- return /* @__PURE__ */ jsx46("div", { className: containerClass, children: content });
3075
+ return /* @__PURE__ */ jsx44("div", { className: containerClass, children: content });
3294
3076
  }
3295
3077
 
3296
3078
  // src/components/SectionHeader/SectionHeader.tsx
3297
- import { twMerge as twMerge17 } from "tailwind-merge";
3298
- import { jsx as jsx47, jsxs as jsxs32 } from "react/jsx-runtime";
3079
+ import { twMerge as twMerge16 } from "tailwind-merge";
3080
+ import { jsx as jsx45, jsxs as jsxs31 } from "react/jsx-runtime";
3299
3081
  function SectionHeader({
3300
3082
  title,
3301
3083
  children,
3302
3084
  className
3303
3085
  }) {
3304
- return /* @__PURE__ */ jsxs32(
3086
+ return /* @__PURE__ */ jsxs31(
3305
3087
  "div",
3306
3088
  {
3307
- className: twMerge17(
3089
+ className: twMerge16(
3308
3090
  "flex flex-wrap items-center gap-3 py-4",
3309
3091
  className
3310
3092
  ),
3311
3093
  children: [
3312
- /* @__PURE__ */ jsx47(H2, { children: title }),
3313
- children && /* @__PURE__ */ jsx47("div", { className: "ml-auto flex flex-wrap items-center gap-2", children })
3094
+ /* @__PURE__ */ jsx45(H2, { children: title }),
3095
+ children && /* @__PURE__ */ jsx45("div", { className: "ml-auto flex flex-wrap items-center gap-2", children })
3314
3096
  ]
3315
3097
  }
3316
3098
  );
3317
3099
  }
3318
3100
 
3101
+ // src/components/Pill/Pill.tsx
3102
+ import { twMerge as twMerge17 } from "tailwind-merge";
3103
+ import { jsx as jsx46 } from "react/jsx-runtime";
3104
+ var hashColors = {
3105
+ purple: "bg-(--color-badge-purple-bg) text-(--color-badge-purple-text) border-(--color-badge-purple-text)/20",
3106
+ teal: "bg-(--color-badge-teal-bg) text-(--color-badge-teal-text) border-(--color-badge-teal-text)/20",
3107
+ rose: "bg-(--color-badge-rose-bg) text-(--color-badge-rose-text) border-(--color-badge-rose-text)/20",
3108
+ green: "bg-(--color-badge-green-bg) text-(--color-badge-green-text) border-(--color-badge-green-text)/20",
3109
+ amber: "bg-(--color-badge-amber-bg) text-(--color-badge-amber-text) border-(--color-badge-amber-text)/20"
3110
+ };
3111
+ var colorStyles = {
3112
+ ...hashColors,
3113
+ slate: "bg-(--color-badge-slate-bg) text-(--color-badge-slate-text) border-(--color-badge-slate-text)/20"
3114
+ };
3115
+ var hashKeys = Object.keys(hashColors);
3116
+ function pillColorFromName(name = "") {
3117
+ let hash = 0;
3118
+ for (let i = 0; i < name.length; i++) {
3119
+ hash = name.charCodeAt(i) + ((hash << 5) - hash);
3120
+ }
3121
+ return hashKeys[Math.abs(hash) % hashKeys.length];
3122
+ }
3123
+ function Pill({
3124
+ children,
3125
+ color = pillColorFromName(children),
3126
+ className,
3127
+ ...rest
3128
+ }) {
3129
+ const cx = twMerge17(
3130
+ `
3131
+ inline-flex items-center
3132
+ rounded-full
3133
+ border
3134
+ px-2 py-0.5
3135
+ text-xs font-medium
3136
+ leading-tight
3137
+ `,
3138
+ colorStyles[color],
3139
+ className
3140
+ );
3141
+ return /* @__PURE__ */ jsx46("span", { className: cx, ...rest, children });
3142
+ }
3143
+
3144
+ // src/components/Pill/PathPill.tsx
3145
+ import { twMerge as twMerge18 } from "tailwind-merge";
3146
+ import { jsx as jsx47 } from "react/jsx-runtime";
3147
+ function PathPill({
3148
+ children,
3149
+ visibleCount = 1,
3150
+ className
3151
+ }) {
3152
+ const segments = children.split("/").filter(Boolean);
3153
+ if (segments.length === 0) return null;
3154
+ const dotCount = Math.max(0, segments.length - visibleCount);
3155
+ const fullPath = segments.join(" / ");
3156
+ return /* @__PURE__ */ jsx47(
3157
+ "div",
3158
+ {
3159
+ className: twMerge18("relative flex", className),
3160
+ "aria-label": `Path: ${fullPath}`,
3161
+ children: segments.map((segment, i) => {
3162
+ const isCollapsed = i < dotCount;
3163
+ const isLast = i === segments.length - 1;
3164
+ const cx = twMerge18(!isLast && "pr-5 -mr-4", isCollapsed && "pr-3");
3165
+ const color = pillColorFromName(segment);
3166
+ return /* @__PURE__ */ jsx47(
3167
+ Pill,
3168
+ {
3169
+ className: cx,
3170
+ color,
3171
+ "aria-hidden": isCollapsed || void 0,
3172
+ children: isCollapsed ? void 0 : segment
3173
+ },
3174
+ `pill-${i}-${segment}`
3175
+ );
3176
+ })
3177
+ }
3178
+ );
3179
+ }
3180
+
3319
3181
  // src/components/FormWizard/FormWizard.tsx
3320
3182
  import { createContext as createContext6, useContext as useContext6, useCallback as useCallback6, useMemo } from "react";
3321
3183
  import { jsx as jsx48 } from "react/jsx-runtime";
@@ -3357,8 +3219,8 @@ function FormWizard({
3357
3219
  }
3358
3220
 
3359
3221
  // src/components/FormWizard/FormWizardProgress.tsx
3360
- import { jsx as jsx49, jsxs as jsxs33 } from "react/jsx-runtime";
3361
- function CheckIcon2() {
3222
+ import { jsx as jsx49, jsxs as jsxs32 } from "react/jsx-runtime";
3223
+ function CheckIcon() {
3362
3224
  return /* @__PURE__ */ jsx49(
3363
3225
  "svg",
3364
3226
  {
@@ -3380,13 +3242,13 @@ function FormWizardProgress({ labels }) {
3380
3242
  const isCompleted = index < currentStep;
3381
3243
  const isCurrent = index === currentStep;
3382
3244
  const isFuture = index > currentStep;
3383
- return /* @__PURE__ */ jsxs33(
3245
+ return /* @__PURE__ */ jsxs32(
3384
3246
  "li",
3385
3247
  {
3386
3248
  className: "flex flex-1 flex-col items-center",
3387
3249
  "aria-current": isCurrent ? "step" : void 0,
3388
3250
  children: [
3389
- /* @__PURE__ */ jsxs33("div", { className: "flex w-full items-center", children: [
3251
+ /* @__PURE__ */ jsxs32("div", { className: "flex w-full items-center", children: [
3390
3252
  index > 0 ? /* @__PURE__ */ jsx49(
3391
3253
  "div",
3392
3254
  {
@@ -3409,7 +3271,7 @@ function FormWizardProgress({ labels }) {
3409
3271
  isFuture ? "border-2 border-(--color-border-default) bg-(--color-surface-default) text-(--color-text-tertiary)" : ""
3410
3272
  ].join(" "),
3411
3273
  "aria-hidden": "true",
3412
- children: isCompleted ? /* @__PURE__ */ jsx49(CheckIcon2, {}) : index + 1
3274
+ children: isCompleted ? /* @__PURE__ */ jsx49(CheckIcon, {}) : index + 1
3413
3275
  }
3414
3276
  ),
3415
3277
  index < totalSteps - 1 ? /* @__PURE__ */ jsx49(
@@ -3441,14 +3303,14 @@ function FormWizardProgress({ labels }) {
3441
3303
  }
3442
3304
 
3443
3305
  // src/components/FormWizard/FormWizardNav.tsx
3444
- import { jsx as jsx50, jsxs as jsxs34 } from "react/jsx-runtime";
3306
+ import { jsx as jsx50, jsxs as jsxs33 } from "react/jsx-runtime";
3445
3307
  function FormWizardNav({
3446
3308
  onNext,
3447
3309
  isSubmitting = false,
3448
3310
  submitLabel = "Submit"
3449
3311
  }) {
3450
3312
  const { canGoBack, goBack, isLastStep } = useFormWizard();
3451
- return /* @__PURE__ */ jsxs34("div", { className: "flex items-center justify-end gap-3", children: [
3313
+ return /* @__PURE__ */ jsxs33("div", { className: "flex items-center justify-end gap-3", children: [
3452
3314
  canGoBack && /* @__PURE__ */ jsx50(
3453
3315
  Button,
3454
3316
  {
@@ -3632,7 +3494,7 @@ var ColorBannerSuccessIcon = "#22c55e";
3632
3494
  var ColorBadgePurpleBg = "#ead9f5";
3633
3495
  var ColorBadgePurpleText = "#5c2483";
3634
3496
  var ColorBadgeTealBg = "#d0f0f0";
3635
- var ColorBadgeTealText = "#217d7e";
3497
+ var ColorBadgeTealText = "#1a6364";
3636
3498
  var ColorBadgeSlateBg = "#f1f5f9";
3637
3499
  var ColorBadgeSlateText = "#334155";
3638
3500
  var ColorBadgeRoseBg = "#ffe4e6";
@@ -3642,7 +3504,7 @@ var ColorBadgeNeutralText = "#374151";
3642
3504
  var ColorBadgeGreenBg = "#dcfce7";
3643
3505
  var ColorBadgeGreenText = "#15803d";
3644
3506
  var ColorBadgeAmberBg = "#fef3c7";
3645
- var ColorBadgeAmberText = "#b45309";
3507
+ var ColorBadgeAmberText = "#92400e";
3646
3508
  var Spacing1 = "4px";
3647
3509
  var Spacing2 = "8px";
3648
3510
  var Spacing3 = "12px";
@@ -3867,7 +3729,6 @@ export {
3867
3729
  Field,
3868
3730
  Fieldset,
3869
3731
  FileCard,
3870
- FileIcon,
3871
3732
  FontSize2xl,
3872
3733
  FontSize3xl,
3873
3734
  FontSize4xl,
@@ -3886,7 +3747,6 @@ export {
3886
3747
  FormWizard,
3887
3748
  FormWizardNav,
3888
3749
  FormWizardProgress,
3889
- GroupPill,
3890
3750
  H1,
3891
3751
  H2,
3892
3752
  H3,
@@ -3910,6 +3770,7 @@ export {
3910
3770
  MenuSection,
3911
3771
  MenuSeparator,
3912
3772
  MetricCard,
3773
+ PathPill,
3913
3774
  Pill,
3914
3775
  Popover3 as Popover,
3915
3776
  PopoverContent,
@@ -3953,8 +3814,6 @@ export {
3953
3814
  TabPanel2 as UnstyledTabPanel,
3954
3815
  Tabs2 as UnstyledTabs,
3955
3816
  createToastBridge,
3956
- getFileIcon,
3957
- getTypeLabel,
3958
3817
  pillColorFromName,
3959
3818
  useFormWizard,
3960
3819
  useInputGroup,