@sovereignfs/ui 0.33.0 → 0.37.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.
Files changed (45) hide show
  1. package/README.md +1 -1
  2. package/dist/CheckableListRow.module.css +95 -0
  3. package/dist/Dialog.module.css +12 -12
  4. package/dist/IconPicker.module.css +63 -0
  5. package/dist/QuantityStepper.module.css +67 -0
  6. package/dist/SuggestionInput.module.css +103 -0
  7. package/dist/index.d.ts +128 -2
  8. package/dist/index.js +1007 -169
  9. package/package.json +1 -1
  10. package/src/components/CheckableListRow/CheckableListRow.module.css +95 -0
  11. package/src/components/CheckableListRow/CheckableListRow.stories.tsx +99 -0
  12. package/src/components/CheckableListRow/CheckableListRow.tsx +89 -0
  13. package/src/components/Dialog/Dialog.module.css +12 -12
  14. package/src/components/Icon/icons/apple.tsx +21 -0
  15. package/src/components/Icon/icons/banana.tsx +21 -0
  16. package/src/components/Icon/icons/beef.tsx +22 -0
  17. package/src/components/Icon/icons/beer.tsx +24 -0
  18. package/src/components/Icon/icons/candy.tsx +24 -0
  19. package/src/components/Icon/icons/carrot.tsx +22 -0
  20. package/src/components/Icon/icons/coffee.tsx +23 -0
  21. package/src/components/Icon/icons/cookie.tsx +25 -0
  22. package/src/components/Icon/icons/croissant.tsx +24 -0
  23. package/src/components/Icon/icons/cup-soda.tsx +23 -0
  24. package/src/components/Icon/icons/drumstick.tsx +21 -0
  25. package/src/components/Icon/icons/egg.tsx +20 -0
  26. package/src/components/Icon/icons/fish.tsx +25 -0
  27. package/src/components/Icon/icons/index.ts +81 -1
  28. package/src/components/Icon/icons/milk.tsx +22 -0
  29. package/src/components/Icon/icons/pizza.tsx +24 -0
  30. package/src/components/Icon/icons/salad.tsx +24 -0
  31. package/src/components/Icon/icons/shopping-basket.tsx +26 -0
  32. package/src/components/Icon/icons/snowflake.tsx +31 -0
  33. package/src/components/Icon/icons/spray-can.tsx +29 -0
  34. package/src/components/Icon/icons/wine.tsx +23 -0
  35. package/src/components/IconPicker/IconPicker.module.css +63 -0
  36. package/src/components/IconPicker/IconPicker.stories.tsx +84 -0
  37. package/src/components/IconPicker/IconPicker.tsx +90 -0
  38. package/src/components/QuantityStepper/QuantityStepper.module.css +67 -0
  39. package/src/components/QuantityStepper/QuantityStepper.stories.tsx +79 -0
  40. package/src/components/QuantityStepper/QuantityStepper.tsx +107 -0
  41. package/src/components/SuggestionInput/SuggestionInput.module.css +103 -0
  42. package/src/components/SuggestionInput/SuggestionInput.stories.tsx +144 -0
  43. package/src/components/SuggestionInput/SuggestionInput.tsx +207 -0
  44. package/src/index.ts +11 -0
  45. package/src/stories/DesignSystemOverview.stories.tsx +107 -0
package/README.md CHANGED
@@ -19,7 +19,7 @@ npm install @sovereignfs/ui
19
19
  import { Button, Input, Card, Dialog, Drawer } from '@sovereignfs/ui';
20
20
  ```
21
21
 
22
- Available components: `Avatar`, `Badge`, `Button`, `Card`, `Dialog`, `Drawer`, `EmptyState`, `FormField`, `Icon`, `Input`, `NavTabs`, `PageHeader`, `Popover`, `SegmentedControl`, `Select`, `Spinner`, `SystemBanner`, `Tabs`, `Toast` / `useToast`, `Toggle`, `Tooltip`.
22
+ Available components and hooks: `Avatar`, `Badge`, `Button`, `Calendar`, `Card`, `CheckableListRow`, `Checkbox`, `CodeTextarea`, `ConfirmDialog`, `DatePicker`, `Dialog`, `DragHandleRow`, `Drawer`, `EmptyState`, `FormField`, `Icon`, `IconPicker`, `Input`, `Menu`, `NavTabs`, `OverlayHeader`, `PageHeader`, `Popover`, `QuantityStepper`, `SegmentedControl`, `Select`, `Sheet`, `Spinner`, `SplitPane`, `StatusBadge`, `SuggestionInput`, `SystemBanner`, `Tabs`, `TagInput`, `Textarea`, `Toast` / `useToast`, `Toggle`, `Tooltip`, `useDoubleTapHandler`, `useIsMobile`, `useLongPress`, and `useSingleOrDoubleTap`.
23
23
 
24
24
  ### Tokens
25
25
 
@@ -0,0 +1,95 @@
1
+ .row {
2
+ display: flex;
3
+ align-items: center;
4
+ gap: var(--sv-space-3);
5
+ width: 100%;
6
+ }
7
+
8
+ .tapTarget {
9
+ display: flex;
10
+ align-items: center;
11
+ gap: var(--sv-space-2);
12
+ flex: 1;
13
+ min-width: 0;
14
+ min-height: var(--sv-touch-target-min);
15
+ cursor: pointer;
16
+ }
17
+
18
+ .tapTarget:focus-visible {
19
+ outline: 2px solid var(--sv-color-focus-ring);
20
+ outline-offset: 2px;
21
+ border-radius: var(--sv-radius-sm);
22
+ }
23
+
24
+ /* Visual box — matches Checkbox.module.css's .box/.checked/.tick. */
25
+ .box {
26
+ --checkbox-box-size: 18px;
27
+ flex-shrink: 0;
28
+ width: var(--checkbox-box-size);
29
+ height: var(--checkbox-box-size);
30
+ border-radius: var(--sv-radius-sm);
31
+ border: 1.5px solid var(--sv-color-border-strong);
32
+ background: var(--sv-color-surface);
33
+ transition:
34
+ background-color 0.15s ease,
35
+ border-color 0.15s ease;
36
+ display: flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ }
40
+
41
+ .checked {
42
+ background-color: var(--sv-color-accent);
43
+ border-color: var(--sv-color-accent);
44
+ color: var(--sv-white);
45
+ }
46
+
47
+ .tick {
48
+ width: 10px;
49
+ height: 8px;
50
+ pointer-events: none;
51
+ }
52
+
53
+ .icon {
54
+ display: flex;
55
+ align-items: center;
56
+ flex-shrink: 0;
57
+ color: var(--sv-color-text-muted);
58
+ }
59
+
60
+ .label {
61
+ flex: 1;
62
+ min-width: 0;
63
+ font-size: var(--sv-font-size-sm);
64
+ color: var(--sv-color-text-primary);
65
+ overflow: hidden;
66
+ text-overflow: ellipsis;
67
+ white-space: nowrap;
68
+ transition: color 0.15s ease;
69
+ position: relative;
70
+ }
71
+
72
+ .label::after {
73
+ content: '';
74
+ position: absolute;
75
+ left: 0;
76
+ top: 50%;
77
+ width: 100%;
78
+ height: 1.5px;
79
+ background: var(--sv-color-text-muted);
80
+ transform: scaleX(0);
81
+ transform-origin: left center;
82
+ transition: transform 0.2s ease;
83
+ }
84
+
85
+ .struck {
86
+ color: var(--sv-color-text-muted);
87
+ }
88
+
89
+ .struck::after {
90
+ transform: scaleX(1);
91
+ }
92
+
93
+ .trailing {
94
+ flex-shrink: 0;
95
+ }
@@ -205,19 +205,19 @@
205
205
 
206
206
  /* Title + close button in one solid row, via the shared OverlayHeader
207
207
  component. Being a flex sibling before .content means it never scrolls —
208
- the content area scrolls below it. */
208
+ the content area scrolls below it.
209
+ .content itself needs no mobile override here any more: it used to zero
210
+ out padding-top so a plugin's hand-rolled sticky header (rendered as
211
+ .content's own first child, right below OverlayHeader) would sit flush
212
+ against it. That case no longer exists — a plugin with a tab strip/
213
+ secondary nav now hands it to OverlayHeader's own secondRow slot
214
+ (useOverlaySecondRow) instead of rendering it inside .content; Account
215
+ and Console both migrated to this (mobile design-system plan, Phase
216
+ C1b). With .content's first child back to being genuine page content, it
217
+ needs the same breathing room from the header that .content's own base
218
+ padding (var(--sv-space-6) on every side) already provides everywhere
219
+ else. */
209
220
  .mobileHeader {
210
221
  display: block;
211
222
  }
212
-
213
- /* Remove top padding so the sticky plugin header sits flush against
214
- OverlayHeader — no gap for scrolling content to bleed through.
215
- padding-bottom no longer adds --sv-shell-footer-height on top of
216
- --sv-space-6 — the scrim above already stops short of the footer, so
217
- .content doesn't need to additionally compensate for it here (that used
218
- to double-count the footer clearance). */
219
- .content {
220
- padding-top: 0;
221
- padding-bottom: var(--sv-space-6, 24px);
222
- }
223
223
  }
@@ -0,0 +1,63 @@
1
+ .trigger {
2
+ display: flex;
3
+ align-items: center;
4
+ gap: var(--sv-space-2);
5
+ padding: var(--sv-space-2);
6
+ border: 1px solid var(--sv-color-border-strong);
7
+ border-radius: var(--sv-radius-md);
8
+ background: var(--sv-color-surface);
9
+ color: var(--sv-color-text-primary);
10
+ cursor: pointer;
11
+ }
12
+
13
+ .trigger:hover {
14
+ background: var(--sv-color-surface-sunken);
15
+ }
16
+
17
+ .trigger:disabled {
18
+ opacity: 0.5;
19
+ cursor: not-allowed;
20
+ }
21
+
22
+ .placeholder {
23
+ display: flex;
24
+ align-items: center;
25
+ justify-content: center;
26
+ width: var(--sv-icon-size-md);
27
+ height: var(--sv-icon-size-md);
28
+ color: var(--sv-color-text-subtle);
29
+ font-size: var(--sv-font-size-sm);
30
+ }
31
+
32
+ .triggerLabel {
33
+ font-size: var(--sv-font-size-sm);
34
+ color: var(--sv-color-text-primary);
35
+ }
36
+
37
+ .grid {
38
+ display: grid;
39
+ grid-template-columns: repeat(5, 1fr);
40
+ gap: var(--sv-space-1);
41
+ padding: var(--sv-space-2);
42
+ }
43
+
44
+ .option {
45
+ display: flex;
46
+ align-items: center;
47
+ justify-content: center;
48
+ width: var(--sv-touch-target-min);
49
+ height: var(--sv-touch-target-min);
50
+ border: none;
51
+ border-radius: var(--sv-radius-sm);
52
+ background: transparent;
53
+ color: var(--sv-color-text-primary);
54
+ cursor: pointer;
55
+ }
56
+
57
+ .option:hover {
58
+ background: var(--sv-color-surface-sunken);
59
+ }
60
+
61
+ .optionSelected {
62
+ background: var(--sv-color-accent-subtle);
63
+ }
@@ -0,0 +1,67 @@
1
+ .root {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ gap: var(--sv-space-1);
5
+ padding: var(--sv-space-1);
6
+ border: 1px solid var(--sv-color-border-strong);
7
+ border-radius: var(--sv-radius-full);
8
+ background: var(--sv-color-surface-sunken);
9
+ }
10
+
11
+ .button {
12
+ all: unset;
13
+ display: flex;
14
+ align-items: center;
15
+ justify-content: center;
16
+ width: var(--sv-space-6);
17
+ height: var(--sv-space-6);
18
+ border-radius: var(--sv-radius-full);
19
+ color: var(--sv-color-text-primary);
20
+ font-size: var(--sv-font-size-md);
21
+ line-height: 1;
22
+ cursor: pointer;
23
+ }
24
+
25
+ .button:hover:not(:disabled) {
26
+ background: var(--sv-color-surface);
27
+ }
28
+
29
+ .button:disabled {
30
+ color: var(--sv-color-text-subtle);
31
+ cursor: not-allowed;
32
+ }
33
+
34
+ .input {
35
+ all: unset;
36
+ width: 3ch;
37
+ text-align: center;
38
+ font-family: var(--sv-font-family);
39
+ font-size: var(--sv-font-size-sm);
40
+ color: var(--sv-color-text-primary);
41
+ /* Hide the native spinner — the +/- buttons are the stepper affordance,
42
+ a second one from the browser would be redundant and often looks
43
+ inconsistent across browsers anyway. */
44
+ -moz-appearance: textfield;
45
+ }
46
+
47
+ .input::-webkit-outer-spin-button,
48
+ .input::-webkit-inner-spin-button {
49
+ -webkit-appearance: none;
50
+ margin: 0;
51
+ }
52
+
53
+ .input:focus-visible {
54
+ outline: none;
55
+ box-shadow: 0 0 0 2px var(--sv-color-focus-ring);
56
+ border-radius: var(--sv-radius-sm);
57
+ }
58
+
59
+ .input:disabled {
60
+ color: var(--sv-color-text-muted);
61
+ }
62
+
63
+ .unit {
64
+ font-size: var(--sv-font-size-xs);
65
+ color: var(--sv-color-text-subtle);
66
+ white-space: nowrap;
67
+ }
@@ -0,0 +1,103 @@
1
+ .input {
2
+ display: block;
3
+ width: 100%;
4
+ padding: var(--sv-space-2) var(--sv-space-3);
5
+ font-family: var(--sv-font-family);
6
+ font-size: var(--sv-font-size-sm);
7
+ line-height: 1.5;
8
+ color: var(--sv-color-text-primary);
9
+ background-color: var(--sv-color-surface);
10
+ border: 1px solid var(--sv-color-border-strong);
11
+ border-radius: var(--sv-radius-md);
12
+ transition:
13
+ border-color 0.15s ease,
14
+ box-shadow 0.15s ease;
15
+ }
16
+
17
+ /* iOS Safari auto-zooms on focused inputs under 16px — see Input.module.css
18
+ for the full rationale; kept in sync here since this isn't built on Input. */
19
+ @media (pointer: coarse) {
20
+ .input {
21
+ font-size: var(--sv-font-size-md);
22
+ }
23
+ }
24
+
25
+ .input::placeholder {
26
+ color: var(--sv-color-text-muted);
27
+ }
28
+
29
+ .input:focus-visible {
30
+ outline: none;
31
+ border-color: var(--sv-color-accent);
32
+ box-shadow: 0 0 0 2px var(--sv-color-focus-ring);
33
+ }
34
+
35
+ .input:disabled {
36
+ opacity: 0.5;
37
+ cursor: not-allowed;
38
+ }
39
+
40
+ .list {
41
+ list-style: none;
42
+ margin: 0;
43
+ padding: var(--sv-space-1);
44
+ max-height: 320px;
45
+ overflow-y: auto;
46
+ }
47
+
48
+ .status {
49
+ padding: var(--sv-space-2) var(--sv-space-3);
50
+ font-size: var(--sv-font-size-sm);
51
+ color: var(--sv-color-text-muted);
52
+ }
53
+
54
+ .option {
55
+ display: flex;
56
+ align-items: center;
57
+ gap: var(--sv-space-2);
58
+ width: 100%;
59
+ padding: var(--sv-space-2) var(--sv-space-3);
60
+ border: none;
61
+ border-radius: var(--sv-radius-sm);
62
+ background: transparent;
63
+ font-family: var(--sv-font-family);
64
+ font-size: var(--sv-font-size-sm);
65
+ color: var(--sv-color-text-primary);
66
+ text-align: left;
67
+ cursor: pointer;
68
+ }
69
+
70
+ .option:hover,
71
+ .optionActive {
72
+ background: var(--sv-color-surface-sunken);
73
+ }
74
+
75
+ .optionIcon {
76
+ display: flex;
77
+ align-items: center;
78
+ flex-shrink: 0;
79
+ }
80
+
81
+ .optionLabel {
82
+ flex: 1;
83
+ min-width: 0;
84
+ overflow: hidden;
85
+ text-overflow: ellipsis;
86
+ white-space: nowrap;
87
+ }
88
+
89
+ .optionMeta {
90
+ flex-shrink: 0;
91
+ font-size: var(--sv-font-size-xs);
92
+ color: var(--sv-color-text-subtle);
93
+ }
94
+
95
+ .optionCreate {
96
+ font-style: italic;
97
+ color: var(--sv-color-text-muted);
98
+ }
99
+
100
+ .divider {
101
+ margin: var(--sv-space-1) var(--sv-space-2);
102
+ border-top: 1px solid var(--sv-color-border);
103
+ }
package/dist/index.d.ts CHANGED
@@ -18,7 +18,7 @@ interface BadgeProps {
18
18
  */
19
19
  declare function Badge({ variant, status, children }: BadgeProps): react.JSX.Element;
20
20
 
21
- type IconName = 'house' | 'settings' | 'log-out' | 'chevron-right' | 'chevron-left' | 'chevron-down' | 'chevron-up' | 'x' | 'check' | 'plus' | 'trash-2' | 'pencil' | 'rotate-ccw' | 'search' | 'user' | 'shield' | 'lock' | 'eye' | 'eye-off' | 'mail' | 'bell' | 'activity' | 'package' | 'grid-2x2' | 'info' | 'alert-triangle' | 'calendar' | 'sliders-horizontal' | 'ellipsis-vertical';
21
+ type IconName = 'house' | 'settings' | 'log-out' | 'chevron-right' | 'chevron-left' | 'chevron-down' | 'chevron-up' | 'x' | 'check' | 'plus' | 'trash-2' | 'pencil' | 'rotate-ccw' | 'search' | 'user' | 'shield' | 'lock' | 'eye' | 'eye-off' | 'mail' | 'bell' | 'activity' | 'package' | 'grid-2x2' | 'info' | 'alert-triangle' | 'calendar' | 'sliders-horizontal' | 'ellipsis-vertical' | 'banana' | 'apple' | 'carrot' | 'egg' | 'beef' | 'fish' | 'coffee' | 'wine' | 'beer' | 'cookie' | 'pizza' | 'candy' | 'salad' | 'milk' | 'drumstick' | 'croissant' | 'cup-soda' | 'spray-can' | 'snowflake' | 'shopping-basket';
22
22
 
23
23
  /** Decorative icon — visually meaningful but described by surrounding text. */
24
24
  type DecorativeProps = {
@@ -747,6 +747,132 @@ interface DatePickerProps {
747
747
  */
748
748
  declare function DatePicker({ value, onChange, minDate, maxDate, placeholder, 'aria-label': ariaLabel, disabled, }: DatePickerProps): react.JSX.Element;
749
749
 
750
+ interface SuggestionOption {
751
+ id: string;
752
+ label: string;
753
+ icon?: ReactNode;
754
+ /** Secondary text shown right-aligned on the row, e.g. "bought 4× recently". */
755
+ meta?: string;
756
+ }
757
+ interface SuggestionInputProps {
758
+ value: string;
759
+ onChange: (value: string) => void;
760
+ options: SuggestionOption[];
761
+ onSelect: (option: SuggestionOption) => void;
762
+ placeholder?: string;
763
+ 'aria-label': string;
764
+ id?: string;
765
+ disabled?: boolean;
766
+ /** Shown in place of the options list while a suggestion fetch is in flight. */
767
+ loading?: boolean;
768
+ /**
769
+ * Label for a trailing, always-selectable row that commits the raw typed
770
+ * text instead of a matched option — e.g. `(v) => \`Add "${v}" as a new item\`}`.
771
+ * Shown whenever `value` is non-empty and `onCreate` is provided, even
772
+ * when `options` is empty, so the input is never a dead end.
773
+ */
774
+ createLabel?: (value: string) => string;
775
+ onCreate?: (value: string) => void;
776
+ className?: string;
777
+ }
778
+ /**
779
+ * SuggestionInput — a text field with an anchored, keyboard-navigable list
780
+ * of async suggestions (a combobox), plus an optional trailing "create new"
781
+ * row so free text is always a valid commit, not just a matched option.
782
+ *
783
+ * Fully controlled: the caller owns `value`/`onChange` and supplies
784
+ * `options` (e.g. debounced server-fetched results) — this component only
785
+ * handles open/close, keyboard navigation, and selection. Built on `Popover`
786
+ * for positioning (`width: 'trigger'`, so the panel always matches the
787
+ * input's own width).
788
+ */
789
+ declare function SuggestionInput({ value, onChange, options, onSelect, placeholder, 'aria-label': ariaLabel, id, disabled, loading, createLabel, onCreate, className, }: SuggestionInputProps): react.JSX.Element;
790
+
791
+ interface IconPickerProps {
792
+ value: IconName | null;
793
+ onChange: (icon: IconName) => void;
794
+ /** Icons offered in the grid, in display order. */
795
+ options: readonly IconName[];
796
+ 'aria-label': string;
797
+ /** Shown next to the trigger's icon preview, e.g. the item's name. */
798
+ triggerLabel?: string;
799
+ disabled?: boolean;
800
+ className?: string;
801
+ }
802
+ /**
803
+ * IconPicker — a trigger button showing the current icon that opens a
804
+ * `Popover` grid of selectable icons. Built for cases with a curated,
805
+ * bounded icon set (e.g. Sovereign Shopper's grocery category icons,
806
+ * SHP-05) rather than the full design-system icon library.
807
+ *
808
+ * Selecting an icon both closes the picker and calls `onChange` — a
809
+ * consumer's `onChange` never needs to close the picker itself.
810
+ */
811
+ declare function IconPicker({ value, onChange, options, 'aria-label': ariaLabel, triggerLabel, disabled, className, }: IconPickerProps): react.JSX.Element;
812
+
813
+ interface QuantityStepperProps {
814
+ value: number;
815
+ onChange: (value: number) => void;
816
+ /** Smallest selectable value. Default `0`. */
817
+ min?: number;
818
+ /** Largest selectable value. Default unbounded. */
819
+ max?: number;
820
+ /** Amount +/- adjusts by. Default `1` — pass e.g. `0.5` for fractional
821
+ * quantities (kg, L). */
822
+ step?: number;
823
+ /** Read-only suffix shown after the number, e.g. "pcs" or "kg" — for
824
+ * compact contexts (a list row) where a separate unit selector doesn't
825
+ * fit. Editable unit selection (a `<Select>` of units) lives outside
826
+ * this component. */
827
+ unit?: string;
828
+ 'aria-label': string;
829
+ disabled?: boolean;
830
+ id?: string;
831
+ className?: string;
832
+ }
833
+ /**
834
+ * QuantityStepper — a numeric input with +/- buttons and an optional
835
+ * read-only unit suffix. Built for grocery/inventory-style quantities
836
+ * (Sovereign Shopper, SHP-06) — supports fractional `step` values since
837
+ * quantities like "1.5 kg" are common, unlike a typical integer counter.
838
+ *
839
+ * The middle field is a real `<input type="number">` so keyboard entry,
840
+ * paste, and the browser's native numeric affordances all work — the
841
+ * buttons are a convenience on top, not the only way to change the value.
842
+ */
843
+ declare function QuantityStepper({ value, onChange, min, max, step, unit, 'aria-label': ariaLabel, disabled, id, className, }: QuantityStepperProps): react.JSX.Element;
844
+
845
+ interface CheckableListRowProps {
846
+ checked: boolean;
847
+ onCheckedChange: (checked: boolean) => void;
848
+ label: string;
849
+ /** Leading icon, e.g. a per-item `<Icon>`. */
850
+ icon?: ReactNode;
851
+ /** Trailing content, e.g. a quantity, a `QuantityStepper`, or a badge. */
852
+ trailing?: ReactNode;
853
+ disabled?: boolean;
854
+ className?: string;
855
+ }
856
+ /**
857
+ * CheckableListRow — a whole-row tap target that toggles a checked state,
858
+ * with strike-through on the label when checked. Built for "tap the row to
859
+ * mark it done" lists (Sovereign Shopper's tap-to-buy, SHP-07) where the
860
+ * checkbox itself is too small a target on mobile and the row already has
861
+ * nothing else competing for the tap.
862
+ *
863
+ * Renders as `role="checkbox"` on the row itself rather than composing
864
+ * `Checkbox`'s native `<input>` — nesting a real checkbox input inside the
865
+ * row's own click handler would mean two overlapping interactive elements
866
+ * (invalid HTML, and the input's own click would double-fire the row's
867
+ * toggle). The visual box matches `Checkbox`'s styling for consistency.
868
+ *
869
+ * `trailing` content (e.g. a `QuantityStepper`) is rendered outside the
870
+ * `role="checkbox"` element so its own interactive controls (+/- buttons)
871
+ * don't sit inside another interactive element either — clicking those
872
+ * doesn't toggle the row.
873
+ */
874
+ declare function CheckableListRow({ checked, onCheckedChange, label, icon, trailing, disabled, className, }: CheckableListRowProps): react.JSX.Element;
875
+
750
876
  interface UseLongPressOptions {
751
877
  /** Called once the press has been held for `delay` without exceeding `moveTolerance`. */
752
878
  onLongPress: () => void;
@@ -853,4 +979,4 @@ declare const MOBILE_BREAKPOINT_PX = 768;
853
979
  */
854
980
  declare function useIsMobile(breakpointPx?: number): boolean;
855
981
 
856
- export { Avatar, type AvatarProps, Badge, type BadgeProps, type BadgeStatus, type BadgeVariant, type BannerVariant, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Calendar, type CalendarProps, Card, type CardProps, Checkbox, type CheckboxProps, CodeTextarea, type CodeTextareaProps, ConfirmDialog, type ConfirmDialogProps, DatePicker, type DatePickerProps, Dialog, type DialogProps, type DialogSize, DragHandleRow, type DragHandleRowProps, Drawer, type DrawerProps, EmptyState, type EmptyStateProps, FormField, type FormFieldProps, type FormFieldRenderProps, Icon, type IconName, type IconProps, Input, type InputProps, type LongPressHandlers, MOBILE_BREAKPOINT_PX, Menu, type MenuEntry, type MenuItem, type MenuLabel, type MenuProps, type MenuSeparator, type NavTabItem, NavTabs, type NavTabsProps, OverlayHeader, type OverlayHeaderProps, PageHeader, type PageHeaderProps, Popover, type PopoverProps, SegmentedControl, type SegmentedControlProps, type SegmentedOption, Select, type SelectProps, Sheet, type SheetProps, Spinner, type SpinnerProps, SplitPane, type SplitPaneProps, StatusBadge, type StatusBadgeProps, type StatusBadgeStatus, SystemBanner, type SystemBannerProps, type TabItem, Tabs, type TabsProps, TagInput, type TagInputProps, Textarea, type TextareaProps, type ToastContextValue, type ToastItem, ToastProvider, Toggle, type ToggleProps, Tooltip, type TooltipProps, type UseLongPressOptions, useDoubleTapHandler, useIsMobile, useLongPress, useOverlaySecondRow, useSingleOrDoubleTap, useToast };
982
+ export { Avatar, type AvatarProps, Badge, type BadgeProps, type BadgeStatus, type BadgeVariant, type BannerVariant, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Calendar, type CalendarProps, Card, type CardProps, CheckableListRow, type CheckableListRowProps, Checkbox, type CheckboxProps, CodeTextarea, type CodeTextareaProps, ConfirmDialog, type ConfirmDialogProps, DatePicker, type DatePickerProps, Dialog, type DialogProps, type DialogSize, DragHandleRow, type DragHandleRowProps, Drawer, type DrawerProps, EmptyState, type EmptyStateProps, FormField, type FormFieldProps, type FormFieldRenderProps, Icon, type IconName, IconPicker, type IconPickerProps, type IconProps, Input, type InputProps, type LongPressHandlers, MOBILE_BREAKPOINT_PX, Menu, type MenuEntry, type MenuItem, type MenuLabel, type MenuProps, type MenuSeparator, type NavTabItem, NavTabs, type NavTabsProps, OverlayHeader, type OverlayHeaderProps, PageHeader, type PageHeaderProps, Popover, type PopoverProps, QuantityStepper, type QuantityStepperProps, SegmentedControl, type SegmentedControlProps, type SegmentedOption, Select, type SelectProps, Sheet, type SheetProps, Spinner, type SpinnerProps, SplitPane, type SplitPaneProps, StatusBadge, type StatusBadgeProps, type StatusBadgeStatus, SuggestionInput, type SuggestionInputProps, type SuggestionOption, SystemBanner, type SystemBannerProps, type TabItem, Tabs, type TabsProps, TagInput, type TagInputProps, Textarea, type TextareaProps, type ToastContextValue, type ToastItem, ToastProvider, Toggle, type ToggleProps, Tooltip, type TooltipProps, type UseLongPressOptions, useDoubleTapHandler, useIsMobile, useLongPress, useOverlaySecondRow, useSingleOrDoubleTap, useToast };