@universal-uploader/react 1.0.0 β 1.0.1
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 +185 -0
- package/package.json +17 -3
package/README.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# @usu/react
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@usu/react)
|
|
4
|
+
[](https://www.npmjs.com/package/@usu/react)
|
|
5
|
+
|
|
6
|
+
**[π¦ NPM](https://www.npmjs.com/package/@usu/react)** | **[π Main README](../../README.md)** | **[βοΈ Core](./packages/core)**
|
|
7
|
+
|
|
8
|
+
React Hook wrapper for @usu/core. Minimal, powerful, type-safe.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @usu/react @usu/core
|
|
14
|
+
yarn add @usu/react @usu/core
|
|
15
|
+
pnpm add @usu/react @usu/core
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
NPM Packages:
|
|
19
|
+
- [@usu/react](https://www.npmjs.com/package/@usu/react)
|
|
20
|
+
- [@usu/core](https://www.npmjs.com/package/@usu/core)
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { useUniversalUpload } from '@usu/react';
|
|
26
|
+
|
|
27
|
+
export const Upload = () => {
|
|
28
|
+
const { upload, pause, resume, status, progress, error } = useUniversalUpload({
|
|
29
|
+
url: '/api/upload',
|
|
30
|
+
options: { method: 'auto', retryCount: 3 }
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const handleUpload = async (file: File) => {
|
|
34
|
+
await upload(file);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<div>
|
|
39
|
+
<input
|
|
40
|
+
type="file"
|
|
41
|
+
onChange={(e) => e.target.files && handleUpload(e.target.files[0])}
|
|
42
|
+
disabled={status === 'uploading'}
|
|
43
|
+
/>
|
|
44
|
+
<progress value={progress} max={100} />
|
|
45
|
+
<p>Status: {status}</p>
|
|
46
|
+
|
|
47
|
+
{status === 'uploading' && (
|
|
48
|
+
<>
|
|
49
|
+
<button onClick={pause}>Pause</button>
|
|
50
|
+
<button onClick={() => /* abort */}>Abort</button>
|
|
51
|
+
</>
|
|
52
|
+
)}
|
|
53
|
+
|
|
54
|
+
{status === 'paused' && (
|
|
55
|
+
<button onClick={resume}>Resume</button>
|
|
56
|
+
)}
|
|
57
|
+
|
|
58
|
+
{error && <p style={{ color: 'red' }}>{error.message}</p>}
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Hook API
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
const {
|
|
68
|
+
upload, // (file: File) => Promise<UploadResult>
|
|
69
|
+
pause, // () => void
|
|
70
|
+
resume, // () => void
|
|
71
|
+
abort, // () => void
|
|
72
|
+
refresh, // () => void
|
|
73
|
+
retry, // (file: File) => Promise<UploadResult>
|
|
74
|
+
|
|
75
|
+
status, // 'idle' | 'uploading' | 'paused' | 'success' | 'error' | 'aborted'
|
|
76
|
+
progress, // 0-100
|
|
77
|
+
result, // { ok: boolean; total: number; status: ... }
|
|
78
|
+
error // Error | null
|
|
79
|
+
} = useUniversalUpload({ url, options });
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Control Semantics
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
pause(); // β status: "paused" (resumable)
|
|
86
|
+
resume(); // β continues from offset
|
|
87
|
+
abort(); // β status: "aborted" (terminal)
|
|
88
|
+
refresh(); // β full restart from initial options
|
|
89
|
+
retry(file); // β manual retry
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Configuration
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
interface UseUniversalUploadConfig {
|
|
96
|
+
url: string;
|
|
97
|
+
options?: {
|
|
98
|
+
method?: 'stream' | 'stream chunked' | 'xhr chunked' | 'auto';
|
|
99
|
+
chunkSize?: number; // 512KB default
|
|
100
|
+
retryCount?: number; // 3 default
|
|
101
|
+
retryDelay?: number | ((attempt: number) => number);
|
|
102
|
+
customHeaders?: Record<string, string>;
|
|
103
|
+
withCredentials?: boolean;
|
|
104
|
+
onProgress?: (p: { loaded: number; total: number; percentage: number }) => void;
|
|
105
|
+
onError?: (error: Error) => void;
|
|
106
|
+
onRetry?: () => void;
|
|
107
|
+
onPause?: () => void;
|
|
108
|
+
onResume?: () => void;
|
|
109
|
+
onAbort?: () => void;
|
|
110
|
+
throwOnError?: boolean;
|
|
111
|
+
};
|
|
112
|
+
onUrlChange?: (url: string) => void;
|
|
113
|
+
onMethodChange?: (method: UploadMethod) => void;
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Examples
|
|
118
|
+
|
|
119
|
+
### With Error Recovery
|
|
120
|
+
```typescript
|
|
121
|
+
const { upload, retry, error } = useUniversalUpload({ url });
|
|
122
|
+
|
|
123
|
+
const handleUpload = async (file: File) => {
|
|
124
|
+
try {
|
|
125
|
+
await upload(file);
|
|
126
|
+
} catch (err) {
|
|
127
|
+
console.error(err);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
return (
|
|
132
|
+
<>
|
|
133
|
+
{error && <button onClick={() => retry(file)}>Retry</button>}
|
|
134
|
+
</>
|
|
135
|
+
);
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Lifecycle Hooks
|
|
139
|
+
```typescript
|
|
140
|
+
const { upload } = useUniversalUpload({
|
|
141
|
+
url: '/api/upload',
|
|
142
|
+
options: {
|
|
143
|
+
onProgress: ({ percentage }) => console.log(`${percentage}%`),
|
|
144
|
+
onComplete: () => console.log('β
Done'),
|
|
145
|
+
onError: (err) => console.error('β', err),
|
|
146
|
+
onRetry: () => console.log('π Retrying'),
|
|
147
|
+
onPause: () => console.log('βΈοΈ Paused'),
|
|
148
|
+
onResume: () => console.log('βΆοΈ Resumed')
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Multiple Files
|
|
154
|
+
```typescript
|
|
155
|
+
export const MultiUpload = ({ files }: { files: File[] }) => {
|
|
156
|
+
return (
|
|
157
|
+
<div className="grid">
|
|
158
|
+
{files.map((file) => (
|
|
159
|
+
<UploadCard key={file.name} file={file} />
|
|
160
|
+
))}
|
|
161
|
+
</div>
|
|
162
|
+
);
|
|
163
|
+
};
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Type Safety
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
import type {
|
|
170
|
+
UploadStatus,
|
|
171
|
+
UploadResult,
|
|
172
|
+
UploadOptions,
|
|
173
|
+
UploadMethod
|
|
174
|
+
} from '@usu/react';
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Browser Support
|
|
178
|
+
|
|
179
|
+
- Chrome/Edge: Fetch Stream β
|
|
180
|
+
- Firefox: Fetch Stream β
|
|
181
|
+
- Safari/IE: XHR Fallback β
|
|
182
|
+
|
|
183
|
+
## License
|
|
184
|
+
|
|
185
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@universal-uploader/react",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "React hook
|
|
5
|
+
"description": "React hook for streaming file uploads with progress tracking, retries, pause/resume, and fetch/XHR fallback powered by @universal-uploader/core.",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"module": "dist/index.js",
|
|
8
8
|
"types": "dist/index.d.ts",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"react": "^19.2.6"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@universal-uploader/core": "1.0.
|
|
16
|
+
"@universal-uploader/core": "1.0.1"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@types/react": "^19.2.14",
|
|
@@ -27,6 +27,20 @@
|
|
|
27
27
|
"url": "https://github.com/jdy8739/universal-uploader.git",
|
|
28
28
|
"directory": "packages/react"
|
|
29
29
|
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"react",
|
|
32
|
+
"react-hook",
|
|
33
|
+
"hooks",
|
|
34
|
+
"file-upload",
|
|
35
|
+
"upload",
|
|
36
|
+
"streaming",
|
|
37
|
+
"progress",
|
|
38
|
+
"fetch",
|
|
39
|
+
"xhr",
|
|
40
|
+
"chunked-upload",
|
|
41
|
+
"large-files",
|
|
42
|
+
"universal-uploader"
|
|
43
|
+
],
|
|
30
44
|
"license": "MIT",
|
|
31
45
|
"scripts": {
|
|
32
46
|
"build": "rollup -c rollup.config.mjs",
|