-
Notifications
You must be signed in to change notification settings - Fork 252
/
Copy pathupload.ts
73 lines (61 loc) · 1.89 KB
/
upload.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import {
createFileList,
getWindow,
isDisabled,
isElementType,
setFiles,
} from '../utils'
import {type Instance} from '../setup'
export interface uploadInit {
changeInit?: EventInit
}
export async function upload(
this: Instance,
element: HTMLElement,
fileOrFiles: File | File[],
) {
const input = isElementType(element, 'label') ? element.control : element
if (!input || !isElementType(input, 'input', {type: 'file' as const})) {
throw new TypeError(
`The ${input === element ? 'given' : 'associated'} ${
input?.tagName
} element does not accept file uploads`,
)
}
if (isDisabled(element)) return
const files = (Array.isArray(fileOrFiles) ? fileOrFiles : [fileOrFiles])
.filter(
file => !this.config.applyAccept || isAcceptableFile(file, input.accept),
)
.slice(0, input.multiple ? undefined : 1)
const fileDialog = () => {
// do not fire an input event if the file selection does not change
if (
files.length === input.files?.length &&
files.every((f, i) => f === input.files?.item(i))
) {
return
}
setFiles(input, createFileList(getWindow(element), files))
this.dispatchUIEvent(input, 'input')
this.dispatchUIEvent(input, 'change')
}
input.addEventListener('fileDialog', fileDialog)
await this.click(element)
input.removeEventListener('fileDialog', fileDialog)
}
function isAcceptableFile(file: File, accept: string) {
if (!accept) {
return true
}
const wildcards = ['audio/*', 'image/*', 'video/*']
return accept.split(',').some(acceptToken => {
if (acceptToken.startsWith('.')) {
// tokens starting with a dot represent a file extension
return file.name.endsWith(acceptToken)
} else if (wildcards.includes(acceptToken)) {
return file.type.startsWith(acceptToken.substr(0, acceptToken.length - 1))
}
return file.type === acceptToken
})
}