@delightui/components 0.1.105 → 0.1.107

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 (102) hide show
  1. package/README.md +104 -1
  2. package/dist/cjs/components/molecules/Modal/DemoModal.d.ts +8 -0
  3. package/dist/cjs/components/molecules/Modal/ModalContext/ModalContext.d.ts +41 -0
  4. package/dist/cjs/components/molecules/Modal/ModalContext/ModalContext.types.d.ts +87 -0
  5. package/dist/cjs/components/molecules/Modal/ModalContext/index.d.ts +3 -0
  6. package/dist/cjs/components/molecules/Modal/ModalContext/useModal.d.ts +34 -0
  7. package/dist/cjs/components/molecules/Modal/index.d.ts +2 -0
  8. package/dist/cjs/components/molecules/index.d.ts +2 -0
  9. package/dist/cjs/library.css +19 -6
  10. package/dist/cjs/library.js +3 -3
  11. package/dist/cjs/library.js.map +1 -1
  12. package/dist/esm/components/molecules/Modal/DemoModal.d.ts +8 -0
  13. package/dist/esm/components/molecules/Modal/ModalContext/ModalContext.d.ts +41 -0
  14. package/dist/esm/components/molecules/Modal/ModalContext/ModalContext.types.d.ts +87 -0
  15. package/dist/esm/components/molecules/Modal/ModalContext/index.d.ts +3 -0
  16. package/dist/esm/components/molecules/Modal/ModalContext/useModal.d.ts +34 -0
  17. package/dist/esm/components/molecules/Modal/index.d.ts +2 -0
  18. package/dist/esm/components/molecules/index.d.ts +2 -0
  19. package/dist/esm/library.css +19 -6
  20. package/dist/esm/library.js +3 -3
  21. package/dist/esm/library.js.map +1 -1
  22. package/dist/index.d.ts +108 -2
  23. package/docs/README.md +264 -0
  24. package/docs/components/atoms/ActionImage.md +119 -0
  25. package/docs/components/atoms/Button.md +197 -0
  26. package/docs/components/atoms/Checkbox.md +299 -0
  27. package/docs/components/atoms/CheckboxItem.md +314 -0
  28. package/docs/components/atoms/Chip.md +380 -0
  29. package/docs/components/atoms/CustomToggle.md +270 -0
  30. package/docs/components/atoms/Icon.md +365 -0
  31. package/docs/components/atoms/IconButton.md +407 -0
  32. package/docs/components/atoms/Image.md +448 -0
  33. package/docs/components/atoms/Input.md +430 -0
  34. package/docs/components/atoms/ListItem.md +502 -0
  35. package/docs/components/atoms/Password.md +472 -0
  36. package/docs/components/atoms/RadioButton.md +614 -0
  37. package/docs/components/atoms/RadioButtonItem.md +588 -0
  38. package/docs/components/atoms/ResponsiveComponent.md +612 -0
  39. package/docs/components/atoms/SelectListItem.md +609 -0
  40. package/docs/components/atoms/Slider.md +605 -0
  41. package/docs/components/atoms/Spinner.md +605 -0
  42. package/docs/components/atoms/Text.md +463 -0
  43. package/docs/components/atoms/TextArea.md +670 -0
  44. package/docs/components/atoms/ToastNotification.md +668 -0
  45. package/docs/components/atoms/Toggle.md +737 -0
  46. package/docs/components/atoms/ToggleButton.md +751 -0
  47. package/docs/components/atoms/Tooltip.md +391 -0
  48. package/docs/components/molecules/Accordion.md +440 -0
  49. package/docs/components/molecules/AccordionGroup.md +547 -0
  50. package/docs/components/molecules/ActionCard.md +546 -0
  51. package/docs/components/molecules/Breadcrumb.md +403 -0
  52. package/docs/components/molecules/Breadcrumbs.md +485 -0
  53. package/docs/components/molecules/ButtonGroup.md +383 -0
  54. package/docs/components/molecules/Card.md +298 -0
  55. package/docs/components/molecules/ChipInput.md +646 -0
  56. package/docs/components/molecules/ContextMenu.md +768 -0
  57. package/docs/components/molecules/CustomTimeSelector.md +116 -0
  58. package/docs/components/molecules/DatePicker.md +516 -0
  59. package/docs/components/molecules/DateTimeSelector.md +166 -0
  60. package/docs/components/molecules/FormField.md +312 -0
  61. package/docs/components/molecules/Grid.md +577 -0
  62. package/docs/components/molecules/GridItem.md +834 -0
  63. package/docs/components/molecules/GridList.md +244 -0
  64. package/docs/components/molecules/List.md +485 -0
  65. package/docs/components/molecules/Modal.md +470 -0
  66. package/docs/components/molecules/ModalFooter.md +702 -0
  67. package/docs/components/molecules/ModalHeader.md +756 -0
  68. package/docs/components/molecules/ModalProvider.md +205 -0
  69. package/docs/components/molecules/Nav.md +530 -0
  70. package/docs/components/molecules/NavItem.md +572 -0
  71. package/docs/components/molecules/NavLink.md +499 -0
  72. package/docs/components/molecules/Option.md +521 -0
  73. package/docs/components/molecules/Pagination.md +592 -0
  74. package/docs/components/molecules/PaginationNumberField.md +722 -0
  75. package/docs/components/molecules/Popover.md +516 -0
  76. package/docs/components/molecules/ProgressBar.md +624 -0
  77. package/docs/components/molecules/RadioGroup.md +831 -0
  78. package/docs/components/molecules/RepeaterList.md +185 -0
  79. package/docs/components/molecules/Select.md +402 -0
  80. package/docs/components/molecules/SortableTrigger.md +82 -0
  81. package/docs/components/molecules/useModal.md +379 -0
  82. package/docs/components/organisms/Dropzone.md +346 -0
  83. package/docs/components/organisms/DropzoneClear.md +135 -0
  84. package/docs/components/organisms/DropzoneContent.md +216 -0
  85. package/docs/components/organisms/DropzoneFilename.md +191 -0
  86. package/docs/components/organisms/DropzoneSupportedFormats.md +184 -0
  87. package/docs/components/organisms/DropzoneTrigger.md +209 -0
  88. package/docs/components/organisms/Form.md +533 -0
  89. package/docs/components/organisms/SlideOutPanel.md +662 -0
  90. package/docs/components/organisms/TabContent.md +902 -0
  91. package/docs/components/organisms/TabItem.md +1091 -0
  92. package/docs/components/organisms/Table.md +611 -0
  93. package/docs/components/organisms/TableBody.md +679 -0
  94. package/docs/components/organisms/TableCell.md +482 -0
  95. package/docs/components/organisms/TableHeader.md +513 -0
  96. package/docs/components/organisms/TableHeaderCell.md +661 -0
  97. package/docs/components/organisms/TableRow.md +715 -0
  98. package/docs/components/organisms/Tabs.md +1330 -0
  99. package/docs/components/utils/ConditionalView.md +568 -0
  100. package/docs/components/utils/RenderStateView.md +726 -0
  101. package/docs/components/utils/WrapTextNodes.md +614 -0
  102. package/package.json +3 -2
@@ -0,0 +1,485 @@
1
+ # List
2
+
3
+ ## Description
4
+
5
+ A flexible list component that renders collections of data with support for custom item components, sorting functionality, and both horizontal and vertical layouts. Provides efficient rendering for dynamic data sets with keyboard navigation and accessibility features.
6
+
7
+ ## Aliases
8
+
9
+ - List
10
+ - ListView
11
+ - DataList
12
+ - ItemList
13
+ - Collection
14
+
15
+ ## Props Breakdown
16
+
17
+ **Extends:** `HTMLAttributes<HTMLUListElement>` (excluding `children`)
18
+
19
+ | Prop | Type | Default | Required | Description |
20
+ |------|------|---------|----------|-------------|
21
+ | `data` | `T[]` | - | No | Array of data items to render |
22
+ | `component` | `React.ComponentType<T>` | - | Yes | Component to render each list item |
23
+ | `keyExtractor` | `(item: T, index: number) => string \| number` | - | No | Function to extract unique keys for items |
24
+ | `wrap` | `boolean` | - | No | Whether list content should wrap |
25
+ | `align` | `'Horizontal' \| 'Vertical'` | `'Vertical'` | No | Layout direction for the list |
26
+ | `sortable` | `boolean` | - | No | Enable drag-and-drop sorting |
27
+ | `updateSortOrder` | `(data: T[]) => void` | - | No | Callback when sort order changes |
28
+ | `className` | `string` | - | No | Additional CSS class names |
29
+
30
+ Plus all standard HTML ul attributes (role, aria-*, data-*, etc.).
31
+
32
+ ## Examples
33
+
34
+ ### Basic Usage with Data Array
35
+ ```tsx
36
+ import { List } from '@delightui/components';
37
+
38
+ const ListItem = ({ children }) => (
39
+ <div className="list-item">
40
+ <span>{children}</span>
41
+ </div>
42
+ );
43
+
44
+ function BasicListExample() {
45
+ const items = [
46
+ { id: 1, title: 'Apple' },
47
+ { id: 2, title: 'Banana' },
48
+ { id: 3, title: 'Cherry' },
49
+ { id: 4, title: 'Date' }
50
+ ];
51
+
52
+ const SimpleItem = ({ title }) => (
53
+ <ListItem>{title}</ListItem>
54
+ );
55
+
56
+ return (
57
+ <List
58
+ data={items}
59
+ component={SimpleItem}
60
+ className="simple-list"
61
+ />
62
+ );
63
+ }
64
+ ```
65
+
66
+ ### User List with Custom Components
67
+ ```tsx
68
+ import { Icon, Text, Chip } from '@delightui/components';
69
+
70
+ function UserListExample() {
71
+ const users = [
72
+ { id: 1, name: 'John Doe', email: 'john@example.com', role: 'Admin', avatar: '/avatar1.jpg' },
73
+ { id: 2, name: 'Jane Smith', email: 'jane@example.com', role: 'User', avatar: '/avatar2.jpg' },
74
+ { id: 3, name: 'Bob Johnson', email: 'bob@example.com', role: 'Editor', avatar: '/avatar3.jpg' }
75
+ ];
76
+
77
+ const UserItem = ({ name, email, role, avatar }) => (
78
+ <div className="user-item">
79
+ <img src={avatar} alt={name} className="user-avatar" />
80
+ <div className="user-info">
81
+ <Text type="Body" weight="Medium">{name}</Text>
82
+ <Text type="Caption" color="Secondary">{email}</Text>
83
+ </div>
84
+ <Chip size="Small">{role}</Chip>
85
+ </div>
86
+ );
87
+
88
+ return (
89
+ <List
90
+ data={users}
91
+ component={UserItem}
92
+ className="user-list"
93
+ />
94
+ );
95
+ }
96
+ ```
97
+
98
+ ### Horizontal Navigation List
99
+ ```tsx
100
+ import { Icon, Text } from '@delightui/components';
101
+
102
+ function HorizontalListExample() {
103
+ const categories = [
104
+ { id: 1, name: 'Technology', icon: 'Computer' },
105
+ { id: 2, name: 'Design', icon: 'Palette' },
106
+ { id: 3, name: 'Business', icon: 'Business' },
107
+ { id: 4, name: 'Marketing', icon: 'Campaign' }
108
+ ];
109
+
110
+ const CategoryItem = ({ name, icon }) => (
111
+ <div className="category-item">
112
+ <Icon icon={icon} size="Small" />
113
+ <Text type="Body">{name}</Text>
114
+ </div>
115
+ );
116
+
117
+ return (
118
+ <List
119
+ data={categories}
120
+ component={CategoryItem}
121
+ align="Horizontal"
122
+ className="horizontal-categories"
123
+ />
124
+ );
125
+ }
126
+ ```
127
+
128
+ ### Sortable Task List
129
+ ```tsx
130
+ import { Icon, Text, Chip } from '@delightui/components';
131
+
132
+ function SortableListExample() {
133
+ const [tasks, setTasks] = useState([
134
+ { id: 1, title: 'Review designs', priority: 'High' },
135
+ { id: 2, title: 'Update documentation', priority: 'Medium' },
136
+ { id: 3, title: 'Fix bug reports', priority: 'High' },
137
+ { id: 4, title: 'Plan next sprint', priority: 'Low' }
138
+ ]);
139
+
140
+ const TaskItem = ({ title, priority }) => (
141
+ <div className="task-item">
142
+ <Icon icon="DragHandle" className="drag-handle" />
143
+ <div className="task-content">
144
+ <Text type="Body" weight="Medium">{title}</Text>
145
+ <Chip size="Small">{priority}</Chip>
146
+ </div>
147
+ </div>
148
+ );
149
+
150
+ return (
151
+ <List
152
+ data={tasks}
153
+ component={TaskItem}
154
+ sortable
155
+ updateSortOrder={setTasks}
156
+ keyExtractor={(task) => task.id}
157
+ />
158
+ );
159
+ }
160
+ ```
161
+
162
+ ### Interactive Project List
163
+ ```tsx
164
+ import { Checkbox, Text, Button, Icon } from '@delightui/components';
165
+
166
+ function InteractiveListExample() {
167
+ const [selectedItems, setSelectedItems] = useState([]);
168
+
169
+ const projects = [
170
+ { id: 1, name: 'Project Alpha', status: 'Active' },
171
+ { id: 2, name: 'Project Beta', status: 'Pending' },
172
+ { id: 3, name: 'Project Gamma', status: 'Completed' }
173
+ ];
174
+
175
+ const toggleSelection = (itemId) => {
176
+ setSelectedItems(prev =>
177
+ prev.includes(itemId)
178
+ ? prev.filter(id => id !== itemId)
179
+ : [...prev, itemId]
180
+ );
181
+ };
182
+
183
+ const ProjectItem = ({ id, name, status, onToggle, onEdit }) => (
184
+ <div className="project-item" onClick={() => onToggle(id)}>
185
+ <Checkbox
186
+ checked={selectedItems.includes(id)}
187
+ onChange={() => onToggle(id)}
188
+ />
189
+ <div className="project-info">
190
+ <Text type="Body" weight="Medium">{name}</Text>
191
+ <Text type="Caption" color="Secondary">{status}</Text>
192
+ </div>
193
+ <Button
194
+ type="Ghost"
195
+ size="Small"
196
+ onClick={(e) => {
197
+ e.stopPropagation();
198
+ onEdit(id);
199
+ }}
200
+ >
201
+ <Icon icon="Edit" />
202
+ </Button>
203
+ </div>
204
+ );
205
+
206
+ const handleEdit = (projectId) => {
207
+ console.log('Edit project:', projectId);
208
+ };
209
+
210
+ return (
211
+ <div className="interactive-list">
212
+ <div className="list-header">
213
+ <Text type="Heading" size="Medium">Projects</Text>
214
+ {selectedItems.length > 0 && (
215
+ <Text type="Caption">
216
+ {selectedItems.length} item(s) selected
217
+ </Text>
218
+ )}
219
+ </div>
220
+
221
+ <List
222
+ data={projects.map(project => ({
223
+ ...project,
224
+ onToggle: toggleSelection,
225
+ onEdit: handleEdit
226
+ }))}
227
+ component={ProjectItem}
228
+ className="project-list"
229
+ />
230
+ </div>
231
+ );
232
+ }
233
+ ```
234
+
235
+ ### Empty State
236
+ ```tsx
237
+ function EmptyStateExample() {
238
+ const [items, setItems] = useState([]);
239
+
240
+ const EmptyState = () => (
241
+ <div className="empty-state">
242
+ <Icon icon="Inbox" size="Large" />
243
+ <Text type="Heading6">No items found</Text>
244
+ <Text type="BodySmall">Add some items to get started</Text>
245
+ <Button onClick={() => setItems([{ id: 1, name: 'New Item' }])}>
246
+ Add Item
247
+ </Button>
248
+ </div>
249
+ );
250
+
251
+ const ItemComponent = ({ item }) => (
252
+ <ListItem>
253
+ <Text>{item.name}</Text>
254
+ </ListItem>
255
+ );
256
+
257
+ return (
258
+ <div className="list-with-empty-state">
259
+ {items.length > 0 ? (
260
+ <List
261
+ data={items}
262
+ component={ItemComponent}
263
+ keyExtractor={(item) => item.id}
264
+ />
265
+ ) : (
266
+ <EmptyState />
267
+ )}
268
+ </div>
269
+ );
270
+ }
271
+ ```
272
+
273
+ ### List with Loading State
274
+ ```tsx
275
+ function LoadingListExample() {
276
+ const [items, setItems] = useState([]);
277
+ const [loading, setLoading] = useState(true);
278
+
279
+ useEffect(() => {
280
+ // Simulate API call
281
+ setTimeout(() => {
282
+ setItems([
283
+ { id: 1, name: 'Item 1' },
284
+ { id: 2, name: 'Item 2' },
285
+ { id: 3, name: 'Item 3' }
286
+ ]);
287
+ setLoading(false);
288
+ }, 2000);
289
+ }, []);
290
+
291
+ const LoadingItem = () => (
292
+ <ListItem className="loading-item">
293
+ <Spinner size="Small" />
294
+ <Text type="BodyMedium">Loading...</Text>
295
+ </ListItem>
296
+ );
297
+
298
+ const ItemComponent = ({ item }) => (
299
+ <ListItem>
300
+ <Text>{item.name}</Text>
301
+ </ListItem>
302
+ );
303
+
304
+ if (loading) {
305
+ return (
306
+ <List
307
+ data={[1, 2, 3]} // Placeholder data for loading items
308
+ component={LoadingItem}
309
+ />
310
+ );
311
+ }
312
+
313
+ return (
314
+ <List
315
+ data={items}
316
+ component={ItemComponent}
317
+ keyExtractor={(item) => item.id}
318
+ />
319
+ );
320
+ }
321
+ ```
322
+
323
+ ### Filterable List
324
+ ```tsx
325
+ function FilterableListExample() {
326
+ const [searchTerm, setSearchTerm] = useState('');
327
+ const [filter, setFilter] = useState('all');
328
+
329
+ const allItems = [
330
+ { id: 1, name: 'Apple', category: 'fruit', color: 'red' },
331
+ { id: 2, name: 'Banana', category: 'fruit', color: 'yellow' },
332
+ { id: 3, name: 'Carrot', category: 'vegetable', color: 'orange' },
333
+ { id: 4, name: 'Broccoli', category: 'vegetable', color: 'green' }
334
+ ];
335
+
336
+ const filteredItems = allItems.filter(item => {
337
+ const matchesSearch = item.name.toLowerCase().includes(searchTerm.toLowerCase());
338
+ const matchesFilter = filter === 'all' || item.category === filter;
339
+ return matchesSearch && matchesFilter;
340
+ });
341
+
342
+ const ItemComponent = ({ item }) => (
343
+ <ListItem className="filterable-item">
344
+ <Text type="BodyMedium">{item.name}</Text>
345
+ <Chip size="Small" style="B">{item.category}</Chip>
346
+ </ListItem>
347
+ );
348
+
349
+ return (
350
+ <div className="filterable-list">
351
+ <div className="list-controls">
352
+ <Input
353
+ placeholder="Search items..."
354
+ value={searchTerm}
355
+ onValueChange={setSearchTerm}
356
+ leadingIcon={<Icon icon="Search" />}
357
+ />
358
+
359
+ <Select value={filter} onValueChange={setFilter}>
360
+ <Option value="all">All Categories</Option>
361
+ <Option value="fruit">Fruits</Option>
362
+ <Option value="vegetable">Vegetables</Option>
363
+ </Select>
364
+ </div>
365
+
366
+ <List
367
+ data={filteredItems}
368
+ component={ItemComponent}
369
+ keyExtractor={(item) => item.id}
370
+ />
371
+ </div>
372
+ );
373
+ }
374
+ ```
375
+
376
+ ### Pagination List
377
+ ```tsx
378
+ function PaginatedListExample() {
379
+ const [currentPage, setCurrentPage] = useState(1);
380
+ const itemsPerPage = 5;
381
+
382
+ const allItems = Array.from({ length: 23 }, (_, i) => ({
383
+ id: i + 1,
384
+ name: `Item ${i + 1}`,
385
+ description: `Description for item ${i + 1}`
386
+ }));
387
+
388
+ const totalPages = Math.ceil(allItems.length / itemsPerPage);
389
+ const startIndex = (currentPage - 1) * itemsPerPage;
390
+ const currentItems = allItems.slice(startIndex, startIndex + itemsPerPage);
391
+
392
+ const ItemComponent = ({ item }) => (
393
+ <ListItem>
394
+ <div className="item-content">
395
+ <Text type="BodyMedium">{item.name}</Text>
396
+ <Text type="BodySmall">{item.description}</Text>
397
+ </div>
398
+ </ListItem>
399
+ );
400
+
401
+ return (
402
+ <div className="paginated-list">
403
+ <List
404
+ data={currentItems}
405
+ component={ItemComponent}
406
+ keyExtractor={(item) => item.id}
407
+ />
408
+
409
+ <Pagination
410
+ currentPage={currentPage}
411
+ totalPages={totalPages}
412
+ onPageChange={setCurrentPage}
413
+ />
414
+ </div>
415
+ );
416
+ }
417
+ ```
418
+
419
+ ### Nested Lists
420
+ ```tsx
421
+ function NestedListExample() {
422
+ const [expandedCategories, setExpandedCategories] = useState([]);
423
+
424
+ const categories = [
425
+ {
426
+ id: 1,
427
+ name: 'Frontend',
428
+ items: ['React', 'Vue', 'Angular', 'Svelte']
429
+ },
430
+ {
431
+ id: 2,
432
+ name: 'Backend',
433
+ items: ['Node.js', 'Python', 'Java', 'Go']
434
+ },
435
+ {
436
+ id: 3,
437
+ name: 'Database',
438
+ items: ['PostgreSQL', 'MongoDB', 'MySQL', 'Redis']
439
+ }
440
+ ];
441
+
442
+ const toggleCategory = (categoryId) => {
443
+ setExpandedCategories(prev =>
444
+ prev.includes(categoryId)
445
+ ? prev.filter(id => id !== categoryId)
446
+ : [...prev, categoryId]
447
+ );
448
+ };
449
+
450
+ const CategoryItem = ({ item: category }) => (
451
+ <div className="category-item">
452
+ <ListItem
453
+ onClick={() => toggleCategory(category.id)}
454
+ className="category-header"
455
+ >
456
+ <Icon
457
+ icon={expandedCategories.includes(category.id) ? 'ExpandLess' : 'ExpandMore'}
458
+ />
459
+ <Text type="BodyMedium">{category.name}</Text>
460
+ </ListItem>
461
+
462
+ {expandedCategories.includes(category.id) && (
463
+ <div className="nested-items">
464
+ <List
465
+ data={category.items}
466
+ component={({ item }) => (
467
+ <ListItem className="nested-item">
468
+ <Text type="BodySmall">{item}</Text>
469
+ </ListItem>
470
+ )}
471
+ />
472
+ </div>
473
+ )}
474
+ </div>
475
+ );
476
+
477
+ return (
478
+ <List
479
+ data={categories}
480
+ component={CategoryItem}
481
+ keyExtractor={(category) => category.id}
482
+ />
483
+ );
484
+ }
485
+ ```