@cytario/design 1.14.0 → 1.16.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
@@ -542,6 +542,7 @@ function Select({
542
542
  items,
543
543
  placeholder = "Select an option",
544
544
  errorMessage,
545
+ hideLabel = false,
545
546
  isDisabled,
546
547
  isRequired,
547
548
  className,
@@ -561,8 +562,9 @@ function Select({
561
562
  Label2,
562
563
  {
563
564
  className: [
564
- "text-[length:var(--font-size-sm)] font-[var(--font-weight-medium)] text-[var(--color-text-primary)]"
565
- ].join(" "),
565
+ "text-[length:var(--font-size-sm)] font-[var(--font-weight-medium)] text-[var(--color-text-primary)]",
566
+ hideLabel && "sr-only"
567
+ ].filter(Boolean).join(" "),
566
568
  children: [
567
569
  label,
568
570
  isRequired && /* @__PURE__ */ jsx7(
@@ -1598,27 +1600,28 @@ import {
1598
1600
  Popover as Popover2
1599
1601
  } from "react-aria-components";
1600
1602
  import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
1601
- function Menu({ items, children, className }) {
1603
+ var popoverStyles = [
1604
+ "bg-[var(--color-surface-default)] rounded-[var(--border-radius-md)]",
1605
+ "shadow-lg border border-[var(--color-border-default)]",
1606
+ "py-1 min-w-48",
1607
+ "entering:animate-in entering:fade-in entering:zoom-in-95",
1608
+ "exiting:animate-out exiting:fade-out exiting:zoom-out-95"
1609
+ ].join(" ");
1610
+ function Menu({ items, content, children, onAction, className }) {
1602
1611
  return /* @__PURE__ */ jsxs18(MenuTrigger, { children: [
1603
1612
  children,
1604
1613
  /* @__PURE__ */ jsx25(
1605
1614
  Popover2,
1606
1615
  {
1607
- className: [
1608
- "bg-[var(--color-surface-default)] rounded-[var(--border-radius-md)]",
1609
- "shadow-lg border border-[var(--color-border-default)]",
1610
- "py-1 min-w-48",
1611
- "entering:animate-in entering:fade-in entering:zoom-in-95",
1612
- "exiting:animate-out exiting:fade-out exiting:zoom-out-95",
1613
- className
1614
- ].filter(Boolean).join(" "),
1615
- children: /* @__PURE__ */ jsx25(
1616
+ className: [popoverStyles, className].filter(Boolean).join(" "),
1617
+ children: items ? /* @__PURE__ */ jsx25(
1616
1618
  AriaMenu,
1617
1619
  {
1618
1620
  items,
1619
1621
  onAction: (key) => {
1620
1622
  const item = items.find((i) => i.id === key);
1621
1623
  item?.onAction?.();
1624
+ onAction?.(key);
1622
1625
  },
1623
1626
  className: "outline-none",
1624
1627
  children: (item) => /* @__PURE__ */ jsxs18(
@@ -1638,17 +1641,120 @@ function Menu({ items, children, className }) {
1638
1641
  ].filter(Boolean).join(" "),
1639
1642
  children: [
1640
1643
  item.icon && /* @__PURE__ */ jsx25(Icon, { icon: item.icon, size: "sm" }),
1641
- item.label
1644
+ /* @__PURE__ */ jsx25("span", { className: "flex-1", children: item.label }),
1645
+ item.endContent && /* @__PURE__ */ jsx25("span", { className: "ml-auto flex items-center", children: item.endContent })
1642
1646
  ]
1643
1647
  }
1644
1648
  )
1645
1649
  }
1650
+ ) : /* @__PURE__ */ jsx25(
1651
+ AriaMenu,
1652
+ {
1653
+ onAction: (key) => onAction?.(key),
1654
+ className: "outline-none",
1655
+ children: content
1656
+ }
1646
1657
  )
1647
1658
  }
1648
1659
  )
1649
1660
  ] });
1650
1661
  }
1651
1662
 
1663
+ // src/components/Menu/MenuItem.tsx
1664
+ import { MenuItem as AriaMenuItem2 } from "react-aria-components";
1665
+ import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
1666
+ function MenuItem({
1667
+ id,
1668
+ children,
1669
+ icon,
1670
+ endContent,
1671
+ onAction,
1672
+ href,
1673
+ target,
1674
+ isDisabled,
1675
+ isDanger,
1676
+ textValue,
1677
+ className
1678
+ }) {
1679
+ return /* @__PURE__ */ jsxs19(
1680
+ AriaMenuItem2,
1681
+ {
1682
+ id,
1683
+ href,
1684
+ target,
1685
+ isDisabled,
1686
+ onAction,
1687
+ textValue,
1688
+ className: [
1689
+ "flex items-center gap-2 px-3 py-2 text-sm outline-none cursor-default",
1690
+ "transition-colors",
1691
+ "focus:bg-[var(--color-surface-muted)]",
1692
+ "hover:bg-[var(--color-surface-muted)]",
1693
+ "disabled:opacity-50 disabled:pointer-events-none",
1694
+ isDanger ? "text-[var(--color-text-danger)]" : "text-[var(--color-text-primary)]",
1695
+ className
1696
+ ].filter(Boolean).join(" "),
1697
+ children: [
1698
+ icon && /* @__PURE__ */ jsx26(Icon, { icon, size: "sm" }),
1699
+ /* @__PURE__ */ jsx26("span", { className: "flex-1", children }),
1700
+ endContent && /* @__PURE__ */ jsx26("span", { className: "ml-auto flex items-center", children: endContent })
1701
+ ]
1702
+ }
1703
+ );
1704
+ }
1705
+
1706
+ // src/components/Menu/MenuSection.tsx
1707
+ import {
1708
+ MenuSection as AriaMenuSection,
1709
+ Header
1710
+ } from "react-aria-components";
1711
+ import { jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
1712
+ function MenuSection({
1713
+ header,
1714
+ children,
1715
+ "aria-label": ariaLabel,
1716
+ className
1717
+ }) {
1718
+ return /* @__PURE__ */ jsxs20(AriaMenuSection, { className, "aria-label": ariaLabel, children: [
1719
+ header && /* @__PURE__ */ jsx27(
1720
+ Header,
1721
+ {
1722
+ className: [
1723
+ "px-3 py-1.5",
1724
+ "text-[length:var(--font-size-xs)] font-[number:var(--font-weight-semibold)]",
1725
+ "text-[var(--color-text-secondary)]",
1726
+ "uppercase tracking-wider",
1727
+ "select-none"
1728
+ ].join(" "),
1729
+ children: header
1730
+ }
1731
+ ),
1732
+ children
1733
+ ] });
1734
+ }
1735
+
1736
+ // src/components/Menu/MenuHeader.tsx
1737
+ import { Header as Header2 } from "react-aria-components";
1738
+ import { jsx as jsx28 } from "react/jsx-runtime";
1739
+ function MenuHeader({ children, className }) {
1740
+ return /* @__PURE__ */ jsx28(Header2, { className, children });
1741
+ }
1742
+
1743
+ // src/components/Menu/MenuSeparator.tsx
1744
+ import { Separator } from "react-aria-components";
1745
+ import { jsx as jsx29 } from "react/jsx-runtime";
1746
+ function MenuSeparator({ className }) {
1747
+ return /* @__PURE__ */ jsx29(
1748
+ Separator,
1749
+ {
1750
+ className: [
1751
+ "border-t border-[var(--color-border-default)] my-1",
1752
+ className
1753
+ ].filter(Boolean).join(" ")
1754
+ }
1755
+ );
1756
+ }
1757
+
1652
1758
  // src/components/Popover/Popover.tsx
1653
1759
  import {
1654
1760
  DialogTrigger,
@@ -1656,12 +1762,12 @@ import {
1656
1762
  Dialog as AriaDialog2,
1657
1763
  Button as AriaButton3
1658
1764
  } from "react-aria-components";
1659
- import { Fragment as Fragment7, jsx as jsx26 } from "react/jsx-runtime";
1765
+ import { Fragment as Fragment7, jsx as jsx30 } from "react/jsx-runtime";
1660
1766
  function Popover3({ children, isOpen, onOpenChange }) {
1661
- return /* @__PURE__ */ jsx26(DialogTrigger, { isOpen, onOpenChange, children });
1767
+ return /* @__PURE__ */ jsx30(DialogTrigger, { isOpen, onOpenChange, children });
1662
1768
  }
1663
1769
  function PopoverTrigger({ children, className }) {
1664
- return /* @__PURE__ */ jsx26(
1770
+ return /* @__PURE__ */ jsx30(
1665
1771
  AriaButton3,
1666
1772
  {
1667
1773
  className: [
@@ -1679,7 +1785,7 @@ function PopoverContent({
1679
1785
  className,
1680
1786
  children
1681
1787
  }) {
1682
- return /* @__PURE__ */ jsx26(
1788
+ return /* @__PURE__ */ jsx30(
1683
1789
  AriaPopover,
1684
1790
  {
1685
1791
  placement,
@@ -1696,7 +1802,7 @@ function PopoverContent({
1696
1802
  "entering:placement-right:slide-in-from-left-1",
1697
1803
  className
1698
1804
  ].filter(Boolean).join(" "),
1699
- children: /* @__PURE__ */ jsx26(AriaDialog2, { className: "outline-none", children: ({ close }) => /* @__PURE__ */ jsx26(Fragment7, { children: typeof children === "function" ? children({ close }) : children }) })
1805
+ children: /* @__PURE__ */ jsx30(AriaDialog2, { className: "outline-none", children: ({ close }) => /* @__PURE__ */ jsx30(Fragment7, { children: typeof children === "function" ? children({ close }) : children }) })
1700
1806
  }
1701
1807
  );
1702
1808
  }
@@ -1710,7 +1816,7 @@ import {
1710
1816
  Tab as AriaTab,
1711
1817
  TabPanel as AriaTabPanel
1712
1818
  } from "react-aria-components";
1713
- import { jsx as jsx27 } from "react/jsx-runtime";
1819
+ import { jsx as jsx31 } from "react/jsx-runtime";
1714
1820
  var TabsContext = createContext3({
1715
1821
  variant: "underline",
1716
1822
  size: "md"
@@ -1728,7 +1834,7 @@ function Tabs({
1728
1834
  children,
1729
1835
  ...props
1730
1836
  }) {
1731
- return /* @__PURE__ */ jsx27(TabsContext.Provider, { value: { variant, size }, children: /* @__PURE__ */ jsx27(
1837
+ return /* @__PURE__ */ jsx31(TabsContext.Provider, { value: { variant, size }, children: /* @__PURE__ */ jsx31(
1732
1838
  AriaTabs,
1733
1839
  {
1734
1840
  ...props,
@@ -1748,7 +1854,7 @@ function TabList({
1748
1854
  const { variant } = useContext3(TabsContext);
1749
1855
  const baseStyles = variant === "unstyled" ? "flex items-center" : variant === "underline" ? "flex items-center border-b border-[var(--color-border-default)]" : "inline-flex items-center bg-[var(--color-surface-muted)] rounded-[var(--border-radius-lg)] p-1 gap-1";
1750
1856
  const verticalStyles = variant === "unstyled" ? "flex-col" : variant === "underline" ? "flex-col border-b-0 border-r border-[var(--color-border-default)]" : "flex-col";
1751
- return /* @__PURE__ */ jsx27(
1857
+ return /* @__PURE__ */ jsx31(
1752
1858
  AriaTabList,
1753
1859
  {
1754
1860
  ...props,
@@ -1762,7 +1868,7 @@ function TabList({
1762
1868
  }
1763
1869
  function Tab({ className, ...props }) {
1764
1870
  const { variant, size } = useContext3(TabsContext);
1765
- return /* @__PURE__ */ jsx27(
1871
+ return /* @__PURE__ */ jsx31(
1766
1872
  AriaTab,
1767
1873
  {
1768
1874
  ...props,
@@ -1819,7 +1925,7 @@ function getTabVariantStyles(variant, state) {
1819
1925
  }
1820
1926
  function TabPanel({ className, ...props }) {
1821
1927
  const { variant } = useContext3(TabsContext);
1822
- return /* @__PURE__ */ jsx27(
1928
+ return /* @__PURE__ */ jsx31(
1823
1929
  AriaTabPanel,
1824
1930
  {
1825
1931
  ...props,
@@ -1844,7 +1950,7 @@ import { useCallback as useCallback2, useImperativeHandle, useRef as useRef2, us
1844
1950
  import { Tree as ArboristTree } from "react-arborist";
1845
1951
  import { ChevronRight as ChevronRight2, Folder, File } from "lucide-react";
1846
1952
  import { Check as Check2 } from "lucide-react";
1847
- import { jsx as jsx28, jsxs as jsxs19 } from "react/jsx-runtime";
1953
+ import { jsx as jsx32, jsxs as jsxs21 } from "react/jsx-runtime";
1848
1954
  var rowHeightMap = {
1849
1955
  compact: 32,
1850
1956
  comfortable: 40
@@ -1867,7 +1973,7 @@ function NodeRenderer({
1867
1973
  const isSelected = node.isSelected && !isCheckbox;
1868
1974
  const isCompact = size === "compact";
1869
1975
  const IconComponent = data.icon ? data.icon : node.isInternal ? Folder : File;
1870
- return /* @__PURE__ */ jsxs19(
1976
+ return /* @__PURE__ */ jsxs21(
1871
1977
  "div",
1872
1978
  {
1873
1979
  ref: dragHandle,
@@ -1902,7 +2008,7 @@ function NodeRenderer({
1902
2008
  }
1903
2009
  },
1904
2010
  children: [
1905
- /* @__PURE__ */ jsx28(
2011
+ /* @__PURE__ */ jsx32(
1906
2012
  "button",
1907
2013
  {
1908
2014
  type: "button",
@@ -1920,7 +2026,7 @@ function NodeRenderer({
1920
2026
  },
1921
2027
  tabIndex: -1,
1922
2028
  "aria-label": node.isOpen ? "Collapse" : "Expand",
1923
- children: /* @__PURE__ */ jsx28(
2029
+ children: /* @__PURE__ */ jsx32(
1924
2030
  ChevronRight2,
1925
2031
  {
1926
2032
  size: 14,
@@ -1932,7 +2038,7 @@ function NodeRenderer({
1932
2038
  )
1933
2039
  }
1934
2040
  ),
1935
- isCheckbox && /* @__PURE__ */ jsx28(
2041
+ isCheckbox && /* @__PURE__ */ jsx32(
1936
2042
  "div",
1937
2043
  {
1938
2044
  className: [
@@ -1943,7 +2049,7 @@ function NodeRenderer({
1943
2049
  role: "checkbox",
1944
2050
  "aria-checked": isChecked,
1945
2051
  "aria-label": `Select ${data.name}`,
1946
- children: isChecked && /* @__PURE__ */ jsx28(
2052
+ children: isChecked && /* @__PURE__ */ jsx32(
1947
2053
  Check2,
1948
2054
  {
1949
2055
  className: "w-3 h-3 text-[var(--color-text-inverse)]",
@@ -1952,7 +2058,7 @@ function NodeRenderer({
1952
2058
  )
1953
2059
  }
1954
2060
  ),
1955
- /* @__PURE__ */ jsx28(
2061
+ /* @__PURE__ */ jsx32(
1956
2062
  IconComponent,
1957
2063
  {
1958
2064
  size: 16,
@@ -1960,7 +2066,7 @@ function NodeRenderer({
1960
2066
  "aria-hidden": "true"
1961
2067
  }
1962
2068
  ),
1963
- /* @__PURE__ */ jsx28("span", { className: "truncate", children: data.name })
2069
+ /* @__PURE__ */ jsx32("span", { className: "truncate", children: data.name })
1964
2070
  ]
1965
2071
  }
1966
2072
  );
@@ -2026,13 +2132,13 @@ function Tree({
2026
2132
  );
2027
2133
  const arboristSearchMatch = searchMatch ? (node, term) => searchMatch(node.data, term) : void 0;
2028
2134
  const selectionProp = selectionMode === "single" && selectedIds && selectedIds.size > 0 ? [...selectedIds][0] : void 0;
2029
- return /* @__PURE__ */ jsx28(
2135
+ return /* @__PURE__ */ jsx32(
2030
2136
  "div",
2031
2137
  {
2032
2138
  role: "tree",
2033
2139
  "aria-label": ariaLabel,
2034
2140
  className: ["outline-none overflow-hidden", className].filter(Boolean).join(" "),
2035
- children: /* @__PURE__ */ jsx28(
2141
+ children: /* @__PURE__ */ jsx32(
2036
2142
  ArboristTree,
2037
2143
  {
2038
2144
  ref: internalRef,
@@ -2051,7 +2157,7 @@ function Tree({
2051
2157
  onSelect: handleSelect,
2052
2158
  onActivate: handleActivate,
2053
2159
  disableEdit: true,
2054
- children: (props) => /* @__PURE__ */ jsx28(
2160
+ children: (props) => /* @__PURE__ */ jsx32(
2055
2161
  NodeRenderer,
2056
2162
  {
2057
2163
  ...props,
@@ -2076,7 +2182,7 @@ import {
2076
2182
  ToggleButtonGroup as AriaToggleButtonGroup,
2077
2183
  ToggleButton as AriaToggleButton2
2078
2184
  } from "react-aria-components";
2079
- import { jsx as jsx29 } from "react/jsx-runtime";
2185
+ import { jsx as jsx33 } from "react/jsx-runtime";
2080
2186
  var SegmentedControlContext = createContext4({
2081
2187
  size: "md"
2082
2188
  });
@@ -2096,7 +2202,7 @@ function SegmentedControl({
2096
2202
  ...props
2097
2203
  }) {
2098
2204
  const isNoneMode = selectionMode === "none";
2099
- return /* @__PURE__ */ jsx29(SegmentedControlContext.Provider, { value: { size }, children: /* @__PURE__ */ jsx29(
2205
+ return /* @__PURE__ */ jsx33(SegmentedControlContext.Provider, { value: { size }, children: /* @__PURE__ */ jsx33(
2100
2206
  AriaToggleButtonGroup,
2101
2207
  {
2102
2208
  ...props,
@@ -2117,7 +2223,7 @@ function SegmentedControlItem({
2117
2223
  ...props
2118
2224
  }) {
2119
2225
  const { size } = useContext4(SegmentedControlContext);
2120
- return /* @__PURE__ */ jsx29(
2226
+ return /* @__PURE__ */ jsx33(
2121
2227
  AriaToggleButton2,
2122
2228
  {
2123
2229
  ...props,
@@ -2141,13 +2247,194 @@ function SegmentedControlItem({
2141
2247
  );
2142
2248
  }
2143
2249
 
2250
+ // src/components/FileCard/FileCard.tsx
2251
+ import { useCallback as useCallback3 } from "react";
2252
+ import {
2253
+ File as File2,
2254
+ FileSpreadsheet,
2255
+ Folder as Folder2,
2256
+ Image,
2257
+ Info as Info2,
2258
+ Microscope
2259
+ } from "lucide-react";
2260
+ import { Fragment as Fragment8, jsx as jsx34, jsxs as jsxs22 } from "react/jsx-runtime";
2261
+ function getFileIcon(type, extension) {
2262
+ if (type === "directory") return Folder2;
2263
+ const ext = (extension ?? "").toLowerCase();
2264
+ if (ext === "ome.tif" || ext === "ome.tiff") return Microscope;
2265
+ if (/^(tiff?|png|jpe?g)$/.test(ext)) return Image;
2266
+ if (/^(csv|parquet)$/.test(ext)) return FileSpreadsheet;
2267
+ return File2;
2268
+ }
2269
+ function getTypeLabel(type, extension) {
2270
+ if (type === "directory") return "Folder";
2271
+ const ext = (extension ?? "").toLowerCase();
2272
+ if (ext === "ome.tif" || ext === "ome.tiff") return "OME-TIFF";
2273
+ if (/^tiff?$/.test(ext)) return "TIFF";
2274
+ if (ext === "csv") return "CSV";
2275
+ if (ext === "parquet") return "Parquet";
2276
+ if (ext === "png") return "PNG";
2277
+ if (/^jpe?g$/.test(ext)) return "JPEG";
2278
+ return ext.toUpperCase() || "File";
2279
+ }
2280
+ function FileIcon({
2281
+ type,
2282
+ extension,
2283
+ size = 16
2284
+ }) {
2285
+ const IconComponent = getFileIcon(type, extension);
2286
+ return /* @__PURE__ */ jsx34(
2287
+ IconComponent,
2288
+ {
2289
+ size,
2290
+ className: "shrink-0 text-[var(--color-text-secondary)]"
2291
+ }
2292
+ );
2293
+ }
2294
+ function FileCard({
2295
+ name,
2296
+ type,
2297
+ size,
2298
+ extension,
2299
+ compact = false,
2300
+ children,
2301
+ onInfo,
2302
+ href,
2303
+ onPress,
2304
+ className
2305
+ }) {
2306
+ const isInteractive = !!href || !!onPress;
2307
+ const radius = compact ? "rounded-[var(--border-radius-md)]" : "rounded-[var(--border-radius-lg)]";
2308
+ const IconComponent = getFileIcon(type, extension);
2309
+ const iconSize = compact ? 24 : 32;
2310
+ const iconColor = type === "directory" ? "text-[var(--color-text-tertiary)]" : "text-[var(--color-text-secondary)]";
2311
+ const thumbnailClass = compact ? "aspect-square rounded-t-[var(--border-radius-md)]" : "aspect-[4/3] rounded-t-[var(--border-radius-lg)]";
2312
+ const handleInfoClick = useCallback3(
2313
+ (e) => {
2314
+ if (isInteractive) {
2315
+ e.stopPropagation();
2316
+ e.preventDefault();
2317
+ }
2318
+ onInfo?.();
2319
+ },
2320
+ [onInfo, isInteractive]
2321
+ );
2322
+ const handleKeyDown = useCallback3(
2323
+ (e) => {
2324
+ if (onPress && (e.key === "Enter" || e.key === " ")) {
2325
+ e.preventDefault();
2326
+ onPress();
2327
+ }
2328
+ },
2329
+ [onPress]
2330
+ );
2331
+ const cardContent = /* @__PURE__ */ jsxs22(Fragment8, { children: [
2332
+ /* @__PURE__ */ jsxs22(
2333
+ "div",
2334
+ {
2335
+ className: `shrink-0 relative overflow-hidden bg-[var(--color-neutral-900)] ${thumbnailClass}`,
2336
+ children: [
2337
+ children ? /* @__PURE__ */ jsx34("div", { className: "h-full w-full overflow-hidden", children }) : /* @__PURE__ */ jsx34("div", { className: "flex h-full w-full items-center justify-center", children: /* @__PURE__ */ jsx34(IconComponent, { size: iconSize, className: iconColor }) }),
2338
+ onInfo && /* @__PURE__ */ jsx34(
2339
+ "div",
2340
+ {
2341
+ className: [
2342
+ "absolute opacity-0 group-hover:opacity-100 group-focus-within:opacity-100",
2343
+ "transition-opacity duration-150",
2344
+ compact ? "bottom-1.5 right-1.5" : "bottom-2 right-2"
2345
+ ].join(" "),
2346
+ children: /* @__PURE__ */ jsx34(
2347
+ "span",
2348
+ {
2349
+ onClick: handleInfoClick,
2350
+ onKeyDown: (e) => {
2351
+ if (e.key === "Enter" || e.key === " ") {
2352
+ handleInfoClick(e);
2353
+ }
2354
+ },
2355
+ role: "presentation",
2356
+ children: /* @__PURE__ */ jsx34(
2357
+ IconButton,
2358
+ {
2359
+ icon: Info2,
2360
+ "aria-label": `Show info for ${name}`,
2361
+ variant: "ghost",
2362
+ size: "sm",
2363
+ className: "bg-[var(--color-neutral-900)]/75 text-[var(--color-text-inverse)] hover:bg-[var(--color-neutral-900)]/90 rounded-[var(--border-radius-sm)]",
2364
+ onPress: onInfo
2365
+ }
2366
+ )
2367
+ }
2368
+ )
2369
+ }
2370
+ )
2371
+ ]
2372
+ }
2373
+ ),
2374
+ /* @__PURE__ */ jsx34(
2375
+ "div",
2376
+ {
2377
+ className: [
2378
+ "flex flex-col border-t border-[var(--color-border-default)]",
2379
+ "bg-[var(--color-surface-default)]",
2380
+ compact ? "px-2 py-1.5 rounded-b-[var(--border-radius-md)]" : "gap-0.5 px-3 py-2 rounded-b-[var(--border-radius-lg)]"
2381
+ ].join(" "),
2382
+ children: compact ? /* @__PURE__ */ jsx34("span", { className: "text-xs font-medium text-[var(--color-text-primary)] truncate", children: name }) : /* @__PURE__ */ jsxs22(Fragment8, { children: [
2383
+ /* @__PURE__ */ jsxs22("span", { className: "flex items-center gap-1.5", children: [
2384
+ /* @__PURE__ */ jsx34(FileIcon, { type, extension, size: 16 }),
2385
+ /* @__PURE__ */ jsx34("span", { className: "text-sm font-medium text-[var(--color-text-primary)] truncate", children: name })
2386
+ ] }),
2387
+ size && /* @__PURE__ */ jsx34("span", { className: "text-xs text-[var(--color-text-secondary)] tabular-nums pl-[22px]", children: size })
2388
+ ] })
2389
+ }
2390
+ )
2391
+ ] });
2392
+ const baseStyles = [
2393
+ "group flex flex-col overflow-hidden",
2394
+ radius,
2395
+ "border border-[var(--color-border-default)]",
2396
+ "shadow-sm",
2397
+ "transition-all",
2398
+ isInteractive && "hover:border-[var(--color-border-focus)] hover:shadow-md cursor-pointer",
2399
+ isInteractive && "focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)] focus-visible:ring-offset-2 outline-none",
2400
+ className
2401
+ ].filter(Boolean).join(" ");
2402
+ if (href) {
2403
+ return /* @__PURE__ */ jsx34(
2404
+ "a",
2405
+ {
2406
+ href,
2407
+ "aria-label": name,
2408
+ className: [baseStyles, "no-underline"].join(" "),
2409
+ children: cardContent
2410
+ }
2411
+ );
2412
+ }
2413
+ if (onPress) {
2414
+ return /* @__PURE__ */ jsx34(
2415
+ "div",
2416
+ {
2417
+ role: "button",
2418
+ tabIndex: 0,
2419
+ "aria-label": name,
2420
+ className: baseStyles,
2421
+ onClick: onPress,
2422
+ onKeyDown: handleKeyDown,
2423
+ children: cardContent
2424
+ }
2425
+ );
2426
+ }
2427
+ return /* @__PURE__ */ jsx34("div", { className: baseStyles, children: cardContent });
2428
+ }
2429
+
2144
2430
  // src/components/StorageConnectionCard/StorageConnectionCard.tsx
2145
- import { AlertCircle, Database, Info as Info2 } from "lucide-react";
2431
+ import { useCallback as useCallback4 } from "react";
2432
+ import { AlertCircle, Database, Info as Info3 } from "lucide-react";
2146
2433
  import { twMerge as twMerge9 } from "tailwind-merge";
2147
2434
 
2148
2435
  // src/components/Pill/Pill.tsx
2149
2436
  import { twMerge as twMerge7 } from "tailwind-merge";
2150
- import { jsx as jsx30 } from "react/jsx-runtime";
2437
+ import { jsx as jsx35 } from "react/jsx-runtime";
2151
2438
  var HASH_PALETTE = [
2152
2439
  "teal",
2153
2440
  // sky
@@ -2198,7 +2485,7 @@ function resolveColor(color, name) {
2198
2485
  }
2199
2486
  function Pill({ children, color, name, className }) {
2200
2487
  const resolved = resolveColor(color, name);
2201
- return /* @__PURE__ */ jsx30(
2488
+ return /* @__PURE__ */ jsx35(
2202
2489
  "span",
2203
2490
  {
2204
2491
  className: twMerge7(
@@ -2215,7 +2502,7 @@ function Pill({ children, color, name, className }) {
2215
2502
 
2216
2503
  // src/components/Pill/GroupPill.tsx
2217
2504
  import { twMerge as twMerge8 } from "tailwind-merge";
2218
- import { jsx as jsx31, jsxs as jsxs20 } from "react/jsx-runtime";
2505
+ import { jsx as jsx36, jsxs as jsxs23 } from "react/jsx-runtime";
2219
2506
  function GroupPill({
2220
2507
  path,
2221
2508
  visibleCount = 3,
@@ -2226,7 +2513,7 @@ function GroupPill({
2226
2513
  const hiddenCount = Math.max(0, segments.length - visibleCount);
2227
2514
  const hiddenSegments = segments.slice(0, hiddenCount);
2228
2515
  const visibleSegments = segments.slice(hiddenCount);
2229
- return /* @__PURE__ */ jsxs20(
2516
+ return /* @__PURE__ */ jsxs23(
2230
2517
  "span",
2231
2518
  {
2232
2519
  className: twMerge8(
@@ -2237,7 +2524,7 @@ function GroupPill({
2237
2524
  children: [
2238
2525
  hiddenSegments.map((segment, index) => {
2239
2526
  const color = pillColorFromName(segment);
2240
- return /* @__PURE__ */ jsx31(
2527
+ return /* @__PURE__ */ jsx36(
2241
2528
  "span",
2242
2529
  {
2243
2530
  className: twMerge8(
@@ -2250,14 +2537,14 @@ function GroupPill({
2250
2537
  `dot-${index}-${segment}`
2251
2538
  );
2252
2539
  }),
2253
- visibleSegments.map((segment, index) => /* @__PURE__ */ jsx31(Pill, { name: segment, children: segment }, `pill-${index}-${segment}`))
2540
+ visibleSegments.map((segment, index) => /* @__PURE__ */ jsx36(Pill, { name: segment, children: segment }, `pill-${index}-${segment}`))
2254
2541
  ]
2255
2542
  }
2256
2543
  );
2257
2544
  }
2258
2545
 
2259
2546
  // src/components/StorageConnectionCard/StorageConnectionCard.tsx
2260
- import { Fragment as Fragment8, jsx as jsx32, jsxs as jsxs21 } from "react/jsx-runtime";
2547
+ import { Fragment as Fragment9, jsx as jsx37, jsxs as jsxs24 } from "react/jsx-runtime";
2261
2548
  var statusDotStyles = {
2262
2549
  connected: "bg-[var(--color-status-success)]",
2263
2550
  error: "border-2 border-[var(--color-status-danger)] bg-transparent",
@@ -2273,7 +2560,7 @@ function ProviderBadge({ provider }) {
2273
2560
  const config = providerConfig[provider.toLowerCase()];
2274
2561
  const label = config?.label ?? provider;
2275
2562
  const color = config?.color ?? "neutral";
2276
- return /* @__PURE__ */ jsx32(Pill, { color, children: label });
2563
+ return /* @__PURE__ */ jsx37(Pill, { color, children: label });
2277
2564
  }
2278
2565
  function PreviewArea({
2279
2566
  status = "connected",
@@ -2281,11 +2568,11 @@ function PreviewArea({
2281
2568
  children
2282
2569
  }) {
2283
2570
  if (status === "loading") {
2284
- return /* @__PURE__ */ jsx32("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx32(Spinner, { size: "lg", "aria-label": "Loading connection" }) });
2571
+ return /* @__PURE__ */ jsx37("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx37(Spinner, { size: "lg", "aria-label": "Loading connection" }) });
2285
2572
  }
2286
2573
  if (status === "error") {
2287
- return /* @__PURE__ */ jsxs21("div", { className: "flex h-full flex-col items-center justify-center gap-2 bg-[var(--color-surface-danger)] px-4", children: [
2288
- /* @__PURE__ */ jsx32(
2574
+ return /* @__PURE__ */ jsxs24("div", { className: "flex h-full flex-col items-center justify-center gap-2 bg-[var(--color-surface-danger)] px-4", children: [
2575
+ /* @__PURE__ */ jsx37(
2289
2576
  Icon,
2290
2577
  {
2291
2578
  icon: AlertCircle,
@@ -2293,13 +2580,13 @@ function PreviewArea({
2293
2580
  className: "text-[var(--color-text-danger)]"
2294
2581
  }
2295
2582
  ),
2296
- errorMessage && /* @__PURE__ */ jsx32("p", { className: "text-center text-xs text-[var(--color-text-danger)]", children: errorMessage })
2583
+ errorMessage && /* @__PURE__ */ jsx37("p", { className: "text-center text-xs text-[var(--color-text-danger)]", children: errorMessage })
2297
2584
  ] });
2298
2585
  }
2299
2586
  if (children) {
2300
- return /* @__PURE__ */ jsx32("div", { className: "h-full w-full overflow-hidden", children });
2587
+ return /* @__PURE__ */ jsx37("div", { className: "h-full w-full overflow-hidden", children });
2301
2588
  }
2302
- return /* @__PURE__ */ jsx32("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx32(
2589
+ return /* @__PURE__ */ jsx37("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx37(
2303
2590
  Icon,
2304
2591
  {
2305
2592
  icon: Database,
@@ -2317,14 +2604,35 @@ function StorageConnectionCard({
2317
2604
  imageCount,
2318
2605
  children,
2319
2606
  href,
2607
+ onPress,
2320
2608
  onInfo,
2321
2609
  className
2322
2610
  }) {
2323
- const cardContent = /* @__PURE__ */ jsxs21(Fragment8, { children: [
2324
- /* @__PURE__ */ jsx32("div", { className: "aspect-[4/3] bg-[var(--color-neutral-900)] overflow-hidden rounded-t-[var(--border-radius-lg)]", children: /* @__PURE__ */ jsx32(PreviewArea, { status, errorMessage, children }) }),
2325
- /* @__PURE__ */ jsxs21("div", { className: "flex flex-col gap-1.5 border-t border-[var(--color-border-default)] bg-[var(--color-surface-default)] px-3 py-2.5 rounded-b-[var(--border-radius-lg)]", children: [
2326
- /* @__PURE__ */ jsxs21("div", { className: "flex items-start gap-2", children: [
2327
- status && /* @__PURE__ */ jsx32(
2611
+ const isInteractive = !!href || !!onPress;
2612
+ const handleInfoPress = useCallback4(
2613
+ (e) => {
2614
+ if (isInteractive) {
2615
+ e.stopPropagation();
2616
+ e.preventDefault();
2617
+ }
2618
+ onInfo?.();
2619
+ },
2620
+ [onInfo, isInteractive]
2621
+ );
2622
+ const handleKeyDown = useCallback4(
2623
+ (e) => {
2624
+ if (onPress && (e.key === "Enter" || e.key === " ")) {
2625
+ e.preventDefault();
2626
+ onPress();
2627
+ }
2628
+ },
2629
+ [onPress]
2630
+ );
2631
+ const cardContent = /* @__PURE__ */ jsxs24(Fragment9, { children: [
2632
+ /* @__PURE__ */ jsx37("div", { className: "aspect-[4/3] bg-[var(--color-neutral-900)] overflow-hidden rounded-t-[var(--border-radius-lg)]", children: /* @__PURE__ */ jsx37(PreviewArea, { status, errorMessage, children }) }),
2633
+ /* @__PURE__ */ jsxs24("div", { className: "flex flex-col gap-1.5 border-t border-[var(--color-border-default)] bg-[var(--color-surface-default)] px-3 py-2.5 rounded-b-[var(--border-radius-lg)]", children: [
2634
+ /* @__PURE__ */ jsxs24("div", { className: "flex items-start gap-2", children: [
2635
+ status && /* @__PURE__ */ jsx37(
2328
2636
  "span",
2329
2637
  {
2330
2638
  className: twMerge9(
@@ -2334,25 +2642,35 @@ function StorageConnectionCard({
2334
2642
  "aria-label": `Status: ${status}`
2335
2643
  }
2336
2644
  ),
2337
- /* @__PURE__ */ jsx32("span", { className: "min-w-0 flex-1 line-clamp-2 text-sm font-medium text-[var(--color-text-primary)]", children: name }),
2338
- onInfo && /* @__PURE__ */ jsx32(
2339
- IconButton,
2645
+ /* @__PURE__ */ jsx37("span", { className: "min-w-0 flex-1 line-clamp-2 text-sm font-medium text-[var(--color-text-primary)]", children: name }),
2646
+ onInfo && /* @__PURE__ */ jsx37(
2647
+ "span",
2340
2648
  {
2341
- icon: Info2,
2342
- "aria-label": "Connection info",
2343
- variant: "ghost",
2344
- size: "sm",
2345
- className: "shrink-0 -mt-1 -mr-1",
2346
- onPress: () => {
2347
- onInfo();
2348
- }
2649
+ onClick: handleInfoPress,
2650
+ onKeyDown: (e) => {
2651
+ if (e.key === "Enter" || e.key === " ") {
2652
+ handleInfoPress(e);
2653
+ }
2654
+ },
2655
+ role: "presentation",
2656
+ children: /* @__PURE__ */ jsx37(
2657
+ IconButton,
2658
+ {
2659
+ icon: Info3,
2660
+ "aria-label": "Connection info",
2661
+ variant: "ghost",
2662
+ size: "sm",
2663
+ className: "shrink-0 -mt-1 -mr-1",
2664
+ onPress: onInfo
2665
+ }
2666
+ )
2349
2667
  }
2350
2668
  )
2351
2669
  ] }),
2352
- (provider || imageCount != null && (!status || status === "connected")) && /* @__PURE__ */ jsxs21("div", { className: twMerge9("flex items-center gap-2", status && "pl-4"), children: [
2353
- provider && /* @__PURE__ */ jsx32(ProviderBadge, { provider }),
2354
- provider && region && /* @__PURE__ */ jsx32("span", { className: "shrink-0 text-xs text-[var(--color-text-secondary)]", children: region }),
2355
- imageCount != null && (!status || status === "connected") && /* @__PURE__ */ jsxs21("span", { className: "ml-auto shrink-0 text-xs tabular-nums text-[var(--color-text-tertiary)]", children: [
2670
+ (provider || imageCount != null && (!status || status === "connected")) && /* @__PURE__ */ jsxs24("div", { className: twMerge9("flex items-center gap-2", status && "pl-4"), children: [
2671
+ provider && /* @__PURE__ */ jsx37(ProviderBadge, { provider }),
2672
+ provider && region && /* @__PURE__ */ jsx37("span", { className: "shrink-0 text-xs text-[var(--color-text-secondary)]", children: region }),
2673
+ imageCount != null && (!status || status === "connected") && /* @__PURE__ */ jsxs24("span", { className: "ml-auto shrink-0 text-xs tabular-nums text-[var(--color-text-secondary)]", children: [
2356
2674
  imageCount,
2357
2675
  " ",
2358
2676
  imageCount === 1 ? "image" : "images"
@@ -2364,18 +2682,32 @@ function StorageConnectionCard({
2364
2682
  "flex flex-col overflow-hidden rounded-[var(--border-radius-lg)]",
2365
2683
  "border border-[var(--color-border-default)]",
2366
2684
  "shadow-sm transition-all",
2367
- href && "hover:border-[var(--color-border-focus)] hover:shadow-md cursor-pointer",
2685
+ isInteractive && "hover:border-[var(--color-border-focus)] hover:shadow-md cursor-pointer",
2686
+ isInteractive && "focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)] focus-visible:ring-offset-2 outline-none",
2368
2687
  className
2369
2688
  );
2370
2689
  if (href) {
2371
- return /* @__PURE__ */ jsx32("a", { href, className: twMerge9(baseStyles, "no-underline"), children: cardContent });
2690
+ return /* @__PURE__ */ jsx37("a", { href, className: twMerge9(baseStyles, "no-underline"), children: cardContent });
2691
+ }
2692
+ if (onPress) {
2693
+ return /* @__PURE__ */ jsx37(
2694
+ "div",
2695
+ {
2696
+ role: "button",
2697
+ tabIndex: 0,
2698
+ className: baseStyles,
2699
+ onClick: onPress,
2700
+ onKeyDown: handleKeyDown,
2701
+ children: cardContent
2702
+ }
2703
+ );
2372
2704
  }
2373
- return /* @__PURE__ */ jsx32("div", { className: baseStyles, children: cardContent });
2705
+ return /* @__PURE__ */ jsx37("div", { className: baseStyles, children: cardContent });
2374
2706
  }
2375
2707
 
2376
2708
  // src/components/Badge/Badge.tsx
2377
2709
  import { twMerge as twMerge10 } from "tailwind-merge";
2378
- import { jsx as jsx33, jsxs as jsxs22 } from "react/jsx-runtime";
2710
+ import { jsx as jsx38, jsxs as jsxs25 } from "react/jsx-runtime";
2379
2711
  var variantStyles4 = {
2380
2712
  neutral: "bg-[var(--color-badge-neutral-bg)] text-[var(--color-badge-neutral-text)]",
2381
2713
  purple: "bg-[var(--color-badge-purple-bg)] text-[var(--color-badge-purple-text)]",
@@ -2400,7 +2732,7 @@ function Badge({
2400
2732
  icon: IconComponent,
2401
2733
  className
2402
2734
  }) {
2403
- return /* @__PURE__ */ jsxs22(
2735
+ return /* @__PURE__ */ jsxs25(
2404
2736
  "span",
2405
2737
  {
2406
2738
  className: twMerge10(
@@ -2411,7 +2743,7 @@ function Badge({
2411
2743
  className
2412
2744
  ),
2413
2745
  children: [
2414
- IconComponent && /* @__PURE__ */ jsx33(IconComponent, { size: iconSizeMap4[size], "aria-hidden": "true" }),
2746
+ IconComponent && /* @__PURE__ */ jsx38(IconComponent, { size: iconSizeMap4[size], "aria-hidden": "true" }),
2415
2747
  children
2416
2748
  ]
2417
2749
  }
@@ -2419,8 +2751,9 @@ function Badge({
2419
2751
  }
2420
2752
 
2421
2753
  // src/components/Card/Card.tsx
2754
+ import { useCallback as useCallback5 } from "react";
2422
2755
  import { twMerge as twMerge11 } from "tailwind-merge";
2423
- import { Fragment as Fragment9, jsx as jsx34, jsxs as jsxs23 } from "react/jsx-runtime";
2756
+ import { Fragment as Fragment10, jsx as jsx39, jsxs as jsxs26 } from "react/jsx-runtime";
2424
2757
  var paddingStyles = {
2425
2758
  none: "p-0",
2426
2759
  sm: "p-3",
@@ -2433,18 +2766,28 @@ function Card({
2433
2766
  footer,
2434
2767
  padding = "md",
2435
2768
  href,
2769
+ onPress,
2436
2770
  interactive = false,
2437
2771
  className
2438
2772
  }) {
2439
- const isInteractive = interactive || !!href;
2773
+ const isInteractive = interactive || !!href || !!onPress;
2440
2774
  const containerClass = twMerge11(
2441
2775
  "bg-[var(--color-surface-default)] border border-[var(--color-border-default)] rounded-[var(--border-radius-lg)] overflow-hidden shadow-sm",
2442
- isInteractive && "transition-shadow hover:shadow-md hover:border-[var(--color-border-focus)] cursor-pointer",
2443
- href && "block focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)] focus-visible:ring-offset-2 outline-none",
2776
+ isInteractive && "transition-all hover:shadow-md hover:border-[var(--color-border-focus)] cursor-pointer",
2777
+ (href || onPress) && "block focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)] focus-visible:ring-offset-2 outline-none",
2444
2778
  className
2445
2779
  );
2446
- const content = /* @__PURE__ */ jsxs23(Fragment9, { children: [
2447
- header && /* @__PURE__ */ jsx34(
2780
+ const handleKeyDown = useCallback5(
2781
+ (e) => {
2782
+ if (onPress && (e.key === "Enter" || e.key === " ")) {
2783
+ e.preventDefault();
2784
+ onPress();
2785
+ }
2786
+ },
2787
+ [onPress]
2788
+ );
2789
+ const content = /* @__PURE__ */ jsxs26(Fragment10, { children: [
2790
+ header && /* @__PURE__ */ jsx39(
2448
2791
  "div",
2449
2792
  {
2450
2793
  className: twMerge11(
@@ -2454,8 +2797,8 @@ function Card({
2454
2797
  children: header
2455
2798
  }
2456
2799
  ),
2457
- /* @__PURE__ */ jsx34("div", { className: paddingStyles[padding], children }),
2458
- footer && /* @__PURE__ */ jsx34(
2800
+ /* @__PURE__ */ jsx39("div", { className: paddingStyles[padding], children }),
2801
+ footer && /* @__PURE__ */ jsx39(
2459
2802
  "div",
2460
2803
  {
2461
2804
  className: twMerge11(
@@ -2467,15 +2810,28 @@ function Card({
2467
2810
  )
2468
2811
  ] });
2469
2812
  if (href) {
2470
- return /* @__PURE__ */ jsx34("a", { href, className: containerClass, children: content });
2813
+ return /* @__PURE__ */ jsx39("a", { href, className: containerClass, children: content });
2814
+ }
2815
+ if (onPress) {
2816
+ return /* @__PURE__ */ jsx39(
2817
+ "div",
2818
+ {
2819
+ role: "button",
2820
+ tabIndex: 0,
2821
+ className: containerClass,
2822
+ onClick: onPress,
2823
+ onKeyDown: handleKeyDown,
2824
+ children: content
2825
+ }
2826
+ );
2471
2827
  }
2472
- return /* @__PURE__ */ jsx34("div", { className: containerClass, children: content });
2828
+ return /* @__PURE__ */ jsx39("div", { className: containerClass, children: content });
2473
2829
  }
2474
2830
 
2475
2831
  // src/components/DeltaIndicator/DeltaIndicator.tsx
2476
2832
  import { ArrowUp, ArrowDown, Minus } from "lucide-react";
2477
2833
  import { twMerge as twMerge12 } from "tailwind-merge";
2478
- import { jsx as jsx35, jsxs as jsxs24 } from "react/jsx-runtime";
2834
+ import { jsx as jsx40, jsxs as jsxs27 } from "react/jsx-runtime";
2479
2835
  function getDirection(current, previous) {
2480
2836
  const diff = current - previous;
2481
2837
  if (diff > 0) return "increase";
@@ -2528,7 +2884,7 @@ function DeltaIndicator({
2528
2884
  className
2529
2885
  }) {
2530
2886
  if (unavailable) {
2531
- return /* @__PURE__ */ jsxs24(
2887
+ return /* @__PURE__ */ jsxs27(
2532
2888
  "span",
2533
2889
  {
2534
2890
  className: twMerge12(
@@ -2537,7 +2893,7 @@ function DeltaIndicator({
2537
2893
  className
2538
2894
  ),
2539
2895
  children: [
2540
- label && /* @__PURE__ */ jsx35("span", { className: "text-[length:var(--font-size-sm)] text-[var(--color-text-secondary)] mr-1", children: label }),
2896
+ label && /* @__PURE__ */ jsx40("span", { className: "text-[length:var(--font-size-sm)] text-[var(--color-text-secondary)] mr-1", children: label }),
2541
2897
  unavailableText
2542
2898
  ]
2543
2899
  }
@@ -2567,7 +2923,7 @@ function DeltaIndicator({
2567
2923
  }
2568
2924
  }
2569
2925
  const isPill = mode === "pill";
2570
- return /* @__PURE__ */ jsxs24(
2926
+ return /* @__PURE__ */ jsxs27(
2571
2927
  "span",
2572
2928
  {
2573
2929
  className: twMerge12(
@@ -2581,8 +2937,8 @@ function DeltaIndicator({
2581
2937
  className
2582
2938
  ),
2583
2939
  children: [
2584
- label && /* @__PURE__ */ jsx35("span", { className: "text-[length:var(--font-size-sm)] text-[var(--color-text-secondary)] mr-1", children: label }),
2585
- /* @__PURE__ */ jsx35(IconComponent, { size: 14, "aria-hidden": true }),
2940
+ label && /* @__PURE__ */ jsx40("span", { className: "text-[length:var(--font-size-sm)] text-[var(--color-text-secondary)] mr-1", children: label }),
2941
+ /* @__PURE__ */ jsx40(IconComponent, { size: 14, "aria-hidden": true }),
2586
2942
  valueText
2587
2943
  ]
2588
2944
  }
@@ -2591,7 +2947,7 @@ function DeltaIndicator({
2591
2947
 
2592
2948
  // src/components/ProgressBar/ProgressBar.tsx
2593
2949
  import { twMerge as twMerge13 } from "tailwind-merge";
2594
- import { jsx as jsx36, jsxs as jsxs25 } from "react/jsx-runtime";
2950
+ import { jsx as jsx41, jsxs as jsxs28 } from "react/jsx-runtime";
2595
2951
  var fillStyles = {
2596
2952
  brand: "bg-[var(--color-progress-fill)]",
2597
2953
  success: "bg-[var(--color-progress-fill-success)]",
@@ -2614,12 +2970,12 @@ function ProgressBar({
2614
2970
  className
2615
2971
  }) {
2616
2972
  const clampedValue = Math.min(100, Math.max(0, value));
2617
- return /* @__PURE__ */ jsxs25("div", { className: twMerge13("w-full", className), children: [
2618
- (label || description || showValue) && /* @__PURE__ */ jsxs25("div", { className: "flex items-center justify-between mb-2", children: [
2619
- /* @__PURE__ */ jsx36("span", { className: "text-[length:var(--font-size-sm)] font-[number:var(--font-weight-medium)] text-[var(--color-text-primary)]", children: label }),
2620
- /* @__PURE__ */ jsx36("span", { className: "text-[length:var(--font-size-sm)] text-[var(--color-text-secondary)]", children: description ?? (showValue ? `${clampedValue}%` : null) })
2973
+ return /* @__PURE__ */ jsxs28("div", { className: twMerge13("w-full", className), children: [
2974
+ (label || description || showValue) && /* @__PURE__ */ jsxs28("div", { className: "flex items-center justify-between mb-2", children: [
2975
+ /* @__PURE__ */ jsx41("span", { className: "text-[length:var(--font-size-sm)] font-[number:var(--font-weight-medium)] text-[var(--color-text-primary)]", children: label }),
2976
+ /* @__PURE__ */ jsx41("span", { className: "text-[length:var(--font-size-sm)] text-[var(--color-text-secondary)]", children: description ?? (showValue ? `${clampedValue}%` : null) })
2621
2977
  ] }),
2622
- /* @__PURE__ */ jsx36(
2978
+ /* @__PURE__ */ jsx41(
2623
2979
  "div",
2624
2980
  {
2625
2981
  role: "progressbar",
@@ -2631,7 +2987,7 @@ function ProgressBar({
2631
2987
  "w-full rounded-[var(--border-radius-full)] bg-[var(--color-progress-track)]",
2632
2988
  sizeStyles8[size]
2633
2989
  ),
2634
- children: /* @__PURE__ */ jsx36(
2990
+ children: /* @__PURE__ */ jsx41(
2635
2991
  "div",
2636
2992
  {
2637
2993
  className: twMerge13(
@@ -2649,17 +3005,17 @@ function ProgressBar({
2649
3005
  // src/components/Banner/Banner.tsx
2650
3006
  import { useState as useState3 } from "react";
2651
3007
  import {
2652
- Info as Info3,
3008
+ Info as Info4,
2653
3009
  AlertTriangle,
2654
3010
  AlertCircle as AlertCircle2,
2655
3011
  CheckCircle2,
2656
3012
  X as X3
2657
3013
  } from "lucide-react";
2658
3014
  import { twMerge as twMerge14 } from "tailwind-merge";
2659
- import { jsx as jsx37, jsxs as jsxs26 } from "react/jsx-runtime";
3015
+ import { jsx as jsx42, jsxs as jsxs29 } from "react/jsx-runtime";
2660
3016
  var variantConfig2 = {
2661
3017
  info: {
2662
- icon: Info3,
3018
+ icon: Info4,
2663
3019
  containerClass: "bg-[var(--color-banner-info-bg)] border-[var(--color-banner-info-border)] text-[var(--color-banner-info-text)]",
2664
3020
  iconClass: "text-[var(--color-banner-info-icon)]",
2665
3021
  role: "status"
@@ -2700,7 +3056,7 @@ function Banner({
2700
3056
  setDismissed(true);
2701
3057
  onDismiss?.();
2702
3058
  };
2703
- return /* @__PURE__ */ jsxs26(
3059
+ return /* @__PURE__ */ jsxs29(
2704
3060
  "div",
2705
3061
  {
2706
3062
  role: config.role,
@@ -2711,7 +3067,7 @@ function Banner({
2711
3067
  className
2712
3068
  ),
2713
3069
  children: [
2714
- /* @__PURE__ */ jsx37(
3070
+ /* @__PURE__ */ jsx42(
2715
3071
  IconComponent,
2716
3072
  {
2717
3073
  size: 20,
@@ -2719,21 +3075,21 @@ function Banner({
2719
3075
  "aria-hidden": "true"
2720
3076
  }
2721
3077
  ),
2722
- /* @__PURE__ */ jsxs26("div", { className: "flex-1", children: [
2723
- title && /* @__PURE__ */ jsxs26("span", { className: "font-[number:var(--font-weight-medium)]", children: [
3078
+ /* @__PURE__ */ jsxs29("div", { className: "flex-1", children: [
3079
+ title && /* @__PURE__ */ jsxs29("span", { className: "font-[number:var(--font-weight-medium)]", children: [
2724
3080
  title,
2725
3081
  " \u2014 "
2726
3082
  ] }),
2727
3083
  children
2728
3084
  ] }),
2729
- dismissible && /* @__PURE__ */ jsx37(
3085
+ dismissible && /* @__PURE__ */ jsx42(
2730
3086
  "button",
2731
3087
  {
2732
3088
  type: "button",
2733
3089
  onClick: handleDismiss,
2734
3090
  className: "shrink-0 rounded-[var(--border-radius-sm)] p-0.5 opacity-70 hover:opacity-100 transition-opacity outline-none focus-visible:ring-2 focus-visible:ring-current",
2735
3091
  "aria-label": "Dismiss",
2736
- children: /* @__PURE__ */ jsx37(X3, { size: 16, "aria-hidden": "true" })
3092
+ children: /* @__PURE__ */ jsx42(X3, { size: 16, "aria-hidden": "true" })
2737
3093
  }
2738
3094
  )
2739
3095
  ]
@@ -2743,7 +3099,7 @@ function Banner({
2743
3099
 
2744
3100
  // src/components/MetricCard/MetricCard.tsx
2745
3101
  import { twMerge as twMerge15 } from "tailwind-merge";
2746
- import { Fragment as Fragment10, jsx as jsx38, jsxs as jsxs27 } from "react/jsx-runtime";
3102
+ import { Fragment as Fragment11, jsx as jsx43, jsxs as jsxs30 } from "react/jsx-runtime";
2747
3103
  var sizeConfig = {
2748
3104
  sm: {
2749
3105
  padding: "p-3",
@@ -2771,9 +3127,9 @@ function MetricCard({
2771
3127
  href && "block transition-shadow hover:shadow-md hover:border-[var(--color-border-focus)] focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)] focus-visible:ring-offset-2 outline-none",
2772
3128
  className
2773
3129
  );
2774
- const content = /* @__PURE__ */ jsxs27(Fragment10, { children: [
2775
- /* @__PURE__ */ jsx38("div", { className: twMerge15(config.labelClass, "text-[var(--color-text-secondary)]"), children: label }),
2776
- /* @__PURE__ */ jsx38(
3130
+ const content = /* @__PURE__ */ jsxs30(Fragment11, { children: [
3131
+ /* @__PURE__ */ jsx43("div", { className: twMerge15(config.labelClass, "text-[var(--color-text-secondary)]"), children: label }),
3132
+ /* @__PURE__ */ jsx43(
2777
3133
  "div",
2778
3134
  {
2779
3135
  className: twMerge15(
@@ -2783,23 +3139,23 @@ function MetricCard({
2783
3139
  children: value
2784
3140
  }
2785
3141
  ),
2786
- secondary && /* @__PURE__ */ jsx38("div", { className: "mt-1 text-sm", children: secondary })
3142
+ secondary && /* @__PURE__ */ jsx43("div", { className: "mt-1 text-sm", children: secondary })
2787
3143
  ] });
2788
3144
  if (href) {
2789
- return /* @__PURE__ */ jsx38("a", { href, className: containerClass, children: content });
3145
+ return /* @__PURE__ */ jsx43("a", { href, className: containerClass, children: content });
2790
3146
  }
2791
- return /* @__PURE__ */ jsx38("div", { className: containerClass, children: content });
3147
+ return /* @__PURE__ */ jsx43("div", { className: containerClass, children: content });
2792
3148
  }
2793
3149
 
2794
3150
  // src/components/SectionHeader/SectionHeader.tsx
2795
3151
  import { twMerge as twMerge16 } from "tailwind-merge";
2796
- import { jsx as jsx39, jsxs as jsxs28 } from "react/jsx-runtime";
3152
+ import { jsx as jsx44, jsxs as jsxs31 } from "react/jsx-runtime";
2797
3153
  function SectionHeader({
2798
3154
  title,
2799
3155
  children,
2800
3156
  className
2801
3157
  }) {
2802
- return /* @__PURE__ */ jsxs28(
3158
+ return /* @__PURE__ */ jsxs31(
2803
3159
  "div",
2804
3160
  {
2805
3161
  className: twMerge16(
@@ -2807,16 +3163,16 @@ function SectionHeader({
2807
3163
  className
2808
3164
  ),
2809
3165
  children: [
2810
- /* @__PURE__ */ jsx39(H2, { children: title }),
2811
- children && /* @__PURE__ */ jsx39("div", { className: "ml-auto flex flex-wrap items-center gap-[var(--spacing-2)]", children })
3166
+ /* @__PURE__ */ jsx44(H2, { children: title }),
3167
+ children && /* @__PURE__ */ jsx44("div", { className: "ml-auto flex flex-wrap items-center gap-[var(--spacing-2)]", children })
2812
3168
  ]
2813
3169
  }
2814
3170
  );
2815
3171
  }
2816
3172
 
2817
3173
  // src/components/FormWizard/FormWizard.tsx
2818
- import { createContext as createContext5, useContext as useContext5, useCallback as useCallback3, useMemo } from "react";
2819
- import { jsx as jsx40 } from "react/jsx-runtime";
3174
+ import { createContext as createContext5, useContext as useContext5, useCallback as useCallback6, useMemo } from "react";
3175
+ import { jsx as jsx45 } from "react/jsx-runtime";
2820
3176
  var FormWizardContext = createContext5({
2821
3177
  currentStep: 0,
2822
3178
  totalSteps: 1,
@@ -2836,7 +3192,7 @@ function FormWizard({
2836
3192
  }) {
2837
3193
  const canGoBack = currentStep > 0;
2838
3194
  const isLastStep = currentStep >= totalSteps - 1;
2839
- const goBack = useCallback3(() => {
3195
+ const goBack = useCallback6(() => {
2840
3196
  if (currentStep > 0) {
2841
3197
  onStepChange(currentStep - 1);
2842
3198
  }
@@ -2851,13 +3207,13 @@ function FormWizard({
2851
3207
  }),
2852
3208
  [currentStep, totalSteps, canGoBack, goBack, isLastStep]
2853
3209
  );
2854
- return /* @__PURE__ */ jsx40(FormWizardContext.Provider, { value, children });
3210
+ return /* @__PURE__ */ jsx45(FormWizardContext.Provider, { value, children });
2855
3211
  }
2856
3212
 
2857
3213
  // src/components/FormWizard/FormWizardProgress.tsx
2858
- import { jsx as jsx41, jsxs as jsxs29 } from "react/jsx-runtime";
3214
+ import { jsx as jsx46, jsxs as jsxs32 } from "react/jsx-runtime";
2859
3215
  function CheckIcon2() {
2860
- return /* @__PURE__ */ jsx41(
3216
+ return /* @__PURE__ */ jsx46(
2861
3217
  "svg",
2862
3218
  {
2863
3219
  "aria-hidden": "true",
@@ -2868,24 +3224,24 @@ function CheckIcon2() {
2868
3224
  strokeWidth: "2",
2869
3225
  strokeLinecap: "round",
2870
3226
  strokeLinejoin: "round",
2871
- children: /* @__PURE__ */ jsx41("path", { d: "M3 8.5l3.5 3.5 6.5-7" })
3227
+ children: /* @__PURE__ */ jsx46("path", { d: "M3 8.5l3.5 3.5 6.5-7" })
2872
3228
  }
2873
3229
  );
2874
3230
  }
2875
3231
  function FormWizardProgress({ labels }) {
2876
3232
  const { currentStep, totalSteps } = useFormWizard();
2877
- return /* @__PURE__ */ jsx41("nav", { "aria-label": "Form progress", children: /* @__PURE__ */ jsx41("ol", { className: "flex items-start", role: "list", children: labels.map((label, index) => {
3233
+ return /* @__PURE__ */ jsx46("nav", { "aria-label": "Form progress", children: /* @__PURE__ */ jsx46("ol", { className: "flex items-start", role: "list", children: labels.map((label, index) => {
2878
3234
  const isCompleted = index < currentStep;
2879
3235
  const isCurrent = index === currentStep;
2880
3236
  const isFuture = index > currentStep;
2881
- return /* @__PURE__ */ jsxs29(
3237
+ return /* @__PURE__ */ jsxs32(
2882
3238
  "li",
2883
3239
  {
2884
3240
  className: "flex flex-1 flex-col items-center",
2885
3241
  "aria-current": isCurrent ? "step" : void 0,
2886
3242
  children: [
2887
- /* @__PURE__ */ jsxs29("div", { className: "flex w-full items-center", children: [
2888
- index > 0 ? /* @__PURE__ */ jsx41(
3243
+ /* @__PURE__ */ jsxs32("div", { className: "flex w-full items-center", children: [
3244
+ index > 0 ? /* @__PURE__ */ jsx46(
2889
3245
  "div",
2890
3246
  {
2891
3247
  "aria-hidden": "true",
@@ -2894,8 +3250,8 @@ function FormWizardProgress({ labels }) {
2894
3250
  index <= currentStep ? "bg-[var(--color-brand-primary)]" : "bg-[var(--color-border-default)]"
2895
3251
  ].join(" ")
2896
3252
  }
2897
- ) : /* @__PURE__ */ jsx41("div", { className: "flex-1", "aria-hidden": "true" }),
2898
- /* @__PURE__ */ jsx41(
3253
+ ) : /* @__PURE__ */ jsx46("div", { className: "flex-1", "aria-hidden": "true" }),
3254
+ /* @__PURE__ */ jsx46(
2899
3255
  "div",
2900
3256
  {
2901
3257
  className: [
@@ -2907,10 +3263,10 @@ function FormWizardProgress({ labels }) {
2907
3263
  isFuture ? "border-2 border-[var(--color-border-default)] bg-[var(--color-surface-default)] text-[var(--color-text-tertiary)]" : ""
2908
3264
  ].join(" "),
2909
3265
  "aria-hidden": "true",
2910
- children: isCompleted ? /* @__PURE__ */ jsx41(CheckIcon2, {}) : index + 1
3266
+ children: isCompleted ? /* @__PURE__ */ jsx46(CheckIcon2, {}) : index + 1
2911
3267
  }
2912
3268
  ),
2913
- index < totalSteps - 1 ? /* @__PURE__ */ jsx41(
3269
+ index < totalSteps - 1 ? /* @__PURE__ */ jsx46(
2914
3270
  "div",
2915
3271
  {
2916
3272
  "aria-hidden": "true",
@@ -2919,9 +3275,9 @@ function FormWizardProgress({ labels }) {
2919
3275
  index < currentStep ? "bg-[var(--color-brand-primary)]" : "bg-[var(--color-border-default)]"
2920
3276
  ].join(" ")
2921
3277
  }
2922
- ) : /* @__PURE__ */ jsx41("div", { className: "flex-1", "aria-hidden": "true" })
3278
+ ) : /* @__PURE__ */ jsx46("div", { className: "flex-1", "aria-hidden": "true" })
2923
3279
  ] }),
2924
- /* @__PURE__ */ jsx41(
3280
+ /* @__PURE__ */ jsx46(
2925
3281
  "span",
2926
3282
  {
2927
3283
  className: [
@@ -2939,15 +3295,15 @@ function FormWizardProgress({ labels }) {
2939
3295
  }
2940
3296
 
2941
3297
  // src/components/FormWizard/FormWizardNav.tsx
2942
- import { jsx as jsx42, jsxs as jsxs30 } from "react/jsx-runtime";
3298
+ import { jsx as jsx47, jsxs as jsxs33 } from "react/jsx-runtime";
2943
3299
  function FormWizardNav({
2944
3300
  onNext,
2945
3301
  isSubmitting = false,
2946
3302
  submitLabel = "Submit"
2947
3303
  }) {
2948
3304
  const { canGoBack, goBack, isLastStep } = useFormWizard();
2949
- return /* @__PURE__ */ jsxs30("div", { className: "flex items-center justify-end gap-[var(--spacing-3)]", children: [
2950
- canGoBack && /* @__PURE__ */ jsx42(
3305
+ return /* @__PURE__ */ jsxs33("div", { className: "flex items-center justify-end gap-[var(--spacing-3)]", children: [
3306
+ canGoBack && /* @__PURE__ */ jsx47(
2951
3307
  Button,
2952
3308
  {
2953
3309
  variant: "secondary",
@@ -2957,7 +3313,7 @@ function FormWizardNav({
2957
3313
  children: "Back"
2958
3314
  }
2959
3315
  ),
2960
- /* @__PURE__ */ jsx42(
3316
+ /* @__PURE__ */ jsx47(
2961
3317
  Button,
2962
3318
  {
2963
3319
  variant: "primary",
@@ -3364,6 +3720,8 @@ export {
3364
3720
  EmptyState,
3365
3721
  Field,
3366
3722
  Fieldset,
3723
+ FileCard,
3724
+ FileIcon,
3367
3725
  FontSize2xl,
3368
3726
  FontSize3xl,
3369
3727
  FontSize4xl,
@@ -3400,6 +3758,10 @@ export {
3400
3758
  LineHeightTight,
3401
3759
  Link,
3402
3760
  Menu,
3761
+ MenuHeader,
3762
+ MenuItem,
3763
+ MenuSection,
3764
+ MenuSeparator,
3403
3765
  MetricCard,
3404
3766
  Pill,
3405
3767
  Popover3 as Popover,
@@ -3442,6 +3804,8 @@ export {
3442
3804
  TabPanel2 as UnstyledTabPanel,
3443
3805
  Tabs2 as UnstyledTabs,
3444
3806
  createToastBridge,
3807
+ getFileIcon,
3808
+ getTypeLabel,
3445
3809
  pillColorFromName,
3446
3810
  useFormWizard,
3447
3811
  useInputGroup,