@cytario/design 1.9.0 → 1.11.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.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { ButtonProps as ButtonProps$1, TextFieldProps, SelectProps as SelectProps$1, CellProps, ColumnProps, TableProps, RowProps, TableBodyProps, TableHeaderProps, CheckboxProps as CheckboxProps$1, SwitchProps as SwitchProps$1, RadioProps as RadioProps$1, RadioGroupProps as RadioGroupProps$1, LabelProps as LabelProps$1, LinkProps as LinkProps$1, ToggleButtonProps as ToggleButtonProps$1, PopoverProps as PopoverProps$1, TabProps as TabProps$1, TabListProps as TabListProps$1, TabPanelProps as TabPanelProps$1, TabsProps as TabsProps$1 } from 'react-aria-components';
2
- export { Key, RouterConfig, RouterProvider } from 'react-aria-components';
1
+ import { ButtonProps as ButtonProps$1, TextFieldProps, SelectProps as SelectProps$1, CellProps, ColumnProps, TableProps, RowProps, TableBodyProps, TableHeaderProps, CheckboxProps as CheckboxProps$1, SwitchProps as SwitchProps$1, RadioProps as RadioProps$1, RadioGroupProps as RadioGroupProps$1, LabelProps as LabelProps$1, LinkProps as LinkProps$1, ToggleButtonProps as ToggleButtonProps$1, PopoverProps as PopoverProps$1, TabProps as TabProps$1, TabListProps as TabListProps$1, TabPanelProps as TabPanelProps$1, TabsProps as TabsProps$1, ToggleButtonGroupProps, Key } from 'react-aria-components';
2
+ export { Key, RouterConfig, RouterProvider, Tab as UnstyledTab, TabList as UnstyledTabList, TabPanel as UnstyledTabPanel, Tabs as UnstyledTabs } from 'react-aria-components';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import { LucideIcon } from 'lucide-react';
5
5
  import * as React$1 from 'react';
@@ -137,10 +137,12 @@ interface DialogProps {
137
137
  onOpenChange: (isOpen: boolean) => void;
138
138
  title: string;
139
139
  size?: "sm" | "md" | "lg" | "xl";
140
+ /** Whether clicking outside the dialog dismisses it. Defaults to true. */
141
+ isDismissable?: boolean;
140
142
  children: React__default.ReactNode;
141
143
  className?: string;
142
144
  }
143
- declare function Dialog({ isOpen, onOpenChange, title, size, children, className, }: DialogProps): react_jsx_runtime.JSX.Element;
145
+ declare function Dialog({ isOpen, onOpenChange, title, size, isDismissable, children, className, }: DialogProps): react_jsx_runtime.JSX.Element;
144
146
 
145
147
  type ToastVariant = "success" | "error" | "info";
146
148
  interface ToastData {
@@ -408,7 +410,7 @@ declare function PopoverTrigger({ children, className }: PopoverTriggerProps): r
408
410
  */
409
411
  declare function PopoverContent({ placement, offset: offsetPx, className, children, }: PopoverContentProps): react_jsx_runtime.JSX.Element;
410
412
 
411
- type TabsVariant = "underline" | "pills";
413
+ type TabsVariant = "underline" | "pills" | "unstyled";
412
414
  type TabsSize = "sm" | "md" | "lg";
413
415
  interface TabsProps extends Omit<TabsProps$1, "className" | "orientation"> {
414
416
  /** Visual style variant */
@@ -452,6 +454,10 @@ interface TreeProps<T extends TreeNode = TreeNode> {
452
454
  selectedIds?: Set<string>;
453
455
  onSelectionChange?: (ids: Set<string>) => void;
454
456
  onActivate?: (node: T) => void;
457
+ /** Called when the pointer enters a tree node row. */
458
+ onHover?: (node: T) => void;
459
+ /** Called when the pointer leaves a tree node row. */
460
+ onHoverEnd?: (node: T) => void;
455
461
  openByDefault?: boolean;
456
462
  searchTerm?: string;
457
463
  searchMatch?: (node: T, term: string) => boolean;
@@ -462,7 +468,55 @@ interface TreeProps<T extends TreeNode = TreeNode> {
462
468
  treeRef?: React.Ref<TreeApi<T>>;
463
469
  className?: string;
464
470
  }
465
- declare function Tree<T extends TreeNode = TreeNode>({ data, "aria-label": ariaLabel, size, selectionMode, selectedIds, onSelectionChange, onActivate, openByDefault, searchTerm, searchMatch, height, indent, disableDrag, disableDrop, treeRef, className, }: TreeProps<T>): react_jsx_runtime.JSX.Element;
471
+ declare function Tree<T extends TreeNode = TreeNode>({ data, "aria-label": ariaLabel, size, selectionMode, selectedIds, onSelectionChange, onActivate, onHover, onHoverEnd, openByDefault, searchTerm, searchMatch, height, indent, disableDrag, disableDrop, treeRef, className, }: TreeProps<T>): react_jsx_runtime.JSX.Element;
472
+
473
+ type SegmentedControlSize = "sm" | "md" | "lg";
474
+ type SegmentedControlSelectionMode = "single" | "none";
475
+ interface SegmentedControlProps extends Omit<ToggleButtonGroupProps, "className" | "selectionMode" | "selectedKeys" | "defaultSelectedKeys" | "onSelectionChange"> {
476
+ /** Size preset for all items */
477
+ size?: SegmentedControlSize;
478
+ /** Selection behavior: "single" keeps one item selected, "none" means buttons fire actions without staying selected */
479
+ selectionMode?: SegmentedControlSelectionMode;
480
+ /** The currently selected keys (controlled, only for selectionMode="single") */
481
+ selectedKeys?: Iterable<Key>;
482
+ /** The initial selected keys (uncontrolled, only for selectionMode="single") */
483
+ defaultSelectedKeys?: Iterable<Key>;
484
+ /** Called when selection changes (only for selectionMode="single") */
485
+ onSelectionChange?: (keys: Set<Key>) => void;
486
+ /** Additional CSS classes */
487
+ className?: string;
488
+ children: ReactNode;
489
+ }
490
+ declare function SegmentedControl({ size, selectionMode, selectedKeys, defaultSelectedKeys, onSelectionChange, className, children, ...props }: SegmentedControlProps): react_jsx_runtime.JSX.Element;
491
+ interface SegmentedControlItemProps extends Omit<ToggleButtonProps$1, "className"> {
492
+ /** Additional CSS classes */
493
+ className?: string;
494
+ }
495
+ declare function SegmentedControlItem({ className, ...props }: SegmentedControlItemProps): react_jsx_runtime.JSX.Element;
496
+
497
+ interface StorageConnectionCardProps {
498
+ /** Display name for the connection */
499
+ name: string;
500
+ /** Cloud provider identifier (e.g., "aws", "minio", "azure", "gcp") */
501
+ provider: string;
502
+ /** AWS region or equivalent */
503
+ region?: string;
504
+ /** Connection health status */
505
+ status: "connected" | "error" | "loading";
506
+ /** Human-readable error message when status is "error" */
507
+ errorMessage?: string;
508
+ /** Number of viewable images in the bucket */
509
+ imageCount?: number;
510
+ /** Children rendered in the preview area (e.g., an actual tile viewer, or an img) */
511
+ children?: React__default.ReactNode;
512
+ /** Navigation target — clicking the card navigates here */
513
+ href?: string;
514
+ /** Info button handler */
515
+ onInfo?: () => void;
516
+ /** Additional CSS classes */
517
+ className?: string;
518
+ }
519
+ declare function StorageConnectionCard({ name, provider, region, status, errorMessage, imageCount, children, href, onInfo, className, }: StorageConnectionCardProps): react_jsx_runtime.JSX.Element;
466
520
 
467
521
  /**
468
522
  * Do not edit directly, this file was auto-generated.
@@ -608,4 +662,4 @@ declare const LineHeightTight = 1.25;
608
662
  declare const LineHeightNormal = 1.5;
609
663
  declare const LineHeightRelaxed = 1.625;
610
664
 
611
- export { BorderRadiusFull, BorderRadiusLg, BorderRadiusMd, BorderRadiusNone, BorderRadiusSm, BorderRadiusXl, type BreadcrumbItem, Breadcrumbs, type BreadcrumbsProps, Button, ButtonLink, type ButtonLinkProps, type ButtonProps, type ButtonSize, type ButtonVariant, Cell, Checkbox, type CheckboxProps, ColorActionDanger, ColorActionDangerHover, ColorActionDefault, ColorActionDefaultHover, ColorActionInfo, ColorActionInfoHover, ColorActionPrimary, ColorActionPrimaryActive, ColorActionPrimaryHover, ColorActionSecondary, ColorActionSecondaryHover, ColorActionSuccess, ColorActionSuccessHover, ColorBorderAccent, ColorBorderBrand, ColorBorderDanger, ColorBorderDefault, ColorBorderFocus, ColorBorderInfo, ColorBorderStrong, ColorBorderSuccess, ColorBorderWarning, ColorBrandAccent, ColorBrandPrimary, ColorGreen100, ColorGreen200, ColorGreen300, ColorGreen400, ColorGreen50, ColorGreen500, ColorGreen600, ColorGreen700, ColorGreen800, ColorGreen900, ColorNeutral0, ColorNeutral100, ColorNeutral1000, ColorNeutral200, ColorNeutral300, ColorNeutral400, ColorNeutral50, ColorNeutral500, ColorNeutral600, ColorNeutral700, ColorNeutral800, ColorNeutral900, ColorNeutral950, ColorOverlayBackdrop, ColorPurple100, ColorPurple200, ColorPurple300, ColorPurple400, ColorPurple50, ColorPurple500, ColorPurple600, ColorPurple700, ColorPurple800, ColorPurple900, ColorRose100, ColorRose200, ColorRose300, ColorRose400, ColorRose50, ColorRose500, ColorRose600, ColorRose700, ColorRose800, ColorRose900, ColorSlate100, ColorSlate200, ColorSlate300, ColorSlate400, ColorSlate50, ColorSlate500, ColorSlate600, ColorSlate700, ColorSlate800, ColorSlate900, ColorSurfaceAccent, ColorSurfaceBrand, ColorSurfaceDanger, ColorSurfaceDefault, ColorSurfaceInfo, ColorSurfaceMuted, ColorSurfaceOverlay, ColorSurfaceSubtle, ColorSurfaceSuccess, ColorSurfaceWarning, ColorTeal100, ColorTeal200, ColorTeal300, ColorTeal400, ColorTeal50, ColorTeal500, ColorTeal600, ColorTeal700, ColorTeal800, ColorTeal900, ColorTextAccent, ColorTextBrand, ColorTextDanger, ColorTextInfo, ColorTextInverse, ColorTextPrimary, ColorTextSecondary, ColorTextSuccess, ColorTextTertiary, ColorTextWarning, Column, type DataTableProps, Dialog, type DialogProps, EmptyState, type EmptyStateProps, Field, type FieldProps, Fieldset, type FieldsetProps, FontSize2xl, FontSize3xl, FontSize4xl, FontSize5xl, FontSizeBase, FontSizeLg, FontSizeSm, FontSizeXl, FontSizeXs, FontWeightBold, FontWeightExtrabold, FontWeightLight, FontWeightMedium, FontWeightRegular, FontWeightSemibold, type GroupPosition, H1, H2, H3, Heading, type HeadingLevel, type HeadingProps, type HeadingSize, Icon, IconButton, IconButtonLink, type IconButtonLinkProps, type IconButtonProps, type IconProps, Input, InputAddon, type InputAddonProps, InputGroup, InputGroupContext, type InputGroupProps, type InputProps, Label, type LabelProps, LineHeightNormal, LineHeightRelaxed, LineHeightTight, Link, type LinkProps, type LinkVariant, Menu, type MenuItemData, type MenuProps, Popover, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverTrigger, type PopoverTriggerProps, Radio, RadioButton, type RadioButtonProps, RadioGroup, type RadioGroupProps, type RadioProps, Row, Select, type SelectItem, type SelectProps, Spacing1, Spacing12, Spacing16, Spacing2, Spacing3, Spacing4, Spacing6, Spacing8, Spinner, type SpinnerProps, Switch, type SwitchProps, Tab, TabList, type TabListProps, TabPanel, type TabPanelProps, type TabProps, Table, TableBody, TableHeader, type TableSize, Tabs, type TabsProps, type TabsSize, type TabsVariant, type ToastBridge, type ToastContextValue, type ToastData, ToastProvider, type ToastVariant, ToggleButton, type ToggleButtonProps, type ToggleButtonSize, type ToggleButtonVariant, Tooltip, type TooltipProps, Tree, type TreeNode, type TreeProps, createToastBridge, useInputGroup, useToast };
665
+ export { BorderRadiusFull, BorderRadiusLg, BorderRadiusMd, BorderRadiusNone, BorderRadiusSm, BorderRadiusXl, type BreadcrumbItem, Breadcrumbs, type BreadcrumbsProps, Button, ButtonLink, type ButtonLinkProps, type ButtonProps, type ButtonSize, type ButtonVariant, Cell, Checkbox, type CheckboxProps, ColorActionDanger, ColorActionDangerHover, ColorActionDefault, ColorActionDefaultHover, ColorActionInfo, ColorActionInfoHover, ColorActionPrimary, ColorActionPrimaryActive, ColorActionPrimaryHover, ColorActionSecondary, ColorActionSecondaryHover, ColorActionSuccess, ColorActionSuccessHover, ColorBorderAccent, ColorBorderBrand, ColorBorderDanger, ColorBorderDefault, ColorBorderFocus, ColorBorderInfo, ColorBorderStrong, ColorBorderSuccess, ColorBorderWarning, ColorBrandAccent, ColorBrandPrimary, ColorGreen100, ColorGreen200, ColorGreen300, ColorGreen400, ColorGreen50, ColorGreen500, ColorGreen600, ColorGreen700, ColorGreen800, ColorGreen900, ColorNeutral0, ColorNeutral100, ColorNeutral1000, ColorNeutral200, ColorNeutral300, ColorNeutral400, ColorNeutral50, ColorNeutral500, ColorNeutral600, ColorNeutral700, ColorNeutral800, ColorNeutral900, ColorNeutral950, ColorOverlayBackdrop, ColorPurple100, ColorPurple200, ColorPurple300, ColorPurple400, ColorPurple50, ColorPurple500, ColorPurple600, ColorPurple700, ColorPurple800, ColorPurple900, ColorRose100, ColorRose200, ColorRose300, ColorRose400, ColorRose50, ColorRose500, ColorRose600, ColorRose700, ColorRose800, ColorRose900, ColorSlate100, ColorSlate200, ColorSlate300, ColorSlate400, ColorSlate50, ColorSlate500, ColorSlate600, ColorSlate700, ColorSlate800, ColorSlate900, ColorSurfaceAccent, ColorSurfaceBrand, ColorSurfaceDanger, ColorSurfaceDefault, ColorSurfaceInfo, ColorSurfaceMuted, ColorSurfaceOverlay, ColorSurfaceSubtle, ColorSurfaceSuccess, ColorSurfaceWarning, ColorTeal100, ColorTeal200, ColorTeal300, ColorTeal400, ColorTeal50, ColorTeal500, ColorTeal600, ColorTeal700, ColorTeal800, ColorTeal900, ColorTextAccent, ColorTextBrand, ColorTextDanger, ColorTextInfo, ColorTextInverse, ColorTextPrimary, ColorTextSecondary, ColorTextSuccess, ColorTextTertiary, ColorTextWarning, Column, type DataTableProps, Dialog, type DialogProps, EmptyState, type EmptyStateProps, Field, type FieldProps, Fieldset, type FieldsetProps, FontSize2xl, FontSize3xl, FontSize4xl, FontSize5xl, FontSizeBase, FontSizeLg, FontSizeSm, FontSizeXl, FontSizeXs, FontWeightBold, FontWeightExtrabold, FontWeightLight, FontWeightMedium, FontWeightRegular, FontWeightSemibold, type GroupPosition, H1, H2, H3, Heading, type HeadingLevel, type HeadingProps, type HeadingSize, Icon, IconButton, IconButtonLink, type IconButtonLinkProps, type IconButtonProps, type IconProps, Input, InputAddon, type InputAddonProps, InputGroup, InputGroupContext, type InputGroupProps, type InputProps, Label, type LabelProps, LineHeightNormal, LineHeightRelaxed, LineHeightTight, Link, type LinkProps, type LinkVariant, Menu, type MenuItemData, type MenuProps, Popover, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverTrigger, type PopoverTriggerProps, Radio, RadioButton, type RadioButtonProps, RadioGroup, type RadioGroupProps, type RadioProps, Row, SegmentedControl, SegmentedControlItem, type SegmentedControlItemProps, type SegmentedControlProps, type SegmentedControlSelectionMode, type SegmentedControlSize, Select, type SelectItem, type SelectProps, Spacing1, Spacing12, Spacing16, Spacing2, Spacing3, Spacing4, Spacing6, Spacing8, Spinner, type SpinnerProps, StorageConnectionCard, type StorageConnectionCardProps, Switch, type SwitchProps, Tab, TabList, type TabListProps, TabPanel, type TabPanelProps, type TabProps, Table, TableBody, TableHeader, type TableSize, Tabs, type TabsProps, type TabsSize, type TabsVariant, type ToastBridge, type ToastContextValue, type ToastData, ToastProvider, type ToastVariant, ToggleButton, type ToggleButtonProps, type ToggleButtonSize, type ToggleButtonVariant, Tooltip, type TooltipProps, Tree, type TreeNode, type TreeProps, createToastBridge, useInputGroup, useToast };
package/dist/index.js CHANGED
@@ -710,6 +710,7 @@ function Cell(props) {
710
710
  ...props,
711
711
  className: [
712
712
  "px-3 py-[var(--table-row-py)]",
713
+ "text-[var(--color-text-primary)]",
713
714
  "outline-none",
714
715
  "focus-visible:outline-2 focus-visible:outline-[var(--color-border-focus)] focus-visible:outline-offset-[-2px]"
715
716
  ].join(" ")
@@ -737,6 +738,7 @@ function Dialog({
737
738
  onOpenChange,
738
739
  title,
739
740
  size = "md",
741
+ isDismissable = true,
740
742
  children,
741
743
  className
742
744
  }) {
@@ -745,7 +747,7 @@ function Dialog({
745
747
  {
746
748
  isOpen,
747
749
  onOpenChange,
748
- isDismissable: true,
750
+ isDismissable,
749
751
  className: [
750
752
  "fixed inset-0 z-50 bg-[var(--color-overlay-backdrop)] backdrop-blur-sm",
751
753
  "flex items-center justify-center",
@@ -1701,6 +1703,7 @@ function PopoverContent({
1701
1703
 
1702
1704
  // src/components/Tabs/Tabs.tsx
1703
1705
  import { createContext as createContext3, useContext as useContext3 } from "react";
1706
+ import { twMerge as twMerge5 } from "tailwind-merge";
1704
1707
  import {
1705
1708
  Tabs as AriaTabs,
1706
1709
  TabList as AriaTabList,
@@ -1730,10 +1733,10 @@ function Tabs({
1730
1733
  {
1731
1734
  ...props,
1732
1735
  orientation,
1733
- className: [
1736
+ className: twMerge5(
1734
1737
  orientation === "vertical" ? "flex" : "",
1735
1738
  className
1736
- ].filter(Boolean).join(" "),
1739
+ ),
1737
1740
  children
1738
1741
  }
1739
1742
  ) });
@@ -1743,17 +1746,17 @@ function TabList({
1743
1746
  ...props
1744
1747
  }) {
1745
1748
  const { variant } = useContext3(TabsContext);
1746
- const baseStyles = 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";
1747
- const verticalStyles = variant === "underline" ? "flex-col border-b-0 border-r border-[var(--color-border-default)]" : "flex-col";
1749
+ 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
+ const verticalStyles = variant === "unstyled" ? "flex-col" : variant === "underline" ? "flex-col border-b-0 border-r border-[var(--color-border-default)]" : "flex-col";
1748
1751
  return /* @__PURE__ */ jsx27(
1749
1752
  AriaTabList,
1750
1753
  {
1751
1754
  ...props,
1752
- className: ({ orientation }) => [
1755
+ className: ({ orientation }) => twMerge5(
1753
1756
  baseStyles,
1754
1757
  orientation === "vertical" ? verticalStyles : "",
1755
1758
  className
1756
- ].filter(Boolean).join(" ")
1759
+ )
1757
1760
  }
1758
1761
  );
1759
1762
  }
@@ -1763,25 +1766,34 @@ function Tab({ className, ...props }) {
1763
1766
  AriaTab,
1764
1767
  {
1765
1768
  ...props,
1766
- className: ({ isSelected, isDisabled, isHovered, isPressed }) => [
1767
- // Base
1768
- "cursor-pointer outline-none transition-colors",
1769
- "font-[var(--font-weight-medium)]",
1770
- // Focus ring
1771
- "focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)] focus-visible:ring-offset-2",
1772
- // Disabled
1773
- isDisabled ? "opacity-50 pointer-events-none" : "",
1774
- // Size
1775
- sizeStyles5[size],
1776
- // Variant-specific styles
1777
- ...getTabVariantStyles(variant, {
1778
- isSelected,
1779
- isHovered,
1780
- isPressed,
1781
- isDisabled
1782
- }),
1783
- className
1784
- ].filter(Boolean).join(" ")
1769
+ className: ({ isSelected, isDisabled, isHovered, isPressed }) => {
1770
+ if (variant === "unstyled") {
1771
+ return twMerge5(
1772
+ "cursor-pointer outline-none",
1773
+ "focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)] focus-visible:ring-offset-2",
1774
+ isDisabled ? "opacity-50 pointer-events-none" : "",
1775
+ className
1776
+ );
1777
+ }
1778
+ return twMerge5(
1779
+ // Base
1780
+ "cursor-pointer outline-none transition-colors",
1781
+ "font-[var(--font-weight-medium)]",
1782
+ // Focus ring
1783
+ "focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)] focus-visible:ring-offset-2",
1784
+ // Disabled
1785
+ isDisabled ? "opacity-50 pointer-events-none" : "",
1786
+ // Size
1787
+ sizeStyles5[size],
1788
+ ...getTabVariantStyles(variant, {
1789
+ isSelected,
1790
+ isHovered,
1791
+ isPressed,
1792
+ isDisabled
1793
+ }),
1794
+ className
1795
+ );
1796
+ }
1785
1797
  }
1786
1798
  );
1787
1799
  }
@@ -1806,15 +1818,27 @@ function getTabVariantStyles(variant, state) {
1806
1818
  ];
1807
1819
  }
1808
1820
  function TabPanel({ className, ...props }) {
1821
+ const { variant } = useContext3(TabsContext);
1809
1822
  return /* @__PURE__ */ jsx27(
1810
1823
  AriaTabPanel,
1811
1824
  {
1812
1825
  ...props,
1813
- className: ["mt-4 outline-none", className].filter(Boolean).join(" ")
1826
+ className: twMerge5(
1827
+ variant === "unstyled" ? "outline-none" : "mt-4 outline-none",
1828
+ className
1829
+ )
1814
1830
  }
1815
1831
  );
1816
1832
  }
1817
1833
 
1834
+ // src/index.ts
1835
+ import {
1836
+ Tabs as Tabs2,
1837
+ TabList as TabList2,
1838
+ Tab as Tab2,
1839
+ TabPanel as TabPanel2
1840
+ } from "react-aria-components";
1841
+
1818
1842
  // src/components/Tree/Tree.tsx
1819
1843
  import { useCallback as useCallback2, useImperativeHandle, useRef as useRef2, useState as useState2 } from "react";
1820
1844
  import { Tree as ArboristTree } from "react-arborist";
@@ -1832,7 +1856,9 @@ function NodeRenderer({
1832
1856
  dragHandle,
1833
1857
  checkedIds,
1834
1858
  onCheckToggle,
1835
- selectionMode
1859
+ selectionMode,
1860
+ onHover,
1861
+ onHoverEnd
1836
1862
  }) {
1837
1863
  const data = node.data;
1838
1864
  const isCheckbox = selectionMode === "checkbox";
@@ -1854,6 +1880,8 @@ function NodeRenderer({
1854
1880
  role: "treeitem",
1855
1881
  "aria-selected": isCheckbox ? isChecked : node.isSelected,
1856
1882
  "aria-expanded": node.isInternal ? node.isOpen : void 0,
1883
+ onPointerEnter: () => onHover?.(node.data),
1884
+ onPointerLeave: () => onHoverEnd?.(node.data),
1857
1885
  onClick: (e) => {
1858
1886
  if (isCheckbox) {
1859
1887
  onCheckToggle(node.id);
@@ -1939,6 +1967,8 @@ function Tree({
1939
1967
  selectedIds,
1940
1968
  onSelectionChange,
1941
1969
  onActivate,
1970
+ onHover,
1971
+ onHoverEnd,
1942
1972
  openByDefault = false,
1943
1973
  searchTerm,
1944
1974
  searchMatch,
@@ -2021,7 +2051,9 @@ function Tree({
2021
2051
  ...props,
2022
2052
  checkedIds,
2023
2053
  onCheckToggle: handleCheckToggle,
2024
- selectionMode
2054
+ selectionMode,
2055
+ onHover,
2056
+ onHoverEnd
2025
2057
  }
2026
2058
  )
2027
2059
  }
@@ -2030,6 +2062,206 @@ function Tree({
2030
2062
  );
2031
2063
  }
2032
2064
 
2065
+ // src/components/SegmentedControl/SegmentedControl.tsx
2066
+ import { createContext as createContext4, useContext as useContext4 } from "react";
2067
+ import { twMerge as twMerge6 } from "tailwind-merge";
2068
+ import {
2069
+ ToggleButtonGroup as AriaToggleButtonGroup,
2070
+ ToggleButton as AriaToggleButton2
2071
+ } from "react-aria-components";
2072
+ import { jsx as jsx29 } from "react/jsx-runtime";
2073
+ var SegmentedControlContext = createContext4({
2074
+ size: "md"
2075
+ });
2076
+ var sizeStyles6 = {
2077
+ sm: "px-2.5 py-1 text-xs",
2078
+ md: "px-3 py-1.5 text-sm",
2079
+ lg: "px-4 py-2 text-base"
2080
+ };
2081
+ function SegmentedControl({
2082
+ size = "md",
2083
+ selectionMode = "single",
2084
+ selectedKeys,
2085
+ defaultSelectedKeys,
2086
+ onSelectionChange,
2087
+ className,
2088
+ children,
2089
+ ...props
2090
+ }) {
2091
+ const isNoneMode = selectionMode === "none";
2092
+ return /* @__PURE__ */ jsx29(SegmentedControlContext.Provider, { value: { size }, children: /* @__PURE__ */ jsx29(
2093
+ AriaToggleButtonGroup,
2094
+ {
2095
+ ...props,
2096
+ selectionMode: "single",
2097
+ selectedKeys: isNoneMode ? /* @__PURE__ */ new Set() : selectedKeys,
2098
+ defaultSelectedKeys: isNoneMode ? void 0 : defaultSelectedKeys,
2099
+ onSelectionChange: isNoneMode ? void 0 : onSelectionChange,
2100
+ className: twMerge6(
2101
+ "inline-flex items-center rounded-[var(--border-radius-lg)] border border-[var(--color-border-default)] bg-[var(--color-surface-muted)] p-0.5 gap-0.5",
2102
+ className
2103
+ ),
2104
+ children
2105
+ }
2106
+ ) });
2107
+ }
2108
+ function SegmentedControlItem({
2109
+ className,
2110
+ ...props
2111
+ }) {
2112
+ const { size } = useContext4(SegmentedControlContext);
2113
+ return /* @__PURE__ */ jsx29(
2114
+ AriaToggleButton2,
2115
+ {
2116
+ ...props,
2117
+ className: ({ isSelected, isHovered, isPressed, isDisabled }) => twMerge6(
2118
+ // Base layout
2119
+ "inline-flex items-center justify-center",
2120
+ "rounded-[var(--border-radius-md)]",
2121
+ "font-[var(--font-weight-medium)]",
2122
+ "outline-none transition-colors cursor-pointer",
2123
+ // Focus ring
2124
+ "focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)] focus-visible:ring-offset-1",
2125
+ // Disabled
2126
+ isDisabled && "opacity-50 pointer-events-none",
2127
+ // Size
2128
+ sizeStyles6[size],
2129
+ // Selected state
2130
+ isSelected ? "bg-[var(--color-surface-default)] text-[var(--color-text-primary)] shadow-sm font-[var(--font-weight-semibold)]" : isPressed ? "bg-[var(--color-surface-subtle)] text-[var(--color-text-primary)]" : isHovered ? "bg-[var(--color-surface-subtle)] text-[var(--color-text-primary)]" : "bg-transparent text-[var(--color-text-secondary)]",
2131
+ className
2132
+ )
2133
+ }
2134
+ );
2135
+ }
2136
+
2137
+ // src/components/StorageConnectionCard/StorageConnectionCard.tsx
2138
+ import { AlertCircle, Database, Info as Info2 } from "lucide-react";
2139
+ import { twMerge as twMerge7 } from "tailwind-merge";
2140
+ import { Fragment as Fragment8, jsx as jsx30, jsxs as jsxs20 } from "react/jsx-runtime";
2141
+ var statusDotStyles = {
2142
+ connected: "bg-emerald-500",
2143
+ error: "bg-red-500",
2144
+ loading: "bg-amber-500 animate-pulse"
2145
+ };
2146
+ var providerConfig = {
2147
+ aws: { label: "AWS", color: "bg-orange-100 text-orange-700" },
2148
+ azure: { label: "Azure", color: "bg-blue-100 text-blue-700" },
2149
+ gcp: { label: "GCP", color: "bg-sky-100 text-sky-700" },
2150
+ minio: { label: "MinIO", color: "bg-red-100 text-red-700" }
2151
+ };
2152
+ function ProviderBadge({ provider }) {
2153
+ const config = providerConfig[provider.toLowerCase()];
2154
+ const label = config?.label ?? provider;
2155
+ const colorClass = config?.color ?? "bg-neutral-100 text-neutral-700";
2156
+ return /* @__PURE__ */ jsx30(
2157
+ "span",
2158
+ {
2159
+ className: twMerge7(
2160
+ "inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium",
2161
+ colorClass
2162
+ ),
2163
+ children: label
2164
+ }
2165
+ );
2166
+ }
2167
+ function PreviewArea({
2168
+ status,
2169
+ errorMessage,
2170
+ children
2171
+ }) {
2172
+ if (status === "loading") {
2173
+ return /* @__PURE__ */ jsx30("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx30(Spinner, { size: "lg", "aria-label": "Loading connection" }) });
2174
+ }
2175
+ if (status === "error") {
2176
+ return /* @__PURE__ */ jsxs20("div", { className: "flex h-full flex-col items-center justify-center gap-2 bg-red-950/20 px-4", children: [
2177
+ /* @__PURE__ */ jsx30(
2178
+ Icon,
2179
+ {
2180
+ icon: AlertCircle,
2181
+ size: "lg",
2182
+ className: "text-red-400"
2183
+ }
2184
+ ),
2185
+ errorMessage && /* @__PURE__ */ jsx30("p", { className: "text-center text-xs text-red-300", children: errorMessage })
2186
+ ] });
2187
+ }
2188
+ if (children) {
2189
+ return /* @__PURE__ */ jsx30("div", { className: "h-full w-full overflow-hidden", children });
2190
+ }
2191
+ return /* @__PURE__ */ jsx30("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx30(
2192
+ Icon,
2193
+ {
2194
+ icon: Database,
2195
+ size: "xl",
2196
+ className: "text-[var(--color-neutral-600)]"
2197
+ }
2198
+ ) });
2199
+ }
2200
+ function StorageConnectionCard({
2201
+ name,
2202
+ provider,
2203
+ region,
2204
+ status,
2205
+ errorMessage,
2206
+ imageCount,
2207
+ children,
2208
+ href,
2209
+ onInfo,
2210
+ className
2211
+ }) {
2212
+ const cardContent = /* @__PURE__ */ jsxs20(Fragment8, { children: [
2213
+ /* @__PURE__ */ jsx30("div", { className: "aspect-[4/3] bg-[var(--color-neutral-900)] overflow-hidden rounded-t-[var(--border-radius-lg)]", children: /* @__PURE__ */ jsx30(PreviewArea, { status, errorMessage, children }) }),
2214
+ /* @__PURE__ */ jsxs20("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: [
2215
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-start gap-2", children: [
2216
+ /* @__PURE__ */ jsx30(
2217
+ "span",
2218
+ {
2219
+ className: twMerge7(
2220
+ "mt-1.5 h-2 w-2 shrink-0 rounded-full",
2221
+ statusDotStyles[status]
2222
+ ),
2223
+ "aria-label": `Status: ${status}`
2224
+ }
2225
+ ),
2226
+ /* @__PURE__ */ jsx30("span", { className: "min-w-0 flex-1 line-clamp-2 text-sm font-medium text-[var(--color-text-primary)]", children: name }),
2227
+ onInfo && /* @__PURE__ */ jsx30(
2228
+ IconButton,
2229
+ {
2230
+ icon: Info2,
2231
+ "aria-label": "Connection info",
2232
+ variant: "ghost",
2233
+ size: "sm",
2234
+ className: "shrink-0 -mt-1 -mr-1",
2235
+ onPress: () => {
2236
+ onInfo();
2237
+ }
2238
+ }
2239
+ )
2240
+ ] }),
2241
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2 pl-4", children: [
2242
+ /* @__PURE__ */ jsx30(ProviderBadge, { provider }),
2243
+ region && /* @__PURE__ */ jsx30("span", { className: "shrink-0 text-xs text-[var(--color-text-secondary)]", children: region }),
2244
+ imageCount != null && status === "connected" && /* @__PURE__ */ jsxs20("span", { className: "ml-auto shrink-0 text-xs tabular-nums text-[var(--color-text-tertiary)]", children: [
2245
+ imageCount,
2246
+ " ",
2247
+ imageCount === 1 ? "image" : "images"
2248
+ ] })
2249
+ ] })
2250
+ ] })
2251
+ ] });
2252
+ const baseStyles = twMerge7(
2253
+ "flex flex-col overflow-hidden rounded-[var(--border-radius-lg)]",
2254
+ "border border-[var(--color-border-default)]",
2255
+ "shadow-sm transition-all",
2256
+ href && "hover:border-[var(--color-border-focus)] hover:shadow-md cursor-pointer",
2257
+ className
2258
+ );
2259
+ if (href) {
2260
+ return /* @__PURE__ */ jsx30("a", { href, className: twMerge7(baseStyles, "no-underline"), children: cardContent });
2261
+ }
2262
+ return /* @__PURE__ */ jsx30("div", { className: baseStyles, children: cardContent });
2263
+ }
2264
+
2033
2265
  // src/tokens/tokens.ts
2034
2266
  var ColorPurple50 = "#f5f0fa";
2035
2267
  var ColorPurple100 = "#ead9f5";
@@ -2336,6 +2568,8 @@ export {
2336
2568
  RadioGroup,
2337
2569
  RouterProvider,
2338
2570
  Row,
2571
+ SegmentedControl,
2572
+ SegmentedControlItem,
2339
2573
  Select,
2340
2574
  Spacing1,
2341
2575
  Spacing12,
@@ -2346,6 +2580,7 @@ export {
2346
2580
  Spacing6,
2347
2581
  Spacing8,
2348
2582
  Spinner,
2583
+ StorageConnectionCard,
2349
2584
  Switch,
2350
2585
  Tab,
2351
2586
  TabList,
@@ -2358,6 +2593,10 @@ export {
2358
2593
  ToggleButton,
2359
2594
  Tooltip,
2360
2595
  Tree,
2596
+ Tab2 as UnstyledTab,
2597
+ TabList2 as UnstyledTabList,
2598
+ TabPanel2 as UnstyledTabPanel,
2599
+ Tabs2 as UnstyledTabs,
2361
2600
  createToastBridge,
2362
2601
  useInputGroup,
2363
2602
  useToast