@plugable-io/react 0.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 +527 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
# @plugable-io/react
|
|
2
|
+
|
|
3
|
+
React components and hooks for the Plugable File Management API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @plugable-io/react
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Components & Hooks
|
|
12
|
+
|
|
13
|
+
| Export | Type | Description |
|
|
14
|
+
|--------|------|-------------|
|
|
15
|
+
| `PlugableProvider` | Component | Context provider for configuration |
|
|
16
|
+
| `Dropzone` | Component | Drag & drop file uploader |
|
|
17
|
+
| `FilePreview` | Component | Universal file preview (images + file type icons) |
|
|
18
|
+
| `FileImage` | Component | Image display with caching |
|
|
19
|
+
| `useFiles` | Hook | File fetching with pagination |
|
|
20
|
+
| `usePlugable` | Hook | Access client and context |
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
### Provider Setup
|
|
25
|
+
|
|
26
|
+
Wrap your app with `PlugableProvider`. You can provide a `getToken` function or use a supported auth provider.
|
|
27
|
+
|
|
28
|
+
#### With Clerk
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import { PlugableProvider } from '@plugable-io/react';
|
|
32
|
+
|
|
33
|
+
function App() {
|
|
34
|
+
return (
|
|
35
|
+
<PlugableProvider
|
|
36
|
+
bucketId="your-bucket-id"
|
|
37
|
+
authProvider="clerk"
|
|
38
|
+
clerkJWTTemplate="plugable" // optional
|
|
39
|
+
>
|
|
40
|
+
<YourApp />
|
|
41
|
+
</PlugableProvider>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
#### With Supabase
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
<PlugableProvider
|
|
50
|
+
bucketId="your-bucket-id"
|
|
51
|
+
authProvider="supabase"
|
|
52
|
+
>
|
|
53
|
+
<YourApp />
|
|
54
|
+
</PlugableProvider>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
#### With Custom getToken
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
<PlugableProvider
|
|
61
|
+
bucketId="your-bucket-id"
|
|
62
|
+
getToken={async () => {
|
|
63
|
+
return await getAuthToken();
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
<YourApp />
|
|
67
|
+
</PlugableProvider>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Dropzone
|
|
73
|
+
|
|
74
|
+
File uploader with drag-and-drop support. Works with default UI or custom render function.
|
|
75
|
+
|
|
76
|
+
### Default UI
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
import { Dropzone } from '@plugable-io/react';
|
|
80
|
+
|
|
81
|
+
function ProfileUploader() {
|
|
82
|
+
return (
|
|
83
|
+
<Dropzone
|
|
84
|
+
metadata={{ category: 'avatar', userId: '123' }}
|
|
85
|
+
accept="image/*"
|
|
86
|
+
maxFiles={1}
|
|
87
|
+
onUploadComplete={(files) => {
|
|
88
|
+
console.log('Avatar uploaded:', files[0]);
|
|
89
|
+
}}
|
|
90
|
+
onUploadError={(error) => {
|
|
91
|
+
console.error('Upload failed:', error);
|
|
92
|
+
}}
|
|
93
|
+
/>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Custom UI with Render Props
|
|
99
|
+
|
|
100
|
+
```tsx
|
|
101
|
+
import { Dropzone } from '@plugable-io/react';
|
|
102
|
+
|
|
103
|
+
function DocumentUploader() {
|
|
104
|
+
return (
|
|
105
|
+
<Dropzone
|
|
106
|
+
metadata={{ type: 'document' }}
|
|
107
|
+
accept=".pdf,.doc,.docx"
|
|
108
|
+
maxFiles={10}
|
|
109
|
+
onUploadComplete={(files) => console.log('Uploaded:', files)}
|
|
110
|
+
>
|
|
111
|
+
{({ isDragActive, isUploading, uploadProgress, openFileDialog, uploadedFiles }) => (
|
|
112
|
+
<div
|
|
113
|
+
onClick={openFileDialog}
|
|
114
|
+
className={`border-2 border-dashed rounded-lg p-8 text-center cursor-pointer
|
|
115
|
+
${isDragActive ? 'border-blue-500 bg-blue-50' : 'border-gray-300'}`}
|
|
116
|
+
>
|
|
117
|
+
{isUploading ? (
|
|
118
|
+
<div className="space-y-2">
|
|
119
|
+
<p className="font-medium">Uploading...</p>
|
|
120
|
+
{Object.entries(uploadProgress).map(([name, progress]) => (
|
|
121
|
+
<div key={name} className="text-sm">
|
|
122
|
+
<span>{name}</span>
|
|
123
|
+
<div className="w-full bg-gray-200 rounded h-2 mt-1">
|
|
124
|
+
<div
|
|
125
|
+
className="bg-blue-500 h-2 rounded transition-all"
|
|
126
|
+
style={{ width: `${progress}%` }}
|
|
127
|
+
/>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
))}
|
|
131
|
+
</div>
|
|
132
|
+
) : (
|
|
133
|
+
<>
|
|
134
|
+
<p className="font-medium">
|
|
135
|
+
{isDragActive ? 'Drop files here' : 'Drag & drop documents'}
|
|
136
|
+
</p>
|
|
137
|
+
<p className="text-sm text-gray-500 mt-1">or click to browse</p>
|
|
138
|
+
</>
|
|
139
|
+
)}
|
|
140
|
+
|
|
141
|
+
{uploadedFiles.length > 0 && (
|
|
142
|
+
<div className="mt-4 text-sm text-green-600">
|
|
143
|
+
✓ {uploadedFiles.length} file(s) uploaded
|
|
144
|
+
</div>
|
|
145
|
+
)}
|
|
146
|
+
</div>
|
|
147
|
+
)}
|
|
148
|
+
</Dropzone>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Props
|
|
154
|
+
|
|
155
|
+
| Prop | Type | Description |
|
|
156
|
+
|------|------|-------------|
|
|
157
|
+
| `bucketId` | `string` | Override default bucket ID |
|
|
158
|
+
| `metadata` | `Record<string, any>` | Metadata to attach to uploaded files |
|
|
159
|
+
| `accept` | `string` | File types to accept (e.g., `"image/*"`, `".pdf,.doc"`) |
|
|
160
|
+
| `maxFiles` | `number` | Maximum number of files |
|
|
161
|
+
| `onUploadComplete` | `(files: FileObject[]) => void` | Called when uploads complete |
|
|
162
|
+
| `onUploadError` | `(error: Error) => void` | Called on upload error |
|
|
163
|
+
| `onProgressUpdate` | `(fileName: string, progress: number) => void` | Progress callback |
|
|
164
|
+
| `children` | `(props: DropzoneRenderProps) => ReactNode` | Custom render function |
|
|
165
|
+
| `className` | `string` | CSS class name |
|
|
166
|
+
| `style` | `CSSProperties` | Inline styles |
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## useFiles Hook
|
|
171
|
+
|
|
172
|
+
Fetch and paginate files with automatic refresh on uploads.
|
|
173
|
+
|
|
174
|
+
### Basic Usage
|
|
175
|
+
|
|
176
|
+
```tsx
|
|
177
|
+
import { useFiles, FilePreview } from '@plugable-io/react';
|
|
178
|
+
|
|
179
|
+
function InvoiceList() {
|
|
180
|
+
const { files, isLoading, pagination, refresh } = useFiles({
|
|
181
|
+
metadata: { type: 'invoice' },
|
|
182
|
+
perPage: 10,
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
if (isLoading) return <div>Loading...</div>;
|
|
186
|
+
|
|
187
|
+
return (
|
|
188
|
+
<div>
|
|
189
|
+
<div className="grid grid-cols-4 gap-4">
|
|
190
|
+
{files.map((file) => (
|
|
191
|
+
<div key={file.id} className="border rounded p-3">
|
|
192
|
+
<FilePreview file={file} width={60} height={60} />
|
|
193
|
+
<p className="text-sm mt-2 truncate">{file.name}</p>
|
|
194
|
+
<div className="flex gap-2 mt-2">
|
|
195
|
+
<button onClick={() => file.delete()}>Delete</button>
|
|
196
|
+
<a href={file.download_url} download>Download</a>
|
|
197
|
+
</div>
|
|
198
|
+
</div>
|
|
199
|
+
))}
|
|
200
|
+
</div>
|
|
201
|
+
|
|
202
|
+
<div className="flex gap-2 mt-4">
|
|
203
|
+
<button
|
|
204
|
+
onClick={pagination.loadPreviousPage}
|
|
205
|
+
disabled={!pagination.hasPrevious}
|
|
206
|
+
>
|
|
207
|
+
Previous
|
|
208
|
+
</button>
|
|
209
|
+
<span>Page {pagination.current}</span>
|
|
210
|
+
<button
|
|
211
|
+
onClick={pagination.loadNextPage}
|
|
212
|
+
disabled={!pagination.hasNext}
|
|
213
|
+
>
|
|
214
|
+
Next
|
|
215
|
+
</button>
|
|
216
|
+
</div>
|
|
217
|
+
</div>
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Filter by Media Type
|
|
223
|
+
|
|
224
|
+
```tsx
|
|
225
|
+
function ImageGallery() {
|
|
226
|
+
const { files, isLoading } = useFiles({
|
|
227
|
+
mediaType: 'image',
|
|
228
|
+
perPage: 20,
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
return (
|
|
232
|
+
<div className="grid grid-cols-3 gap-4">
|
|
233
|
+
{files.map((file) => (
|
|
234
|
+
<FilePreview key={file.id} file={file} width="100%" height={200} objectFit="cover" />
|
|
235
|
+
))}
|
|
236
|
+
</div>
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Manual Loading
|
|
242
|
+
|
|
243
|
+
```tsx
|
|
244
|
+
function LazyFileList() {
|
|
245
|
+
const { files, isLoading, refresh } = useFiles({
|
|
246
|
+
metadata: { folder: 'reports' },
|
|
247
|
+
autoLoad: false, // Don't load on mount
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
return (
|
|
251
|
+
<div>
|
|
252
|
+
<button onClick={refresh}>Load Files</button>
|
|
253
|
+
{isLoading && <span>Loading...</span>}
|
|
254
|
+
{files.map((file) => (
|
|
255
|
+
<div key={file.id}>{file.name}</div>
|
|
256
|
+
))}
|
|
257
|
+
</div>
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Options
|
|
263
|
+
|
|
264
|
+
| Option | Type | Default | Description |
|
|
265
|
+
|--------|------|---------|-------------|
|
|
266
|
+
| `metadata` | `Record<string, any>` | - | Filter files by metadata |
|
|
267
|
+
| `mediaType` | `string` | - | Filter by media type (`image`, `video`, etc.) |
|
|
268
|
+
| `perPage` | `number` | `20` | Files per page |
|
|
269
|
+
| `startPage` | `number` | `1` | Initial page number |
|
|
270
|
+
| `autoLoad` | `boolean` | `true` | Fetch on mount |
|
|
271
|
+
|
|
272
|
+
### Return Value
|
|
273
|
+
|
|
274
|
+
| Property | Type | Description |
|
|
275
|
+
|----------|------|-------------|
|
|
276
|
+
| `files` | `FileObject[]` | Array of files |
|
|
277
|
+
| `isLoading` | `boolean` | Loading state |
|
|
278
|
+
| `pagination.current` | `number` | Current page |
|
|
279
|
+
| `pagination.hasNext` | `boolean` | Has next page |
|
|
280
|
+
| `pagination.hasPrevious` | `boolean` | Has previous page |
|
|
281
|
+
| `pagination.loadNextPage` | `() => void` | Go to next page |
|
|
282
|
+
| `pagination.loadPreviousPage` | `() => void` | Go to previous page |
|
|
283
|
+
| `setPage` | `(page: number) => void` | Jump to specific page |
|
|
284
|
+
| `refresh` | `() => Promise<void>` | Refresh current page |
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## FilePreview
|
|
289
|
+
|
|
290
|
+
Universal file preview component. Displays images inline and shows file type icons for other files.
|
|
291
|
+
|
|
292
|
+
### Basic Usage
|
|
293
|
+
|
|
294
|
+
```tsx
|
|
295
|
+
import { FilePreview } from '@plugable-io/react';
|
|
296
|
+
|
|
297
|
+
function FileCard({ file }) {
|
|
298
|
+
return (
|
|
299
|
+
<div className="flex items-center gap-3 p-3 border rounded">
|
|
300
|
+
<FilePreview file={file} width={48} height={48} />
|
|
301
|
+
<div>
|
|
302
|
+
<p className="font-medium">{file.name}</p>
|
|
303
|
+
<p className="text-sm text-gray-500">{file.content_type}</p>
|
|
304
|
+
</div>
|
|
305
|
+
</div>
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Custom Non-Image Rendering
|
|
311
|
+
|
|
312
|
+
```tsx
|
|
313
|
+
import { FilePreview } from '@plugable-io/react';
|
|
314
|
+
|
|
315
|
+
function CustomFilePreview({ file }) {
|
|
316
|
+
return (
|
|
317
|
+
<FilePreview
|
|
318
|
+
file={file}
|
|
319
|
+
width={80}
|
|
320
|
+
height={80}
|
|
321
|
+
objectFit="cover"
|
|
322
|
+
renderNonImage={(file) => (
|
|
323
|
+
<div className="flex flex-col items-center justify-center text-gray-500">
|
|
324
|
+
<span className="text-2xl">📄</span>
|
|
325
|
+
<span className="text-xs mt-1">{file.name.split('.').pop()}</span>
|
|
326
|
+
</div>
|
|
327
|
+
)}
|
|
328
|
+
/>
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Props
|
|
334
|
+
|
|
335
|
+
| Prop | Type | Default | Description |
|
|
336
|
+
|------|------|---------|-------------|
|
|
337
|
+
| `file` | `FileObject` | required | File to preview |
|
|
338
|
+
| `width` | `number \| string` | `80` | Preview width |
|
|
339
|
+
| `height` | `number \| string` | `80` | Preview height |
|
|
340
|
+
| `objectFit` | `'contain' \| 'cover' \| 'fill' \| 'none' \| 'scale-down'` | `'cover'` | Image fit mode |
|
|
341
|
+
| `className` | `string` | - | CSS class name |
|
|
342
|
+
| `style` | `CSSProperties` | - | Inline styles |
|
|
343
|
+
| `showExtension` | `boolean` | `true` | Show file extension for non-images |
|
|
344
|
+
| `renderNonImage` | `(file: FileObject) => ReactNode` | - | Custom renderer for non-image files |
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## FileImage
|
|
349
|
+
|
|
350
|
+
Display images with automatic URL fetching and caching.
|
|
351
|
+
|
|
352
|
+
```tsx
|
|
353
|
+
import { FileImage } from '@plugable-io/react';
|
|
354
|
+
|
|
355
|
+
function Avatar({ file }) {
|
|
356
|
+
return (
|
|
357
|
+
<FileImage
|
|
358
|
+
file={file}
|
|
359
|
+
width={100}
|
|
360
|
+
height={100}
|
|
361
|
+
objectFit="cover"
|
|
362
|
+
borderRadius={50}
|
|
363
|
+
alt="User avatar"
|
|
364
|
+
onLoad={() => console.log('Loaded')}
|
|
365
|
+
/>
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## File Object Methods
|
|
373
|
+
|
|
374
|
+
Each `FileObject` provides built-in methods for updating, downloading, and deleting files:
|
|
375
|
+
|
|
376
|
+
```tsx
|
|
377
|
+
// Update file metadata or name
|
|
378
|
+
await file.update(
|
|
379
|
+
{ tags: ['important', 'reviewed'] }, // metadata (optional)
|
|
380
|
+
'new-filename.txt' // name (optional)
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
// Download the file (initiates browser download)
|
|
384
|
+
await file.download();
|
|
385
|
+
|
|
386
|
+
// Delete the file
|
|
387
|
+
await file.delete();
|
|
388
|
+
|
|
389
|
+
// Access properties
|
|
390
|
+
console.log(file.id); // Unique ID
|
|
391
|
+
console.log(file.name); // Filename
|
|
392
|
+
console.log(file.content_type); // MIME type
|
|
393
|
+
console.log(file.download_url); // Signed download URL
|
|
394
|
+
console.log(file.metadata); // Custom metadata
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## Full Example
|
|
400
|
+
|
|
401
|
+
Complete file manager with upload, list, and preview:
|
|
402
|
+
|
|
403
|
+
```tsx
|
|
404
|
+
import {
|
|
405
|
+
PlugableProvider,
|
|
406
|
+
Dropzone,
|
|
407
|
+
useFiles,
|
|
408
|
+
FilePreview
|
|
409
|
+
} from '@plugable-io/react';
|
|
410
|
+
|
|
411
|
+
function FileManager() {
|
|
412
|
+
const { files, isLoading, pagination, refresh } = useFiles({
|
|
413
|
+
perPage: 12,
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
return (
|
|
417
|
+
<div className="max-w-4xl mx-auto p-6">
|
|
418
|
+
<h1 className="text-2xl font-bold mb-6">File Manager</h1>
|
|
419
|
+
|
|
420
|
+
{/* Upload Section */}
|
|
421
|
+
<Dropzone
|
|
422
|
+
maxFiles={5}
|
|
423
|
+
onUploadComplete={(uploaded) => {
|
|
424
|
+
console.log('Uploaded:', uploaded);
|
|
425
|
+
// Files list auto-refreshes via event system
|
|
426
|
+
}}
|
|
427
|
+
className="mb-8"
|
|
428
|
+
/>
|
|
429
|
+
|
|
430
|
+
{/* Files Grid */}
|
|
431
|
+
{isLoading ? (
|
|
432
|
+
<div className="text-center py-8">Loading...</div>
|
|
433
|
+
) : (
|
|
434
|
+
<div className="grid grid-cols-4 gap-4">
|
|
435
|
+
{files.map((file) => (
|
|
436
|
+
<div key={file.id} className="border rounded-lg p-3">
|
|
437
|
+
<FilePreview
|
|
438
|
+
file={file}
|
|
439
|
+
width="100%"
|
|
440
|
+
height={120}
|
|
441
|
+
objectFit="cover"
|
|
442
|
+
/>
|
|
443
|
+
<p className="text-sm mt-2 truncate" title={file.name}>
|
|
444
|
+
{file.name}
|
|
445
|
+
</p>
|
|
446
|
+
<div className="flex gap-2 mt-2">
|
|
447
|
+
<a
|
|
448
|
+
href={file.download_url}
|
|
449
|
+
download
|
|
450
|
+
className="text-blue-500 text-sm"
|
|
451
|
+
>
|
|
452
|
+
Download
|
|
453
|
+
</a>
|
|
454
|
+
<button
|
|
455
|
+
onClick={() => file.delete()}
|
|
456
|
+
className="text-red-500 text-sm"
|
|
457
|
+
>
|
|
458
|
+
Delete
|
|
459
|
+
</button>
|
|
460
|
+
</div>
|
|
461
|
+
</div>
|
|
462
|
+
))}
|
|
463
|
+
</div>
|
|
464
|
+
)}
|
|
465
|
+
|
|
466
|
+
{/* Pagination */}
|
|
467
|
+
<div className="flex justify-center gap-4 mt-6">
|
|
468
|
+
<button
|
|
469
|
+
onClick={pagination.loadPreviousPage}
|
|
470
|
+
disabled={!pagination.hasPrevious}
|
|
471
|
+
className="px-4 py-2 border rounded disabled:opacity-50"
|
|
472
|
+
>
|
|
473
|
+
Previous
|
|
474
|
+
</button>
|
|
475
|
+
<span className="py-2">Page {pagination.current}</span>
|
|
476
|
+
<button
|
|
477
|
+
onClick={pagination.loadNextPage}
|
|
478
|
+
disabled={!pagination.hasNext}
|
|
479
|
+
className="px-4 py-2 border rounded disabled:opacity-50"
|
|
480
|
+
>
|
|
481
|
+
Next
|
|
482
|
+
</button>
|
|
483
|
+
</div>
|
|
484
|
+
</div>
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// App wrapper
|
|
489
|
+
function App() {
|
|
490
|
+
return (
|
|
491
|
+
<PlugableProvider
|
|
492
|
+
bucketId="your-bucket-id"
|
|
493
|
+
authProvider="clerk"
|
|
494
|
+
>
|
|
495
|
+
<FileManager />
|
|
496
|
+
</PlugableProvider>
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
---
|
|
502
|
+
|
|
503
|
+
## TypeScript
|
|
504
|
+
|
|
505
|
+
All types are exported:
|
|
506
|
+
|
|
507
|
+
```tsx
|
|
508
|
+
import type {
|
|
509
|
+
PlugableProviderProps,
|
|
510
|
+
AuthProvider,
|
|
511
|
+
DropzoneProps,
|
|
512
|
+
DropzoneRenderProps,
|
|
513
|
+
FilePreviewProps,
|
|
514
|
+
FileImageProps,
|
|
515
|
+
FileListProps,
|
|
516
|
+
FileListRenderProps,
|
|
517
|
+
UseFilesOptions,
|
|
518
|
+
UseFilesResult,
|
|
519
|
+
FileObject,
|
|
520
|
+
SearchOptions,
|
|
521
|
+
UpdateOptions,
|
|
522
|
+
} from '@plugable-io/react';
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
## License
|
|
526
|
+
|
|
527
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@plugable-io/react",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "React components and hooks for Plugable File Management API",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --external react --external react-dom",
|
|
13
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch --external react --external react-dom",
|
|
14
|
+
"lint": "tsc --noEmit"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"react",
|
|
18
|
+
"file-upload",
|
|
19
|
+
"dropzone",
|
|
20
|
+
"storage",
|
|
21
|
+
"file-management",
|
|
22
|
+
"cloud-storage",
|
|
23
|
+
"typescript",
|
|
24
|
+
"hooks",
|
|
25
|
+
"components",
|
|
26
|
+
"plugable"
|
|
27
|
+
],
|
|
28
|
+
"author": "",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/Plugable-IO/react.git"
|
|
33
|
+
},
|
|
34
|
+
"peer Dependencies": {
|
|
35
|
+
"react": ">=16.8.0",
|
|
36
|
+
"react-dom": ">=16.8.0"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@plugable-io/js": "^0.0.8"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "^20.0.0",
|
|
43
|
+
"@types/react": "^18.0.0",
|
|
44
|
+
"@types/react-dom": "^18.0.0",
|
|
45
|
+
"react": "^18.0.0",
|
|
46
|
+
"react-dom": "^18.0.0",
|
|
47
|
+
"tsup": "^8.0.0",
|
|
48
|
+
"typescript": "^5.0.0"
|
|
49
|
+
}
|
|
50
|
+
}
|