@app-studio/web 0.9.31 → 0.9.32

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 (60) 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/package.json +1 -1
@@ -0,0 +1,426 @@
1
+ # Uploader
2
+
3
+ A versatile file upload component with support for single and multiple file uploads, drag & drop functionality, file validation, preview capabilities, and progress tracking. Perfect for handling images, videos, documents, and any file type with built-in error handling and customizable UI.
4
+
5
+ ### **Import**
6
+ ```tsx
7
+ import { Uploader } from '@app-studio/web';
8
+ ```
9
+
10
+ ### **Basic Usage**
11
+ ```tsx
12
+ import React from 'react';
13
+ import { Uploader } from '@app-studio/web';
14
+ import { UploadIcon } from '@app-studio/web';
15
+
16
+ export const BasicUploader = () => {
17
+ const handleFileSelect = (file: File) => {
18
+ console.log('Selected file:', file);
19
+ // Handle the uploaded file
20
+ };
21
+
22
+ return (
23
+ <Uploader
24
+ icon={<UploadIcon widthHeight={32} />}
25
+ text="Click to upload a file"
26
+ onFileSelect={handleFileSelect}
27
+ maxSize={10 * 1024 * 1024} // 10MB limit
28
+ />
29
+ );
30
+ };
31
+ ```
32
+
33
+ ### **Multiple File Upload**
34
+ ```tsx
35
+ import React, { useState } from 'react';
36
+ import { Uploader } from '@app-studio/web';
37
+ import { UploadIcon } from '@app-studio/web';
38
+
39
+ export const MultipleFileUploader = () => {
40
+ const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
41
+
42
+ const handleMultipleFileSelect = (files: File[]) => {
43
+ console.log('Selected files:', files);
44
+ setSelectedFiles(files);
45
+ };
46
+
47
+ return (
48
+ <Uploader
49
+ icon={<UploadIcon widthHeight={32} />}
50
+ text="Click to upload multiple files"
51
+ multiple={true}
52
+ onMultipleFileSelect={handleMultipleFileSelect}
53
+ maxSize={50 * 1024 * 1024} // 50MB limit per file
54
+ accept="image/*,video/*,.pdf,.doc,.docx"
55
+ />
56
+ );
57
+ };
58
+ ```
59
+
60
+ ### **Image Upload with Preview**
61
+ ```tsx
62
+ import React, { useState } from 'react';
63
+ import { Uploader } from '@app-studio/web';
64
+ import { ImageIcon } from '@app-studio/web';
65
+
66
+ export const ImageUploader = () => {
67
+ const [isLoading, setIsLoading] = useState(false);
68
+ const [progress, setProgress] = useState(0);
69
+
70
+ const handleImageSelect = (file: File) => {
71
+ console.log('Selected image:', file);
72
+
73
+ // Simulate upload progress
74
+ setIsLoading(true);
75
+ setProgress(0);
76
+
77
+ const interval = setInterval(() => {
78
+ setProgress((prev) => {
79
+ if (prev >= 100) {
80
+ clearInterval(interval);
81
+ setIsLoading(false);
82
+ return 100;
83
+ }
84
+ return prev + 10;
85
+ });
86
+ }, 200);
87
+ };
88
+
89
+ return (
90
+ <Uploader
91
+ accept="image/*"
92
+ icon={<ImageIcon widthHeight={32} />}
93
+ text="Upload Image"
94
+ onFileSelect={handleImageSelect}
95
+ isLoading={isLoading}
96
+ progress={progress}
97
+ fileType="image"
98
+ maxSize={5 * 1024 * 1024} // 5MB limit
99
+ containerProps={{
100
+ height: progress === 100 ? '200px' : 'auto',
101
+ minHeight: '120px'
102
+ }}
103
+ />
104
+ );
105
+ };
106
+ ```
107
+
108
+ ### **Video Upload with Thumbnail**
109
+ ```tsx
110
+ import React, { useState } from 'react';
111
+ import { Uploader } from '@app-studio/web';
112
+ import { VideoIcon } from '@app-studio/web';
113
+
114
+ export const VideoUploader = () => {
115
+ const [isLoading, setIsLoading] = useState(false);
116
+ const [progress, setProgress] = useState(0);
117
+
118
+ const handleVideoSelect = (file: File) => {
119
+ console.log('Selected video:', file);
120
+
121
+ // Simulate upload progress
122
+ setIsLoading(true);
123
+ setProgress(0);
124
+
125
+ const interval = setInterval(() => {
126
+ setProgress((prev) => {
127
+ if (prev >= 100) {
128
+ clearInterval(interval);
129
+ setIsLoading(false);
130
+ return 100;
131
+ }
132
+ return prev + 5;
133
+ });
134
+ }, 300);
135
+ };
136
+
137
+ return (
138
+ <Uploader
139
+ accept="video/*"
140
+ icon={<VideoIcon widthHeight={32} />}
141
+ text="Upload Video"
142
+ onFileSelect={handleVideoSelect}
143
+ isLoading={isLoading}
144
+ progress={progress}
145
+ fileType="video"
146
+ maxSize={100 * 1024 * 1024} // 100MB limit
147
+ containerProps={{
148
+ height: progress === 100 ? '200px' : 'auto',
149
+ minHeight: '120px'
150
+ }}
151
+ />
152
+ );
153
+ };
154
+ ```
155
+
156
+ ### **File Validation**
157
+ ```tsx
158
+ import React from 'react';
159
+ import { Uploader } from '@app-studio/web';
160
+ import { UploadIcon } from '@app-studio/web';
161
+
162
+ export const ValidatedUploader = () => {
163
+ const validateFile = (file: File): string | null => {
164
+ // Custom validation logic
165
+ if (file.size > 10 * 1024 * 1024) {
166
+ return 'File size must be less than 10MB';
167
+ }
168
+
169
+ if (!file.type.startsWith('image/')) {
170
+ return 'Only image files are allowed';
171
+ }
172
+
173
+ if (file.name.length > 50) {
174
+ return 'File name must be less than 50 characters';
175
+ }
176
+
177
+ return null; // No validation errors
178
+ };
179
+
180
+ const handleFileSelect = (file: File) => {
181
+ console.log('Valid file selected:', file);
182
+ };
183
+
184
+ const handleError = (error: string) => {
185
+ console.error('Upload error:', error);
186
+ // Show error message to user
187
+ };
188
+
189
+ return (
190
+ <Uploader
191
+ icon={<UploadIcon widthHeight={32} />}
192
+ text="Upload Image (Max 10MB)"
193
+ accept="image/*"
194
+ onFileSelect={handleFileSelect}
195
+ validateFile={validateFile}
196
+ onError={handleError}
197
+ maxSize={10 * 1024 * 1024}
198
+ />
199
+ );
200
+ };
201
+ ```
202
+
203
+ ### **Custom Rendering**
204
+ ```tsx
205
+ import React from 'react';
206
+ import { Uploader } from '@app-studio/web';
207
+ import { View, Text } from 'app-studio';
208
+ import { CheckIcon, ErrorIcon } from '@app-studio/web';
209
+
210
+ export const CustomUploader = () => {
211
+ const handleFileSelect = (file: File) => {
212
+ console.log('File selected:', file);
213
+ };
214
+
215
+ const customErrorRenderer = ({ errorMessage }: any) => (
216
+ <View
217
+ padding={8}
218
+ backgroundColor="color.red.50"
219
+ borderRadius={4}
220
+ marginTop={8}
221
+ >
222
+ <Text color="color.red.600" fontSize={12}>
223
+ <ErrorIcon widthHeight={16} /> {errorMessage}
224
+ </Text>
225
+ </View>
226
+ );
227
+
228
+ const customFileRenderer = ({ selectedFile }: any) => (
229
+ <View
230
+ padding={12}
231
+ backgroundColor="color.green.50"
232
+ borderRadius={4}
233
+ marginTop={8}
234
+ >
235
+ <Text color="color.green.700" fontSize={14}>
236
+ <CheckIcon widthHeight={16} /> {selectedFile.name}
237
+ </Text>
238
+ <Text color="color.green.600" fontSize={12}>
239
+ Size: {Math.round(selectedFile.size / 1024)} KB
240
+ </Text>
241
+ </View>
242
+ );
243
+
244
+ return (
245
+ <Uploader
246
+ text="Drop your file here or click to browse"
247
+ onFileSelect={handleFileSelect}
248
+ renderError={customErrorRenderer}
249
+ renderFile={customFileRenderer}
250
+ views={{
251
+ container: {
252
+ border: '2px dashed',
253
+ borderColor: 'color.blue.300',
254
+ backgroundColor: 'color.blue.50',
255
+ borderRadius: 12,
256
+ padding: 24,
257
+ },
258
+ text: {
259
+ color: 'color.blue.700',
260
+ fontWeight: 'medium',
261
+ },
262
+ }}
263
+ />
264
+ );
265
+ };
266
+ ```
267
+
268
+ ### **Integration with ChatInput**
269
+ The Uploader component is seamlessly integrated into the ChatInput component for file attachments:
270
+
271
+ ```tsx
272
+ import React, { useState } from 'react';
273
+ import { ChatInput } from '@app-studio/web';
274
+ import { View } from 'app-studio';
275
+
276
+ export const ChatWithFileUpload = () => {
277
+ const [inputValue, setInputValue] = useState('');
278
+
279
+ const handleSubmit = (message: string, options?: any) => {
280
+ console.log('Message with files:', message);
281
+ console.log('Upload options:', options);
282
+ setInputValue('');
283
+ };
284
+
285
+ return (
286
+ <View width="100%">
287
+ <ChatInput
288
+ onSubmit={handleSubmit}
289
+ value={inputValue}
290
+ onChange={setInputValue}
291
+ placeholder="Type a message or upload files..."
292
+ hideAttachments={false} // Enable file upload button
293
+ />
294
+ </View>
295
+ );
296
+ };
297
+ ```
298
+
299
+ ### **Props**
300
+
301
+ | Prop | Type | Default | Description |
302
+ | ---- | ---- | ------- | ----------- |
303
+ | accept | string | '*/*' | File types to accept (MIME types) |
304
+ | icon | React.ReactNode | undefined | Icon to display in the upload area |
305
+ | text | string | undefined | Text to display in the upload area |
306
+ | maxSize | number | 100MB | Maximum file size in bytes |
307
+ | onFileSelect | `(file: File) => void` | undefined | Callback when a single file is selected |
308
+ | onMultipleFileSelect | `(files: File[]) => void` | undefined | Callback when multiple files are selected |
309
+ | validateFile | `(file: File) => string \| null` | undefined | Custom validation function |
310
+ | isLoading | boolean | false | Whether the uploader is in loading state |
311
+ | progress | number | 0 | Upload progress (0-100) |
312
+ | fileType | `'video' \| 'image' \| 'file'` | undefined | Type of file for preview rendering |
313
+ | multiple | boolean | false | Allow multiple file selection |
314
+ | onError | `(error: string) => void` | undefined | Error callback function |
315
+ | thumbnail | string | undefined | Thumbnail URL for preview |
316
+
317
+ ### **Custom Rendering Props**
318
+
319
+ | Prop | Type | Description |
320
+ | ---- | ---- | ----------- |
321
+ | renderVideo | `(props: any) => React.ReactNode` | Custom video preview renderer |
322
+ | renderText | `(props: any) => React.ReactNode` | Custom text renderer |
323
+ | renderImage | `(props: any) => React.ReactNode` | Custom image preview renderer |
324
+ | renderError | `(props: any) => React.ReactNode` | Custom error message renderer |
325
+ | renderFile | `(props: any) => React.ReactNode` | Custom file info renderer |
326
+ | renderProgress | `(props: any) => React.ReactNode` | Custom progress indicator renderer |
327
+
328
+ ### **View Customization**
329
+
330
+ The `views` prop allows you to customize different parts of the component:
331
+
332
+ ```tsx
333
+ <Uploader
334
+ // ...other props
335
+ views={{
336
+ container: { /* styles for the main container */ },
337
+ view: { /* styles for the content wrapper */ },
338
+ image: { /* styles for image preview */ },
339
+ horizontal: { /* styles for horizontal layout */ },
340
+ text: { /* styles for text elements */ },
341
+ }}
342
+ />
343
+ ```
344
+
345
+ ### **File Type Detection**
346
+
347
+ The Uploader automatically detects file types and renders appropriate previews:
348
+
349
+ - **Images**: Shows image preview with proper scaling
350
+ - **Videos**: Generates thumbnail and shows video preview
351
+ - **Files**: Displays file name and size information
352
+
353
+ ### **Error Handling**
354
+
355
+ The component provides comprehensive error handling:
356
+
357
+ - **File size validation**: Automatic validation against `maxSize` prop
358
+ - **Custom validation**: Use `validateFile` prop for custom rules
359
+ - **Error callbacks**: Handle errors with `onError` callback
360
+ - **Visual feedback**: Error messages displayed in the UI
361
+
362
+ ### **Best Practices**
363
+
364
+ **File Size Limits:**
365
+ - Set appropriate `maxSize` limits based on your use case
366
+ - Consider server-side validation as well
367
+ - Provide clear feedback about size limits to users
368
+
369
+ **File Type Restrictions:**
370
+ - Use the `accept` prop to limit file types
371
+ - Implement additional validation in `validateFile` if needed
372
+ - Consider security implications of allowed file types
373
+
374
+ **User Experience:**
375
+ - Provide clear instructions with the `text` prop
376
+ - Use appropriate icons to indicate file types
377
+ - Show progress feedback for large uploads
378
+ - Handle errors gracefully with user-friendly messages
379
+
380
+ **Performance:**
381
+ - Consider lazy loading for large file previews
382
+ - Implement proper cleanup for object URLs
383
+ - Use appropriate file size limits to prevent memory issues
384
+
385
+ ### **Accessibility**
386
+
387
+ The Uploader component includes built-in accessibility features:
388
+
389
+ - Keyboard navigation support
390
+ - ARIA attributes for screen readers
391
+ - Focus management
392
+ - Proper contrast for visual elements
393
+
394
+ ### **Integration Examples**
395
+
396
+ **With Form Libraries:**
397
+ ```tsx
398
+ // Integration with Formik
399
+ import { useFormikContext } from 'formik';
400
+
401
+ const FormikUploader = ({ name, ...props }) => {
402
+ const { setFieldValue } = useFormikContext();
403
+
404
+ return (
405
+ <Uploader
406
+ onFileSelect={(file) => setFieldValue(name, file)}
407
+ {...props}
408
+ />
409
+ );
410
+ };
411
+ ```
412
+
413
+ **With State Management:**
414
+ ```tsx
415
+ // Integration with Redux or other state management
416
+ const ConnectedUploader = () => {
417
+ const dispatch = useDispatch();
418
+
419
+ return (
420
+ <Uploader
421
+ onFileSelect={(file) => dispatch(uploadFile(file))}
422
+ onMultipleFileSelect={(files) => dispatch(uploadMultipleFiles(files))}
423
+ />
424
+ );
425
+ };
426
+ ```