@shipstatic/drop 0.1.8 → 0.1.9
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 +38 -39
- package/dist/index.cjs +13 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -10
- package/dist/index.d.ts +19 -10
- package/dist/index.js +14 -9
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -107,15 +107,15 @@ function MyUploader() {
|
|
|
107
107
|
{drop.isDragging ? '📂 Drop here' : '📁 Click or drag files/folders'}
|
|
108
108
|
</div>
|
|
109
109
|
|
|
110
|
-
{/* Status - using state machine */}
|
|
111
|
-
{drop.
|
|
110
|
+
{/* Status - using state machine phase */}
|
|
111
|
+
{drop.status && (
|
|
112
112
|
<p>
|
|
113
|
-
<strong>{drop.
|
|
113
|
+
<strong>{drop.status.title}:</strong> {drop.status.details}
|
|
114
114
|
</p>
|
|
115
115
|
)}
|
|
116
116
|
|
|
117
117
|
{/* File list */}
|
|
118
|
-
{drop.
|
|
118
|
+
{drop.files.map(file => (
|
|
119
119
|
<div key={file.id}>
|
|
120
120
|
{file.name} - {file.status}
|
|
121
121
|
</div>
|
|
@@ -124,7 +124,7 @@ function MyUploader() {
|
|
|
124
124
|
{/* Upload button */}
|
|
125
125
|
<button
|
|
126
126
|
onClick={handleUpload}
|
|
127
|
-
disabled={drop.
|
|
127
|
+
disabled={drop.phase !== 'ready'}
|
|
128
128
|
>
|
|
129
129
|
Upload {drop.getValidFiles().length} files
|
|
130
130
|
</button>
|
|
@@ -232,17 +232,22 @@ interface DropOptions {
|
|
|
232
232
|
|
|
233
233
|
**Returns:**
|
|
234
234
|
|
|
235
|
+
```typescript
|
|
235
236
|
```typescript
|
|
236
237
|
interface DropReturn {
|
|
237
|
-
// State machine
|
|
238
|
-
/** Current state of the drop hook */
|
|
239
|
-
state: DropState;
|
|
240
|
-
|
|
241
238
|
// Convenience getters (computed from state)
|
|
239
|
+
/** Current phase of the state machine */
|
|
240
|
+
phase: DropStateValue;
|
|
242
241
|
/** Whether currently processing files (ZIP extraction, etc.) */
|
|
243
242
|
isProcessing: boolean;
|
|
244
243
|
/** Whether user is currently dragging over the dropzone */
|
|
245
244
|
isDragging: boolean;
|
|
245
|
+
/** Flattened access to files */
|
|
246
|
+
files: ProcessedFile[];
|
|
247
|
+
/** Flattened access to source name */
|
|
248
|
+
sourceName: string;
|
|
249
|
+
/** Flattened access to status */
|
|
250
|
+
status: DropStatus | null;
|
|
246
251
|
|
|
247
252
|
// Primary API: Prop getters for easy integration
|
|
248
253
|
/** Get props to spread on dropzone element (handles drag & drop) */
|
|
@@ -289,22 +294,16 @@ type DropStateValue =
|
|
|
289
294
|
| 'ready' // Files are valid and ready for deployment
|
|
290
295
|
| 'error'; // An error occurred during processing
|
|
291
296
|
|
|
292
|
-
interface DropState {
|
|
293
|
-
value: DropStateValue;
|
|
294
|
-
files: ProcessedFile[];
|
|
295
|
-
sourceName: string;
|
|
296
|
-
status: DropStatus | null;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
297
|
interface DropStatus {
|
|
300
298
|
title: string;
|
|
301
299
|
details: string;
|
|
300
|
+
errors?: string[];
|
|
302
301
|
}
|
|
303
302
|
```
|
|
304
303
|
|
|
305
304
|
## State Machine
|
|
306
305
|
|
|
307
|
-
The drop hook uses a state machine for predictable, clear state management. Instead of multiple boolean flags, you have a single `
|
|
306
|
+
The drop hook uses a state machine for predictable, clear state management. Instead of multiple boolean flags, you have a single `drop.phase` that represents exactly what's happening.
|
|
308
307
|
|
|
309
308
|
### State Flow
|
|
310
309
|
|
|
@@ -320,9 +319,8 @@ error → dragging → processing → ... (retry)
|
|
|
320
319
|
|
|
321
320
|
```tsx
|
|
322
321
|
function StatusIndicator({ drop }) {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
switch (state.value) {
|
|
322
|
+
// Use drop.phase to switch-case on the state
|
|
323
|
+
switch (drop.phase) {
|
|
326
324
|
case 'idle':
|
|
327
325
|
return <p>Drop files here or click to select</p>;
|
|
328
326
|
|
|
@@ -330,12 +328,12 @@ function StatusIndicator({ drop }) {
|
|
|
330
328
|
return <p>Drop your files now!</p>;
|
|
331
329
|
|
|
332
330
|
case 'processing':
|
|
333
|
-
return <p>{
|
|
331
|
+
return <p>{drop.status?.details || 'Processing...'}</p>;
|
|
334
332
|
|
|
335
333
|
case 'ready':
|
|
336
334
|
return (
|
|
337
335
|
<div>
|
|
338
|
-
<p>✓ {
|
|
336
|
+
<p>✓ {drop.files.length} files ready</p>
|
|
339
337
|
<button>Upload to Ship</button>
|
|
340
338
|
</div>
|
|
341
339
|
);
|
|
@@ -343,8 +341,8 @@ function StatusIndicator({ drop }) {
|
|
|
343
341
|
case 'error':
|
|
344
342
|
return (
|
|
345
343
|
<div>
|
|
346
|
-
<p>✗ {
|
|
347
|
-
<p>{
|
|
344
|
+
<p>✗ {drop.status?.title}</p>
|
|
345
|
+
<p>{drop.status?.details}</p>
|
|
348
346
|
<button onClick={drop.clearAll}>Try Again</button>
|
|
349
347
|
</div>
|
|
350
348
|
);
|
|
@@ -357,14 +355,14 @@ function StatusIndicator({ drop }) {
|
|
|
357
355
|
For simpler use cases, boolean convenience getters are provided:
|
|
358
356
|
|
|
359
357
|
```tsx
|
|
360
|
-
// These are computed from
|
|
361
|
-
drop.isProcessing // true when
|
|
362
|
-
drop.isDragging // true when
|
|
363
|
-
|
|
364
|
-
// For error information, use the
|
|
365
|
-
drop.
|
|
366
|
-
drop.
|
|
367
|
-
drop.
|
|
358
|
+
// These are computed from drop.phase (read-only projections)
|
|
359
|
+
drop.isProcessing // true when phase === 'processing'
|
|
360
|
+
drop.isDragging // true when phase === 'dragging'
|
|
361
|
+
|
|
362
|
+
// For error information, use the flattened status object
|
|
363
|
+
drop.phase === 'error' // Check if in error state
|
|
364
|
+
drop.status?.title // Error title
|
|
365
|
+
drop.status?.details // Error details
|
|
368
366
|
```
|
|
369
367
|
|
|
370
368
|
### Benefits
|
|
@@ -384,7 +382,8 @@ Each file in the `state.files` array contains its own `status` and `statusMessag
|
|
|
384
382
|
function FileList({ drop }) {
|
|
385
383
|
return (
|
|
386
384
|
<div>
|
|
387
|
-
{
|
|
385
|
+
{/* Flattened access to files array */}
|
|
386
|
+
{drop.files.map(file => (
|
|
388
387
|
<div key={file.id}>
|
|
389
388
|
<span>{file.path}</span>
|
|
390
389
|
|
|
@@ -401,7 +400,7 @@ function FileList({ drop }) {
|
|
|
401
400
|
))}
|
|
402
401
|
|
|
403
402
|
{/* If validation fails, allow user to clear all and try again */}
|
|
404
|
-
{drop.
|
|
403
|
+
{drop.phase === 'error' && (
|
|
405
404
|
<button onClick={drop.clearAll}>
|
|
406
405
|
Clear All & Try Again
|
|
407
406
|
</button>
|
|
@@ -422,10 +421,10 @@ function FileList({ drop }) {
|
|
|
422
421
|
When files fail validation or processing, check the error state:
|
|
423
422
|
|
|
424
423
|
```tsx
|
|
425
|
-
{drop.
|
|
424
|
+
{drop.phase === 'error' && drop.status && (
|
|
426
425
|
<div>
|
|
427
|
-
<p>{drop.
|
|
428
|
-
<p>{drop.
|
|
426
|
+
<p>{drop.status.title}</p>
|
|
427
|
+
<p>{drop.status.details}</p>
|
|
429
428
|
</div>
|
|
430
429
|
)}
|
|
431
430
|
```
|
|
@@ -455,10 +454,10 @@ Use `clearAll()` to reset and try again:
|
|
|
455
454
|
|
|
456
455
|
```tsx
|
|
457
456
|
// If validation fails, show user which files failed
|
|
458
|
-
{drop.
|
|
457
|
+
{drop.phase === 'error' && (
|
|
459
458
|
<div>
|
|
460
459
|
<p>Validation failed. Please fix the issues and try again:</p>
|
|
461
|
-
{drop.
|
|
460
|
+
{drop.files.map(file => (
|
|
462
461
|
<div key={file.id}>
|
|
463
462
|
{file.path}: {file.statusMessage}
|
|
464
463
|
</div>
|
package/dist/index.cjs
CHANGED
|
@@ -11813,7 +11813,6 @@ async function createProcessedFile(file, options) {
|
|
|
11813
11813
|
status: FILE_STATUSES.PENDING
|
|
11814
11814
|
};
|
|
11815
11815
|
}
|
|
11816
|
-
var getValidFiles = ship.getValidFiles;
|
|
11817
11816
|
function stripCommonPrefix(files) {
|
|
11818
11817
|
if (files.length === 0) return files;
|
|
11819
11818
|
const paths = files.map((f) => f.path);
|
|
@@ -11888,6 +11887,7 @@ function useDrop(options) {
|
|
|
11888
11887
|
const inputRef = react.useRef(null);
|
|
11889
11888
|
const isProcessing = react.useMemo(() => state.value === "processing", [state.value]);
|
|
11890
11889
|
const isDragging = react.useMemo(() => state.value === "dragging", [state.value]);
|
|
11890
|
+
const validFiles = react.useMemo(() => ship.getValidFiles(state.files), [state.files]);
|
|
11891
11891
|
const processFiles = react.useCallback(async (newFiles) => {
|
|
11892
11892
|
if (isProcessingRef.current) {
|
|
11893
11893
|
console.warn("File processing already in progress. Ignoring duplicate call.");
|
|
@@ -11953,7 +11953,11 @@ function useDrop(options) {
|
|
|
11953
11953
|
value: "error",
|
|
11954
11954
|
files: validation.files,
|
|
11955
11955
|
sourceName: detectedSourceName,
|
|
11956
|
-
status: {
|
|
11956
|
+
status: {
|
|
11957
|
+
title: validation.error.error,
|
|
11958
|
+
details: validation.error.details,
|
|
11959
|
+
errors: validation.error.errors
|
|
11960
|
+
}
|
|
11957
11961
|
});
|
|
11958
11962
|
onValidationError?.(validation.error);
|
|
11959
11963
|
} else if (validation.validFiles.length > 0) {
|
|
@@ -11998,9 +12002,6 @@ function useDrop(options) {
|
|
|
11998
12002
|
setState(initialState);
|
|
11999
12003
|
isProcessingRef.current = false;
|
|
12000
12004
|
}, []);
|
|
12001
|
-
const getValidFilesCallback = react.useCallback(() => {
|
|
12002
|
-
return getValidFiles(state.files);
|
|
12003
|
-
}, [state.files]);
|
|
12004
12005
|
const updateFileStatus = react.useCallback((fileId, fileState) => {
|
|
12005
12006
|
setState((prev) => ({
|
|
12006
12007
|
...prev,
|
|
@@ -12091,10 +12092,14 @@ function useDrop(options) {
|
|
|
12091
12092
|
}), [handleInputChange]);
|
|
12092
12093
|
return {
|
|
12093
12094
|
// State machine
|
|
12094
|
-
state,
|
|
12095
|
+
// state, // REMOVED
|
|
12095
12096
|
// Convenience getters (computed from state)
|
|
12097
|
+
phase: state.value,
|
|
12096
12098
|
isProcessing,
|
|
12097
12099
|
isDragging,
|
|
12100
|
+
files: state.files,
|
|
12101
|
+
sourceName: state.sourceName,
|
|
12102
|
+
status: state.status,
|
|
12098
12103
|
// Primary API: Prop getters
|
|
12099
12104
|
getDropzoneProps,
|
|
12100
12105
|
getInputProps,
|
|
@@ -12103,7 +12108,7 @@ function useDrop(options) {
|
|
|
12103
12108
|
processFiles,
|
|
12104
12109
|
clearAll,
|
|
12105
12110
|
// Helpers
|
|
12106
|
-
|
|
12111
|
+
validFiles,
|
|
12107
12112
|
updateFileStatus
|
|
12108
12113
|
};
|
|
12109
12114
|
}
|
|
@@ -12135,10 +12140,10 @@ exports.FILE_STATUSES = FILE_STATUSES;
|
|
|
12135
12140
|
exports.createProcessedFile = createProcessedFile;
|
|
12136
12141
|
exports.extractZipToFiles = extractZipToFiles;
|
|
12137
12142
|
exports.formatFileSize = formatFileSize;
|
|
12138
|
-
exports.getValidFiles = getValidFiles;
|
|
12139
12143
|
exports.isZipFile = isZipFile;
|
|
12140
12144
|
exports.normalizePath = normalizePath;
|
|
12141
12145
|
exports.stripCommonPrefix = stripCommonPrefix;
|
|
12146
|
+
exports.traverseFileTree = traverseFileTree;
|
|
12142
12147
|
exports.useDrop = useDrop;
|
|
12143
12148
|
//# sourceMappingURL=index.cjs.map
|
|
12144
12149
|
//# sourceMappingURL=index.cjs.map
|