|
32 | 32 | export let containerStyles = ""; |
33 | 33 | export let disableDefaultStyles = false; |
34 | 34 | export let name = ""; |
| 35 | + export let inputElement; |
| 36 | + export let required = false; |
35 | 37 | const dispatch = createEventDispatcher(); |
36 | 38 |
|
37 | 39 | //state |
|
44 | 46 | isDragReject: false, |
45 | 47 | draggedFiles: [], |
46 | 48 | acceptedFiles: [], |
47 | | - fileRejections: [] |
| 49 | + fileRejections: [], |
48 | 50 | }; |
49 | 51 |
|
50 | 52 | let rootRef; |
51 | | - let inputRef; |
52 | 53 |
|
53 | 54 | function resetState() { |
54 | 55 | state.isFileDialogActive = false; |
|
60 | 61 |
|
61 | 62 | // Fn for opening the file dialog programmatically |
62 | 63 | function openFileDialog() { |
63 | | - if (inputRef) { |
64 | | - inputRef.value = null; // TODO check if null needs to be set |
| 64 | + if (inputElement) { |
| 65 | + inputElement.value = null; // TODO check if null needs to be set |
65 | 66 | state.isFileDialogActive = true; |
66 | | - inputRef.click(); |
| 67 | + inputElement.click(); |
67 | 68 | } |
68 | 69 | } |
69 | 70 |
|
|
211 | 212 | acceptedFiles.splice(0); |
212 | 213 | } |
213 | 214 |
|
| 215 | + // Files dropped keep input in sync |
| 216 | + if (event.dataTransfer) { |
| 217 | + inputElement.files = event.dataTransfer.files; |
| 218 | + } |
| 219 | +
|
214 | 220 | state.acceptedFiles = acceptedFiles; |
215 | 221 | state.fileRejections = fileRejections; |
216 | 222 |
|
|
281 | 287 | // Execute the timeout only if the file dialog is opened in the browser |
282 | 288 | if (state.isFileDialogActive) { |
283 | 289 | setTimeout(() => { |
284 | | - if (inputRef) { |
285 | | - const { files } = inputRef; |
| 290 | + if (inputElement) { |
| 291 | + const { files } = inputElement; |
286 | 292 |
|
287 | 293 | if (!files.length) { |
288 | 294 | state.isFileDialogActive = false; |
|
295 | 301 |
|
296 | 302 | onDestroy(() => { |
297 | 303 | // This is critical for canceling the timeout behaviour on `onWindowFocus()` |
298 | | - inputRef = null; |
| 304 | + inputElement = null; |
299 | 305 | }); |
300 | 306 |
|
301 | 307 | function onInputElementClick(event) { |
|
339 | 345 | on:dragenter={composeDragHandler(onDragEnterCb)} |
340 | 346 | on:dragover={composeDragHandler(onDragOverCb)} |
341 | 347 | on:dragleave={composeDragHandler(onDragLeaveCb)} |
342 | | - on:drop={composeDragHandler(onDropCb)}> |
| 348 | + on:drop={composeDragHandler(onDropCb)} |
| 349 | +> |
343 | 350 | <input |
344 | 351 | {accept} |
345 | 352 | {multiple} |
| 353 | + {required} |
346 | 354 | type="file" |
347 | | - name={name} |
| 355 | + {name} |
348 | 356 | autocomplete="off" |
349 | 357 | tabindex="-1" |
350 | 358 | on:change={onDropCb} |
351 | 359 | on:click={onInputElementClick} |
352 | | - bind:this={inputRef} |
353 | | - style="display: none;" /> |
| 360 | + bind:this={inputElement} |
| 361 | + style="display: none;" |
| 362 | + /> |
354 | 363 | <slot> |
355 | 364 | <p>Drag 'n' drop some files here, or click to select files</p> |
356 | 365 | </slot> |
|
0 commit comments