@redis-ui/components 42.8.0 → 43.2.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/AutoCompleteSelect/AutoCompleteSelect.cjs +7 -1
- package/dist/AutoCompleteSelect/AutoCompleteSelect.js +7 -1
- package/dist/AutoCompleteSelect/hooks/useAutoCompleteSelect.cjs +7 -1
- package/dist/AutoCompleteSelect/hooks/useAutoCompleteSelect.d.ts +8 -1
- package/dist/AutoCompleteSelect/hooks/useAutoCompleteSelect.js +7 -1
- package/dist/BoxSelectionGroup/components/Item/components/BoxStateIndicator/BoxStateIndicator.cjs +8 -4
- package/dist/BoxSelectionGroup/components/Item/components/BoxStateIndicator/BoxStateIndicator.js +8 -4
- package/dist/BoxSelectionGroup/components/Item/components/Compose/Compose.style.cjs +18 -4
- package/dist/BoxSelectionGroup/components/Item/components/Compose/Compose.style.js +18 -4
- package/dist/BoxSelectionGroup/hooks/useBoxSelectionGroup.cjs +3 -1
- package/dist/BoxSelectionGroup/hooks/useBoxSelectionGroup.js +3 -1
- package/dist/Button/Button.style.cjs +4 -1
- package/dist/Button/Button.style.js +4 -1
- package/dist/Button/Button.style.utils.cjs +16 -1
- package/dist/Button/Button.style.utils.js +16 -1
- package/dist/Button/Button.types.cjs +1 -1
- package/dist/Button/Button.types.d.ts +1 -1
- package/dist/Button/Button.types.js +1 -1
- package/dist/Button/CopyToClipboardButton/CopyToClipboardButton.cjs +59 -0
- package/dist/Button/CopyToClipboardButton/CopyToClipboardButton.d.ts +4 -0
- package/dist/Button/CopyToClipboardButton/CopyToClipboardButton.js +57 -0
- package/dist/Button/CopyToClipboardButton/CopyToClipboardButton.style.cjs +40 -0
- package/dist/Button/CopyToClipboardButton/CopyToClipboardButton.style.d.ts +8 -0
- package/dist/Button/CopyToClipboardButton/CopyToClipboardButton.style.js +38 -0
- package/dist/Button/CopyToClipboardButton/CopyToClipboardButton.types.d.ts +5 -0
- package/dist/Button/TextButton/TextButton.style.cjs +4 -1
- package/dist/Button/TextButton/TextButton.style.js +4 -1
- package/dist/Button/TextButton/TextButton.types.cjs +1 -1
- package/dist/Button/TextButton/TextButton.types.d.ts +1 -1
- package/dist/Button/TextButton/TextButton.types.js +1 -1
- package/dist/Button/index.d.ts +2 -0
- package/dist/Checkbox/components/Label/Label.style.cjs +15 -3
- package/dist/Checkbox/components/Label/Label.style.js +15 -3
- package/dist/Chip/components/CloseButton/CloseButton.cjs +3 -1
- package/dist/Chip/components/CloseButton/CloseButton.js +3 -1
- package/dist/Chip/components/Compose/Compose.style.cjs +4 -1
- package/dist/Chip/components/Compose/Compose.style.js +4 -1
- package/dist/Drawer/components/Description/Description.cjs +3 -1
- package/dist/Drawer/components/Description/Description.js +3 -1
- package/dist/Helpers/contexts/Popper/PopperCollisionBoundaryManager.cjs +3 -1
- package/dist/Helpers/contexts/Popper/PopperCollisionBoundaryManager.js +3 -1
- package/dist/Helpers/contexts/PrimitiveContextState.cjs +28 -16
- package/dist/Helpers/contexts/PrimitiveContextState.js +28 -16
- package/dist/Helpers/contexts/SharedId.context.cjs +9 -5
- package/dist/Helpers/contexts/SharedId.context.js +9 -5
- package/dist/Helpers/css.utils.cjs +18 -4
- package/dist/Helpers/css.utils.d.ts +15 -3
- package/dist/Helpers/css.utils.js +18 -4
- package/dist/Helpers/hooks/useScrollable.cjs +3 -1
- package/dist/Helpers/hooks/useScrollable.js +3 -1
- package/dist/Helpers/react.utils.cjs +6 -2
- package/dist/Helpers/react.utils.js +6 -2
- package/dist/HighlightedIcon/HighlightedIcon.cjs +26 -0
- package/dist/HighlightedIcon/HighlightedIcon.d.ts +3 -0
- package/dist/HighlightedIcon/HighlightedIcon.js +26 -0
- package/dist/HighlightedIcon/HighlightedIcon.style.cjs +49 -0
- package/dist/HighlightedIcon/HighlightedIcon.style.d.ts +5 -0
- package/dist/HighlightedIcon/HighlightedIcon.style.js +47 -0
- package/dist/HighlightedIcon/HighlightedIcon.types.d.ts +8 -0
- package/dist/HighlightedIcon/index.d.ts +3 -0
- package/dist/Inputs/QuantityCounter/components/InputGroup/components/ValueLabel/ValueLabel.cjs +9 -5
- package/dist/Inputs/QuantityCounter/components/InputGroup/components/ValueLabel/ValueLabel.js +9 -5
- package/dist/Inputs/components/Compose/Compose.style.cjs +29 -6
- package/dist/Inputs/components/Compose/Compose.style.js +29 -6
- package/dist/Inputs/hooks/numericInput/numericInput.utils.cjs +12 -4
- package/dist/Inputs/hooks/numericInput/numericInput.utils.js +12 -4
- package/dist/Inputs/hooks/numericInput/useNumericInput.cjs +15 -3
- package/dist/Inputs/hooks/numericInput/useNumericInput.js +15 -3
- package/dist/Loader/Loader.cjs +1 -0
- package/dist/Loader/Loader.js +1 -0
- package/dist/Menu/components/Content/components/Item/Components/Compose/Compose.style.cjs +19 -4
- package/dist/Menu/components/Content/components/Item/Components/Compose/Compose.style.js +19 -4
- package/dist/Menu/components/Content/components/Label/components/Compose/Compose.style.cjs +4 -1
- package/dist/Menu/components/Content/components/Label/components/Compose/Compose.style.js +4 -1
- package/dist/Modal/components/Content/components/Compose/Compose.cjs +3 -1
- package/dist/Modal/components/Content/components/Compose/Compose.js +3 -1
- package/dist/Modal/components/Content/components/Description/Description.cjs +3 -1
- package/dist/Modal/components/Content/components/Description/Description.js +3 -1
- package/dist/MultiSelect/components/Compose/hooks/useMultiSelectContextApi.cjs +3 -1
- package/dist/MultiSelect/components/Compose/hooks/useMultiSelectContextApi.js +3 -1
- package/dist/MultiSelect/components/Trigger/components/MultiValue/MultiValue.cjs +3 -1
- package/dist/MultiSelect/components/Trigger/components/MultiValue/MultiValue.js +3 -1
- package/dist/Overflow/Overflow.cjs +3 -1
- package/dist/Overflow/Overflow.js +3 -1
- package/dist/Overflow/Overflow.utils.cjs +15 -6
- package/dist/Overflow/Overflow.utils.js +15 -6
- package/dist/Overflow/components/OverflowContainer/OverflowContainer.cjs +3 -1
- package/dist/Overflow/components/OverflowContainer/OverflowContainer.js +3 -1
- package/dist/Pagination/components/PageSizeSelect.cjs +3 -1
- package/dist/Pagination/components/PageSizeSelect.js +3 -1
- package/dist/Popover/components/Content/Content.cjs +3 -1
- package/dist/Popover/components/Content/Content.js +3 -1
- package/dist/Popover/components/Content/components/Footer/Footer.cjs +3 -1
- package/dist/Popover/components/Content/components/Footer/Footer.js +3 -1
- package/dist/RadioGroup/components/Item/components/Label/Label.style.cjs +15 -3
- package/dist/RadioGroup/components/Item/components/Label/Label.style.js +15 -3
- package/dist/ScreenReaderAnnounce/ScreenReaderAnnounce.cjs +3 -1
- package/dist/ScreenReaderAnnounce/ScreenReaderAnnounce.js +3 -1
- package/dist/Section/components/Header/components/CollapseButton/CollapseButton.cjs +3 -1
- package/dist/Section/components/Header/components/CollapseButton/CollapseButton.js +3 -1
- package/dist/Select/components/Content/components/Option/components/Compose/Compose.style.cjs +16 -4
- package/dist/Select/components/Content/components/Option/components/Compose/Compose.style.js +16 -4
- package/dist/Select/components/Content/components/OptionList/OptionList.cjs +6 -4
- package/dist/Select/components/Content/components/OptionList/OptionList.js +6 -4
- package/dist/Select/components/Content/components/OptionList/Virtual.cjs +9 -5
- package/dist/Select/components/Content/components/OptionList/Virtual.js +9 -5
- package/dist/Select/components/Context/hooks/useSearch.cjs +3 -1
- package/dist/Select/components/Context/hooks/useSearch.js +3 -1
- package/dist/Select/components/Trigger/components/Compose/Compose.style.cjs +33 -7
- package/dist/Select/components/Trigger/components/Compose/Compose.style.js +33 -7
- package/dist/SideBar/components/Item/Item.style.cjs +14 -3
- package/dist/SideBar/components/Item/Item.style.js +14 -3
- package/dist/Skeleton/components/Circle/Circle.cjs +1 -1
- package/dist/Skeleton/components/Circle/Circle.js +1 -1
- package/dist/Skeleton/components/Square/Square.cjs +1 -1
- package/dist/Skeleton/components/Square/Square.js +1 -1
- package/dist/Slider/components/Label/Compose/Compose.cjs +3 -1
- package/dist/Slider/components/Label/Compose/Compose.js +3 -1
- package/dist/Slider/components/Mark/Compose/Compose.cjs +3 -1
- package/dist/Slider/components/Mark/Compose/Compose.js +3 -1
- package/dist/Slider/hooks/useOffset.cjs +3 -1
- package/dist/Slider/hooks/useOffset.js +3 -1
- package/dist/Stepper/Stepper.cjs +14 -5
- package/dist/Stepper/Stepper.d.ts +2 -0
- package/dist/Stepper/Stepper.js +14 -5
- package/dist/Stepper/Stepper.utils.cjs +12 -0
- package/dist/Stepper/Stepper.utils.d.ts +2 -0
- package/dist/Stepper/Stepper.utils.js +12 -0
- package/dist/Stepper/components/Compose/Compose.d.ts +1 -0
- package/dist/Stepper/components/Step/Step.cjs +2 -0
- package/dist/Stepper/components/Step/Step.d.ts +1 -0
- package/dist/Stepper/components/Step/Step.js +2 -0
- package/dist/Stepper/components/Step/components/Compose/Compose.cjs +5 -10
- package/dist/Stepper/components/Step/components/Compose/Compose.js +5 -10
- package/dist/Stepper/components/Step/components/Separator/Separator.cjs +15 -0
- package/dist/Stepper/components/Step/components/Separator/Separator.d.ts +3 -0
- package/dist/Stepper/components/Step/components/Separator/Separator.js +15 -0
- package/dist/Stepper/components/Step/components/Separator/Separator.style.cjs +24 -0
- package/dist/Stepper/components/Step/components/Separator/Separator.style.d.ts +1 -0
- package/dist/Stepper/components/Step/components/Separator/Separator.style.js +22 -0
- package/dist/Stepper/components/Step/components/Separator/Separator.types.d.ts +5 -0
- package/dist/Stepper/hooks/useStepperInteractive.cjs +12 -4
- package/dist/Stepper/hooks/useStepperInteractive.js +12 -4
- package/dist/Switch/components/Switcher/Switcher.cjs +3 -1
- package/dist/Switch/components/Switcher/Switcher.js +3 -1
- package/dist/Switch/components/Switcher/Switcher.style.cjs +31 -8
- package/dist/Switch/components/Switcher/Switcher.style.js +31 -8
- package/dist/Tabs/components/TabBar/components/Trigger/components/Marker/Marker.style.cjs +24 -5
- package/dist/Tabs/components/TabBar/components/Trigger/components/Marker/Marker.style.js +24 -5
- package/dist/Tabs/components/TabBar/components/Trigger/components/Tab/Tab.style.cjs +24 -5
- package/dist/Tabs/components/TabBar/components/Trigger/components/Tab/Tab.style.js +24 -5
- package/dist/ThemeModeSwitch/useThemeModeSwitch.cjs +6 -2
- package/dist/ThemeModeSwitch/useThemeModeSwitch.js +6 -2
- package/dist/Toast/core/content.helper.cjs +8 -4
- package/dist/Toast/core/content.helper.js +8 -4
- package/dist/Tooltip/components/Content/Content.cjs +3 -1
- package/dist/Tooltip/components/Content/Content.js +3 -1
- package/dist/TreeView/TreeView.cjs +3 -1
- package/dist/TreeView/TreeView.js +3 -1
- package/dist/TreeView/components/TreeItem/components/Compose/Compose.cjs +6 -4
- package/dist/TreeView/components/TreeItem/components/Compose/Compose.js +6 -4
- package/dist/Typography/Typography.types.cjs +4 -0
- package/dist/Typography/Typography.types.d.ts +2 -1
- package/dist/Typography/Typography.types.js +4 -0
- package/dist/index.cjs +8 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +98 -90
- package/package.json +10 -9
- package/skills/redis-ui-components/SKILL.md +126 -0
- package/skills/redis-ui-components/references/ActionIconButton.md +96 -0
- package/skills/redis-ui-components/references/AppBar.md +161 -0
- package/skills/redis-ui-components/references/AppSelectionMenu.md +184 -0
- package/skills/redis-ui-components/references/AutoCompleteSelect.md +193 -0
- package/skills/redis-ui-components/references/Badge.md +77 -0
- package/skills/redis-ui-components/references/Banner.md +563 -0
- package/skills/redis-ui-components/references/BoxSelectionGroup.md +487 -0
- package/skills/redis-ui-components/references/Breadcrumbs.md +214 -0
- package/skills/redis-ui-components/references/Button.md +169 -0
- package/skills/redis-ui-components/references/ButtonGroup.md +126 -0
- package/skills/redis-ui-components/references/Card.md +56 -0
- package/skills/redis-ui-components/references/Checkbox.md +171 -0
- package/skills/redis-ui-components/references/Chip.md +154 -0
- package/skills/redis-ui-components/references/ChipList.md +307 -0
- package/skills/redis-ui-components/references/CopyToClipboardButton.md +47 -0
- package/skills/redis-ui-components/references/CountryFlag.md +57 -0
- package/skills/redis-ui-components/references/Drawer.md +298 -0
- package/skills/redis-ui-components/references/Filters.md +162 -0
- package/skills/redis-ui-components/references/FlexDivider.md +152 -0
- package/skills/redis-ui-components/references/FlexGroup.md +149 -0
- package/skills/redis-ui-components/references/FlexItem.md +58 -0
- package/skills/redis-ui-components/references/FlexSplit.md +37 -0
- package/skills/redis-ui-components/references/FormField.md +678 -0
- package/skills/redis-ui-components/references/IconButton.md +63 -0
- package/skills/redis-ui-components/references/Input.md +295 -0
- package/skills/redis-ui-components/references/KeyValueList.md +501 -0
- package/skills/redis-ui-components/references/Label.md +238 -0
- package/skills/redis-ui-components/references/Link.md +402 -0
- package/skills/redis-ui-components/references/Loader.md +100 -0
- package/skills/redis-ui-components/references/Menu.md +988 -0
- package/skills/redis-ui-components/references/MidBar.md +358 -0
- package/skills/redis-ui-components/references/Modal.md +525 -0
- package/skills/redis-ui-components/references/MoreInfoIcon.md +119 -0
- package/skills/redis-ui-components/references/MultiSelect.md +558 -0
- package/skills/redis-ui-components/references/NumericInput.md +322 -0
- package/skills/redis-ui-components/references/Overflow.md +127 -0
- package/skills/redis-ui-components/references/Pagination.md +151 -0
- package/skills/redis-ui-components/references/PasswordInput.md +262 -0
- package/skills/redis-ui-components/references/Popover.md +868 -0
- package/skills/redis-ui-components/references/ProfileIcon.md +65 -0
- package/skills/redis-ui-components/references/ProgressBar.md +103 -0
- package/skills/redis-ui-components/references/QuantityCounter.md +555 -0
- package/skills/redis-ui-components/references/RadioGroup.md +265 -0
- package/skills/redis-ui-components/references/ScreenReaderAnnounce.md +147 -0
- package/skills/redis-ui-components/references/SearchBar.md +242 -0
- package/skills/redis-ui-components/references/SearchInput.md +213 -0
- package/skills/redis-ui-components/references/Section.md +349 -0
- package/skills/redis-ui-components/references/Select.md +517 -0
- package/skills/redis-ui-components/references/SideBar.md +468 -0
- package/skills/redis-ui-components/references/Slider.md +398 -0
- package/skills/redis-ui-components/references/Stepper.md +288 -0
- package/skills/redis-ui-components/references/Switch.md +193 -0
- package/skills/redis-ui-components/references/Tabs.md +383 -0
- package/skills/redis-ui-components/references/TextArea.md +139 -0
- package/skills/redis-ui-components/references/TextButton.md +217 -0
- package/skills/redis-ui-components/references/Toast.md +399 -0
- package/skills/redis-ui-components/references/ToggleButton.md +163 -0
- package/skills/redis-ui-components/references/Tooltip.md +636 -0
- package/skills/redis-ui-components/references/Typography.md +323 -0
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
# MultiSelect
|
|
2
|
+
|
|
3
|
+
A multi-select dropdown built on the Select primitives. Supports chip-based multi-value selection, searchable lists, virtualized rendering, select-all actions, and compound composition for custom trigger, content, and option layouts.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { MultiSelect } from '@redislabsdev/redis-ui-components';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
|------|------|---------|-------------|
|
|
15
|
+
| options | `TOption[]` (extends `SelectOption`) | *required* | Array of selectable options. |
|
|
16
|
+
| disabled | `boolean` | `false` | Disables the select. |
|
|
17
|
+
| defaultOpen | `boolean` | - | Uncontrolled initial open state. |
|
|
18
|
+
| open | `boolean` | - | Controlled open state. |
|
|
19
|
+
| onOpenChange | `(open: boolean) => void` | - | Called when the dropdown open state changes. |
|
|
20
|
+
| defaultValue | `TValue[]` | - | Uncontrolled initial selected values. |
|
|
21
|
+
| value | `TValue[]` | - | Controlled selected values. |
|
|
22
|
+
| onChange | `(value: TValue[]) => void` | - | Called when selected values change. |
|
|
23
|
+
| customCompare | `SelectCompareHandler<TOption>` | - | Custom search comparison handler for filtering options. |
|
|
24
|
+
| error | `string \| ReactElement` | - | Error message or element. Enables error state and tooltip content. |
|
|
25
|
+
| valid | `boolean` | - | Enables valid status. |
|
|
26
|
+
| placeholder | `ReactNode` | `'Select...'` | Placeholder text shown in the trigger when nothing is selected. |
|
|
27
|
+
| valueRender | `SelectValueRender<TOption>` | - | Custom render function for trigger chips and dropdown option values. |
|
|
28
|
+
| searchable | `boolean` | `false` | Enables the search input in the dropdown content. |
|
|
29
|
+
| placement | `'top' \| 'bottom' \| 'left' \| 'right'` | - | Dropdown placement relative to the trigger. |
|
|
30
|
+
| maxVisibleItems | `number` | - | Maximum visible items before scrolling. |
|
|
31
|
+
| virtualized | `boolean` | `false` | Enables virtualized rendering for long lists. |
|
|
32
|
+
| contentWidth | `string` | - | Custom width for the dropdown content. |
|
|
33
|
+
| allowSelectAll | `boolean` | `false` | Adds the select/unselect-all footer action. |
|
|
34
|
+
| allowReset | `boolean` | `true` | Shows the trigger reset button. |
|
|
35
|
+
| loading | `boolean` | `false` | Shows the loading indicator in the trigger. |
|
|
36
|
+
| id | `string` | - | Custom trigger id for label and accessibility wiring. |
|
|
37
|
+
| className | `string` | - | Class name passed through to the trigger wrapper. |
|
|
38
|
+
|
|
39
|
+
The component also extends Radix UI `SelectTriggerProps` through `RestSelectTriggerComposeProps` (excluding `children`, `placeholder`, `asChild`, and `onChange`).
|
|
40
|
+
|
|
41
|
+
### SelectOption Type
|
|
42
|
+
|
|
43
|
+
| Field | Type | Description |
|
|
44
|
+
|-------|------|-------------|
|
|
45
|
+
| value | `string` | *required* - Unique option value. |
|
|
46
|
+
| label | `string` | Optional display label. |
|
|
47
|
+
| icon | `IconType \| ComponentType` | Optional icon component. |
|
|
48
|
+
| disabled | `boolean` | Whether the option is disabled. |
|
|
49
|
+
| hidden | `boolean` | Whether the option is hidden. |
|
|
50
|
+
|
|
51
|
+
## Sub-components
|
|
52
|
+
|
|
53
|
+
- `MultiSelect.Compose` - Context provider that wires up selection state, validation state, and the trigger/content pair. Use this when building custom layouts or when you need `allowResetDisabledItems`.
|
|
54
|
+
- `MultiSelect.Trigger` - Default trigger that renders selected values as chips, plus reset, status, loading, and arrow indicators.
|
|
55
|
+
- `MultiSelect.Trigger.Compose` - Composable trigger wrapper for custom trigger UI. Use `customContainer` when you need to replace the default combobox-style button.
|
|
56
|
+
- `MultiSelect.Trigger.MultiValue` - Renders selected values as chips and the placeholder when nothing is selected. Accepts `allowRemove` to hide chip remove controls.
|
|
57
|
+
- `MultiSelect.Trigger.ResetButton` - Clears the current selection.
|
|
58
|
+
- `MultiSelect.Trigger.StatusIndicator` - Shows the validation state indicator.
|
|
59
|
+
- `MultiSelect.Trigger.LoadingIndicator` - Shows the loading indicator.
|
|
60
|
+
- `MultiSelect.Trigger.Arrow` - Dropdown arrow indicator.
|
|
61
|
+
- `MultiSelect.Trigger.ErrorIcon` - Deprecated alias for `MultiSelect.Trigger.StatusIndicator`.
|
|
62
|
+
- `MultiSelect.Content` - Default dropdown content with optional search, option list, custom `optionValueRender` / `optionComponent`, and select-all footer.
|
|
63
|
+
- `MultiSelect.Content.Compose` - Composable content wrapper for custom dropdown layouts and static elements.
|
|
64
|
+
- `MultiSelect.Content.Search` - Search input for filtering options.
|
|
65
|
+
- `MultiSelect.Content.OptionList` - Renders the list of options.
|
|
66
|
+
- `MultiSelect.Content.Footer` - Footer container used for select-all and custom footer content.
|
|
67
|
+
- `MultiSelect.Content.SelectAll` - Toggle button that selects or unselects all options. Accepts `selectAllTitle` and `unselectAllTitle`.
|
|
68
|
+
- `MultiSelect.Option` - Default multi-select option row.
|
|
69
|
+
- `MultiSelect.Option.Compose` - Composable option wrapper for custom option rendering. This is the required root for custom option components.
|
|
70
|
+
- `MultiSelect.Option.Content` - Content area inside an option row.
|
|
71
|
+
- `MultiSelect.Option.Indicator` - Selection indicator rendered for each option.
|
|
72
|
+
|
|
73
|
+
## Hooks
|
|
74
|
+
|
|
75
|
+
- `useMultiSelectContext` - Reads multi-select state inside custom trigger, content, or option components. The context exposes `getSelectAllApi(inSearchResults?)` for select/unselect-all flows, and the returned API should be memoized before reuse. `selectAll()` is deprecated.
|
|
76
|
+
|
|
77
|
+
## Examples
|
|
78
|
+
|
|
79
|
+
### MultiSelect
|
|
80
|
+
|
|
81
|
+
#### Playground
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
import { MultiSelect } from '@redislabsdev/redis-ui-components';
|
|
85
|
+
|
|
86
|
+
<MultiSelect
|
|
87
|
+
options={options}
|
|
88
|
+
searchable
|
|
89
|
+
onChange={(value) => console.log(value)}
|
|
90
|
+
onOpenChange={(open) => console.log(open)}
|
|
91
|
+
/>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
#### WithLabel
|
|
95
|
+
|
|
96
|
+
> Component doesn't have internal label or any other external decoration elements.
|
|
97
|
+
> For these purposes, use `FormField`.
|
|
98
|
+
> If a custom id is specified, `FormField` inherits it; otherwise the label is auto-connected to the select with a generated id.
|
|
99
|
+
> Custom ids must start with a letter to work correctly.
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
import { FormField, MultiSelect } from '@redislabsdev/redis-ui-components';
|
|
103
|
+
|
|
104
|
+
<FormField label="FormField Label with custom id" additionalText="Additional text">
|
|
105
|
+
<MultiSelect
|
|
106
|
+
options={options}
|
|
107
|
+
placeholder="MultiSelect placeholder"
|
|
108
|
+
id="custom-id"
|
|
109
|
+
onChange={(value) => console.log(value)}
|
|
110
|
+
onOpenChange={(open) => console.log(open)}
|
|
111
|
+
/>
|
|
112
|
+
</FormField>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### Status
|
|
116
|
+
|
|
117
|
+
> Adding `valid` enables valid status.
|
|
118
|
+
> Adding text to `error` enables error state and shows the tooltip on hover.
|
|
119
|
+
> Error status overrides valid status.
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
import { MultiSelect } from '@redislabsdev/redis-ui-components';
|
|
123
|
+
|
|
124
|
+
<>
|
|
125
|
+
Valid status
|
|
126
|
+
<MultiSelect options={options} valid onChange={(value) => console.log(value)} onOpenChange={(open) => console.log(open)} />
|
|
127
|
+
Error status
|
|
128
|
+
<MultiSelect options={options} error="Error message" onChange={(value) => console.log(value)} onOpenChange={(open) => console.log(open)} />
|
|
129
|
+
</>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### ResetButton
|
|
133
|
+
|
|
134
|
+
> The reset button appears only when something is selected.
|
|
135
|
+
> Set `allowReset` to `false` to hide it.
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
import { MultiSelect } from '@redislabsdev/redis-ui-components';
|
|
139
|
+
|
|
140
|
+
<MultiSelect
|
|
141
|
+
options={options}
|
|
142
|
+
defaultValue={['orange']}
|
|
143
|
+
allowReset={false}
|
|
144
|
+
onChange={(value) => console.log(value)}
|
|
145
|
+
onOpenChange={(open) => console.log(open)}
|
|
146
|
+
/>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### Loading
|
|
150
|
+
|
|
151
|
+
> Adding `loading` enables the loading indicator.
|
|
152
|
+
> It can be used together with other indicators and states.
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
import { MultiSelect } from '@redislabsdev/redis-ui-components';
|
|
156
|
+
|
|
157
|
+
<>
|
|
158
|
+
Loading indicator
|
|
159
|
+
<MultiSelect options={options} loading onChange={(value) => console.log(value)} onOpenChange={(open) => console.log(open)} />
|
|
160
|
+
With other elements
|
|
161
|
+
<MultiSelect
|
|
162
|
+
options={options}
|
|
163
|
+
defaultValue={['banana']}
|
|
164
|
+
valid
|
|
165
|
+
allowReset
|
|
166
|
+
loading
|
|
167
|
+
onChange={(value) => console.log(value)}
|
|
168
|
+
onOpenChange={(open) => console.log(open)}
|
|
169
|
+
/>
|
|
170
|
+
</>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
#### Disabled
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
import { MultiSelect } from '@redislabsdev/redis-ui-components';
|
|
177
|
+
|
|
178
|
+
<>
|
|
179
|
+
Default
|
|
180
|
+
<MultiSelect options={options} disabled onChange={() => {}} onOpenChange={() => {}} />
|
|
181
|
+
With selected items
|
|
182
|
+
<MultiSelect options={options} disabled value={['orange']} onChange={() => {}} onOpenChange={() => {}} />
|
|
183
|
+
With error message
|
|
184
|
+
<MultiSelect
|
|
185
|
+
options={options}
|
|
186
|
+
disabled
|
|
187
|
+
value={['banana']}
|
|
188
|
+
error="Error message"
|
|
189
|
+
loading
|
|
190
|
+
onChange={() => {}}
|
|
191
|
+
onOpenChange={() => {}}
|
|
192
|
+
/>
|
|
193
|
+
</>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
#### ValueRender
|
|
197
|
+
|
|
198
|
+
> `valueRender` customizes both trigger chips and dropdown option values.
|
|
199
|
+
> The handler receives the current `option`, `isSelected`, and `isOptionValue` flags.
|
|
200
|
+
> Returning `undefined` or `null` falls back to the default rendering.
|
|
201
|
+
> When `isOptionValue` is falsy, plain text is extracted from the rendered result for the trigger chip.
|
|
202
|
+
|
|
203
|
+
```tsx
|
|
204
|
+
import { MultiSelect, SelectValueRender } from '@redislabsdev/redis-ui-components';
|
|
205
|
+
|
|
206
|
+
const customValueRender: SelectValueRender = ({ option, isSelected, isOptionValue }) => {
|
|
207
|
+
const color = !isOptionValue ? 'green' : (isSelected && 'blueviolet') || 'orange';
|
|
208
|
+
const stateLabel = isOptionValue ? `${isSelected ? 'Selected Option' : 'Option'}` : 'Value';
|
|
209
|
+
|
|
210
|
+
return (
|
|
211
|
+
<div>
|
|
212
|
+
<span style={{ fontSize: '0.7em', color }}>{stateLabel}: </span>
|
|
213
|
+
{option.label}
|
|
214
|
+
</div>
|
|
215
|
+
);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
<MultiSelect
|
|
219
|
+
options={options}
|
|
220
|
+
defaultValue={['orange']}
|
|
221
|
+
valueRender={customValueRender}
|
|
222
|
+
onChange={(value) => console.log(value)}
|
|
223
|
+
onOpenChange={(open) => console.log(open)}
|
|
224
|
+
/>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
#### SelectAll
|
|
228
|
+
|
|
229
|
+
> `allowSelectAll` adds a footer action to select or unselect all options.
|
|
230
|
+
> When search is active, only search results are affected.
|
|
231
|
+
> Disabled options are ignored by default.
|
|
232
|
+
> Use `Ctrl+A` or `Cmd+A` while focus is on the list to toggle select-all.
|
|
233
|
+
|
|
234
|
+
```tsx
|
|
235
|
+
import { MultiSelect } from '@redislabsdev/redis-ui-components';
|
|
236
|
+
|
|
237
|
+
<MultiSelect
|
|
238
|
+
options={usStates}
|
|
239
|
+
defaultValue={['Arizona', 'California']}
|
|
240
|
+
searchable
|
|
241
|
+
allowSelectAll
|
|
242
|
+
maxVisibleItems={6}
|
|
243
|
+
onChange={(value) => console.log(value)}
|
|
244
|
+
onOpenChange={(open) => console.log(open)}
|
|
245
|
+
/>
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
#### CustomSearch
|
|
249
|
+
|
|
250
|
+
> `customCompare` replaces the default label search.
|
|
251
|
+
> The handler receives an option and a lowercase search string.
|
|
252
|
+
> Include the label in your custom comparison if you still want label matches.
|
|
253
|
+
|
|
254
|
+
```tsx
|
|
255
|
+
import {
|
|
256
|
+
MultiSelect,
|
|
257
|
+
SelectCompareHandler,
|
|
258
|
+
SelectOption,
|
|
259
|
+
SelectValueRender
|
|
260
|
+
} from '@redislabsdev/redis-ui-components';
|
|
261
|
+
|
|
262
|
+
const customCompare: SelectCompareHandler<SelectOption> = (option, searchValue) => {
|
|
263
|
+
const fieldsForSearch = [option.label, option.state as string];
|
|
264
|
+
return fieldsForSearch.some((field) => field?.toLowerCase().includes(searchValue));
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
const valueRender: SelectValueRender = ({ option }) => {
|
|
268
|
+
return (
|
|
269
|
+
<>
|
|
270
|
+
<span>{option.label}</span>
|
|
271
|
+
|
|
272
|
+
<span style={{ fontSize: '0.8em' }}>{`(${option.state})`}</span>
|
|
273
|
+
</>
|
|
274
|
+
);
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
<MultiSelect
|
|
278
|
+
options={usStates}
|
|
279
|
+
searchable
|
|
280
|
+
customCompare={customCompare}
|
|
281
|
+
valueRender={valueRender}
|
|
282
|
+
onChange={(value) => console.log(value)}
|
|
283
|
+
onOpenChange={(open) => console.log(open)}
|
|
284
|
+
/>
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
#### VirtualList
|
|
288
|
+
|
|
289
|
+
> List of options can be virtualized by adding `virtualized`.
|
|
290
|
+
> It helps with long lists without performance drops.
|
|
291
|
+
|
|
292
|
+
```tsx
|
|
293
|
+
import { FormField, MultiSelect } from '@redislabsdev/redis-ui-components';
|
|
294
|
+
|
|
295
|
+
<FormField label="Countries">
|
|
296
|
+
<MultiSelect
|
|
297
|
+
virtualized
|
|
298
|
+
searchable
|
|
299
|
+
options={countryOptions}
|
|
300
|
+
allowReset
|
|
301
|
+
defaultValue={['ua', 'us']}
|
|
302
|
+
maxVisibleItems={6}
|
|
303
|
+
onChange={(value) => console.log(value)}
|
|
304
|
+
onOpenChange={(open) => console.log(open)}
|
|
305
|
+
/>
|
|
306
|
+
</FormField>
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### MultiSelect.Trigger
|
|
310
|
+
|
|
311
|
+
#### Playground
|
|
312
|
+
|
|
313
|
+
```tsx
|
|
314
|
+
import { MultiSelect } from '@redislabsdev/redis-ui-components';
|
|
315
|
+
|
|
316
|
+
<MultiSelect.Compose options={options} onChange={(value) => console.log(value)} onOpenChange={(open) => console.log(open)}>
|
|
317
|
+
<MultiSelect.Trigger placeholder="MultiSelect fruit..." allowReset={false} />
|
|
318
|
+
<MultiSelect.Content />
|
|
319
|
+
</MultiSelect.Compose>
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
#### ValueRender
|
|
323
|
+
|
|
324
|
+
> Trigger value rendering can be customized by specifying `valueRender` on `MultiSelect.Trigger`.
|
|
325
|
+
> The handler receives the current `option`.
|
|
326
|
+
> When `isOptionValue` is falsy, plain text is extracted for the trigger chip.
|
|
327
|
+
|
|
328
|
+
```tsx
|
|
329
|
+
import { MultiSelect } from '@redislabsdev/redis-ui-components';
|
|
330
|
+
|
|
331
|
+
const valueRender = ({ option }) => {
|
|
332
|
+
return (
|
|
333
|
+
<div>
|
|
334
|
+
<span style={{ fontSize: '0.7em', color: 'green' }}> Option: </span> {option.label}
|
|
335
|
+
</div>
|
|
336
|
+
);
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
<MultiSelect.Compose
|
|
340
|
+
options={options}
|
|
341
|
+
defaultValue={['orange']}
|
|
342
|
+
onChange={(value) => console.log(value)}
|
|
343
|
+
onOpenChange={(open) => console.log(open)}
|
|
344
|
+
>
|
|
345
|
+
<MultiSelect.Trigger valueRender={valueRender} />
|
|
346
|
+
<MultiSelect.Content />
|
|
347
|
+
</MultiSelect.Compose>
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
#### CustomContainer
|
|
351
|
+
|
|
352
|
+
> `customContainer` replaces the default combobox-style button container.
|
|
353
|
+
> Wrap the custom container in a `span` or `div` if you need to avoid attribute conflicts.
|
|
354
|
+
|
|
355
|
+
```tsx
|
|
356
|
+
import { useState } from 'react';
|
|
357
|
+
import { MultiSelect, ToggleButton, useSelectContext } from '@redislabsdev/redis-ui-components';
|
|
358
|
+
|
|
359
|
+
function Render() {
|
|
360
|
+
const CustomTriggerValue = () => {
|
|
361
|
+
const { hasSelection, isOptionSelected, options } = useSelectContext();
|
|
362
|
+
|
|
363
|
+
if (!hasSelection) {
|
|
364
|
+
return <>No selection</>;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return <>Selected {options.filter(isOptionSelected).length} item(s)</>;
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
const [open, setOpen] = useState(false);
|
|
371
|
+
|
|
372
|
+
return (
|
|
373
|
+
<MultiSelect.Compose
|
|
374
|
+
options={options}
|
|
375
|
+
defaultValue={['orange']}
|
|
376
|
+
open={open}
|
|
377
|
+
onOpenChange={setOpen}
|
|
378
|
+
onChange={(value) => console.log(value)}
|
|
379
|
+
>
|
|
380
|
+
<MultiSelect.Trigger.Compose customContainer>
|
|
381
|
+
<span>
|
|
382
|
+
<ToggleButton pressed={open}>
|
|
383
|
+
<CustomTriggerValue />
|
|
384
|
+
<MultiSelect.Trigger.Arrow />
|
|
385
|
+
</ToggleButton>
|
|
386
|
+
</span>
|
|
387
|
+
</MultiSelect.Trigger.Compose>
|
|
388
|
+
<MultiSelect.Content />
|
|
389
|
+
</MultiSelect.Compose>
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
#### TriggerComposition
|
|
395
|
+
|
|
396
|
+
> Default composition example includes all parts of `MultiSelect.Trigger`.
|
|
397
|
+
|
|
398
|
+
```tsx
|
|
399
|
+
import { MultiSelect } from '@redislabsdev/redis-ui-components';
|
|
400
|
+
|
|
401
|
+
<MultiSelect.Compose
|
|
402
|
+
options={options}
|
|
403
|
+
defaultValue={['orange']}
|
|
404
|
+
error="error message"
|
|
405
|
+
onChange={(value) => console.log(value)}
|
|
406
|
+
onOpenChange={(open) => console.log(open)}
|
|
407
|
+
>
|
|
408
|
+
<MultiSelect.Trigger.Compose>
|
|
409
|
+
<MultiSelect.Trigger.MultiValue placeholder="Placeholder" />
|
|
410
|
+
<MultiSelect.Trigger.ResetButton />
|
|
411
|
+
<MultiSelect.Trigger.StatusIndicator />
|
|
412
|
+
<MultiSelect.Trigger.LoadingIndicator loading />
|
|
413
|
+
<MultiSelect.Trigger.Arrow />
|
|
414
|
+
</MultiSelect.Trigger.Compose>
|
|
415
|
+
|
|
416
|
+
<MultiSelect.Content />
|
|
417
|
+
</MultiSelect.Compose>
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### MultiSelect.Content
|
|
421
|
+
|
|
422
|
+
#### Playground
|
|
423
|
+
|
|
424
|
+
```tsx
|
|
425
|
+
import { MultiSelect } from '@redislabsdev/redis-ui-components';
|
|
426
|
+
|
|
427
|
+
<MultiSelect.Compose options={options} onChange={(value) => console.log(value)} onOpenChange={(open) => console.log(open)}>
|
|
428
|
+
<MultiSelect.Trigger />
|
|
429
|
+
<MultiSelect.Content />
|
|
430
|
+
</MultiSelect.Compose>
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
#### OptionValueRender
|
|
434
|
+
|
|
435
|
+
> `optionValueRender` customizes option values separately from trigger values.
|
|
436
|
+
> The handler receives the current `option` and `isSelected` flag.
|
|
437
|
+
|
|
438
|
+
```tsx
|
|
439
|
+
import { MultiSelect } from '@redislabsdev/redis-ui-components';
|
|
440
|
+
|
|
441
|
+
<MultiSelect.Compose
|
|
442
|
+
options={options}
|
|
443
|
+
defaultValue={['orange']}
|
|
444
|
+
onChange={(value) => console.log(value)}
|
|
445
|
+
onOpenChange={(open) => console.log(open)}
|
|
446
|
+
>
|
|
447
|
+
<MultiSelect.Trigger />
|
|
448
|
+
<MultiSelect.Content
|
|
449
|
+
optionValueRender={({ option, isSelected }) => {
|
|
450
|
+
return (
|
|
451
|
+
<div>
|
|
452
|
+
<span
|
|
453
|
+
style={{
|
|
454
|
+
fontSize: '0.7em',
|
|
455
|
+
color: (isSelected && 'blueviolet') || 'orange'
|
|
456
|
+
}}
|
|
457
|
+
>
|
|
458
|
+
{isSelected ? 'Selected Option' : 'Option'}:
|
|
459
|
+
</span>{' '}
|
|
460
|
+
{option.label}
|
|
461
|
+
</div>
|
|
462
|
+
);
|
|
463
|
+
}}
|
|
464
|
+
/>
|
|
465
|
+
</MultiSelect.Compose>
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
#### OptionComponent
|
|
469
|
+
|
|
470
|
+
> `optionComponent` renders the entire option, including the multi-selection indicator.
|
|
471
|
+
> If it is not specified, `MultiSelect` renders options using the default `MultiSelect.Option`.
|
|
472
|
+
> A custom option component can still be used together with `optionValueRender`.
|
|
473
|
+
> The custom option component must use `MultiSelect.Option.Compose` as the root element.
|
|
474
|
+
|
|
475
|
+
```tsx
|
|
476
|
+
import { MultiSelect, SelectOptionComponent } from '@redislabsdev/redis-ui-components';
|
|
477
|
+
|
|
478
|
+
const CustomOption: SelectOptionComponent = ({ option, content, ...restProps }) => (
|
|
479
|
+
<MultiSelect.Option.Compose option={option} {...restProps}>
|
|
480
|
+
<MultiSelect.Option.Content>{content}</MultiSelect.Option.Content>
|
|
481
|
+
<MultiSelect.Option.Indicator option={option} />
|
|
482
|
+
</MultiSelect.Option.Compose>
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
<MultiSelect.Compose
|
|
486
|
+
options={options}
|
|
487
|
+
defaultValue={['orange']}
|
|
488
|
+
onChange={(value) => console.log(value)}
|
|
489
|
+
onOpenChange={(open) => console.log(open)}
|
|
490
|
+
>
|
|
491
|
+
<MultiSelect.Trigger />
|
|
492
|
+
<MultiSelect.Content optionComponent={CustomOption} />
|
|
493
|
+
</MultiSelect.Compose>
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
#### ContentComposition
|
|
497
|
+
|
|
498
|
+
> This example includes all parts of `MultiSelect.Content` and shows how to place static elements inside the composed content.
|
|
499
|
+
|
|
500
|
+
```tsx
|
|
501
|
+
import { MultiSelect } from '@redislabsdev/redis-ui-components';
|
|
502
|
+
|
|
503
|
+
<MultiSelect.Compose
|
|
504
|
+
options={options}
|
|
505
|
+
allowResetDisabledItems
|
|
506
|
+
onChange={(value) => console.log(value)}
|
|
507
|
+
onOpenChange={(open) => console.log(open)}
|
|
508
|
+
>
|
|
509
|
+
<MultiSelect.Trigger />
|
|
510
|
+
<MultiSelect.Content.Compose>
|
|
511
|
+
<div style={{ textAlign: 'center' }}>Top static element</div>
|
|
512
|
+
<MultiSelect.Content.Search />
|
|
513
|
+
<div style={{ textAlign: 'center' }}>Middle static element</div>
|
|
514
|
+
<MultiSelect.Content.OptionList style={{ maxHeight: 100 }} />
|
|
515
|
+
<div style={{ textAlign: 'center' }}>Bottom static element</div>
|
|
516
|
+
<MultiSelect.Content.Footer>
|
|
517
|
+
<div style={{ textAlign: 'center' }}>Custom element in Footer</div>
|
|
518
|
+
<MultiSelect.Content.SelectAll selectAllTitle="Select all fruits" unselectAllTitle="Select none" />
|
|
519
|
+
</MultiSelect.Content.Footer>
|
|
520
|
+
</MultiSelect.Content.Compose>
|
|
521
|
+
</MultiSelect.Compose>
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
#### ContentListComposition
|
|
525
|
+
|
|
526
|
+
> Adding an extra list container lets static elements scroll with the options.
|
|
527
|
+
|
|
528
|
+
```tsx
|
|
529
|
+
import { MultiSelect } from '@redislabsdev/redis-ui-components';
|
|
530
|
+
|
|
531
|
+
<MultiSelect.Compose
|
|
532
|
+
options={options}
|
|
533
|
+
allowResetDisabledItems
|
|
534
|
+
onChange={(value) => console.log(value)}
|
|
535
|
+
onOpenChange={(open) => console.log(open)}
|
|
536
|
+
>
|
|
537
|
+
<MultiSelect.Trigger />
|
|
538
|
+
<MultiSelect.Content.Compose>
|
|
539
|
+
<MultiSelect.Content.Search />
|
|
540
|
+
<div style={{ overflowY: 'auto', maxHeight: 200 }}>
|
|
541
|
+
<div style={{ textAlign: 'center' }}>Top scrollable element</div>
|
|
542
|
+
<MultiSelect.Content.OptionList />
|
|
543
|
+
<div style={{ textAlign: 'center' }}>Bottom scrollable element</div>
|
|
544
|
+
</div>
|
|
545
|
+
</MultiSelect.Content.Compose>
|
|
546
|
+
</MultiSelect.Compose>
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
## Notes
|
|
550
|
+
|
|
551
|
+
- `FormField` is the recommended way to add an external label or additional text.
|
|
552
|
+
- `error` overrides `valid`, and the error indicator tooltip shows the error text.
|
|
553
|
+
- `valueRender` customizes both trigger chips and dropdown option values; return `undefined` or `null` to fall back to the default rendering.
|
|
554
|
+
- Use `MultiSelect.Content` or `MultiSelect.Compose` directly when you need `optionValueRender` or `optionComponent`; the top-level wrapper only exposes `valueRender`.
|
|
555
|
+
- `allowSelectAll` affects only the current search results when search is active.
|
|
556
|
+
- `MultiSelect.Trigger.ErrorIcon` is deprecated; use `StatusIndicator`.
|
|
557
|
+
- `allowResetDisabledItems` is available on `MultiSelect.Compose`, not on the top-level `MultiSelect` wrapper.
|
|
558
|
+
- `useMultiSelectContext` is exported for custom trigger and option components.
|