@altruist03/ui 0.0.0-stage → 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 (205) hide show
  1. package/assets/images/noData.webp +0 -0
  2. package/dist/index.js +15318 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/noData-XPRHKMFR.webp +0 -0
  5. package/package.json +51 -4
  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/README.md +0 -3
@@ -0,0 +1,336 @@
1
+ import React, { useCallback, useState } from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import SelectScroll from './SelectScroll';
4
+ import type { SelectScrollProps } from './SelectScroll.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 = ['John Doe', 'Jane Smith', 'Jim Beam', 'Jill Johnson', 'Jack Johnson'];
23
+
24
+ // Options with objects
25
+ const countryObjectOptions = [
26
+ { label: 'India', code: 'in' },
27
+ { label: 'Afghanistan', code: 'af' },
28
+ { label: 'UAE', code: 'ae' },
29
+ { label: 'Albania', code: 'al' },
30
+ { label: 'Algeria', code: 'dz' },
31
+ ];
32
+
33
+ /** Mock directory for the Showcase / API search demo (simulates server-side filtering). */
34
+ const MOCK_API_USERS: { id: string; displayName: string }[] = [
35
+ { id: 'u1', displayName: 'Alice Anderson' },
36
+ { id: 'u2', displayName: 'Bob Brown' },
37
+ { id: 'u3', displayName: 'Carol Chen' },
38
+ { id: 'u4', displayName: 'David Diaz' },
39
+ { id: 'u5', displayName: 'Elena Evans' },
40
+ { id: 'u6', displayName: 'Frank Foster' },
41
+ { id: 'u7', displayName: 'Grace Garcia' },
42
+ { id: 'u8', displayName: 'Henry Hughes' },
43
+ { id: 'u9', displayName: 'Ivy Ibrahim' },
44
+ { id: 'u10', displayName: 'James Johnson' },
45
+ { id: 'u11', displayName: 'Karen Kim' },
46
+ { id: 'u12', displayName: 'Leo Lee' },
47
+ { id: 'u13', displayName: 'Maria Martinez' },
48
+ { id: 'u14', displayName: 'Noah Nguyen' },
49
+ { id: 'u15', displayName: 'Olivia Olsen' },
50
+ { id: 'u16', displayName: 'Paul Patel' },
51
+ { id: 'u17', displayName: 'Quinn Quinn' },
52
+ { id: 'u18', displayName: 'Ryan Roberts' },
53
+ { id: 'u19', displayName: 'Sara Singh' },
54
+ { id: 'u20', displayName: 'Tom Taylor' },
55
+ ];
56
+
57
+ const meta: Meta<typeof SelectScroll> = {
58
+ title: 'Design System/SelectScroll',
59
+ component: SelectScroll,
60
+ tags: [],
61
+ decorators: [
62
+ (Story) => (
63
+ <div style={{ padding: '24px', maxWidth: '420px' }}>
64
+ <Story />
65
+ </div>
66
+ ),
67
+ ],
68
+ args: {
69
+ label: 'Select Country',
70
+ placeholder: 'Select a country',
71
+ required: false,
72
+ isInvalid: false,
73
+ error: '',
74
+ helperText: '',
75
+ size: 'md',
76
+ options: countryOptions,
77
+ color: 'grey',
78
+ isApiSearch: false,
79
+ clearable: true,
80
+ } as SelectScrollProps,
81
+ argTypes: {
82
+ color: {
83
+ control: { type: 'radio' },
84
+ options: ['grey', 'white'],
85
+ },
86
+ size: {
87
+ control: { type: 'radio' },
88
+ options: ['sm', 'md', 'lg'],
89
+ description: 'Size of the select scroll field',
90
+ },
91
+ isInvalid: {
92
+ control: { type: 'boolean' },
93
+ description: 'Shows error state',
94
+ },
95
+ error: {
96
+ control: { type: 'text' },
97
+ description: 'Error message displayed when isInvalid is true',
98
+ },
99
+ helperText: {
100
+ control: { type: 'text' },
101
+ description: 'Helper text displayed when not in error state',
102
+ },
103
+ required: {
104
+ control: { type: 'boolean' },
105
+ description: 'Marks the field as required',
106
+ },
107
+ isDisabled: {
108
+ control: { type: 'boolean' },
109
+ description: 'Disables the field',
110
+ },
111
+ clearable: {
112
+ control: { type: 'boolean' },
113
+ description: 'Shows clear button and allows clearing selection',
114
+ },
115
+ loading: {
116
+ control: { type: 'boolean' },
117
+ description: 'Shows loading state',
118
+ },
119
+ loadingText: {
120
+ control: { type: 'text' },
121
+ description: 'Text shown when loading',
122
+ },
123
+ noOptionsText: {
124
+ control: { type: 'text' },
125
+ description: 'Text shown when no options are available',
126
+ },
127
+ },
128
+ };
129
+
130
+ export default meta;
131
+
132
+ type Story = StoryObj<typeof SelectScroll>;
133
+
134
+ const PlaygroundComponent = (args: SelectScrollProps) => {
135
+ const [value, setValue] = useState<any>(args.value);
136
+
137
+ // Sync external control changes if any
138
+ React.useEffect(() => {
139
+ setValue(args.value);
140
+ }, [args.value]);
141
+
142
+ return (
143
+ <SelectScroll
144
+ {...args}
145
+ value={value}
146
+ onChange={(newValue) => {
147
+ setValue(newValue);
148
+ }}
149
+ />
150
+ );
151
+ };
152
+
153
+ export const Playground: Story = {
154
+ args: {
155
+ label: 'Select Country',
156
+ placeholder: 'Select a country',
157
+ required: true,
158
+ options: countryOptions,
159
+ clearable: true,
160
+ },
161
+ render: (args) => <PlaygroundComponent {...args} />,
162
+ };
163
+
164
+ const ShowcaseComponent = () => {
165
+ const [val1, setVal1] = useState<any>(null);
166
+ const [val2, setVal2] = useState<any>(null);
167
+ const [val3, setVal3] = useState<any>('Jim Beam');
168
+ const [val4, setVal4] = useState<any>(null);
169
+ const [val5, setVal5] = useState<any>(null);
170
+ const [val6] = useState<any>('India');
171
+ const [val7, setVal7] = useState<any>(null);
172
+ const [val8, setVal8] = useState<any>(null);
173
+
174
+ const [apiValue, setApiValue] = useState<{
175
+ id: string;
176
+ displayName: string;
177
+ } | null>(null);
178
+ const [apiOptions, setApiOptions] = useState<typeof MOCK_API_USERS>([]);
179
+ const [apiLoading, setApiLoading] = useState(false);
180
+
181
+ const handleApiSearch = useCallback((term: string) => {
182
+ setApiLoading(true);
183
+ window.setTimeout(() => {
184
+ const q = term.trim().toLowerCase();
185
+ const filtered = MOCK_API_USERS.filter(
186
+ (u) => !q || u.displayName.toLowerCase().includes(q)
187
+ ).slice(0, 40);
188
+ setApiOptions(filtered);
189
+ setApiLoading(false);
190
+ }, 350);
191
+ }, []);
192
+
193
+ return (
194
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '24px' }}>
195
+ {/* Default / Empty */}
196
+ <SelectScroll
197
+ label="Select Country"
198
+ placeholder="Select a country"
199
+ required
200
+ isApiSearch={false}
201
+ options={countryOptions}
202
+ value={val1}
203
+ onChange={setVal1}
204
+ />
205
+
206
+ {/* Color: white */}
207
+ <SelectScroll
208
+ label="Select Country (white)"
209
+ placeholder="Select a country"
210
+ required
211
+ isApiSearch={false}
212
+ options={countryOptions}
213
+ color="white"
214
+ value={val2}
215
+ onChange={setVal2}
216
+ />
217
+
218
+ {/* With Value */}
219
+ <SelectScroll
220
+ label="Username"
221
+ placeholder="Select a username"
222
+ required
223
+ isApiSearch={false}
224
+ options={usernameOptions}
225
+ value={val3}
226
+ clearable={false}
227
+ onChange={setVal3}
228
+ />
229
+
230
+ {/* Error State */}
231
+ <SelectScroll
232
+ label="Select Country"
233
+ placeholder="Select a country"
234
+ required
235
+ isApiSearch={false}
236
+ options={countryOptions}
237
+ isInvalid
238
+ error="Please select a valid country"
239
+ value={val4}
240
+ onChange={setVal4}
241
+ />
242
+
243
+ {/* With Helper Text */}
244
+ <SelectScroll
245
+ label="Select Country"
246
+ placeholder="Select a country"
247
+ required
248
+ isApiSearch={false}
249
+ options={countryOptions}
250
+ helperText="Select your country of residence"
251
+ value={val5}
252
+ onChange={setVal5}
253
+ />
254
+
255
+ {/* Disabled */}
256
+ <SelectScroll
257
+ label="Select Country"
258
+ placeholder="Select a country"
259
+ required
260
+ isApiSearch={false}
261
+ options={countryOptions}
262
+ value={val6}
263
+ isDisabled
264
+ />
265
+
266
+ {/* Small Size */}
267
+ <SelectScroll
268
+ label="Select Country"
269
+ placeholder="Select a country"
270
+ size="sm"
271
+ isApiSearch={false}
272
+ options={countryOptions}
273
+ value={val7}
274
+ onChange={setVal7}
275
+ />
276
+
277
+ {/* With Object Options */}
278
+ <SelectScroll
279
+ label="Select Country (Object)"
280
+ placeholder="Select a country"
281
+ isApiSearch={false}
282
+ options={countryObjectOptions}
283
+ getOptionLabel={(option) => (typeof option === 'string' ? option : option.label)}
284
+ value={val8}
285
+ onChange={setVal8}
286
+ />
287
+
288
+ {/* API search (mock server): debounced onApiSearch, options from parent */}
289
+ <div
290
+ style={{
291
+ display: 'flex',
292
+ flexDirection: 'column',
293
+ gap: '12px',
294
+ paddingTop: '8px',
295
+ borderTop: '1px solid #e8ecef',
296
+ }}
297
+ >
298
+ <p
299
+ style={{
300
+ margin: 0,
301
+ fontSize: 12,
302
+ color: '#5c6368',
303
+ lineHeight: 1.5,
304
+ }}
305
+ >
306
+ <strong>API search:</strong> <code>isApiSearch</code> + <code>onApiSearch</code>{' '}
307
+ (debounced in SelectScroll, default 1000ms). Open loads the mock list; typing filters
308
+ after debounce.
309
+ </p>
310
+ <SelectScroll
311
+ label="Select user (mock API)"
312
+ placeholder="Search by name…"
313
+ size="md"
314
+ isApiSearch
315
+ apiSearchDebounceMs={1000}
316
+ options={apiOptions}
317
+ loading={apiLoading}
318
+ loadingText="Fetching users…"
319
+ value={apiValue}
320
+ getOptionLabel={(o) => o.displayName}
321
+ onChange={setApiValue}
322
+ onApiSearch={handleApiSearch}
323
+ onOpenChange={(open) => {
324
+ if (open && apiOptions.length === 0) {
325
+ handleApiSearch('');
326
+ }
327
+ }}
328
+ />
329
+ </div>
330
+ </div>
331
+ );
332
+ };
333
+
334
+ export const Showcase: Story = {
335
+ render: () => <ShowcaseComponent />,
336
+ };