easy-file-dragdrop 1.0.4
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/README.md +127 -0
- package/dist/index.css +240 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.mts +130 -0
- package/dist/index.d.ts +130 -0
- package/dist/index.js +491 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +462 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +55 -0
- package/styles.css.d.ts +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# easy-file-dragdrop
|
|
2
|
+
|
|
3
|
+
A lightweight React drag-and-drop file input for modern apps.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Drag and drop file uploads
|
|
8
|
+
- Click-to-browse fallback
|
|
9
|
+
- Optional image preview support
|
|
10
|
+
- File type filtering via `accept`
|
|
11
|
+
- File count and size limits
|
|
12
|
+
- Built-in callbacks for add, change, and remove events
|
|
13
|
+
- Optional Base64 callback support with `onFileAddB24`
|
|
14
|
+
- Controlled mode via `value` and `onChange`
|
|
15
|
+
- Works smoothly with React Hook Form `Controller`
|
|
16
|
+
- Built-in light and dark theme variants
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install easy-file-dragdrop
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Peer dependencies:
|
|
25
|
+
|
|
26
|
+
- react (`^18 || ^19`)
|
|
27
|
+
- react-dom (`^18 || ^19`)
|
|
28
|
+
- react-icons (`^5`)
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import React from "react";
|
|
34
|
+
import { InputCanvas } from "easy-file-dragdrop";
|
|
35
|
+
|
|
36
|
+
export default function Example() {
|
|
37
|
+
return (
|
|
38
|
+
<InputCanvas
|
|
39
|
+
label="Upload files"
|
|
40
|
+
description="PNG, JPG or PDF up to 5 MB"
|
|
41
|
+
accept="image/*,.pdf"
|
|
42
|
+
multiple
|
|
43
|
+
maxFiles={5}
|
|
44
|
+
maxFileSize={5}
|
|
45
|
+
onChange={(files) => {
|
|
46
|
+
console.log("Selected files:", files);
|
|
47
|
+
}}
|
|
48
|
+
onFileAdd={(file) => {
|
|
49
|
+
console.log("Added:", file.name);
|
|
50
|
+
}}
|
|
51
|
+
onFileAddB24={(base64) => {
|
|
52
|
+
console.log("Base64 length:", base64.length);
|
|
53
|
+
}}
|
|
54
|
+
onFileRemove={(file) => {
|
|
55
|
+
console.log("Removed:", file.name);
|
|
56
|
+
}}
|
|
57
|
+
/>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## React Hook Form
|
|
63
|
+
|
|
64
|
+
Use `Controller` and pass `field.value` / `field.onChange` directly.
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
import { Controller, useForm } from "react-hook-form";
|
|
68
|
+
import { InputCanvas } from "easy-file-dragdrop";
|
|
69
|
+
|
|
70
|
+
type FormValues = {
|
|
71
|
+
files: File[];
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export default function UploadForm() {
|
|
75
|
+
const { control, handleSubmit } = useForm<FormValues>({
|
|
76
|
+
defaultValues: { files: [] }
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const onSubmit = (data: FormValues) => {
|
|
80
|
+
console.log("Submitted files:", data.files);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<form onSubmit={handleSubmit(onSubmit)}>
|
|
85
|
+
<Controller
|
|
86
|
+
name="files"
|
|
87
|
+
control={control}
|
|
88
|
+
render={({ field }) => (
|
|
89
|
+
<InputCanvas
|
|
90
|
+
name={field.name}
|
|
91
|
+
value={field.value ?? []}
|
|
92
|
+
onChange={field.onChange}
|
|
93
|
+
onBlur={field.onBlur}
|
|
94
|
+
multiple
|
|
95
|
+
maxFiles={5}
|
|
96
|
+
accept="image/*,.pdf"
|
|
97
|
+
/>
|
|
98
|
+
)}
|
|
99
|
+
/>
|
|
100
|
+
|
|
101
|
+
<button type="submit">Submit</button>
|
|
102
|
+
</form>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Exports
|
|
108
|
+
|
|
109
|
+
- `InputCanvas`
|
|
110
|
+
- `useDragdrop`
|
|
111
|
+
- `useDragDrop` (alias)
|
|
112
|
+
- Type exports:
|
|
113
|
+
- `SimpleDragDropParams`
|
|
114
|
+
- `DragDropClassNames`
|
|
115
|
+
- `DragDropFileItem`
|
|
116
|
+
|
|
117
|
+
## Development
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
npm run dev
|
|
121
|
+
npm run build
|
|
122
|
+
npm run clean
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## License
|
|
126
|
+
|
|
127
|
+
ISC
|
package/dist/index.css
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/* src/components/InputCanvas.css */
|
|
2
|
+
.efd-root {
|
|
3
|
+
width: 100%;
|
|
4
|
+
color: #0f172a;
|
|
5
|
+
}
|
|
6
|
+
.efd-header {
|
|
7
|
+
margin-bottom: 0.5rem;
|
|
8
|
+
}
|
|
9
|
+
.efd-label {
|
|
10
|
+
display: block;
|
|
11
|
+
margin-bottom: 0.25rem;
|
|
12
|
+
font-size: 0.875rem;
|
|
13
|
+
font-weight: 600;
|
|
14
|
+
color: #0f172a;
|
|
15
|
+
}
|
|
16
|
+
.efd-description {
|
|
17
|
+
margin: 0;
|
|
18
|
+
font-size: 0.75rem;
|
|
19
|
+
color: #64748b;
|
|
20
|
+
}
|
|
21
|
+
.efd-hidden-input {
|
|
22
|
+
display: none;
|
|
23
|
+
}
|
|
24
|
+
.efd-dropzone {
|
|
25
|
+
border: 2px dashed #cbd5e1;
|
|
26
|
+
background: #f8fafc;
|
|
27
|
+
border-radius: 0.75rem;
|
|
28
|
+
padding: 1.5rem;
|
|
29
|
+
text-align: center;
|
|
30
|
+
transition: border-color 150ms ease, background-color 150ms ease;
|
|
31
|
+
}
|
|
32
|
+
.efd-dropzone--interactive {
|
|
33
|
+
cursor: pointer;
|
|
34
|
+
}
|
|
35
|
+
.efd-dropzone--interactive:hover {
|
|
36
|
+
border-color: #94a3b8;
|
|
37
|
+
background: #f1f5f9;
|
|
38
|
+
}
|
|
39
|
+
.efd-dropzone--active {
|
|
40
|
+
border-color: #0ea5e9;
|
|
41
|
+
background: #f0f9ff;
|
|
42
|
+
}
|
|
43
|
+
.efd-dropzone--disabled {
|
|
44
|
+
cursor: not-allowed;
|
|
45
|
+
opacity: 0.6;
|
|
46
|
+
}
|
|
47
|
+
.efd-upload-icon {
|
|
48
|
+
display: flex;
|
|
49
|
+
justify-content: center;
|
|
50
|
+
margin-bottom: 0.75rem;
|
|
51
|
+
color: #64748b;
|
|
52
|
+
}
|
|
53
|
+
.efd-helper-text {
|
|
54
|
+
margin: 0;
|
|
55
|
+
font-size: 0.875rem;
|
|
56
|
+
color: #334155;
|
|
57
|
+
}
|
|
58
|
+
.efd-browse-text {
|
|
59
|
+
font-weight: 600;
|
|
60
|
+
color: #0f172a;
|
|
61
|
+
}
|
|
62
|
+
.efd-error {
|
|
63
|
+
margin-top: 0.5rem;
|
|
64
|
+
font-size: 0.75rem;
|
|
65
|
+
color: #dc2626;
|
|
66
|
+
}
|
|
67
|
+
.efd-empty {
|
|
68
|
+
margin-top: 0.75rem;
|
|
69
|
+
font-size: 0.75rem;
|
|
70
|
+
color: #64748b;
|
|
71
|
+
}
|
|
72
|
+
.efd-file-list {
|
|
73
|
+
margin-top: 1rem;
|
|
74
|
+
margin-bottom: 0;
|
|
75
|
+
padding: 0;
|
|
76
|
+
list-style: none;
|
|
77
|
+
display: grid;
|
|
78
|
+
gap: 0.5rem;
|
|
79
|
+
}
|
|
80
|
+
.efd-file-item {
|
|
81
|
+
display: flex;
|
|
82
|
+
align-items: center;
|
|
83
|
+
gap: 0.75rem;
|
|
84
|
+
border: 1px solid #e2e8f0;
|
|
85
|
+
border-radius: 0.5rem;
|
|
86
|
+
background: #ffffff;
|
|
87
|
+
padding: 0.75rem;
|
|
88
|
+
}
|
|
89
|
+
.efd-preview {
|
|
90
|
+
width: 5rem;
|
|
91
|
+
height: 5rem;
|
|
92
|
+
flex-shrink: 0;
|
|
93
|
+
border-radius: 0.375rem;
|
|
94
|
+
overflow: hidden;
|
|
95
|
+
background: #f1f5f9;
|
|
96
|
+
}
|
|
97
|
+
.efd-preview-image {
|
|
98
|
+
width: 100%;
|
|
99
|
+
height: 100%;
|
|
100
|
+
object-fit: cover;
|
|
101
|
+
}
|
|
102
|
+
.efd-preview-icon {
|
|
103
|
+
width: 100%;
|
|
104
|
+
height: 100%;
|
|
105
|
+
display: flex;
|
|
106
|
+
align-items: center;
|
|
107
|
+
justify-content: center;
|
|
108
|
+
color: #64748b;
|
|
109
|
+
}
|
|
110
|
+
.efd-file-meta {
|
|
111
|
+
min-width: 0;
|
|
112
|
+
flex: 1;
|
|
113
|
+
}
|
|
114
|
+
.efd-file-name {
|
|
115
|
+
margin: 0;
|
|
116
|
+
font-size: 0.875rem;
|
|
117
|
+
font-weight: 500;
|
|
118
|
+
color: #0f172a;
|
|
119
|
+
white-space: nowrap;
|
|
120
|
+
overflow: hidden;
|
|
121
|
+
text-overflow: ellipsis;
|
|
122
|
+
}
|
|
123
|
+
.efd-file-size {
|
|
124
|
+
margin: 0;
|
|
125
|
+
margin-top: 0.125rem;
|
|
126
|
+
font-size: 0.75rem;
|
|
127
|
+
color: #64748b;
|
|
128
|
+
}
|
|
129
|
+
.efd-remove-button {
|
|
130
|
+
border: 0;
|
|
131
|
+
background: transparent;
|
|
132
|
+
width: 2rem;
|
|
133
|
+
height: 2rem;
|
|
134
|
+
border-radius: 0.375rem;
|
|
135
|
+
color: #64748b;
|
|
136
|
+
display: inline-flex;
|
|
137
|
+
align-items: center;
|
|
138
|
+
justify-content: center;
|
|
139
|
+
cursor: pointer;
|
|
140
|
+
transition: background-color 150ms ease, color 150ms ease;
|
|
141
|
+
}
|
|
142
|
+
.efd-remove-button:hover {
|
|
143
|
+
background: #fef2f2;
|
|
144
|
+
color: #dc2626;
|
|
145
|
+
}
|
|
146
|
+
@media (prefers-color-scheme: dark) {
|
|
147
|
+
.efd-root {
|
|
148
|
+
color: #f1f5f9;
|
|
149
|
+
}
|
|
150
|
+
.efd-label {
|
|
151
|
+
color: #f1f5f9;
|
|
152
|
+
}
|
|
153
|
+
.efd-description,
|
|
154
|
+
.efd-empty,
|
|
155
|
+
.efd-file-size,
|
|
156
|
+
.efd-upload-icon,
|
|
157
|
+
.efd-preview-icon {
|
|
158
|
+
color: #94a3b8;
|
|
159
|
+
}
|
|
160
|
+
.efd-helper-text {
|
|
161
|
+
color: #cbd5e1;
|
|
162
|
+
}
|
|
163
|
+
.efd-browse-text,
|
|
164
|
+
.efd-file-name {
|
|
165
|
+
color: #f1f5f9;
|
|
166
|
+
}
|
|
167
|
+
.efd-dropzone {
|
|
168
|
+
border-color: #334155;
|
|
169
|
+
background: rgba(15, 23, 42, 0.72);
|
|
170
|
+
}
|
|
171
|
+
.efd-dropzone--interactive:hover {
|
|
172
|
+
border-color: #64748b;
|
|
173
|
+
background: #0f172a;
|
|
174
|
+
}
|
|
175
|
+
.efd-dropzone--active {
|
|
176
|
+
border-color: #38bdf8;
|
|
177
|
+
background: rgba(8, 47, 73, 0.45);
|
|
178
|
+
}
|
|
179
|
+
.efd-file-item {
|
|
180
|
+
border-color: #334155;
|
|
181
|
+
background: #0f172a;
|
|
182
|
+
}
|
|
183
|
+
.efd-preview {
|
|
184
|
+
background: #1e293b;
|
|
185
|
+
}
|
|
186
|
+
.efd-remove-button {
|
|
187
|
+
color: #94a3b8;
|
|
188
|
+
}
|
|
189
|
+
.efd-remove-button:hover {
|
|
190
|
+
background: rgba(127, 29, 29, 0.55);
|
|
191
|
+
color: #fca5a5;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
.dark .efd-root {
|
|
195
|
+
color: #f1f5f9;
|
|
196
|
+
}
|
|
197
|
+
.dark .efd-label {
|
|
198
|
+
color: #f1f5f9;
|
|
199
|
+
}
|
|
200
|
+
.dark .efd-description,
|
|
201
|
+
.dark .efd-empty,
|
|
202
|
+
.dark .efd-file-size,
|
|
203
|
+
.dark .efd-upload-icon,
|
|
204
|
+
.dark .efd-preview-icon {
|
|
205
|
+
color: #94a3b8;
|
|
206
|
+
}
|
|
207
|
+
.dark .efd-helper-text {
|
|
208
|
+
color: #cbd5e1;
|
|
209
|
+
}
|
|
210
|
+
.dark .efd-browse-text,
|
|
211
|
+
.dark .efd-file-name {
|
|
212
|
+
color: #f1f5f9;
|
|
213
|
+
}
|
|
214
|
+
.dark .efd-dropzone {
|
|
215
|
+
border-color: #334155;
|
|
216
|
+
background: rgba(15, 23, 42, 0.72);
|
|
217
|
+
}
|
|
218
|
+
.dark .efd-dropzone--interactive:hover {
|
|
219
|
+
border-color: #64748b;
|
|
220
|
+
background: #0f172a;
|
|
221
|
+
}
|
|
222
|
+
.dark .efd-dropzone--active {
|
|
223
|
+
border-color: #38bdf8;
|
|
224
|
+
background: rgba(8, 47, 73, 0.45);
|
|
225
|
+
}
|
|
226
|
+
.dark .efd-file-item {
|
|
227
|
+
border-color: #334155;
|
|
228
|
+
background: #0f172a;
|
|
229
|
+
}
|
|
230
|
+
.dark .efd-preview {
|
|
231
|
+
background: #1e293b;
|
|
232
|
+
}
|
|
233
|
+
.dark .efd-remove-button {
|
|
234
|
+
color: #94a3b8;
|
|
235
|
+
}
|
|
236
|
+
.dark .efd-remove-button:hover {
|
|
237
|
+
background: rgba(127, 29, 29, 0.55);
|
|
238
|
+
color: #fca5a5;
|
|
239
|
+
}
|
|
240
|
+
/*# sourceMappingURL=index.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/InputCanvas.css"],"sourcesContent":[".efd-root {\r\n width: 100%;\r\n color: #0f172a;\r\n}\r\n\r\n.efd-header {\r\n margin-bottom: 0.5rem;\r\n}\r\n\r\n.efd-label {\r\n display: block;\r\n margin-bottom: 0.25rem;\r\n font-size: 0.875rem;\r\n font-weight: 600;\r\n color: #0f172a;\r\n}\r\n\r\n.efd-description {\r\n margin: 0;\r\n font-size: 0.75rem;\r\n color: #64748b;\r\n}\r\n\r\n.efd-hidden-input {\r\n display: none;\r\n}\r\n\r\n.efd-dropzone {\r\n border: 2px dashed #cbd5e1;\r\n background: #f8fafc;\r\n border-radius: 0.75rem;\r\n padding: 1.5rem;\r\n text-align: center;\r\n transition: border-color 150ms ease, background-color 150ms ease;\r\n}\r\n\r\n.efd-dropzone--interactive {\r\n cursor: pointer;\r\n}\r\n\r\n.efd-dropzone--interactive:hover {\r\n border-color: #94a3b8;\r\n background: #f1f5f9;\r\n}\r\n\r\n.efd-dropzone--active {\r\n border-color: #0ea5e9;\r\n background: #f0f9ff;\r\n}\r\n\r\n.efd-dropzone--disabled {\r\n cursor: not-allowed;\r\n opacity: 0.6;\r\n}\r\n\r\n.efd-upload-icon {\r\n display: flex;\r\n justify-content: center;\r\n margin-bottom: 0.75rem;\r\n color: #64748b;\r\n}\r\n\r\n.efd-helper-text {\r\n margin: 0;\r\n font-size: 0.875rem;\r\n color: #334155;\r\n}\r\n\r\n.efd-browse-text {\r\n font-weight: 600;\r\n color: #0f172a;\r\n}\r\n\r\n.efd-error {\r\n margin-top: 0.5rem;\r\n font-size: 0.75rem;\r\n color: #dc2626;\r\n}\r\n\r\n.efd-empty {\r\n margin-top: 0.75rem;\r\n font-size: 0.75rem;\r\n color: #64748b;\r\n}\r\n\r\n.efd-file-list {\r\n margin-top: 1rem;\r\n margin-bottom: 0;\r\n padding: 0;\r\n list-style: none;\r\n display: grid;\r\n gap: 0.5rem;\r\n}\r\n\r\n.efd-file-item {\r\n display: flex;\r\n align-items: center;\r\n gap: 0.75rem;\r\n border: 1px solid #e2e8f0;\r\n border-radius: 0.5rem;\r\n background: #ffffff;\r\n padding: 0.75rem;\r\n}\r\n\r\n.efd-preview {\r\n width: 5rem;\r\n height: 5rem;\r\n flex-shrink: 0;\r\n border-radius: 0.375rem;\r\n overflow: hidden;\r\n background: #f1f5f9;\r\n}\r\n\r\n.efd-preview-image {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: cover;\r\n}\r\n\r\n.efd-preview-icon {\r\n width: 100%;\r\n height: 100%;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: #64748b;\r\n}\r\n\r\n.efd-file-meta {\r\n min-width: 0;\r\n flex: 1;\r\n}\r\n\r\n.efd-file-name {\r\n margin: 0;\r\n font-size: 0.875rem;\r\n font-weight: 500;\r\n color: #0f172a;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n}\r\n\r\n.efd-file-size {\r\n margin: 0;\r\n margin-top: 0.125rem;\r\n font-size: 0.75rem;\r\n color: #64748b;\r\n}\r\n\r\n.efd-remove-button {\r\n border: 0;\r\n background: transparent;\r\n width: 2rem;\r\n height: 2rem;\r\n border-radius: 0.375rem;\r\n color: #64748b;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n transition: background-color 150ms ease, color 150ms ease;\r\n}\r\n\r\n.efd-remove-button:hover {\r\n background: #fef2f2;\r\n color: #dc2626;\r\n}\r\n\r\n@media (prefers-color-scheme: dark) {\r\n .efd-root {\r\n color: #f1f5f9;\r\n }\r\n\r\n .efd-label {\r\n color: #f1f5f9;\r\n }\r\n\r\n .efd-description,\r\n .efd-empty,\r\n .efd-file-size,\r\n .efd-upload-icon,\r\n .efd-preview-icon {\r\n color: #94a3b8;\r\n }\r\n\r\n .efd-helper-text {\r\n color: #cbd5e1;\r\n }\r\n\r\n .efd-browse-text,\r\n .efd-file-name {\r\n color: #f1f5f9;\r\n }\r\n\r\n .efd-dropzone {\r\n border-color: #334155;\r\n background: rgba(15, 23, 42, 0.72);\r\n }\r\n\r\n .efd-dropzone--interactive:hover {\r\n border-color: #64748b;\r\n background: #0f172a;\r\n }\r\n\r\n .efd-dropzone--active {\r\n border-color: #38bdf8;\r\n background: rgba(8, 47, 73, 0.45);\r\n }\r\n\r\n .efd-file-item {\r\n border-color: #334155;\r\n background: #0f172a;\r\n }\r\n\r\n .efd-preview {\r\n background: #1e293b;\r\n }\r\n\r\n .efd-remove-button {\r\n color: #94a3b8;\r\n }\r\n\r\n .efd-remove-button:hover {\r\n background: rgba(127, 29, 29, 0.55);\r\n color: #fca5a5;\r\n }\r\n}\r\n\r\n.dark .efd-root {\r\n color: #f1f5f9;\r\n}\r\n\r\n.dark .efd-label {\r\n color: #f1f5f9;\r\n}\r\n\r\n.dark .efd-description,\r\n.dark .efd-empty,\r\n.dark .efd-file-size,\r\n.dark .efd-upload-icon,\r\n.dark .efd-preview-icon {\r\n color: #94a3b8;\r\n}\r\n\r\n.dark .efd-helper-text {\r\n color: #cbd5e1;\r\n}\r\n\r\n.dark .efd-browse-text,\r\n.dark .efd-file-name {\r\n color: #f1f5f9;\r\n}\r\n\r\n.dark .efd-dropzone {\r\n border-color: #334155;\r\n background: rgba(15, 23, 42, 0.72);\r\n}\r\n\r\n.dark .efd-dropzone--interactive:hover {\r\n border-color: #64748b;\r\n background: #0f172a;\r\n}\r\n\r\n.dark .efd-dropzone--active {\r\n border-color: #38bdf8;\r\n background: rgba(8, 47, 73, 0.45);\r\n}\r\n\r\n.dark .efd-file-item {\r\n border-color: #334155;\r\n background: #0f172a;\r\n}\r\n\r\n.dark .efd-preview {\r\n background: #1e293b;\r\n}\r\n\r\n.dark .efd-remove-button {\r\n color: #94a3b8;\r\n}\r\n\r\n.dark .efd-remove-button:hover {\r\n background: rgba(127, 29, 29, 0.55);\r\n color: #fca5a5;\r\n}\r\n"],"mappings":"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","names":[]}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React$1 from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Public props for the InputCanvas component.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* <InputCanvas
|
|
9
|
+
* name="attachments"
|
|
10
|
+
* value={field.value}
|
|
11
|
+
* onChange={field.onChange}
|
|
12
|
+
* accept="image/*,.pdf"
|
|
13
|
+
* maxFiles={5}
|
|
14
|
+
* />
|
|
15
|
+
*/
|
|
16
|
+
interface SimpleDragDropParams {
|
|
17
|
+
/** Input name. Useful when integrating with form libraries. */
|
|
18
|
+
name?: string;
|
|
19
|
+
/** Heading text shown above the dropzone. */
|
|
20
|
+
label?: string;
|
|
21
|
+
/** Optional helper text shown under the label. */
|
|
22
|
+
description?: string;
|
|
23
|
+
/** Controlled file list from parent state or form state. */
|
|
24
|
+
value?: File[];
|
|
25
|
+
/** Controlled change handler, called with the current file array. */
|
|
26
|
+
onChange?: (files: File[]) => void;
|
|
27
|
+
/** Blur handler for form libraries (for touched state). */
|
|
28
|
+
onBlur?: React$1.FocusEventHandler<HTMLInputElement>;
|
|
29
|
+
/** External validation error (for example from react-hook-form). */
|
|
30
|
+
error?: string;
|
|
31
|
+
/** Called for each file that is successfully added. */
|
|
32
|
+
onFileAdd?: (file: File) => void;
|
|
33
|
+
/** Called for each added file as a base64 data URL string. */
|
|
34
|
+
onFileAddB24?: (file: string) => void;
|
|
35
|
+
/** Called when a file is removed from the list. */
|
|
36
|
+
onFileRemove?: (file: File) => void;
|
|
37
|
+
/** Accepted file types, same format as native input accept attribute. */
|
|
38
|
+
accept?: React$1.ComponentProps<"input">["accept"];
|
|
39
|
+
/** Maximum number of files allowed. */
|
|
40
|
+
maxFiles?: number;
|
|
41
|
+
/** Maximum file size in MB. */
|
|
42
|
+
maxFileSize?: number;
|
|
43
|
+
/** Allow selecting more than one file. */
|
|
44
|
+
multiple?: boolean;
|
|
45
|
+
/** Custom per-file validator. Return false to reject a file. */
|
|
46
|
+
validation?: (file: File) => boolean;
|
|
47
|
+
/** Custom class for the root wrapper. */
|
|
48
|
+
className?: string;
|
|
49
|
+
/** Optional className overrides for internal slots. */
|
|
50
|
+
classNames?: DragDropClassNames;
|
|
51
|
+
/** Show image preview thumbnails for image files. */
|
|
52
|
+
showPreview?: boolean;
|
|
53
|
+
/** Disable all interactions. */
|
|
54
|
+
disabled?: boolean;
|
|
55
|
+
/** Default dropzone instruction text. */
|
|
56
|
+
dropzoneText?: string;
|
|
57
|
+
/** Dropzone text shown while dragging files over the area. */
|
|
58
|
+
dropzoneActiveText?: string;
|
|
59
|
+
/** Emphasized browse action text in the dropzone. */
|
|
60
|
+
browseText?: string;
|
|
61
|
+
/** Accessible label prefix for remove button. */
|
|
62
|
+
removeButtonLabel?: string;
|
|
63
|
+
}
|
|
64
|
+
/** Slot-level className overrides for InputCanvas internals. */
|
|
65
|
+
interface DragDropClassNames {
|
|
66
|
+
/** Root wrapper element. */
|
|
67
|
+
root?: string;
|
|
68
|
+
/** Label element. */
|
|
69
|
+
label?: string;
|
|
70
|
+
/** Description paragraph. */
|
|
71
|
+
description?: string;
|
|
72
|
+
/** Dropzone wrapper. */
|
|
73
|
+
dropzone?: string;
|
|
74
|
+
/** Applied in addition to dropzone while drag is active. */
|
|
75
|
+
dropzoneActive?: string;
|
|
76
|
+
/** Applied in addition to dropzone while disabled. */
|
|
77
|
+
dropzoneDisabled?: string;
|
|
78
|
+
/** Dropzone helper text. */
|
|
79
|
+
helperText?: string;
|
|
80
|
+
/** Error text element. */
|
|
81
|
+
errorText?: string;
|
|
82
|
+
/** File list container. */
|
|
83
|
+
fileList?: string;
|
|
84
|
+
/** Single file item row. */
|
|
85
|
+
fileItem?: string;
|
|
86
|
+
/** Preview/icon wrapper for each file item. */
|
|
87
|
+
preview?: string;
|
|
88
|
+
/** File metadata wrapper (name and size). */
|
|
89
|
+
fileMeta?: string;
|
|
90
|
+
/** File name text. */
|
|
91
|
+
fileName?: string;
|
|
92
|
+
/** File size text. */
|
|
93
|
+
fileSize?: string;
|
|
94
|
+
/** Remove button element. */
|
|
95
|
+
removeButton?: string;
|
|
96
|
+
/** Empty-state text element. */
|
|
97
|
+
emptyState?: string;
|
|
98
|
+
}
|
|
99
|
+
/** Internal file view model returned by the hook and rendered by InputCanvas. */
|
|
100
|
+
interface DragDropFileItem {
|
|
101
|
+
/** Stable client-side ID for list rendering and removal. */
|
|
102
|
+
id: string;
|
|
103
|
+
/** Original browser File object. */
|
|
104
|
+
file: File;
|
|
105
|
+
/** True if file MIME type starts with image/. */
|
|
106
|
+
isImage: boolean;
|
|
107
|
+
/** Object URL for image preview when enabled. */
|
|
108
|
+
previewUrl?: string;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
declare function InputCanvas(props: SimpleDragDropParams): react_jsx_runtime.JSX.Element;
|
|
112
|
+
|
|
113
|
+
interface UseDragDropResult {
|
|
114
|
+
files: DragDropFileItem[];
|
|
115
|
+
dragActive: boolean;
|
|
116
|
+
error: string | null;
|
|
117
|
+
inputRef: React.RefObject<HTMLInputElement | null>;
|
|
118
|
+
addFiles: (incoming: FileList | File[]) => Promise<void>;
|
|
119
|
+
removeFile: (id: string) => void;
|
|
120
|
+
clearFiles: () => void;
|
|
121
|
+
openFileDialog: () => void;
|
|
122
|
+
onDragEnter: (event: React.DragEvent<HTMLElement>) => void;
|
|
123
|
+
onDragOver: (event: React.DragEvent<HTMLElement>) => void;
|
|
124
|
+
onDragLeave: (event: React.DragEvent<HTMLElement>) => void;
|
|
125
|
+
onDrop: (event: React.DragEvent<HTMLElement>) => Promise<void>;
|
|
126
|
+
onInputChange: (event: React.ChangeEvent<HTMLInputElement>) => Promise<void>;
|
|
127
|
+
}
|
|
128
|
+
declare function useDragdrop(options?: SimpleDragDropParams): UseDragDropResult;
|
|
129
|
+
|
|
130
|
+
export { type DragDropClassNames, type DragDropFileItem, InputCanvas, type SimpleDragDropParams, useDragdrop as useDragDrop, useDragdrop };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React$1 from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Public props for the InputCanvas component.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* <InputCanvas
|
|
9
|
+
* name="attachments"
|
|
10
|
+
* value={field.value}
|
|
11
|
+
* onChange={field.onChange}
|
|
12
|
+
* accept="image/*,.pdf"
|
|
13
|
+
* maxFiles={5}
|
|
14
|
+
* />
|
|
15
|
+
*/
|
|
16
|
+
interface SimpleDragDropParams {
|
|
17
|
+
/** Input name. Useful when integrating with form libraries. */
|
|
18
|
+
name?: string;
|
|
19
|
+
/** Heading text shown above the dropzone. */
|
|
20
|
+
label?: string;
|
|
21
|
+
/** Optional helper text shown under the label. */
|
|
22
|
+
description?: string;
|
|
23
|
+
/** Controlled file list from parent state or form state. */
|
|
24
|
+
value?: File[];
|
|
25
|
+
/** Controlled change handler, called with the current file array. */
|
|
26
|
+
onChange?: (files: File[]) => void;
|
|
27
|
+
/** Blur handler for form libraries (for touched state). */
|
|
28
|
+
onBlur?: React$1.FocusEventHandler<HTMLInputElement>;
|
|
29
|
+
/** External validation error (for example from react-hook-form). */
|
|
30
|
+
error?: string;
|
|
31
|
+
/** Called for each file that is successfully added. */
|
|
32
|
+
onFileAdd?: (file: File) => void;
|
|
33
|
+
/** Called for each added file as a base64 data URL string. */
|
|
34
|
+
onFileAddB24?: (file: string) => void;
|
|
35
|
+
/** Called when a file is removed from the list. */
|
|
36
|
+
onFileRemove?: (file: File) => void;
|
|
37
|
+
/** Accepted file types, same format as native input accept attribute. */
|
|
38
|
+
accept?: React$1.ComponentProps<"input">["accept"];
|
|
39
|
+
/** Maximum number of files allowed. */
|
|
40
|
+
maxFiles?: number;
|
|
41
|
+
/** Maximum file size in MB. */
|
|
42
|
+
maxFileSize?: number;
|
|
43
|
+
/** Allow selecting more than one file. */
|
|
44
|
+
multiple?: boolean;
|
|
45
|
+
/** Custom per-file validator. Return false to reject a file. */
|
|
46
|
+
validation?: (file: File) => boolean;
|
|
47
|
+
/** Custom class for the root wrapper. */
|
|
48
|
+
className?: string;
|
|
49
|
+
/** Optional className overrides for internal slots. */
|
|
50
|
+
classNames?: DragDropClassNames;
|
|
51
|
+
/** Show image preview thumbnails for image files. */
|
|
52
|
+
showPreview?: boolean;
|
|
53
|
+
/** Disable all interactions. */
|
|
54
|
+
disabled?: boolean;
|
|
55
|
+
/** Default dropzone instruction text. */
|
|
56
|
+
dropzoneText?: string;
|
|
57
|
+
/** Dropzone text shown while dragging files over the area. */
|
|
58
|
+
dropzoneActiveText?: string;
|
|
59
|
+
/** Emphasized browse action text in the dropzone. */
|
|
60
|
+
browseText?: string;
|
|
61
|
+
/** Accessible label prefix for remove button. */
|
|
62
|
+
removeButtonLabel?: string;
|
|
63
|
+
}
|
|
64
|
+
/** Slot-level className overrides for InputCanvas internals. */
|
|
65
|
+
interface DragDropClassNames {
|
|
66
|
+
/** Root wrapper element. */
|
|
67
|
+
root?: string;
|
|
68
|
+
/** Label element. */
|
|
69
|
+
label?: string;
|
|
70
|
+
/** Description paragraph. */
|
|
71
|
+
description?: string;
|
|
72
|
+
/** Dropzone wrapper. */
|
|
73
|
+
dropzone?: string;
|
|
74
|
+
/** Applied in addition to dropzone while drag is active. */
|
|
75
|
+
dropzoneActive?: string;
|
|
76
|
+
/** Applied in addition to dropzone while disabled. */
|
|
77
|
+
dropzoneDisabled?: string;
|
|
78
|
+
/** Dropzone helper text. */
|
|
79
|
+
helperText?: string;
|
|
80
|
+
/** Error text element. */
|
|
81
|
+
errorText?: string;
|
|
82
|
+
/** File list container. */
|
|
83
|
+
fileList?: string;
|
|
84
|
+
/** Single file item row. */
|
|
85
|
+
fileItem?: string;
|
|
86
|
+
/** Preview/icon wrapper for each file item. */
|
|
87
|
+
preview?: string;
|
|
88
|
+
/** File metadata wrapper (name and size). */
|
|
89
|
+
fileMeta?: string;
|
|
90
|
+
/** File name text. */
|
|
91
|
+
fileName?: string;
|
|
92
|
+
/** File size text. */
|
|
93
|
+
fileSize?: string;
|
|
94
|
+
/** Remove button element. */
|
|
95
|
+
removeButton?: string;
|
|
96
|
+
/** Empty-state text element. */
|
|
97
|
+
emptyState?: string;
|
|
98
|
+
}
|
|
99
|
+
/** Internal file view model returned by the hook and rendered by InputCanvas. */
|
|
100
|
+
interface DragDropFileItem {
|
|
101
|
+
/** Stable client-side ID for list rendering and removal. */
|
|
102
|
+
id: string;
|
|
103
|
+
/** Original browser File object. */
|
|
104
|
+
file: File;
|
|
105
|
+
/** True if file MIME type starts with image/. */
|
|
106
|
+
isImage: boolean;
|
|
107
|
+
/** Object URL for image preview when enabled. */
|
|
108
|
+
previewUrl?: string;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
declare function InputCanvas(props: SimpleDragDropParams): react_jsx_runtime.JSX.Element;
|
|
112
|
+
|
|
113
|
+
interface UseDragDropResult {
|
|
114
|
+
files: DragDropFileItem[];
|
|
115
|
+
dragActive: boolean;
|
|
116
|
+
error: string | null;
|
|
117
|
+
inputRef: React.RefObject<HTMLInputElement | null>;
|
|
118
|
+
addFiles: (incoming: FileList | File[]) => Promise<void>;
|
|
119
|
+
removeFile: (id: string) => void;
|
|
120
|
+
clearFiles: () => void;
|
|
121
|
+
openFileDialog: () => void;
|
|
122
|
+
onDragEnter: (event: React.DragEvent<HTMLElement>) => void;
|
|
123
|
+
onDragOver: (event: React.DragEvent<HTMLElement>) => void;
|
|
124
|
+
onDragLeave: (event: React.DragEvent<HTMLElement>) => void;
|
|
125
|
+
onDrop: (event: React.DragEvent<HTMLElement>) => Promise<void>;
|
|
126
|
+
onInputChange: (event: React.ChangeEvent<HTMLInputElement>) => Promise<void>;
|
|
127
|
+
}
|
|
128
|
+
declare function useDragdrop(options?: SimpleDragDropParams): UseDragDropResult;
|
|
129
|
+
|
|
130
|
+
export { type DragDropClassNames, type DragDropFileItem, InputCanvas, type SimpleDragDropParams, useDragdrop as useDragDrop, useDragdrop };
|