@adamosuiteservices/ui 2.17.0 → 2.18.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.
@@ -86,6 +86,58 @@ State of the currently selected file. Use `null` when there is no file.
86
86
  onFileSelect?: (file: File | null) => void
87
87
  ```
88
88
 
89
+ Callback invoked when the user selects or removes a file. Receives the new file or `null` when removed.
90
+
91
+ #### onFileAdd
92
+
93
+ ```tsx
94
+ onFileAdd?: (file: File) => void
95
+ ```
96
+
97
+ Callback invoked when a new file is added (via drag & drop or file selection). Receives the added file. This fires in addition to `onFileSelect`.
98
+
99
+ **Use case**: Track file additions for logging, analytics, or triggering immediate upload.
100
+
101
+ **Example**:
102
+
103
+ ```tsx
104
+ const handleFileAdd = (file: File) => {
105
+ console.log("File added:", file.name);
106
+ // Optionally start upload immediately
107
+ uploadFile(file);
108
+ };
109
+
110
+ <FileUpload
111
+ selectedFile={file}
112
+ onFileSelect={setFile}
113
+ onFileAdd={handleFileAdd}
114
+ />;
115
+ ```
116
+
117
+ #### onFileRemove
118
+
119
+ ```tsx
120
+ onFileRemove?: (file: File) => void
121
+ ```
122
+
123
+ Callback invoked when a file is removed. Receives the removed file. This fires in addition to `onFileSelect`.
124
+
125
+ **Use case**: Track file removals, call API to delete from server, or update analytics.
126
+
127
+ **Example**:
128
+
129
+ ```tsx
130
+ const handleFileRemove = (file: File) => {
131
+ console.log("File removed:", file.name);
132
+ };
133
+
134
+ <FileUpload
135
+ selectedFile={file}
136
+ onFileSelect={setFile}
137
+ onFileRemove={handleFileRemove}
138
+ />;
139
+ ```
140
+
89
141
  ### Common props
90
142
 
91
143
  #### acceptedExtensions
@@ -289,6 +341,64 @@ onFilesSelect?: (files: File[]) => void
289
341
 
290
342
  Callback invoked when the user selects, adds, or removes files.
291
343
 
344
+ #### onFilesAdd
345
+
346
+ ```tsx
347
+ onFilesAdd?: (files: File[]) => void
348
+ ```
349
+
350
+ Callback invoked when new files are added (via drag & drop or file selection). Receives the array of added files. This fires in addition to `onFilesSelect`.
351
+
352
+ **Use case**: Track file additions, start batch upload, or update UI state.
353
+
354
+ **Example**:
355
+
356
+ ```tsx
357
+ const handleFilesAdd = (files: File[]) => {
358
+ console.log(
359
+ `${files.length} file(s) added:`,
360
+ files.map((f) => f.name),
361
+ );
362
+ // Start batch upload
363
+ files.forEach(uploadFile);
364
+ };
365
+
366
+ <FileUpload
367
+ selectedFiles={files}
368
+ onFilesSelect={setFiles}
369
+ onFilesAdd={handleFilesAdd}
370
+ multiple
371
+ />;
372
+ ```
373
+
374
+ #### onFilesRemove
375
+
376
+ ```tsx
377
+ onFilesRemove?: (files: File[]) => void
378
+ ```
379
+
380
+ Callback invoked when files are removed (individually or via "Clear all"). Receives the array of removed files. This fires in addition to `onFilesSelect`.
381
+
382
+ **Use case**: Track file removals, call API to delete from server, or clean up resources.
383
+
384
+ **Example**:
385
+
386
+ ```tsx
387
+ const handleFilesRemove = (files: File[]) => {
388
+ console.log(
389
+ `${files.length} file(s) removed:`,
390
+ files.map((f) => f.name),
391
+ );
392
+ };
393
+
394
+ <FileUpload
395
+ selectedFiles={files}
396
+ onFilesSelect={setFiles}
397
+ onFilesRemove={handleFilesRemove}
398
+ multiple
399
+ />;
400
+ ```
401
+
292
402
  #### multiple
293
403
 
294
404
  ```tsx
@@ -597,6 +707,104 @@ function CustomInputPropsExample() {
597
707
  }
598
708
  ```
599
709
 
710
+ ### With callbacks for immediate upload
711
+
712
+ ```tsx
713
+ import { useState } from "react";
714
+ import { FileUpload } from "@adamosuiteservices/ui/file-upload";
715
+ import { Typography } from "@adamosuiteservices/ui/typography";
716
+
717
+ function ImmediateUploadExample() {
718
+ const [file, setFile] = useState<File | null>(null);
719
+ const [isUploading, setIsUploading] = useState(false);
720
+
721
+ const handleFileAdd = async (addedFile: File) => {
722
+ console.log("File added, starting upload:", addedFile.name);
723
+ setIsUploading(true);
724
+
725
+ try {
726
+ const formData = new FormData();
727
+ formData.append("file", addedFile);
728
+
729
+ const response = await fetch("/api/upload", {
730
+ method: "POST",
731
+ body: formData,
732
+ });
733
+
734
+ if (response.ok) {
735
+ console.log("Upload successful");
736
+ }
737
+ } catch (error) {
738
+ console.error("Upload failed:", error);
739
+ } finally {
740
+ setIsUploading(false);
741
+ }
742
+ };
743
+
744
+ const handleFileRemove = (removedFile: File) => {
745
+ console.log("File removed:", removedFile.name);
746
+ };
747
+
748
+ return (
749
+ <div className="adm:max-w-xl adm:space-y-4">
750
+ <FileUpload
751
+ selectedFile={file}
752
+ onFileSelect={setFile}
753
+ onFileAdd={handleFileAdd}
754
+ onFileRemove={handleFileRemove}
755
+ />
756
+ {isUploading && <Typography color="muted">Uploading...</Typography>}
757
+ </div>
758
+ );
759
+ }
760
+ ```
761
+
762
+ ### Multiple files with callbacks
763
+
764
+ ```tsx
765
+ import { useState } from "react";
766
+ import { FileUpload } from "@adamosuiteservices/ui/file-upload";
767
+ import { Typography } from "@adamosuiteservices/ui/typography";
768
+
769
+ function MultipleFilesWithCallbacks() {
770
+ const [files, setFiles] = useState<File[]>([]);
771
+ const [eventLog, setEventLog] = useState<string[]>([]);
772
+
773
+ const handleFilesAdd = (addedFiles: File[]) => {
774
+ const message = `Added ${addedFiles.length} file(s): ${addedFiles.map((f) => f.name).join(", ")}`;
775
+ setEventLog((prev) => [...prev, message]);
776
+ };
777
+
778
+ const handleFilesRemove = (removedFiles: File[]) => {
779
+ const message = `Removed ${removedFiles.length} file(s): ${removedFiles.map((f) => f.name).join(", ")}`;
780
+ setEventLog((prev) => [...prev, message]);
781
+ };
782
+
783
+ return (
784
+ <div className="adm:max-w-xl adm:space-y-4">
785
+ <FileUpload
786
+ selectedFiles={files}
787
+ onFilesSelect={setFiles}
788
+ onFilesAdd={handleFilesAdd}
789
+ onFilesRemove={handleFilesRemove}
790
+ multiple
791
+ />
792
+
793
+ {eventLog.length > 0 && (
794
+ <div className="adm:space-y-2">
795
+ <Typography className="adm:font-medium">Event log:</Typography>
796
+ {eventLog.map((log, index) => (
797
+ <Typography key={index} color="muted" className="adm:text-sm">
798
+ {log}
799
+ </Typography>
800
+ ))}
801
+ </div>
802
+ )}
803
+ </div>
804
+ );
805
+ }
806
+ ```
807
+
600
808
  ### Excel files (default)
601
809
 
602
810
  ````tsx
package/llm.txt CHANGED
@@ -1,11 +1,11 @@
1
1
  # Adamo UI Component Library - LLM Context
2
2
 
3
- > **CRITICAL**: This is a COMPLETE React component library with 45+ components. DO NOT create components that already exist. ALWAYS check this file first and use existing components.
3
+ > **CRITICAL**: This is a COMPLETE React component library with 46+ components. DO NOT create components that already exist. ALWAYS check this file first and use existing components.
4
4
 
5
5
  ## 🚨 MOST IMPORTANT RULES
6
6
 
7
7
  1. **NEVER create a component that already exists** - Check the component list below first
8
- - Example: ❌ DON'T create `<input type="file">` ✅ DO use `<FileUpload>`
8
+ - Example: ❌ DON'T create `<input type="file">` ✅ DO use `<FileUpload>` or `<FileUploadV2>`
9
9
 
10
10
  2. **Use individual imports** - `import { Button } from "@adamosuiteservices/ui/button";`
11
11
 
@@ -13,11 +13,11 @@
13
13
 
14
14
  4. **Users NEVER use `adm:` prefix** - Only library internals use it
15
15
 
16
- ## 📦 Available Components (45+)
16
+ ## 📦 Available Components (46+)
17
17
 
18
18
  Before creating ANY component, verify it doesn't exist here. For implementation details, props, and examples, see the linked documentation.
19
19
 
20
- ### Form Components (14)
20
+ ### Form Components (15)
21
21
  - **Button** [`docs/components/ui/button.md`] - `@adamosuiteservices/ui/button`
22
22
  - **Button Group** [`docs/components/ui/button-group.md`] - `@adamosuiteservices/ui/button-group`
23
23
  - **Input** [`docs/components/ui/input.md`] - `@adamosuiteservices/ui/input`
@@ -31,7 +31,8 @@ Before creating ANY component, verify it doesn't exist here. For implementation
31
31
  - **Field** [`docs/components/ui/field.md`] - `@adamosuiteservices/ui/field` (form wrapper with label/error)
32
32
  - **Label** [`docs/components/ui/label.md`] - `@adamosuiteservices/ui/label`
33
33
  - **Input Group** [`docs/components/ui/input-group.md`] - `@adamosuiteservices/ui/input-group`
34
- - **File Upload** [`docs/components/ui/file-upload.md`] - `@adamosuiteservices/ui/file-upload` ⚠️ USE THIS!
34
+ - **File Upload** [`docs/components/ui/file-upload.md`] - `@adamosuiteservices/ui/file-upload` ⚠️ Simple file upload
35
+ - **File Upload V2** [`docs/components/ui/file-upload-v2.md`] - `@adamosuiteservices/ui/file-upload` ⚠️ With IDs for server integration
35
36
 
36
37
  ### Overlay Components (8)
37
38
  - **Dialog** [`docs/components/ui/dialog.md`] - `@adamosuiteservices/ui/dialog` (modal)
@@ -89,6 +90,8 @@ Before creating ANY component, verify it doesn't exist here. For implementation
89
90
  1. ❌ Creating components that already exist (check list above first!)
90
91
  2. ❌ Using barrel imports: `import { X } from "@adamosuiteservices/ui"`
91
92
  3. ❌ Using `adm:` prefix in user code
93
+ 5. ❌ Using FileUploadV2 for simple forms (use FileUpload instead)
94
+ 6. ❌ Using FileUpload when you need server-side file tracking (use FileUploadV2)
92
95
  4. ❌ Not consulting component documentation before implementation
93
96
 
94
97
  ## 📚 Documentation Structure
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adamosuiteservices/ui",
3
- "version": "2.17.0",
3
+ "version": "2.18.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",