@uploadbox/react 0.1.0 → 0.2.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.
- package/README.md +211 -0
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# @uploadbox/react
|
|
2
|
+
|
|
3
|
+
React components and hooks for Uploadbox — `UploadButton`, `UploadDropzone`, and `useUploadbox`.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@uploadbox/react)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm i @uploadbox/react @uploadbox/core
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
**Peer dependencies:** React 18 or 19.
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
### 1. Wrap your app with the provider
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { UploadboxProvider } from "@uploadbox/react";
|
|
22
|
+
import "@uploadbox/react/styles.css";
|
|
23
|
+
|
|
24
|
+
export default function App({ children }) {
|
|
25
|
+
return (
|
|
26
|
+
<UploadboxProvider apiUrl="/api/uploadbox">
|
|
27
|
+
{children}
|
|
28
|
+
</UploadboxProvider>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 2. Add an upload component
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
import { UploadButton, UploadDropzone } from "@uploadbox/react";
|
|
37
|
+
|
|
38
|
+
function MyPage() {
|
|
39
|
+
return (
|
|
40
|
+
<>
|
|
41
|
+
<UploadButton
|
|
42
|
+
endpoint="imageUploader"
|
|
43
|
+
onClientUploadComplete={(files) => console.log("Uploaded:", files)}
|
|
44
|
+
onUploadError={(err) => console.error(err)}
|
|
45
|
+
/>
|
|
46
|
+
|
|
47
|
+
<UploadDropzone
|
|
48
|
+
endpoint="imageUploader"
|
|
49
|
+
onClientUploadComplete={(files) => console.log("Uploaded:", files)}
|
|
50
|
+
onUploadError={(err) => console.error(err)}
|
|
51
|
+
/>
|
|
52
|
+
</>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## `useUploadbox` Hook
|
|
58
|
+
|
|
59
|
+
For full control, use the hook directly:
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
import { useUploadbox } from "@uploadbox/react";
|
|
63
|
+
|
|
64
|
+
function CustomUploader() {
|
|
65
|
+
const {
|
|
66
|
+
startUpload, // (files: File[]) => Promise<UploadedFile[]>
|
|
67
|
+
isUploading, // boolean
|
|
68
|
+
progress, // 0–100
|
|
69
|
+
fileProgress, // FileProgress[] — per-file details
|
|
70
|
+
routeConfig, // fetched route constraints
|
|
71
|
+
abort, // cancel current upload
|
|
72
|
+
} = useUploadbox("imageUploader", {
|
|
73
|
+
onClientUploadComplete: (files) => console.log(files),
|
|
74
|
+
onUploadError: (err) => console.error(err),
|
|
75
|
+
onUploadProgress: (e) => {
|
|
76
|
+
console.log(`Overall: ${e.percent}%`);
|
|
77
|
+
e.fileProgress.forEach((f) => {
|
|
78
|
+
console.log(`${f.name}: ${f.percent}% — ${f.speed} B/s, ETA ${f.eta}s`);
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<div>
|
|
85
|
+
<input type="file" multiple onChange={(e) => startUpload([...e.target.files!])} />
|
|
86
|
+
{isUploading && <p>Uploading... {progress}%</p>}
|
|
87
|
+
<button onClick={abort} disabled={!isUploading}>Cancel</button>
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Per-File Progress
|
|
94
|
+
|
|
95
|
+
Each entry in `fileProgress` contains:
|
|
96
|
+
|
|
97
|
+
| Field | Type | Description |
|
|
98
|
+
|-------|------|-------------|
|
|
99
|
+
| `name` | `string` | File name |
|
|
100
|
+
| `status` | `string` | `"pending"` \| `"uploading"` \| `"retrying"` \| `"complete"` \| `"error"` |
|
|
101
|
+
| `percent` | `number` | 0–100 |
|
|
102
|
+
| `speed` | `number` | Bytes/sec (3-second sliding window) |
|
|
103
|
+
| `eta` | `number` | Estimated seconds remaining |
|
|
104
|
+
| `retryCount` | `number` | Number of retries so far |
|
|
105
|
+
| `error` | `string?` | Error message if failed |
|
|
106
|
+
|
|
107
|
+
### Hook Options
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
useUploadbox("endpoint", {
|
|
111
|
+
onClientUploadComplete: (files) => {},
|
|
112
|
+
onUploadError: (err) => {},
|
|
113
|
+
onUploadProgress: (event) => {},
|
|
114
|
+
onBeforeUploadBegin: (files) => files, // transform files before upload
|
|
115
|
+
headers: { "x-custom": "value" },
|
|
116
|
+
getFileMetadata: (file) => ({ userId: "123" }),
|
|
117
|
+
ttlSeconds: 3600,
|
|
118
|
+
retry: { maxRetries: 5, initialDelayMs: 2000, backoffMultiplier: 2, maxDelayMs: 60000 },
|
|
119
|
+
// retry: false — to disable retries
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Customization
|
|
124
|
+
|
|
125
|
+
### Content Props
|
|
126
|
+
|
|
127
|
+
Override default labels on built-in components:
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
<UploadButton
|
|
131
|
+
endpoint="imageUploader"
|
|
132
|
+
content={{ button: "Choose Image", allowedContent: "PNG, JPG up to 4MB" }}
|
|
133
|
+
/>
|
|
134
|
+
|
|
135
|
+
<UploadDropzone
|
|
136
|
+
endpoint="imageUploader"
|
|
137
|
+
content={{ label: "Drop files here", button: "Browse", allowedContent: "Images up to 4MB" }}
|
|
138
|
+
/>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### CSS Classes
|
|
142
|
+
|
|
143
|
+
All components accept a `className` prop. The default styles use these classes:
|
|
144
|
+
|
|
145
|
+
**Button:** `.uploadbox-button`, `.uploadbox-progress-bar`, `.uploadbox-progress-bar-fill`
|
|
146
|
+
|
|
147
|
+
**Dropzone:** `.uploadbox-dropzone`, `.uploadbox-dropzone--dragover`, `.uploadbox-dropzone--uploading`, `.uploadbox-dropzone--complete`, `.uploadbox-dropzone--error`
|
|
148
|
+
|
|
149
|
+
### Styles
|
|
150
|
+
|
|
151
|
+
Import the default stylesheet:
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
import "@uploadbox/react/styles.css";
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Or write your own — the components work without the default CSS.
|
|
158
|
+
|
|
159
|
+
## Type-Safe Factories
|
|
160
|
+
|
|
161
|
+
Generate components that are typed to your file router:
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
import { generateUploadButton, generateUploadDropzone } from "@uploadbox/react";
|
|
165
|
+
import type { AppRouter } from "@/lib/uploadbox";
|
|
166
|
+
|
|
167
|
+
const UploadButton = generateUploadButton<AppRouter>();
|
|
168
|
+
const UploadDropzone = generateUploadDropzone<AppRouter>();
|
|
169
|
+
|
|
170
|
+
// `endpoint` is now typed to your router keys
|
|
171
|
+
<UploadButton endpoint="imageUploader" />
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Multipart Uploads
|
|
175
|
+
|
|
176
|
+
Files larger than 10 MB are automatically uploaded in parts (10 MB each, 4 concurrent). No extra configuration needed — the hook and components handle this transparently.
|
|
177
|
+
|
|
178
|
+
## Retry
|
|
179
|
+
|
|
180
|
+
Retries are enabled by default with exponential backoff:
|
|
181
|
+
|
|
182
|
+
```ts
|
|
183
|
+
// Default config
|
|
184
|
+
{
|
|
185
|
+
maxRetries: 3,
|
|
186
|
+
initialDelayMs: 1000,
|
|
187
|
+
backoffMultiplier: 2,
|
|
188
|
+
maxDelayMs: 30000,
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Retryable errors: network failures, 408, 429, and 5xx responses. Disable with `retry: false`.
|
|
193
|
+
|
|
194
|
+
## Hosted Mode
|
|
195
|
+
|
|
196
|
+
For the Uploadbox hosted platform, pass an API key to the provider:
|
|
197
|
+
|
|
198
|
+
```tsx
|
|
199
|
+
<UploadboxProvider apiUrl="/api/uploadbox" apiKey="pk_live_xxx">
|
|
200
|
+
{children}
|
|
201
|
+
</UploadboxProvider>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Related Packages
|
|
205
|
+
|
|
206
|
+
- [`@uploadbox/core`](https://www.npmjs.com/package/@uploadbox/core) — Core utilities, builder pattern, S3 operations
|
|
207
|
+
- [`@uploadbox/nextjs`](https://www.npmjs.com/package/@uploadbox/nextjs) — Next.js route handler adapter
|
|
208
|
+
|
|
209
|
+
## License
|
|
210
|
+
|
|
211
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uploadbox/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"react-dropzone": "^14.3.0",
|
|
17
|
-
"@uploadbox/core": "0.
|
|
17
|
+
"@uploadbox/core": "0.2.0"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
20
|
"react": "^18.0.0 || ^19.0.0",
|