@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.
Files changed (2) hide show
  1. package/README.md +211 -0
  2. 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
+ [![npm](https://img.shields.io/npm/v/@uploadbox/react)](https://www.npmjs.com/package/@uploadbox/react)
6
+ [![license](https://img.shields.io/npm/l/@uploadbox/react)](./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.1.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.1.0"
17
+ "@uploadbox/core": "0.2.0"
18
18
  },
19
19
  "peerDependencies": {
20
20
  "react": "^18.0.0 || ^19.0.0",