@idealyst/components 1.0.82 → 1.0.83
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/package.json +7 -7
- package/src/Select/README.md +166 -0
- package/src/Select/Select.native.tsx +270 -0
- package/src/Select/Select.styles.tsx +325 -0
- package/src/Select/Select.web.tsx +436 -0
- package/src/Select/index.native.ts +2 -0
- package/src/Select/index.ts +2 -0
- package/src/Select/index.web.ts +2 -0
- package/src/Select/types.ts +118 -0
- package/src/examples/AllExamples.tsx +4 -0
- package/src/examples/SelectExamples.tsx +423 -0
- package/src/examples/index.ts +1 -0
- package/src/index.ts +4 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Screen, View, Text, Select, Card, Button, Icon, Divider } from '../index';
|
|
3
|
+
|
|
4
|
+
// Mock data for examples
|
|
5
|
+
const fruitOptions = [
|
|
6
|
+
{ value: 'apple', label: 'Apple' },
|
|
7
|
+
{ value: 'banana', label: 'Banana' },
|
|
8
|
+
{ value: 'orange', label: 'Orange' },
|
|
9
|
+
{ value: 'grape', label: 'Grape' },
|
|
10
|
+
{ value: 'strawberry', label: 'Strawberry' },
|
|
11
|
+
{ value: 'pineapple', label: 'Pineapple' },
|
|
12
|
+
{ value: 'mango', label: 'Mango' },
|
|
13
|
+
{ value: 'kiwi', label: 'Kiwi' },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
const countryOptions = [
|
|
17
|
+
{ value: 'us', label: 'United States', icon: '🇺🇸' },
|
|
18
|
+
{ value: 'ca', label: 'Canada', icon: '🇨🇦' },
|
|
19
|
+
{ value: 'uk', label: 'United Kingdom', icon: '🇬🇧' },
|
|
20
|
+
{ value: 'de', label: 'Germany', icon: '🇩🇪' },
|
|
21
|
+
{ value: 'fr', label: 'France', icon: '🇫🇷' },
|
|
22
|
+
{ value: 'jp', label: 'Japan', icon: '🇯🇵' },
|
|
23
|
+
{ value: 'au', label: 'Australia', icon: '🇦🇺' },
|
|
24
|
+
{ value: 'in', label: 'India', icon: '🇮🇳' },
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const priorityOptions = [
|
|
28
|
+
{
|
|
29
|
+
value: 'low',
|
|
30
|
+
label: 'Low Priority',
|
|
31
|
+
icon: <Text style={{ color: '#22c55e' }}>●</Text>
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
value: 'medium',
|
|
35
|
+
label: 'Medium Priority',
|
|
36
|
+
icon: <Text style={{ color: '#f59e0b' }}>●</Text>
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
value: 'high',
|
|
40
|
+
label: 'High Priority',
|
|
41
|
+
icon: <Text style={{ color: '#ef4444' }}>●</Text>
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
value: 'urgent',
|
|
45
|
+
label: 'Urgent',
|
|
46
|
+
icon: <Text style={{ color: '#dc2626' }}>🔥</Text>
|
|
47
|
+
},
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
const statusOptions = [
|
|
51
|
+
{ value: 'draft', label: 'Draft', disabled: false },
|
|
52
|
+
{ value: 'pending', label: 'Pending Review' },
|
|
53
|
+
{ value: 'approved', label: 'Approved' },
|
|
54
|
+
{ value: 'archived', label: 'Archived (Disabled)', disabled: true },
|
|
55
|
+
{ value: 'deleted', label: 'Deleted (Disabled)', disabled: true },
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
export const SelectExamples = () => {
|
|
59
|
+
// State for all select examples
|
|
60
|
+
const [basicSelect, setBasicSelect] = useState('');
|
|
61
|
+
const [fruitSelect, setFruitSelect] = useState('apple');
|
|
62
|
+
const [countrySelect, setCountrySelect] = useState('');
|
|
63
|
+
const [prioritySelect, setPrioritySelect] = useState('medium');
|
|
64
|
+
const [statusSelect, setStatusSelect] = useState('draft');
|
|
65
|
+
const [searchableSelect, setSearchableSelect] = useState('');
|
|
66
|
+
const [formSelect, setFormSelect] = useState('');
|
|
67
|
+
const [sizeSmall, setSizeSmall] = useState('');
|
|
68
|
+
const [sizeMedium, setSizeMedium] = useState('');
|
|
69
|
+
const [sizeLarge, setSizeLarge] = useState('');
|
|
70
|
+
const [outlinedSelect, setOutlinedSelect] = useState('');
|
|
71
|
+
const [filledSelect, setFilledSelect] = useState('');
|
|
72
|
+
const [primarySelect, setPrimarySelect] = useState('');
|
|
73
|
+
const [successSelect, setSuccessSelect] = useState('');
|
|
74
|
+
const [errorSelect, setErrorSelect] = useState('');
|
|
75
|
+
const [warningSelect, setWarningSelect] = useState('');
|
|
76
|
+
|
|
77
|
+
const [formErrors, setFormErrors] = useState<Record<string, string>>({});
|
|
78
|
+
|
|
79
|
+
const validateForm = () => {
|
|
80
|
+
const errors: Record<string, string> = {};
|
|
81
|
+
if (!formSelect) {
|
|
82
|
+
errors.formSelect = 'Please select a country';
|
|
83
|
+
}
|
|
84
|
+
setFormErrors(errors);
|
|
85
|
+
return Object.keys(errors).length === 0;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const handleFormSubmit = () => {
|
|
89
|
+
if (validateForm()) {
|
|
90
|
+
console.log('Form submitted successfully!', { country: formSelect });
|
|
91
|
+
} else {
|
|
92
|
+
console.log('Form has validation errors');
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const resetAllSelections = () => {
|
|
97
|
+
setBasicSelect('');
|
|
98
|
+
setFruitSelect('');
|
|
99
|
+
setCountrySelect('');
|
|
100
|
+
setPrioritySelect('');
|
|
101
|
+
setStatusSelect('');
|
|
102
|
+
setSearchableSelect('');
|
|
103
|
+
setFormSelect('');
|
|
104
|
+
setSizeSmall('');
|
|
105
|
+
setSizeMedium('');
|
|
106
|
+
setSizeLarge('');
|
|
107
|
+
setOutlinedSelect('');
|
|
108
|
+
setFilledSelect('');
|
|
109
|
+
setPrimarySelect('');
|
|
110
|
+
setSuccessSelect('');
|
|
111
|
+
setErrorSelect('');
|
|
112
|
+
setWarningSelect('');
|
|
113
|
+
setFormErrors({});
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<Screen background="primary" padding="lg">
|
|
118
|
+
<View spacing="lg">
|
|
119
|
+
<View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
120
|
+
<Text size="large" weight="bold">
|
|
121
|
+
Select Component Examples
|
|
122
|
+
</Text>
|
|
123
|
+
<Button
|
|
124
|
+
variant="outlined"
|
|
125
|
+
intent="neutral"
|
|
126
|
+
size="small"
|
|
127
|
+
onPress={resetAllSelections}
|
|
128
|
+
>
|
|
129
|
+
Reset All
|
|
130
|
+
</Button>
|
|
131
|
+
</View>
|
|
132
|
+
|
|
133
|
+
{/* Basic Usage */}
|
|
134
|
+
<Card variant="outlined" padding="medium">
|
|
135
|
+
<View spacing="md">
|
|
136
|
+
<Text size="medium" weight="semibold">Basic Usage</Text>
|
|
137
|
+
<Select
|
|
138
|
+
options={fruitOptions}
|
|
139
|
+
value={basicSelect}
|
|
140
|
+
onValueChange={setBasicSelect}
|
|
141
|
+
placeholder="Choose a fruit"
|
|
142
|
+
/>
|
|
143
|
+
<Text size="small" color="secondary">
|
|
144
|
+
Selected: {basicSelect || 'None'}
|
|
145
|
+
</Text>
|
|
146
|
+
</View>
|
|
147
|
+
</Card>
|
|
148
|
+
|
|
149
|
+
{/* With Icons */}
|
|
150
|
+
<Card variant="outlined" padding="medium">
|
|
151
|
+
<View spacing="md">
|
|
152
|
+
<Text size="medium" weight="semibold">With Icons</Text>
|
|
153
|
+
<Select
|
|
154
|
+
options={countryOptions}
|
|
155
|
+
value={countrySelect}
|
|
156
|
+
onValueChange={setCountrySelect}
|
|
157
|
+
placeholder="Select a country"
|
|
158
|
+
label="Country"
|
|
159
|
+
/>
|
|
160
|
+
<Text size="small" color="secondary">
|
|
161
|
+
Selected: {countrySelect || 'None'}
|
|
162
|
+
</Text>
|
|
163
|
+
</View>
|
|
164
|
+
</Card>
|
|
165
|
+
|
|
166
|
+
{/* Custom Icons */}
|
|
167
|
+
<Card variant="outlined" padding="medium">
|
|
168
|
+
<View spacing="md">
|
|
169
|
+
<Text size="medium" weight="semibold">Custom Icon Components</Text>
|
|
170
|
+
<Select
|
|
171
|
+
options={priorityOptions}
|
|
172
|
+
value={prioritySelect}
|
|
173
|
+
onValueChange={setPrioritySelect}
|
|
174
|
+
placeholder="Select priority"
|
|
175
|
+
label="Task Priority"
|
|
176
|
+
/>
|
|
177
|
+
<Text size="small" color="secondary">
|
|
178
|
+
Selected: {prioritySelect || 'None'}
|
|
179
|
+
</Text>
|
|
180
|
+
</View>
|
|
181
|
+
</Card>
|
|
182
|
+
|
|
183
|
+
{/* Disabled Options */}
|
|
184
|
+
<Card variant="outlined" padding="medium">
|
|
185
|
+
<View spacing="md">
|
|
186
|
+
<Text size="medium" weight="semibold">Disabled Options</Text>
|
|
187
|
+
<Select
|
|
188
|
+
options={statusOptions}
|
|
189
|
+
value={statusSelect}
|
|
190
|
+
onValueChange={setStatusSelect}
|
|
191
|
+
placeholder="Select status"
|
|
192
|
+
label="Document Status"
|
|
193
|
+
helperText="Some options are disabled"
|
|
194
|
+
/>
|
|
195
|
+
<Text size="small" color="secondary">
|
|
196
|
+
Selected: {statusSelect || 'None'}
|
|
197
|
+
</Text>
|
|
198
|
+
</View>
|
|
199
|
+
</Card>
|
|
200
|
+
|
|
201
|
+
{/* Searchable */}
|
|
202
|
+
<Card variant="outlined" padding="medium">
|
|
203
|
+
<View spacing="md">
|
|
204
|
+
<Text size="medium" weight="semibold">Searchable Select</Text>
|
|
205
|
+
<Select
|
|
206
|
+
options={fruitOptions}
|
|
207
|
+
value={searchableSelect}
|
|
208
|
+
onValueChange={setSearchableSelect}
|
|
209
|
+
placeholder="Search for fruits..."
|
|
210
|
+
label="Fruit Search"
|
|
211
|
+
searchable
|
|
212
|
+
helperText="Type to filter options"
|
|
213
|
+
/>
|
|
214
|
+
<Text size="small" color="secondary">
|
|
215
|
+
Selected: {searchableSelect || 'None'}
|
|
216
|
+
</Text>
|
|
217
|
+
</View>
|
|
218
|
+
</Card>
|
|
219
|
+
|
|
220
|
+
{/* Sizes */}
|
|
221
|
+
<Card variant="outlined" padding="medium">
|
|
222
|
+
<View spacing="md">
|
|
223
|
+
<Text size="medium" weight="semibold">Sizes</Text>
|
|
224
|
+
<View spacing="sm">
|
|
225
|
+
<View>
|
|
226
|
+
<Text size="small" weight="medium">Small</Text>
|
|
227
|
+
<Select
|
|
228
|
+
options={fruitOptions.slice(0, 3)}
|
|
229
|
+
value={sizeSmall}
|
|
230
|
+
onValueChange={setSizeSmall}
|
|
231
|
+
placeholder="Small select"
|
|
232
|
+
size="small"
|
|
233
|
+
/>
|
|
234
|
+
</View>
|
|
235
|
+
<View>
|
|
236
|
+
<Text size="small" weight="medium">Medium (Default)</Text>
|
|
237
|
+
<Select
|
|
238
|
+
options={fruitOptions.slice(0, 3)}
|
|
239
|
+
value={sizeMedium}
|
|
240
|
+
onValueChange={setSizeMedium}
|
|
241
|
+
placeholder="Medium select"
|
|
242
|
+
size="medium"
|
|
243
|
+
/>
|
|
244
|
+
</View>
|
|
245
|
+
<View>
|
|
246
|
+
<Text size="small" weight="medium">Large</Text>
|
|
247
|
+
<Select
|
|
248
|
+
options={fruitOptions.slice(0, 3)}
|
|
249
|
+
value={sizeLarge}
|
|
250
|
+
onValueChange={setSizeLarge}
|
|
251
|
+
placeholder="Large select"
|
|
252
|
+
size="large"
|
|
253
|
+
/>
|
|
254
|
+
</View>
|
|
255
|
+
</View>
|
|
256
|
+
</View>
|
|
257
|
+
</Card>
|
|
258
|
+
|
|
259
|
+
{/* Variants */}
|
|
260
|
+
<Card variant="outlined" padding="medium">
|
|
261
|
+
<View spacing="md">
|
|
262
|
+
<Text size="medium" weight="semibold">Variants</Text>
|
|
263
|
+
<View spacing="sm">
|
|
264
|
+
<View>
|
|
265
|
+
<Text size="small" weight="medium">Outlined (Default)</Text>
|
|
266
|
+
<Select
|
|
267
|
+
options={fruitOptions.slice(0, 4)}
|
|
268
|
+
value={outlinedSelect}
|
|
269
|
+
onValueChange={setOutlinedSelect}
|
|
270
|
+
placeholder="Outlined variant"
|
|
271
|
+
variant="outlined"
|
|
272
|
+
/>
|
|
273
|
+
</View>
|
|
274
|
+
<View>
|
|
275
|
+
<Text size="small" weight="medium">Filled</Text>
|
|
276
|
+
<Select
|
|
277
|
+
options={fruitOptions.slice(0, 4)}
|
|
278
|
+
value={filledSelect}
|
|
279
|
+
onValueChange={setFilledSelect}
|
|
280
|
+
placeholder="Filled variant"
|
|
281
|
+
variant="filled"
|
|
282
|
+
/>
|
|
283
|
+
</View>
|
|
284
|
+
</View>
|
|
285
|
+
</View>
|
|
286
|
+
</Card>
|
|
287
|
+
|
|
288
|
+
{/* Intents */}
|
|
289
|
+
<Card variant="outlined" padding="medium">
|
|
290
|
+
<View spacing="md">
|
|
291
|
+
<Text size="medium" weight="semibold">Intent Colors</Text>
|
|
292
|
+
<View spacing="sm">
|
|
293
|
+
<View>
|
|
294
|
+
<Text size="small" weight="medium">Primary</Text>
|
|
295
|
+
<Select
|
|
296
|
+
options={fruitOptions.slice(0, 3)}
|
|
297
|
+
value={primarySelect}
|
|
298
|
+
onValueChange={setPrimarySelect}
|
|
299
|
+
placeholder="Primary intent"
|
|
300
|
+
intent="primary"
|
|
301
|
+
variant="outlined"
|
|
302
|
+
/>
|
|
303
|
+
</View>
|
|
304
|
+
<View>
|
|
305
|
+
<Text size="small" weight="medium">Success</Text>
|
|
306
|
+
<Select
|
|
307
|
+
options={fruitOptions.slice(0, 3)}
|
|
308
|
+
value={successSelect}
|
|
309
|
+
onValueChange={setSuccessSelect}
|
|
310
|
+
placeholder="Success intent"
|
|
311
|
+
intent="success"
|
|
312
|
+
variant="outlined"
|
|
313
|
+
/>
|
|
314
|
+
</View>
|
|
315
|
+
<View>
|
|
316
|
+
<Text size="small" weight="medium">Warning</Text>
|
|
317
|
+
<Select
|
|
318
|
+
options={fruitOptions.slice(0, 3)}
|
|
319
|
+
value={warningSelect}
|
|
320
|
+
onValueChange={setWarningSelect}
|
|
321
|
+
placeholder="Warning intent"
|
|
322
|
+
intent="warning"
|
|
323
|
+
variant="outlined"
|
|
324
|
+
/>
|
|
325
|
+
</View>
|
|
326
|
+
<View>
|
|
327
|
+
<Text size="small" weight="medium">Error</Text>
|
|
328
|
+
<Select
|
|
329
|
+
options={fruitOptions.slice(0, 3)}
|
|
330
|
+
value={errorSelect}
|
|
331
|
+
onValueChange={setErrorSelect}
|
|
332
|
+
placeholder="Error intent"
|
|
333
|
+
intent="error"
|
|
334
|
+
variant="outlined"
|
|
335
|
+
/>
|
|
336
|
+
</View>
|
|
337
|
+
</View>
|
|
338
|
+
</View>
|
|
339
|
+
</Card>
|
|
340
|
+
|
|
341
|
+
{/* Form Example */}
|
|
342
|
+
<Card variant="outlined" padding="medium">
|
|
343
|
+
<View spacing="md">
|
|
344
|
+
<Text size="medium" weight="semibold">Form Integration</Text>
|
|
345
|
+
<Select
|
|
346
|
+
options={countryOptions}
|
|
347
|
+
value={formSelect}
|
|
348
|
+
onValueChange={(value) => {
|
|
349
|
+
setFormSelect(value);
|
|
350
|
+
if (formErrors.formSelect) {
|
|
351
|
+
setFormErrors(prev => ({ ...prev, formSelect: '' }));
|
|
352
|
+
}
|
|
353
|
+
}}
|
|
354
|
+
placeholder="Select your country"
|
|
355
|
+
label="Country *"
|
|
356
|
+
error={!!formErrors.formSelect}
|
|
357
|
+
helperText={formErrors.formSelect || "Required field"}
|
|
358
|
+
variant="outlined"
|
|
359
|
+
intent="primary"
|
|
360
|
+
/>
|
|
361
|
+
<Button
|
|
362
|
+
variant="contained"
|
|
363
|
+
intent="primary"
|
|
364
|
+
onPress={handleFormSubmit}
|
|
365
|
+
>
|
|
366
|
+
Submit Form
|
|
367
|
+
</Button>
|
|
368
|
+
</View>
|
|
369
|
+
</Card>
|
|
370
|
+
|
|
371
|
+
{/* Disabled State */}
|
|
372
|
+
<Card variant="outlined" padding="medium">
|
|
373
|
+
<View spacing="md">
|
|
374
|
+
<Text size="medium" weight="semibold">Disabled State</Text>
|
|
375
|
+
<Select
|
|
376
|
+
options={fruitOptions}
|
|
377
|
+
value="apple"
|
|
378
|
+
onValueChange={() => {}}
|
|
379
|
+
placeholder="This select is disabled"
|
|
380
|
+
label="Disabled Select"
|
|
381
|
+
disabled
|
|
382
|
+
helperText="This select cannot be interacted with"
|
|
383
|
+
/>
|
|
384
|
+
</View>
|
|
385
|
+
</Card>
|
|
386
|
+
|
|
387
|
+
{/* Platform-specific Features */}
|
|
388
|
+
<Card variant="outlined" padding="medium">
|
|
389
|
+
<View spacing="md">
|
|
390
|
+
<Text size="medium" weight="semibold">Platform Features</Text>
|
|
391
|
+
<Text size="small" color="secondary">
|
|
392
|
+
On iOS: Try the ActionSheet presentation mode for native feel
|
|
393
|
+
</Text>
|
|
394
|
+
<Select
|
|
395
|
+
options={priorityOptions}
|
|
396
|
+
value={prioritySelect}
|
|
397
|
+
onValueChange={setPrioritySelect}
|
|
398
|
+
placeholder="Select priority"
|
|
399
|
+
label="iOS ActionSheet Mode"
|
|
400
|
+
presentationMode="actionSheet" // iOS only
|
|
401
|
+
helperText="Uses native ActionSheet on iOS"
|
|
402
|
+
/>
|
|
403
|
+
</View>
|
|
404
|
+
</Card>
|
|
405
|
+
|
|
406
|
+
<Divider spacing="lg" />
|
|
407
|
+
|
|
408
|
+
{/* Summary */}
|
|
409
|
+
<Card variant="filled" padding="medium">
|
|
410
|
+
<View spacing="sm">
|
|
411
|
+
<Text size="medium" weight="semibold">Current Selections Summary</Text>
|
|
412
|
+
<Text size="small">Basic: {basicSelect || 'None'}</Text>
|
|
413
|
+
<Text size="small">Country: {countrySelect || 'None'}</Text>
|
|
414
|
+
<Text size="small">Priority: {prioritySelect || 'None'}</Text>
|
|
415
|
+
<Text size="small">Status: {statusSelect || 'None'}</Text>
|
|
416
|
+
<Text size="small">Searchable: {searchableSelect || 'None'}</Text>
|
|
417
|
+
<Text size="small">Form: {formSelect || 'None'}</Text>
|
|
418
|
+
</View>
|
|
419
|
+
</Card>
|
|
420
|
+
</View>
|
|
421
|
+
</Screen>
|
|
422
|
+
);
|
|
423
|
+
};
|
package/src/examples/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ export { ScreenExamples } from './ScreenExamples';
|
|
|
12
12
|
export { SVGImageExamples } from './SVGImageExamples';
|
|
13
13
|
export { DialogExamples } from './DialogExamples';
|
|
14
14
|
export { PopoverExamples } from './PopoverExamples';
|
|
15
|
+
export { SelectExamples } from './SelectExamples';
|
|
15
16
|
export { ThemeExtensionExamples } from './ThemeExtensionExamples';
|
|
16
17
|
export { extendedThemes, } from './extendedTheme';
|
|
17
18
|
export type { ExtendedColorVariant, ExtendedIntentVariant } from './extendedTheme';
|
package/src/index.ts
CHANGED
|
@@ -47,6 +47,9 @@ export * from './Popover/types';
|
|
|
47
47
|
export { default as ActivityIndicator } from './ActivityIndicator';
|
|
48
48
|
export * from './ActivityIndicator/types';
|
|
49
49
|
|
|
50
|
+
export { default as Select } from './Select';
|
|
51
|
+
export * from './Select/types';
|
|
52
|
+
|
|
50
53
|
export type { ButtonProps } from './Button/types';
|
|
51
54
|
export type { TextProps } from './Text/types';
|
|
52
55
|
export type { ViewProps } from './View/types';
|
|
@@ -62,6 +65,7 @@ export type { SVGImageProps } from './SVGImage/types';
|
|
|
62
65
|
export type { DialogProps } from './Dialog/types';
|
|
63
66
|
export type { PopoverProps } from './Popover/types';
|
|
64
67
|
export type { ActivityIndicatorProps } from './ActivityIndicator/types';
|
|
68
|
+
export type { SelectProps } from './Select/types';
|
|
65
69
|
|
|
66
70
|
export { breakpoints } from '@idealyst/theme';
|
|
67
71
|
export type { AppTheme } from '@idealyst/theme';
|