@altruist03/ui 0.1.0 → 0.2.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 (207) hide show
  1. package/assets/images/noData.webp +0 -0
  2. package/dist/index.js +15237 -650
  3. package/dist/index.js.map +1 -1
  4. package/dist/noData-XPRHKMFR.webp +0 -0
  5. package/package.json +21 -7
  6. package/src/ThemeProvider/ThemeContext.tsx +75 -0
  7. package/src/ThemeProvider/index.ts +7 -0
  8. package/src/assets/images/noData.webp +0 -0
  9. package/src/assets.d.ts +10 -0
  10. package/src/components/Accordion/Accordion.stories.tsx +64 -0
  11. package/src/components/Accordion/Accordion.tsx +219 -0
  12. package/src/components/Accordion/Accordion.types.ts +16 -0
  13. package/src/components/Avatar/Avatar.stories.tsx +304 -0
  14. package/src/components/Avatar/Avatar.tsx +211 -0
  15. package/src/components/Avatar/Avatar.types.ts +33 -0
  16. package/src/components/Badge/Badge.stories.tsx +143 -0
  17. package/src/components/Badge/Badge.tsx +138 -0
  18. package/src/components/Badge/Badge.types.ts +24 -0
  19. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +114 -0
  20. package/src/components/Breadcrumb/Breadcrumb.tsx +120 -0
  21. package/src/components/Breadcrumb/Breadcrumb.types.ts +22 -0
  22. package/src/components/Button/Button.stories.tsx +457 -0
  23. package/src/components/Button/Button.tsx +202 -0
  24. package/src/components/Button/Button.types.ts +18 -0
  25. package/src/components/Checkbox/Checkbox.stories.tsx +254 -0
  26. package/src/components/Checkbox/Checkbox.tsx +352 -0
  27. package/src/components/Checkbox/Checkbox.types.ts +123 -0
  28. package/src/components/CloseButton/CloseButton.stories.tsx +100 -0
  29. package/src/components/CloseButton/CloseButton.tsx +117 -0
  30. package/src/components/CloseButton/CloseButton.types.ts +15 -0
  31. package/src/components/CollapsibleSearch/CollapsibleSearch.tsx +120 -0
  32. package/src/components/DataTable/DataTable.stories.tsx +233 -0
  33. package/src/components/DataTable/DataTable.tsx +968 -0
  34. package/src/components/DataTable/DataTable.types.ts +49 -0
  35. package/src/components/DatePicker/DatePicker.stories.tsx +341 -0
  36. package/src/components/DatePicker/DatePicker.tsx +669 -0
  37. package/src/components/DatePicker/DatePicker.types.ts +105 -0
  38. package/src/components/DatePicker/DateTimePicker.tsx +35 -0
  39. package/src/components/DateRangePicker/DateRangePicker.tsx +179 -0
  40. package/src/components/DateRangePicker/DateRangePicker.types.ts +34 -0
  41. package/src/components/Drawer/Drawer.stories.tsx +243 -0
  42. package/src/components/Drawer/Drawer.tsx +196 -0
  43. package/src/components/Drawer/Drawer.types.ts +60 -0
  44. package/src/components/FileUpload/FileUpload.stories.tsx +162 -0
  45. package/src/components/FileUpload/FileUpload.tsx +216 -0
  46. package/src/components/FileUpload/FileUpload.types.ts +80 -0
  47. package/src/components/FilterPopover/FilterPopover.stories.tsx +173 -0
  48. package/src/components/FilterPopover/FilterPopover.tsx +310 -0
  49. package/src/components/FilterPopover/FilterPopover.types.ts +26 -0
  50. package/src/components/ImageViewer/ImageViewerToolbar.jsx +81 -0
  51. package/src/components/ImageViewer/useImagePanRotate.js +102 -0
  52. package/src/components/IpWhitelistField/IpWhitelistField.stories.tsx +138 -0
  53. package/src/components/IpWhitelistField/IpWhitelistField.tsx +164 -0
  54. package/src/components/IpWhitelistField/IpWhitelistField.types.ts +42 -0
  55. package/src/components/Loader/Loader.stories.tsx +95 -0
  56. package/src/components/Loader/Loader.tsx +132 -0
  57. package/src/components/Loader/Loader.types.ts +6 -0
  58. package/src/components/Menu/Menu.tsx +143 -0
  59. package/src/components/Menu/Menu.types.ts +28 -0
  60. package/src/components/MenuButton/MenuButton.stories.tsx +140 -0
  61. package/src/components/MenuButton/MenuButton.tsx +45 -0
  62. package/src/components/MenuButton/MenuButton.types.ts +21 -0
  63. package/src/components/Modal/Modal.stories.tsx +266 -0
  64. package/src/components/Modal/Modal.tsx +399 -0
  65. package/src/components/Modal/index.ts +2 -0
  66. package/src/components/Modal/types.ts +126 -0
  67. package/src/components/Pagination/Pagination.stories.tsx +167 -0
  68. package/src/components/Pagination/Pagination.tsx +266 -0
  69. package/src/components/Pagination/Pagination.types.ts +20 -0
  70. package/src/components/PeriodSelector/PeriodSelector.stories.tsx +50 -0
  71. package/src/components/PeriodSelector/PeriodSelector.tsx +47 -0
  72. package/src/components/PeriodSelector/PeriodSelector.types.ts +10 -0
  73. package/src/components/PhoneField/PhoneField.stories.tsx +141 -0
  74. package/src/components/PhoneField/PhoneField.tsx +284 -0
  75. package/src/components/PhoneField/PhoneField.types.ts +89 -0
  76. package/src/components/PhoneField/countryCodes.ts +236 -0
  77. package/src/components/Progress/Progress.stories.tsx +83 -0
  78. package/src/components/Progress/Progress.tsx +91 -0
  79. package/src/components/Progress/Progress.types.ts +22 -0
  80. package/src/components/RadioButton/RadioButton.stories.tsx +332 -0
  81. package/src/components/RadioButton/RadioButton.tsx +427 -0
  82. package/src/components/RadioButton/RadioButton.types.ts +117 -0
  83. package/src/components/ReportCard/ReportCard.tsx +183 -0
  84. package/src/components/ReportCard/ReportCard.types.ts +17 -0
  85. package/src/components/SectionIcon/SectionIcon.tsx +87 -0
  86. package/src/components/SectionIcon/SectionIcon.types.ts +23 -0
  87. package/src/components/SegmentedInputField/SegmentedInputField.stories.tsx +165 -0
  88. package/src/components/SegmentedInputField/SegmentedInputField.tsx +174 -0
  89. package/src/components/SegmentedInputField/SegmentedInputField.types.ts +51 -0
  90. package/src/components/SelectScroll/SelectScroll.stories.tsx +336 -0
  91. package/src/components/SelectScroll/SelectScroll.tsx +1119 -0
  92. package/src/components/SelectScroll/SelectScroll.types.ts +60 -0
  93. package/src/components/Selector/Selector.stories.tsx +382 -0
  94. package/src/components/Selector/Selector.tsx +1310 -0
  95. package/src/components/Selector/Selector.types.ts +71 -0
  96. package/src/components/Skeleton/Skeleton.stories.tsx +133 -0
  97. package/src/components/Skeleton/Skeleton.tsx +20 -0
  98. package/src/components/Skeleton/Skeleton.types.ts +3 -0
  99. package/src/components/Spinner/Spinner.stories.tsx +84 -0
  100. package/src/components/Spinner/Spinner.tsx +79 -0
  101. package/src/components/Spinner/Spinner.types.ts +8 -0
  102. package/src/components/StatCard/StatCard.stories.tsx +125 -0
  103. package/src/components/StatCard/StatCard.tsx +167 -0
  104. package/src/components/StatCard/StatCard.types.ts +20 -0
  105. package/src/components/StatusBadge/StatusBadge.stories.tsx +179 -0
  106. package/src/components/StatusBadge/StatusBadge.tsx +74 -0
  107. package/src/components/StatusBadge/StatusBadge.types.ts +23 -0
  108. package/src/components/Stepper/Stepper.stories.tsx +85 -0
  109. package/src/components/Stepper/Stepper.tsx +138 -0
  110. package/src/components/Stepper/Stepper.types.ts +16 -0
  111. package/src/components/SubTabs/SubTabs.stories.tsx +128 -0
  112. package/src/components/SubTabs/SubTabs.tsx +279 -0
  113. package/src/components/SubTabs/SubTabs.types.ts +44 -0
  114. package/src/components/SummaryCard/SummaryCard.stories.tsx +100 -0
  115. package/src/components/SummaryCard/SummaryCard.tsx +141 -0
  116. package/src/components/SummaryCard/SummaryCard.types.ts +22 -0
  117. package/src/components/Switch/Switch.stories.tsx +59 -0
  118. package/src/components/Switch/Switch.tsx +217 -0
  119. package/src/components/Switch/Switch.types.ts +22 -0
  120. package/src/components/Tabs/Tabs.stories.tsx +178 -0
  121. package/src/components/Tabs/Tabs.tsx +197 -0
  122. package/src/components/Tabs/Tabs.types.ts +34 -0
  123. package/src/components/TextField/TextField.stories.tsx +249 -0
  124. package/src/components/TextField/TextField.tsx +462 -0
  125. package/src/components/TextField/TextField.types.ts +141 -0
  126. package/src/components/Toast/Toast.stories.tsx +237 -0
  127. package/src/components/Toast/Toast.tsx +246 -0
  128. package/src/components/Toast/Toast.types.ts +31 -0
  129. package/src/components/ToggleButton/ToggleButton.stories.tsx +105 -0
  130. package/src/components/ToggleButton/ToggleButton.tsx +267 -0
  131. package/src/components/ToggleButton/ToggleButton.types.ts +19 -0
  132. package/src/components/UploadDropzone/UploadDropzone.jsx +78 -0
  133. package/src/components/UploadDropzone2/UploadDropzone.stories.tsx +94 -0
  134. package/src/components/UploadDropzone2/UploadDropzone.tsx +222 -0
  135. package/src/components/UploadDropzone2/UploadDropzone.types.ts +54 -0
  136. package/src/components/ViewEditToggle/ViewEditToggle.stories.tsx +40 -0
  137. package/src/components/ViewEditToggle/ViewEditToggle.tsx +239 -0
  138. package/src/components/ViewEditToggle/ViewEditToggle.types.ts +27 -0
  139. package/src/components/index.ts +157 -0
  140. package/src/icons/ReportDollarIcon.tsx +71 -0
  141. package/src/icons/index.ts +27 -0
  142. package/src/index.ts +214 -0
  143. package/src/storybook/preview.tsx +64 -0
  144. package/src/theme/index.ts +4 -0
  145. package/src/theme/types.d.ts +1 -0
  146. package/src/themes/cpc.ts +4 -0
  147. package/src/themes/firebird.ts +4 -0
  148. package/src/tokens/brands/cpc/themes/dark.json +82 -0
  149. package/src/tokens/brands/cpc/themes/light.json +1 -0
  150. package/src/tokens/brands/default/brand.json +20 -0
  151. package/src/tokens/brands/firebird/themes/dark.json +28 -0
  152. package/src/tokens/brands/firebird/themes/light.json +20 -0
  153. package/src/tokens/button.ts +24 -0
  154. package/src/tokens/components/accordion.json +52 -0
  155. package/src/tokens/components/avatar.json +40 -0
  156. package/src/tokens/components/badge.json +41 -0
  157. package/src/tokens/components/breadcrumb.json +13 -0
  158. package/src/tokens/components/button.json +67 -0
  159. package/src/tokens/components/card.json +39 -0
  160. package/src/tokens/components/checkbox.json +64 -0
  161. package/src/tokens/components/closebutton.json +55 -0
  162. package/src/tokens/components/datatable.json +40 -0
  163. package/src/tokens/components/datepicker.json +99 -0
  164. package/src/tokens/components/drawer.json +23 -0
  165. package/src/tokens/components/field.json +29 -0
  166. package/src/tokens/components/fileupload.json +57 -0
  167. package/src/tokens/components/filterpopover.json +29 -0
  168. package/src/tokens/components/input.json +31 -0
  169. package/src/tokens/components/ipwhitelistfield.json +16 -0
  170. package/src/tokens/components/loader.json +15 -0
  171. package/src/tokens/components/menu.json +21 -0
  172. package/src/tokens/components/modal.json +25 -0
  173. package/src/tokens/components/pagination.json +45 -0
  174. package/src/tokens/components/phonefield.json +41 -0
  175. package/src/tokens/components/progress.json +12 -0
  176. package/src/tokens/components/radio.json +87 -0
  177. package/src/tokens/components/reportcard.json +17 -0
  178. package/src/tokens/components/selector.json +87 -0
  179. package/src/tokens/components/selectscroll.json +65 -0
  180. package/src/tokens/components/skeleton.json +6 -0
  181. package/src/tokens/components/stepper.json +38 -0
  182. package/src/tokens/components/subtabs.json +45 -0
  183. package/src/tokens/components/switch.json +55 -0
  184. package/src/tokens/components/tabs.json +38 -0
  185. package/src/tokens/components/textfield.json +59 -0
  186. package/src/tokens/components/togglebutton.json +48 -0
  187. package/src/tokens/components/uploaddropzone.json +61 -0
  188. package/src/tokens/drawer.ts +37 -0
  189. package/src/tokens/foundation/breakpoints.json +10 -0
  190. package/src/tokens/foundation/colors.json +122 -0
  191. package/src/tokens/foundation/opacity.json +16 -0
  192. package/src/tokens/foundation/radius.json +14 -0
  193. package/src/tokens/foundation/size.json +38 -0
  194. package/src/tokens/foundation/spacing.json +19 -0
  195. package/src/tokens/foundation/typography.json +43 -0
  196. package/src/tokens/index.ts +3665 -0
  197. package/src/tokens/modal.ts +42 -0
  198. package/src/tokens/semantic/color.json +148 -0
  199. package/src/tokens/semantic/field.json +28 -0
  200. package/src/tokens/semantic/opacity.json +5 -0
  201. package/src/tokens/semantic/size.json +722 -0
  202. package/src/tokens/semantic/spacing.json +27 -0
  203. package/src/tokens/semantic/typography.json +87 -0
  204. package/src/utils/scrollLock.ts +44 -0
  205. package/dist/index.css +0 -514
  206. package/dist/index.css.map +0 -1
  207. package/dist/index.d.ts +0 -289
@@ -0,0 +1,60 @@
1
+ import React from 'react';
2
+
3
+ export type SelectScrollOption = string | { label?: string; [key: string]: unknown };
4
+
5
+ export interface SelectScrollProps<T = SelectScrollOption> {
6
+ placeholder?: string;
7
+ options?: T[];
8
+ isDisabled?: boolean;
9
+ onChange?: (value: T | null) => void;
10
+ value?: T | null;
11
+ required?: boolean;
12
+ isOptionDisabled?: (option: T) => boolean;
13
+ loading?: boolean;
14
+ onScroll?: (e: React.UIEvent<HTMLUListElement>) => void;
15
+ /** Called when list is scrolled near bottom (e.g. to load next page). Pass your API/loadMore function from parent. */
16
+ onLoadMore?: () => void;
17
+ /** API method to load more: (pageNum, append) => void. Use with loadMorePage, onLoadMorePageChange, loadMoreHasMore. */
18
+ loadMoreMethod?: (pageNum: number, append: boolean) => void;
19
+ /** Current page when using loadMoreMethod (parent state). */
20
+ loadMorePage?: number;
21
+ /** Callback when page changes (e.g. setPage from parent). */
22
+ onLoadMorePageChange?: (nextPage: number) => void;
23
+ /** Whether more data is available when using loadMoreMethod. */
24
+ loadMoreHasMore?: boolean;
25
+ label?: string;
26
+ size?: 'sm' | 'md' | 'lg';
27
+ getOptionLabel?: (option: T) => string;
28
+ isInvalid?: boolean;
29
+ error?: string;
30
+ /** Shown below input when not in error state (when isInvalid is false). */
31
+ helperText?: string;
32
+ renderOption?: (option: T, state: { index: number }) => React.ReactNode;
33
+ onInputChange?: (value: string) => void;
34
+ customRenderOptionView?: (option: T) => React.ReactNode;
35
+ onBlur?: (e: React.FocusEvent) => void;
36
+ id?: string;
37
+ noOptionsText?: string;
38
+ loadingText?: string;
39
+ style?: React.CSSProperties;
40
+ /** Custom filter: (options, { inputValue, getOptionLabel }) => filtered options. When not provided, filters by input matching option label. */
41
+ filterOptions?: (
42
+ options: T[],
43
+ state: { inputValue: string; getOptionLabel: (option: T) => string }
44
+ ) => T[];
45
+ /**
46
+ * When true (default), options are server-driven: no client-side label filtering.
47
+ * Use `onApiSearch` for debounced backend search.
48
+ */
49
+ isApiSearch?: boolean;
50
+ /** Debounce (ms) before `onApiSearch`. Default 1000. */
51
+ apiSearchDebounceMs?: number;
52
+ /** Called after debounce with trimmed search when `isApiSearch` is true. */
53
+ onApiSearch?: (searchTerm: string) => void;
54
+ /** Fires when the dropdown opens or closes (not on initial mount). */
55
+ onOpenChange?: (open: boolean) => void;
56
+ /** Shows clear (X) action and allows clearing when true. */
57
+ clearable?: boolean;
58
+ /** Custom equality for highlighting the selected option. Defaults to matching `value`/`id`, then label. */
59
+ isOptionEqual?: (option: T, value: T) => boolean;
60
+ }
@@ -0,0 +1,382 @@
1
+ import React, { useState } from "react";
2
+ import type { Meta, StoryObj } from "@storybook/react";
3
+ import Selector from "./Selector";
4
+ import type { SelectorProps, SelectorOption } from "./Selector.types";
5
+
6
+ // Sample options
7
+ const countryOptions = [
8
+ "India",
9
+ "Afghanistan",
10
+ "UAE",
11
+ "Albania",
12
+ "Algeria",
13
+ "Andorra",
14
+ "Antigua and Barbuda",
15
+ "Argentina",
16
+ "Armenia",
17
+ "Australia",
18
+ "Austria",
19
+ "Bahrain",
20
+ ];
21
+
22
+ const usernameOptions = [
23
+ "John Doe",
24
+ "Jane Smith",
25
+ "Jim Beam",
26
+ "Jill Johnson",
27
+ "Jack Johnson",
28
+ ];
29
+
30
+ // Options with objects
31
+ const countryObjectOptions = [
32
+ { label: "India", code: "in" },
33
+ { label: "Afghanistan", code: "af" },
34
+ { label: "UAE", code: "ae" },
35
+ { label: "Albania", code: "al" },
36
+ { label: "Algeria", code: "dz" },
37
+ ];
38
+
39
+ type RegionCountryOption = { label: string; code: string; region: string };
40
+
41
+ const regionCountryOptions: RegionCountryOption[] = [
42
+ { label: "India", code: "in", region: "Asia" },
43
+ { label: "Afghanistan", code: "af", region: "Asia" },
44
+ { label: "UAE", code: "ae", region: "Asia" },
45
+ { label: "Albania", code: "al", region: "Europe" },
46
+ { label: "Andorra", code: "ad", region: "Europe" },
47
+ { label: "Argentina", code: "ar", region: "South America" },
48
+ { label: "Australia", code: "au", region: "Oceania" },
49
+ { label: "Algeria", code: "dz", region: "Africa" },
50
+ ];
51
+
52
+ const meta: Meta<typeof Selector> = {
53
+ title: "Design System/Selector",
54
+ component: Selector,
55
+ tags: [],
56
+ decorators: [
57
+ (Story) => (
58
+ <div style={{ padding: "24px", maxWidth: "420px" }}>
59
+ <Story />
60
+ </div>
61
+ ),
62
+ ],
63
+ args: {
64
+ label: "Select Country",
65
+ placeholder: "Select a country",
66
+ error: "",
67
+ helperText: "",
68
+ size: "md",
69
+ options: countryOptions,
70
+ value: null,
71
+ color: "grey",
72
+ } as SelectorProps<SelectorOption>,
73
+ argTypes: {
74
+ color: {
75
+ control: { type: "radio" },
76
+ options: ["grey", "white"],
77
+ },
78
+ size: {
79
+ control: { type: "radio" },
80
+ options: ["xs", "sm", "md", "lg"],
81
+ description: "Size of the select scroll field",
82
+ },
83
+ error: {
84
+ control: { type: "text" },
85
+ description: "Error message displayed when in error state",
86
+ },
87
+ helperText: {
88
+ control: { type: "text" },
89
+ description: "Helper text displayed when not in error state",
90
+ },
91
+ disabled: {
92
+ control: { type: "boolean" },
93
+ description: "Disables the field",
94
+ },
95
+ loading: {
96
+ control: { type: "boolean" },
97
+ description: "Shows loading state",
98
+ },
99
+ loadingText: {
100
+ control: { type: "text" },
101
+ description: "Text shown when loading",
102
+ },
103
+ noOptionsText: {
104
+ control: { type: "text" },
105
+ description: "Text shown when no options are available",
106
+ },
107
+ },
108
+ };
109
+
110
+ export default meta;
111
+
112
+ type Story = StoryObj<typeof Selector>;
113
+
114
+ export const Playground: Story = {
115
+ args: {
116
+ label: "Select Country",
117
+ placeholder: "Select a country",
118
+ options: countryOptions,
119
+ value: null,
120
+ multiple: false,
121
+ },
122
+ render: (args) => {
123
+ const [value, setValue] = useState<any>(args.value);
124
+
125
+ // Sync external control changes if any
126
+ React.useEffect(() => {
127
+ setValue(args.value);
128
+ }, [args.value]);
129
+
130
+ return (
131
+ <Selector
132
+ {...args}
133
+ value={value}
134
+ onChange={(newValue) => {
135
+ setValue(newValue);
136
+ }}
137
+ />
138
+ );
139
+ },
140
+ };
141
+
142
+ const ShowcaseComponent = () => {
143
+ const [singleValue1, setSingleValue1] = useState<string | null>(null);
144
+ const [singleValue2, setSingleValue2] = useState<string | null>("Jim Beam");
145
+ const [singleValue3, setSingleValue3] = useState<string | null>(null);
146
+ const [singleValue4, setSingleValue4] = useState<string | null>(null);
147
+ const [singleValue5, setSingleValue5] = useState<string | null>("India");
148
+ const [singleValue6, setSingleValue6] = useState<string | null>(null);
149
+ const [singleValue7, setSingleValue7] = useState<string | null>(null);
150
+ const [singleValue8, setSingleValue8] = useState<{
151
+ label: string;
152
+ code: string;
153
+ } | null>(null);
154
+ const [singleValue9, setSingleValue9] = useState<RegionCountryOption | null>(
155
+ null,
156
+ );
157
+ const [singleValue10, setSingleValue10] =
158
+ useState<RegionCountryOption | null>(null);
159
+
160
+ const [multipleValue1, setMultipleValue1] = useState<string[]>([]);
161
+ const [multipleValue2, setMultipleValue2] = useState<string[]>([
162
+ "India",
163
+ "UAE",
164
+ "Australia",
165
+ ]);
166
+ const [multipleValue3, setMultipleValue3] = useState<string[]>([
167
+ "India",
168
+ "Afghanistan",
169
+ "UAE",
170
+ "Albania",
171
+ "Algeria",
172
+ "Argentina",
173
+ ]);
174
+ const [multipleValue4, setMultipleValue4] = useState<string[]>([
175
+ "India",
176
+ "UAE",
177
+ ]);
178
+ const [multipleValue5, setMultipleValue5] = useState<string[]>([
179
+ "India",
180
+ "UAE",
181
+ ]);
182
+ const [multipleValue6, setMultipleValue6] = useState<
183
+ { label: string; code: string }[]
184
+ >([]);
185
+
186
+ return (
187
+ <div style={{ display: "flex", flexDirection: "column", gap: "24px" }}>
188
+ {/* Default / Empty */}
189
+ <Selector
190
+ label="Select Country"
191
+ placeholder="Select a country"
192
+ options={countryOptions}
193
+ value={singleValue1}
194
+ onChange={(value) => setSingleValue1(value as string | null)}
195
+ />
196
+
197
+ {/* Color: white */}
198
+ <Selector
199
+ label="Select Country (white)"
200
+ placeholder="Select a country"
201
+ options={countryOptions}
202
+ value={singleValue1}
203
+ onChange={(value) => setSingleValue1(value as string | null)}
204
+ color="white"
205
+ />
206
+
207
+ {/* With Value */}
208
+ <Selector
209
+ label="Username"
210
+ placeholder="Select a username"
211
+ options={usernameOptions}
212
+ value={singleValue2}
213
+ onChange={(value) => setSingleValue2(value as string | null)}
214
+ />
215
+
216
+ {/* Error State */}
217
+ <Selector
218
+ label="Select Country"
219
+ placeholder="Select a country"
220
+ options={countryOptions}
221
+ value={singleValue3}
222
+ onChange={(value) => setSingleValue3(value as string | null)}
223
+ error="Please select a valid country"
224
+ />
225
+
226
+ {/* With Helper Text */}
227
+ <Selector
228
+ label="Select Country"
229
+ placeholder="Select a country"
230
+ options={countryOptions}
231
+ value={singleValue4}
232
+ onChange={(value) => setSingleValue4(value as string | null)}
233
+ helperText="Select your country of residence"
234
+ />
235
+
236
+ {/* Disabled */}
237
+ <Selector
238
+ label="Select Country"
239
+ placeholder="Select a country"
240
+ options={countryOptions}
241
+ value={singleValue5}
242
+ onChange={(value) => setSingleValue5(value as string | null)}
243
+ disabled
244
+ />
245
+
246
+ {/* Extra Small Size */}
247
+ <Selector
248
+ label="Select Country"
249
+ placeholder="Select a country"
250
+ size="xs"
251
+ options={countryOptions}
252
+ value={singleValue6}
253
+ onChange={(value) => setSingleValue6(value as string | null)}
254
+ />
255
+
256
+ {/* Small Size */}
257
+ <Selector
258
+ label="Select Country"
259
+ placeholder="Select a country"
260
+ size="sm"
261
+ options={countryOptions}
262
+ value={singleValue7}
263
+ onChange={(value) => setSingleValue7(value as string | null)}
264
+ />
265
+
266
+ {/* With Object Options */}
267
+ <Selector
268
+ label="Select Country (Object)"
269
+ placeholder="Select a country"
270
+ options={countryObjectOptions}
271
+ value={singleValue8}
272
+ onChange={(value) =>
273
+ setSingleValue8(value as { label: string; code: string } | null)
274
+ }
275
+ getOptionLabel={(option) =>
276
+ typeof option === "string" ? option : option.label
277
+ }
278
+ />
279
+
280
+ {/* Grouped Options - Default Group UI */}
281
+ <Selector
282
+ label="Select Country (Grouped)"
283
+ placeholder="Search country"
284
+ options={regionCountryOptions}
285
+ value={singleValue9}
286
+ onChange={(value) =>
287
+ setSingleValue9(value as RegionCountryOption | null)
288
+ }
289
+ groupBy={(option) => option.region}
290
+ />
291
+
292
+ {/* Grouped Options - Custom renderGroup (MUI-style) */}
293
+ <Selector
294
+ label="Select Country (Grouped, Custom Render)"
295
+ placeholder="Search country"
296
+ options={regionCountryOptions}
297
+ value={singleValue10}
298
+ onChange={(value) =>
299
+ setSingleValue10(value as RegionCountryOption | null)
300
+ }
301
+ groupBy={(option) => option.region}
302
+ renderGroup={(params) => (
303
+ <ul style={{ listStyle: "none", margin: 0, padding: 0 }}>
304
+ {params.children}
305
+ </ul>
306
+ )}
307
+ />
308
+
309
+ {/* Multiple Select - Empty */}
310
+ <Selector
311
+ label="Select Countries (Multiple)"
312
+ placeholder="Select countries"
313
+ options={countryOptions}
314
+ value={multipleValue1}
315
+ onChange={(value) => setMultipleValue1(value as string[])}
316
+ multiple
317
+ />
318
+
319
+ {/* Multiple Select - With Values */}
320
+ <Selector
321
+ label="Selected Countries"
322
+ placeholder="Select countries"
323
+ options={countryOptions}
324
+ value={multipleValue2}
325
+ onChange={(value) => setMultipleValue2(value as string[])}
326
+ multiple
327
+ />
328
+
329
+ {/* Multiple Select - With Limit Tags */}
330
+ <Selector
331
+ label="Select Countries (Limited Tags)"
332
+ placeholder="Select countries"
333
+ options={countryOptions}
334
+ value={multipleValue3}
335
+ onChange={(value) => setMultipleValue3(value as string[])}
336
+ multiple
337
+ limitTags={3}
338
+ />
339
+
340
+ {/* Multiple Select - Disabled */}
341
+ <Selector
342
+ label="Select Countries (Disabled)"
343
+ placeholder="Select countries"
344
+ options={countryOptions}
345
+ value={multipleValue4}
346
+ onChange={(value) => setMultipleValue4(value as string[])}
347
+ multiple
348
+ disabled
349
+ />
350
+
351
+ {/* Multiple Select - Small Size */}
352
+ <Selector
353
+ label="Select Countries (Small)"
354
+ placeholder="Select countries"
355
+ options={countryOptions}
356
+ value={multipleValue5}
357
+ onChange={(value) => setMultipleValue5(value as string[])}
358
+ multiple
359
+ size="sm"
360
+ />
361
+
362
+ {/* Multiple Select - With Object Options */}
363
+ <Selector
364
+ label="Select Countries (Object, Multiple)"
365
+ placeholder="Select countries"
366
+ options={countryObjectOptions}
367
+ value={multipleValue6}
368
+ onChange={(value) =>
369
+ setMultipleValue6(value as { label: string; code: string }[])
370
+ }
371
+ multiple
372
+ getOptionLabel={(option) =>
373
+ typeof option === "string" ? option : option.label
374
+ }
375
+ />
376
+ </div>
377
+ );
378
+ };
379
+
380
+ export const Showcase: Story = {
381
+ render: () => <ShowcaseComponent />,
382
+ };