@cytario/design 1.10.0 → 1.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
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';
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
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';
@@ -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 {
@@ -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.
@@ -565,6 +619,9 @@ declare const ColorSurfaceSuccess = "#f0fdf4";
565
619
  declare const ColorSurfaceWarning = "#fffbeb";
566
620
  declare const ColorSurfaceInfo = "#f8fafc";
567
621
  declare const ColorSurfaceOverlay = "#000000cc";
622
+ declare const ColorSurfaceHover = "#f3f4f6";
623
+ declare const ColorSurfaceSelected = "#edf9f9";
624
+ declare const ColorSurfaceSelectedHover = "#d0f0f0";
568
625
  declare const ColorBorderDefault = "#e5e7eb";
569
626
  declare const ColorBorderStrong = "#d1d5db";
570
627
  declare const ColorBorderBrand = "#5c2483";
@@ -608,4 +665,4 @@ declare const LineHeightTight = 1.25;
608
665
  declare const LineHeightNormal = 1.5;
609
666
  declare const LineHeightRelaxed = 1.625;
610
667
 
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 };
668
+ 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, ColorSurfaceHover, ColorSurfaceInfo, ColorSurfaceMuted, ColorSurfaceOverlay, ColorSurfaceSelected, ColorSurfaceSelectedHover, 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",
@@ -1854,11 +1856,16 @@ function NodeRenderer({
1854
1856
  dragHandle,
1855
1857
  checkedIds,
1856
1858
  onCheckToggle,
1857
- selectionMode
1859
+ selectionMode,
1860
+ size,
1861
+ onHover,
1862
+ onHoverEnd
1858
1863
  }) {
1859
1864
  const data = node.data;
1860
1865
  const isCheckbox = selectionMode === "checkbox";
1861
1866
  const isChecked = isCheckbox && checkedIds.has(node.id);
1867
+ const isSelected = node.isSelected && !isCheckbox;
1868
+ const isCompact = size === "compact";
1862
1869
  const IconComponent = data.icon ? data.icon : node.isInternal ? Folder : File;
1863
1870
  return /* @__PURE__ */ jsxs19(
1864
1871
  "div",
@@ -1866,16 +1873,21 @@ function NodeRenderer({
1866
1873
  ref: dragHandle,
1867
1874
  style,
1868
1875
  className: [
1869
- "flex items-center gap-1 px-2 cursor-default select-none",
1876
+ "relative flex items-center cursor-default select-none",
1877
+ isCompact ? "gap-0.5 px-2" : "gap-1 px-3",
1870
1878
  "text-[length:var(--font-size-sm)] text-[var(--color-text-primary)]",
1871
1879
  "outline-none",
1872
- "transition-colors",
1873
- node.isSelected && !isCheckbox ? "bg-[var(--color-teal-50)]" : "hover:bg-[var(--color-teal-50)]",
1874
- node.isFocused ? "ring-2 ring-inset ring-[var(--color-border-focus)]" : ""
1880
+ // Full-width background via pseudo-element
1881
+ "before:absolute before:inset-y-0 before:left-[-100vw] before:right-0 before:-z-10 before:transition-colors",
1882
+ isSelected ? "before:bg-[var(--color-surface-selected)] hover:before:bg-[var(--color-surface-selected-hover)] border-l-2 border-l-[var(--color-brand-accent)]" : "hover:before:bg-[var(--color-surface-hover)]",
1883
+ node.isFocused ? "outline-2 outline-[var(--color-border-focus)] outline-offset-[-2px]" : ""
1875
1884
  ].filter(Boolean).join(" "),
1876
1885
  role: "treeitem",
1877
1886
  "aria-selected": isCheckbox ? isChecked : node.isSelected,
1878
1887
  "aria-expanded": node.isInternal ? node.isOpen : void 0,
1888
+ "aria-level": node.level + 1,
1889
+ onPointerEnter: () => onHover?.(node.data),
1890
+ onPointerLeave: () => onHoverEnd?.(node.data),
1879
1891
  onClick: (e) => {
1880
1892
  if (isCheckbox) {
1881
1893
  onCheckToggle(node.id);
@@ -1895,10 +1907,10 @@ function NodeRenderer({
1895
1907
  {
1896
1908
  type: "button",
1897
1909
  className: [
1898
- "flex items-center justify-center w-5 h-5 shrink-0",
1910
+ "flex items-center justify-center w-6 h-6 shrink-0",
1899
1911
  "rounded-[var(--border-radius-sm)]",
1900
1912
  "text-[var(--color-text-secondary)]",
1901
- "hover:text-[var(--color-text-primary)] hover:bg-[var(--color-neutral-100)]",
1913
+ "hover:text-[var(--color-text-primary)]",
1902
1914
  "transition-transform",
1903
1915
  node.isInternal ? "visible" : "invisible"
1904
1916
  ].filter(Boolean).join(" "),
@@ -1961,6 +1973,8 @@ function Tree({
1961
1973
  selectedIds,
1962
1974
  onSelectionChange,
1963
1975
  onActivate,
1976
+ onHover,
1977
+ onHoverEnd,
1964
1978
  openByDefault = false,
1965
1979
  searchTerm,
1966
1980
  searchMatch,
@@ -2017,7 +2031,7 @@ function Tree({
2017
2031
  {
2018
2032
  role: "tree",
2019
2033
  "aria-label": ariaLabel,
2020
- className: ["outline-none", className].filter(Boolean).join(" "),
2034
+ className: ["outline-none overflow-hidden", className].filter(Boolean).join(" "),
2021
2035
  children: /* @__PURE__ */ jsx28(
2022
2036
  ArboristTree,
2023
2037
  {
@@ -2043,7 +2057,10 @@ function Tree({
2043
2057
  ...props,
2044
2058
  checkedIds,
2045
2059
  onCheckToggle: handleCheckToggle,
2046
- selectionMode
2060
+ selectionMode,
2061
+ size,
2062
+ onHover,
2063
+ onHoverEnd
2047
2064
  }
2048
2065
  )
2049
2066
  }
@@ -2052,6 +2069,206 @@ function Tree({
2052
2069
  );
2053
2070
  }
2054
2071
 
2072
+ // src/components/SegmentedControl/SegmentedControl.tsx
2073
+ import { createContext as createContext4, useContext as useContext4 } from "react";
2074
+ import { twMerge as twMerge6 } from "tailwind-merge";
2075
+ import {
2076
+ ToggleButtonGroup as AriaToggleButtonGroup,
2077
+ ToggleButton as AriaToggleButton2
2078
+ } from "react-aria-components";
2079
+ import { jsx as jsx29 } from "react/jsx-runtime";
2080
+ var SegmentedControlContext = createContext4({
2081
+ size: "md"
2082
+ });
2083
+ var sizeStyles6 = {
2084
+ sm: "px-2.5 py-1 text-xs",
2085
+ md: "px-3 py-1.5 text-sm",
2086
+ lg: "px-4 py-2 text-base"
2087
+ };
2088
+ function SegmentedControl({
2089
+ size = "md",
2090
+ selectionMode = "single",
2091
+ selectedKeys,
2092
+ defaultSelectedKeys,
2093
+ onSelectionChange,
2094
+ className,
2095
+ children,
2096
+ ...props
2097
+ }) {
2098
+ const isNoneMode = selectionMode === "none";
2099
+ return /* @__PURE__ */ jsx29(SegmentedControlContext.Provider, { value: { size }, children: /* @__PURE__ */ jsx29(
2100
+ AriaToggleButtonGroup,
2101
+ {
2102
+ ...props,
2103
+ selectionMode: "single",
2104
+ selectedKeys: isNoneMode ? /* @__PURE__ */ new Set() : selectedKeys,
2105
+ defaultSelectedKeys: isNoneMode ? void 0 : defaultSelectedKeys,
2106
+ onSelectionChange: isNoneMode ? void 0 : onSelectionChange,
2107
+ className: twMerge6(
2108
+ "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",
2109
+ className
2110
+ ),
2111
+ children
2112
+ }
2113
+ ) });
2114
+ }
2115
+ function SegmentedControlItem({
2116
+ className,
2117
+ ...props
2118
+ }) {
2119
+ const { size } = useContext4(SegmentedControlContext);
2120
+ return /* @__PURE__ */ jsx29(
2121
+ AriaToggleButton2,
2122
+ {
2123
+ ...props,
2124
+ className: ({ isSelected, isHovered, isPressed, isDisabled }) => twMerge6(
2125
+ // Base layout
2126
+ "inline-flex items-center justify-center",
2127
+ "rounded-[var(--border-radius-md)]",
2128
+ "font-[var(--font-weight-medium)]",
2129
+ "outline-none transition-colors cursor-pointer",
2130
+ // Focus ring
2131
+ "focus-visible:ring-2 focus-visible:ring-[var(--color-border-focus)] focus-visible:ring-offset-1",
2132
+ // Disabled
2133
+ isDisabled && "opacity-50 pointer-events-none",
2134
+ // Size
2135
+ sizeStyles6[size],
2136
+ // Selected state
2137
+ 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)]",
2138
+ className
2139
+ )
2140
+ }
2141
+ );
2142
+ }
2143
+
2144
+ // src/components/StorageConnectionCard/StorageConnectionCard.tsx
2145
+ import { AlertCircle, Database, Info as Info2 } from "lucide-react";
2146
+ import { twMerge as twMerge7 } from "tailwind-merge";
2147
+ import { Fragment as Fragment8, jsx as jsx30, jsxs as jsxs20 } from "react/jsx-runtime";
2148
+ var statusDotStyles = {
2149
+ connected: "bg-emerald-500",
2150
+ error: "bg-red-500",
2151
+ loading: "bg-amber-500 animate-pulse"
2152
+ };
2153
+ var providerConfig = {
2154
+ aws: { label: "AWS", color: "bg-orange-100 text-orange-700" },
2155
+ azure: { label: "Azure", color: "bg-blue-100 text-blue-700" },
2156
+ gcp: { label: "GCP", color: "bg-sky-100 text-sky-700" },
2157
+ minio: { label: "MinIO", color: "bg-red-100 text-red-700" }
2158
+ };
2159
+ function ProviderBadge({ provider }) {
2160
+ const config = providerConfig[provider.toLowerCase()];
2161
+ const label = config?.label ?? provider;
2162
+ const colorClass = config?.color ?? "bg-neutral-100 text-neutral-700";
2163
+ return /* @__PURE__ */ jsx30(
2164
+ "span",
2165
+ {
2166
+ className: twMerge7(
2167
+ "inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium",
2168
+ colorClass
2169
+ ),
2170
+ children: label
2171
+ }
2172
+ );
2173
+ }
2174
+ function PreviewArea({
2175
+ status,
2176
+ errorMessage,
2177
+ children
2178
+ }) {
2179
+ if (status === "loading") {
2180
+ return /* @__PURE__ */ jsx30("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx30(Spinner, { size: "lg", "aria-label": "Loading connection" }) });
2181
+ }
2182
+ if (status === "error") {
2183
+ return /* @__PURE__ */ jsxs20("div", { className: "flex h-full flex-col items-center justify-center gap-2 bg-red-950/20 px-4", children: [
2184
+ /* @__PURE__ */ jsx30(
2185
+ Icon,
2186
+ {
2187
+ icon: AlertCircle,
2188
+ size: "lg",
2189
+ className: "text-red-400"
2190
+ }
2191
+ ),
2192
+ errorMessage && /* @__PURE__ */ jsx30("p", { className: "text-center text-xs text-red-300", children: errorMessage })
2193
+ ] });
2194
+ }
2195
+ if (children) {
2196
+ return /* @__PURE__ */ jsx30("div", { className: "h-full w-full overflow-hidden", children });
2197
+ }
2198
+ return /* @__PURE__ */ jsx30("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx30(
2199
+ Icon,
2200
+ {
2201
+ icon: Database,
2202
+ size: "xl",
2203
+ className: "text-[var(--color-neutral-600)]"
2204
+ }
2205
+ ) });
2206
+ }
2207
+ function StorageConnectionCard({
2208
+ name,
2209
+ provider,
2210
+ region,
2211
+ status,
2212
+ errorMessage,
2213
+ imageCount,
2214
+ children,
2215
+ href,
2216
+ onInfo,
2217
+ className
2218
+ }) {
2219
+ const cardContent = /* @__PURE__ */ jsxs20(Fragment8, { children: [
2220
+ /* @__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 }) }),
2221
+ /* @__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: [
2222
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-start gap-2", children: [
2223
+ /* @__PURE__ */ jsx30(
2224
+ "span",
2225
+ {
2226
+ className: twMerge7(
2227
+ "mt-1.5 h-2 w-2 shrink-0 rounded-full",
2228
+ statusDotStyles[status]
2229
+ ),
2230
+ "aria-label": `Status: ${status}`
2231
+ }
2232
+ ),
2233
+ /* @__PURE__ */ jsx30("span", { className: "min-w-0 flex-1 line-clamp-2 text-sm font-medium text-[var(--color-text-primary)]", children: name }),
2234
+ onInfo && /* @__PURE__ */ jsx30(
2235
+ IconButton,
2236
+ {
2237
+ icon: Info2,
2238
+ "aria-label": "Connection info",
2239
+ variant: "ghost",
2240
+ size: "sm",
2241
+ className: "shrink-0 -mt-1 -mr-1",
2242
+ onPress: () => {
2243
+ onInfo();
2244
+ }
2245
+ }
2246
+ )
2247
+ ] }),
2248
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2 pl-4", children: [
2249
+ /* @__PURE__ */ jsx30(ProviderBadge, { provider }),
2250
+ region && /* @__PURE__ */ jsx30("span", { className: "shrink-0 text-xs text-[var(--color-text-secondary)]", children: region }),
2251
+ imageCount != null && status === "connected" && /* @__PURE__ */ jsxs20("span", { className: "ml-auto shrink-0 text-xs tabular-nums text-[var(--color-text-tertiary)]", children: [
2252
+ imageCount,
2253
+ " ",
2254
+ imageCount === 1 ? "image" : "images"
2255
+ ] })
2256
+ ] })
2257
+ ] })
2258
+ ] });
2259
+ const baseStyles = twMerge7(
2260
+ "flex flex-col overflow-hidden rounded-[var(--border-radius-lg)]",
2261
+ "border border-[var(--color-border-default)]",
2262
+ "shadow-sm transition-all",
2263
+ href && "hover:border-[var(--color-border-focus)] hover:shadow-md cursor-pointer",
2264
+ className
2265
+ );
2266
+ if (href) {
2267
+ return /* @__PURE__ */ jsx30("a", { href, className: twMerge7(baseStyles, "no-underline"), children: cardContent });
2268
+ }
2269
+ return /* @__PURE__ */ jsx30("div", { className: baseStyles, children: cardContent });
2270
+ }
2271
+
2055
2272
  // src/tokens/tokens.ts
2056
2273
  var ColorPurple50 = "#f5f0fa";
2057
2274
  var ColorPurple100 = "#ead9f5";
@@ -2151,6 +2368,9 @@ var ColorSurfaceSuccess = "#f0fdf4";
2151
2368
  var ColorSurfaceWarning = "#fffbeb";
2152
2369
  var ColorSurfaceInfo = "#f8fafc";
2153
2370
  var ColorSurfaceOverlay = "#000000cc";
2371
+ var ColorSurfaceHover = "#f3f4f6";
2372
+ var ColorSurfaceSelected = "#edf9f9";
2373
+ var ColorSurfaceSelectedHover = "#d0f0f0";
2154
2374
  var ColorBorderDefault = "#e5e7eb";
2155
2375
  var ColorBorderStrong = "#d1d5db";
2156
2376
  var ColorBorderBrand = "#5c2483";
@@ -2287,9 +2507,12 @@ export {
2287
2507
  ColorSurfaceBrand,
2288
2508
  ColorSurfaceDanger,
2289
2509
  ColorSurfaceDefault,
2510
+ ColorSurfaceHover,
2290
2511
  ColorSurfaceInfo,
2291
2512
  ColorSurfaceMuted,
2292
2513
  ColorSurfaceOverlay,
2514
+ ColorSurfaceSelected,
2515
+ ColorSurfaceSelectedHover,
2293
2516
  ColorSurfaceSubtle,
2294
2517
  ColorSurfaceSuccess,
2295
2518
  ColorSurfaceWarning,
@@ -2358,6 +2581,8 @@ export {
2358
2581
  RadioGroup,
2359
2582
  RouterProvider,
2360
2583
  Row,
2584
+ SegmentedControl,
2585
+ SegmentedControlItem,
2361
2586
  Select,
2362
2587
  Spacing1,
2363
2588
  Spacing12,
@@ -2368,6 +2593,7 @@ export {
2368
2593
  Spacing6,
2369
2594
  Spacing8,
2370
2595
  Spinner,
2596
+ StorageConnectionCard,
2371
2597
  Switch,
2372
2598
  Tab,
2373
2599
  TabList,