@app-studio/web 0.9.31 → 0.9.33

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 (61) hide show
  1. package/docs/components/Accordion.mdx +158 -0
  2. package/docs/components/Alert.mdx +123 -0
  3. package/docs/components/AspectRatio.mdx +55 -0
  4. package/docs/components/Avatar.mdx +85 -0
  5. package/docs/components/Background.mdx +522 -0
  6. package/docs/components/Badge.mdx +220 -0
  7. package/docs/components/Button.mdx +272 -0
  8. package/docs/components/Calendar.mdx +274 -0
  9. package/docs/components/Card.mdx +341 -0
  10. package/docs/components/Carousel.mdx +411 -0
  11. package/docs/components/Center.mdx +474 -0
  12. package/docs/components/Chart.mdx +232 -0
  13. package/docs/components/ChatInput.mdx +373 -0
  14. package/docs/components/Checkbox.mdx +66 -0
  15. package/docs/components/ColorInput.mdx +209 -0
  16. package/docs/components/ComboBox.mdx +364 -0
  17. package/docs/components/Command.mdx +252 -0
  18. package/docs/components/ContextMenu.mdx +219 -0
  19. package/docs/components/CountryPicker.mdx +123 -0
  20. package/docs/components/DatePicker.mdx +77 -0
  21. package/docs/components/DragAndDrop.mdx +539 -0
  22. package/docs/components/DropdownMenu.mdx +205 -0
  23. package/docs/components/File.mdx +8 -0
  24. package/docs/components/Flow.mdx +257 -0
  25. package/docs/components/Form.mdx +681 -0
  26. package/docs/components/Formik.mdx +621 -0
  27. package/docs/components/Gradient.mdx +271 -0
  28. package/docs/components/Horizontal.mdx +40 -0
  29. package/docs/components/HoverCard.mdx +140 -0
  30. package/docs/components/Icon.mdx +438 -0
  31. package/docs/components/Label.mdx +438 -0
  32. package/docs/components/Link.mdx +83 -0
  33. package/docs/components/Loader.mdx +527 -0
  34. package/docs/components/Menubar.mdx +124 -0
  35. package/docs/components/Message.mdx +571 -0
  36. package/docs/components/Modal.mdx +533 -0
  37. package/docs/components/NavigationMenu.mdx +165 -0
  38. package/docs/components/Pagination.mdx +150 -0
  39. package/docs/components/Password.mdx +121 -0
  40. package/docs/components/Resizable.mdx +148 -0
  41. package/docs/components/Select.mdx +126 -0
  42. package/docs/components/Separator.mdx +121 -0
  43. package/docs/components/Sidebar.mdx +147 -0
  44. package/docs/components/Slider.mdx +232 -0
  45. package/docs/components/Switch.mdx +62 -0
  46. package/docs/components/Table.mdx +409 -0
  47. package/docs/components/Tabs.mdx +215 -0
  48. package/docs/components/TagInput.mdx +528 -0
  49. package/docs/components/Text.mdx +163 -0
  50. package/docs/components/TextArea.mdx +136 -0
  51. package/docs/components/TextField.mdx +225 -0
  52. package/docs/components/Title.mdx +535 -0
  53. package/docs/components/Toast.mdx +165 -0
  54. package/docs/components/Toggle.mdx +141 -0
  55. package/docs/components/ToggleGroup.mdx +165 -0
  56. package/docs/components/Tooltip.mdx +191 -0
  57. package/docs/components/Tree.mdx +340 -0
  58. package/docs/components/Uploader.mdx +426 -0
  59. package/docs/components/Vertical.mdx +566 -0
  60. package/docs/components.md +285 -0
  61. package/package.json +1 -1
@@ -0,0 +1,539 @@
1
+ # DragAndDrop
2
+
3
+ A powerful drag and drop component for reordering lists and items with smooth animations, touch support, and customizable rendering. Perfect for creating sortable lists, kanban boards, and interactive interfaces.
4
+
5
+ ### **Import**
6
+ ```tsx
7
+ import { DragAndDrop } from '@app-studio/web';
8
+ ```
9
+
10
+ ### **Basic Usage**
11
+ ```tsx
12
+ import React, { useState } from 'react';
13
+ import { DragAndDrop } from '@app-studio/web';
14
+ import { View, Text } from 'app-studio';
15
+
16
+ export const BasicDragAndDrop = () => {
17
+ const [items, setItems] = useState([
18
+ 'Item 1',
19
+ 'Item 2',
20
+ 'Item 3',
21
+ 'Item 4'
22
+ ]);
23
+
24
+ const handleItemsChange = (newItems: string[]) => {
25
+ console.log('Items reordered:', newItems);
26
+ setItems(newItems);
27
+ };
28
+
29
+ return (
30
+ <DragAndDrop
31
+ items={items}
32
+ onChange={handleItemsChange}
33
+ containerProps={{
34
+ padding: 16,
35
+ backgroundColor: 'color.gray.50',
36
+ borderRadius: 8,
37
+ }}
38
+ itemProps={{
39
+ marginBottom: 8,
40
+ padding: 12,
41
+ backgroundColor: 'color.white',
42
+ borderRadius: 4,
43
+ border: '1px solid',
44
+ borderColor: 'color.gray.200',
45
+ }}
46
+ />
47
+ );
48
+ };
49
+ ```
50
+
51
+ ### **Custom Item Rendering**
52
+ ```tsx
53
+ import React, { useState } from 'react';
54
+ import { DragAndDrop } from '@app-studio/web';
55
+ import { View, Text, Horizontal } from 'app-studio';
56
+ import { DragHandleIcon, EditIcon, DeleteIcon } from '@app-studio/web';
57
+
58
+ interface Task {
59
+ id: string;
60
+ title: string;
61
+ description: string;
62
+ priority: 'low' | 'medium' | 'high';
63
+ completed: boolean;
64
+ }
65
+
66
+ export const TaskDragAndDrop = () => {
67
+ const [tasks, setTasks] = useState<Task[]>([
68
+ {
69
+ id: '1',
70
+ title: 'Design Homepage',
71
+ description: 'Create wireframes and mockups',
72
+ priority: 'high',
73
+ completed: false,
74
+ },
75
+ {
76
+ id: '2',
77
+ title: 'Implement Authentication',
78
+ description: 'Set up user login and registration',
79
+ priority: 'medium',
80
+ completed: false,
81
+ },
82
+ {
83
+ id: '3',
84
+ title: 'Write Documentation',
85
+ description: 'Document API endpoints',
86
+ priority: 'low',
87
+ completed: true,
88
+ },
89
+ ]);
90
+
91
+ const handleTasksChange = (newTasks: Task[]) => {
92
+ setTasks(newTasks);
93
+ };
94
+
95
+ const renderTask = (task: Task, index: number) => {
96
+ const priorityColors = {
97
+ low: 'color.green.500',
98
+ medium: 'color.yellow.500',
99
+ high: 'color.red.500',
100
+ };
101
+
102
+ return (
103
+ <View
104
+ padding={16}
105
+ backgroundColor={task.completed ? 'color.gray.50' : 'color.white'}
106
+ border="1px solid"
107
+ borderColor="color.gray.200"
108
+ borderRadius={8}
109
+ marginBottom={8}
110
+ >
111
+ <Horizontal justifyContent="space-between" alignItems="flex-start">
112
+ <View flex={1}>
113
+ <Horizontal alignItems="center" marginBottom={8}>
114
+ <View
115
+ width={8}
116
+ height={8}
117
+ borderRadius="50%"
118
+ backgroundColor={priorityColors[task.priority]}
119
+ marginRight={8}
120
+ />
121
+ <Text
122
+ fontWeight="semibold"
123
+ textDecoration={task.completed ? 'line-through' : 'none'}
124
+ color={task.completed ? 'color.gray.500' : 'color.gray.900'}
125
+ >
126
+ {task.title}
127
+ </Text>
128
+ </Horizontal>
129
+ <Text
130
+ fontSize={14}
131
+ color="color.gray.600"
132
+ textDecoration={task.completed ? 'line-through' : 'none'}
133
+ >
134
+ {task.description}
135
+ </Text>
136
+ </View>
137
+
138
+ <Horizontal gap={8} alignItems="center">
139
+ <EditIcon widthHeight={16} color="color.gray.400" />
140
+ <DeleteIcon widthHeight={16} color="color.gray.400" />
141
+ <DragHandleIcon widthHeight={16} color="color.gray.400" />
142
+ </Horizontal>
143
+ </Horizontal>
144
+ </View>
145
+ );
146
+ };
147
+
148
+ return (
149
+ <View width="100%" maxWidth={500}>
150
+ <Text fontSize={18} fontWeight="bold" marginBottom={16}>
151
+ Task List (Drag to Reorder)
152
+ </Text>
153
+ <DragAndDrop
154
+ items={tasks}
155
+ onChange={handleTasksChange}
156
+ renderItem={renderTask}
157
+ containerProps={{
158
+ padding: 16,
159
+ backgroundColor: 'color.gray.50',
160
+ borderRadius: 12,
161
+ minHeight: 200,
162
+ }}
163
+ />
164
+ </View>
165
+ );
166
+ };
167
+ ```
168
+
169
+ ### **Kanban Board Example**
170
+ ```tsx
171
+ import React, { useState } from 'react';
172
+ import { DragAndDrop } from '@app-studio/web';
173
+ import { View, Text, Horizontal, Vertical } from 'app-studio';
174
+
175
+ interface KanbanItem {
176
+ id: string;
177
+ title: string;
178
+ assignee: string;
179
+ tags: string[];
180
+ }
181
+
182
+ interface KanbanColumn {
183
+ id: string;
184
+ title: string;
185
+ items: KanbanItem[];
186
+ }
187
+
188
+ export const KanbanBoard = () => {
189
+ const [columns, setColumns] = useState<KanbanColumn[]>([
190
+ {
191
+ id: 'todo',
192
+ title: 'To Do',
193
+ items: [
194
+ { id: '1', title: 'Design System', assignee: 'John', tags: ['Design'] },
195
+ { id: '2', title: 'API Integration', assignee: 'Jane', tags: ['Backend'] },
196
+ ],
197
+ },
198
+ {
199
+ id: 'inprogress',
200
+ title: 'In Progress',
201
+ items: [
202
+ { id: '3', title: 'User Dashboard', assignee: 'Bob', tags: ['Frontend'] },
203
+ ],
204
+ },
205
+ {
206
+ id: 'done',
207
+ title: 'Done',
208
+ items: [
209
+ { id: '4', title: 'Project Setup', assignee: 'Alice', tags: ['DevOps'] },
210
+ ],
211
+ },
212
+ ]);
213
+
214
+ const handleColumnItemsChange = (columnId: string, newItems: KanbanItem[]) => {
215
+ setColumns(prev =>
216
+ prev.map(col =>
217
+ col.id === columnId
218
+ ? { ...col, items: newItems }
219
+ : col
220
+ )
221
+ );
222
+ };
223
+
224
+ const renderKanbanItem = (item: KanbanItem) => (
225
+ <View
226
+ padding={12}
227
+ backgroundColor="color.white"
228
+ border="1px solid"
229
+ borderColor="color.gray.200"
230
+ borderRadius={6}
231
+ marginBottom={8}
232
+ boxShadow="0 1px 3px rgba(0,0,0,0.1)"
233
+ >
234
+ <Text fontWeight="medium" marginBottom={8}>
235
+ {item.title}
236
+ </Text>
237
+ <Horizontal justifyContent="space-between" alignItems="center">
238
+ <Text fontSize={12} color="color.gray.600">
239
+ {item.assignee}
240
+ </Text>
241
+ <Horizontal gap={4}>
242
+ {item.tags.map(tag => (
243
+ <View
244
+ key={tag}
245
+ padding="2px 6px"
246
+ backgroundColor="color.blue.100"
247
+ borderRadius={4}
248
+ >
249
+ <Text fontSize={10} color="color.blue.700">
250
+ {tag}
251
+ </Text>
252
+ </View>
253
+ ))}
254
+ </Horizontal>
255
+ </Horizontal>
256
+ </View>
257
+ );
258
+
259
+ return (
260
+ <Horizontal gap={16} alignItems="flex-start">
261
+ {columns.map(column => (
262
+ <View
263
+ key={column.id}
264
+ width={250}
265
+ backgroundColor="color.gray.100"
266
+ borderRadius={8}
267
+ padding={16}
268
+ >
269
+ <Text fontWeight="bold" marginBottom={16}>
270
+ {column.title} ({column.items.length})
271
+ </Text>
272
+ <DragAndDrop
273
+ items={column.items}
274
+ onChange={(newItems) => handleColumnItemsChange(column.id, newItems)}
275
+ renderItem={renderKanbanItem}
276
+ containerProps={{
277
+ minHeight: 300,
278
+ }}
279
+ />
280
+ </View>
281
+ ))}
282
+ </Horizontal>
283
+ );
284
+ };
285
+ ```
286
+
287
+ ### **Props**
288
+
289
+ | Prop | Type | Default | Description |
290
+ | ---- | ---- | ------- | ----------- |
291
+ | items | any[] | required | Array of items to be rendered and reordered |
292
+ | onChange | `(items: any[]) => void` | undefined | Callback function called when items are reordered |
293
+ | renderItem | `(item: any, index: number) => React.ReactNode` | undefined | Custom render function for each item |
294
+ | containerProps | ViewProps | undefined | Props to apply to the container element |
295
+ | itemProps | ViewProps | undefined | Props to apply to each item wrapper |
296
+
297
+ ### **Advanced Features**
298
+
299
+ **Touch Support:**
300
+ The component automatically supports touch devices for mobile drag and drop:
301
+
302
+ ```tsx
303
+ // Touch events are handled automatically
304
+ <DragAndDrop
305
+ items={items}
306
+ onChange={handleChange}
307
+ // Works on both desktop and mobile
308
+ />
309
+ ```
310
+
311
+ **Visual Feedback:**
312
+ Items provide visual feedback during drag operations:
313
+
314
+ ```tsx
315
+ <DragAndDrop
316
+ items={items}
317
+ onChange={handleChange}
318
+ itemProps={{
319
+ // Styling applied to all items
320
+ transition: 'transform 0.2s ease',
321
+ cursor: 'grab',
322
+ }}
323
+ views={{
324
+ item: {
325
+ // Additional styling for dragged items
326
+ '&:hover': {
327
+ backgroundColor: 'color.gray.50',
328
+ },
329
+ },
330
+ }}
331
+ />
332
+ ```
333
+
334
+ ### **Integration with Other Components**
335
+
336
+ **With Tree Component:**
337
+ ```tsx
338
+ import { Tree } from '@app-studio/web';
339
+
340
+ // Tree component has built-in drag and drop
341
+ <Tree
342
+ items={treeItems}
343
+ allowDragAndDrop={true}
344
+ onItemsReorder={handleTreeReorder}
345
+ dragHandleIcon={<DragHandleIcon />}
346
+ />
347
+ ```
348
+
349
+ **With Flow Component:**
350
+ ```tsx
351
+ import { Flow } from '@app-studio/web';
352
+
353
+ // Flow component supports node dragging
354
+ <Flow
355
+ nodes={flowNodes}
356
+ allowDraggingNodes={true}
357
+ onNodeDragEnd={handleNodeDragEnd}
358
+ />
359
+ ```
360
+
361
+ ### **Styling and Customization**
362
+
363
+ **Custom Drag Handle:**
364
+ ```tsx
365
+ import { DragHandleIcon } from '@app-studio/web';
366
+
367
+ const renderItemWithHandle = (item, index) => (
368
+ <Horizontal alignItems="center" padding={12}>
369
+ <DragHandleIcon
370
+ widthHeight={16}
371
+ color="color.gray.400"
372
+ marginRight={8}
373
+ />
374
+ <Text>{item.name}</Text>
375
+ </Horizontal>
376
+ );
377
+
378
+ <DragAndDrop
379
+ items={items}
380
+ onChange={handleChange}
381
+ renderItem={renderItemWithHandle}
382
+ />
383
+ ```
384
+
385
+ **Conditional Dragging:**
386
+ ```tsx
387
+ const renderConditionalItem = (item, index) => (
388
+ <View
389
+ padding={12}
390
+ backgroundColor={item.locked ? 'color.gray.100' : 'color.white'}
391
+ cursor={item.locked ? 'not-allowed' : 'grab'}
392
+ opacity={item.locked ? 0.6 : 1}
393
+ >
394
+ <Text>{item.name}</Text>
395
+ {item.locked && <Text fontSize={12} color="color.gray.500">Locked</Text>}
396
+ </View>
397
+ );
398
+ ```
399
+
400
+ ### **Performance Considerations**
401
+
402
+ **Large Lists:**
403
+ For large lists, consider implementing virtualization:
404
+
405
+ ```tsx
406
+ import { FixedSizeList as List } from 'react-window';
407
+
408
+ // For very large datasets, combine with virtualization
409
+ const VirtualizedDragAndDrop = ({ items }) => {
410
+ return (
411
+ <List
412
+ height={400}
413
+ itemCount={items.length}
414
+ itemSize={60}
415
+ >
416
+ {({ index, style }) => (
417
+ <div style={style}>
418
+ <DragAndDrop
419
+ items={[items[index]]}
420
+ // Handle single item drag
421
+ />
422
+ </div>
423
+ )}
424
+ </List>
425
+ );
426
+ };
427
+ ```
428
+
429
+ **Memory Management:**
430
+ ```tsx
431
+ // Clean up event listeners and references
432
+ useEffect(() => {
433
+ return () => {
434
+ // Component handles cleanup automatically
435
+ };
436
+ }, []);
437
+ ```
438
+
439
+ ### **Accessibility**
440
+
441
+ The DragAndDrop component includes accessibility features:
442
+
443
+ - **Keyboard Navigation**: Support for keyboard-based reordering
444
+ - **Screen Reader Support**: ARIA attributes for assistive technologies
445
+ - **Focus Management**: Proper focus handling during drag operations
446
+
447
+ ```tsx
448
+ <DragAndDrop
449
+ items={items}
450
+ onChange={handleChange}
451
+ containerProps={{
452
+ role: 'list',
453
+ 'aria-label': 'Reorderable task list',
454
+ }}
455
+ itemProps={{
456
+ role: 'listitem',
457
+ tabIndex: 0,
458
+ 'aria-grabbed': false, // Dynamically updated during drag
459
+ }}
460
+ />
461
+ ```
462
+
463
+ ### **Best Practices**
464
+
465
+ **State Management:**
466
+ - Keep the items state in a parent component
467
+ - Use unique IDs for items when possible
468
+ - Handle state updates immutably
469
+
470
+ **User Experience:**
471
+ - Provide visual feedback during drag operations
472
+ - Use appropriate cursor styles
473
+ - Consider adding drag handles for complex items
474
+ - Test on both desktop and mobile devices
475
+
476
+ **Performance:**
477
+ - Avoid heavy computations in renderItem
478
+ - Use React.memo for complex item components
479
+ - Consider virtualization for large lists
480
+
481
+ **Accessibility:**
482
+ - Provide keyboard alternatives
483
+ - Use semantic HTML structure
484
+ - Include proper ARIA labels
485
+ - Test with screen readers
486
+
487
+ ### **Common Patterns**
488
+
489
+ **Sortable Table Rows:**
490
+ ```tsx
491
+ const SortableTable = ({ data }) => (
492
+ <table>
493
+ <thead>
494
+ <tr>
495
+ <th>Name</th>
496
+ <th>Status</th>
497
+ <th>Actions</th>
498
+ </tr>
499
+ </thead>
500
+ <tbody>
501
+ <DragAndDrop
502
+ items={data}
503
+ onChange={setData}
504
+ renderItem={(item) => (
505
+ <tr>
506
+ <td>{item.name}</td>
507
+ <td>{item.status}</td>
508
+ <td>
509
+ <DragHandleIcon widthHeight={16} />
510
+ </td>
511
+ </tr>
512
+ )}
513
+ />
514
+ </tbody>
515
+ </table>
516
+ );
517
+ ```
518
+
519
+ **Nested Drag and Drop:**
520
+ ```tsx
521
+ const NestedDragAndDrop = ({ categories }) => (
522
+ <DragAndDrop
523
+ items={categories}
524
+ onChange={setCategories}
525
+ renderItem={(category) => (
526
+ <View>
527
+ <Text fontWeight="bold">{category.name}</Text>
528
+ <DragAndDrop
529
+ items={category.items}
530
+ onChange={(newItems) =>
531
+ updateCategoryItems(category.id, newItems)
532
+ }
533
+ renderItem={(item) => <Text>{item.name}</Text>}
534
+ />
535
+ </View>
536
+ )}
537
+ />
538
+ );
539
+ ```