8000 feat(useFileDialog): Allow custom input element for file dialog (#4679) · vueuse/vueuse@0ea16e0 · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Commit 0ea16e0

Browse files
authored
feat(useFileDialog): Allow custom input element for file dialog (#4679)
1 parent 57fee29 commit 0ea16e0

File tree

3 files changed

+56
-2
lines changed

3 files changed

+56
-2
lines changed

packages/core/README.md

Lines changed: 0 additions & 1 deletion
This file was deleted.

packages/core/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../README.md

packages/core/useFileDialog/index.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { describe, expect, it, vi } from 'vitest'
2+
import { shallowRef } from 'vue'
23
import { useFileDialog } from './index'
34

45
class DataTransferMock {
@@ -47,4 +48,49 @@ describe('useFileDialog', () => {
4748
open()
4849
expect(files.value).toBeNull()
4950
})
51+
52+
it('should work with custom input element', () => {
53+
const input = document.createElement('input')
54+
input.click = vi.fn()
55+
const { open } = useFileDialog({ input })
56+
57+
open()
58+
expect(input.type).toBe('file')
59+
expect(input.click).toBeCalled()
60+
})
61+
62+
it('should work with input element passed as template ref', () => {
63+
const inputEl = document.createElement('input')
64+
inputEl.click = vi.fn()
65+
66+
const inputRef = shallowRef<HTMLInputElement>(inputEl)
67+
68+
const { open } = useFileDialog({ input: inputRef })
69+
70+
open()
71+
expect(inputEl.type).toBe('file')
72+
expect(inputEl.click).toHaveBeenCalled()
73+
})
74+
75+
it('should trigger onchange and update files when file is selected', async () => {
76+
const input = document.createElement('input')
77+
const file = new File(['dummy content'], 'example.txt', { type: 'text/plain' })
78+
79+
Object.defineProperty(input, 'files', {
80+
value: [file],
81+
writable: true,
82+
})
83+
84+
const { open, onChange, files } = useFileDialog({ input })
85+
86+
const changeHandler = vi.fn()
87+
onChange(changeHandler)
88+
89+
open()
90+
91+
input.dispatchEvent(new Event('change'))
92+
93+
expect(files.value?.[0]).toEqual(file)
94+
expect(changeHandler).toHaveBeenCalledWith(files.value)
95+
})
5096
})

packages/core/useFileDialog/index.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import type { EventHookOn } from '@vueuse/shared'
22
import type { Ref } from 'vue'
33
import type { ConfigurableDocument } from '../_configurable'
4+
import type { MaybeElementRef } from '../unrefElement'
45
import { createEventHook, hasOwn } from '@vueuse/shared'
56
import { ref as deepRef, readonly } from 'vue'
67
import { defaultDocument } from '../_configurable'
8+
import { unrefElement } from '../unrefElement'
79

810
export interface UseFileDialogOptions extends ConfigurableDocument {
911
/**
@@ -36,6 +38,12 @@ export interface UseFileDialogOptions extends ConfigurableDocument {
3638
* @default null
3739
*/
3840
initialFiles?: Array<File> | FileList
41+
42+
/**
43+
* The input element to use for file dialog.
44+
* @default document.createElement('input')
45+
*/
46+
input?: MaybeElementRef<HTMLInputElement>
3947
}
4048

4149
const DEFAULT_OPTIONS: UseFileDialogOptions = {
@@ -84,7 +92,7 @@ export function useFileDialog(options: UseFileDialogOptions = {}): UseFileDialog
8492
const { on: onCancel, trigger: cancelTrigger } = createEventHook()
8593
let input: HTMLInputElement | undefined
8694
if (document) {
87-
input = document.createElement('input')
95+
input = unrefElement(options.input) || document.createElement('input')
8896
input.type = 'file'
8997

9098
input.onchange = (event: Event) => {

0 commit comments

Comments
 (0)
0