|
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