Skip to content

Commit a95d74a

Browse files
committed
feat: allow file input to take in any format by passing empty array
Also added stories/test for this and the error handler.
1 parent 3558b6b commit a95d74a

File tree

2 files changed

+30
-11
lines changed

2 files changed

+30
-11
lines changed

src/components/LibFileInput/LibFileInput.stories.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,19 @@ type Story = StoryObj<typeof LibFileInput>
2222
export const SingleFile: Story = {
2323
render: args => ({
2424
components,
25-
setup: () => ({ args }),
25+
setup: () => {
26+
function errorHandler(e: any): void {
27+
// eslint-disable-next-line no-console
28+
console.log(e)
29+
}
30+
return { args, errorHandler }
31+
},
2632
template: `
27-
<lib-file-input v-bind="{...args}"></lib-file-input>
33+
<lib-file-input v-bind="{...args}" @errors="errorHandler"></lib-file-input>
2834
`,
2935
}),
3036
}
37+
3138
export const MultipleFile: Story = {
3239
...SingleFile,
3340
args: {
@@ -36,6 +43,15 @@ export const MultipleFile: Story = {
3643
},
3744
}
3845

46+
export const AnyFormat: Story = {
47+
...SingleFile,
48+
args: {
49+
...SingleFile.args,
50+
multiple: true,
51+
formats: [],
52+
},
53+
}
54+
3955
export const Compact: Story = {
4056
...SingleFile,
4157
args: {

src/components/LibFileInput/LibFileInput.vue

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
</slot>
4242
<span v-if="compact && multiple">{{ ` (${files.length})` }}</span>
4343
</label>
44-
<label v-if="!compact" class="flex flex-col items-center text-sm">
44+
<label v-if="!compact && formats?.length > 0" class="flex flex-col items-center text-sm">
4545
<slot name="formats">Accepted Formats: </slot>
4646
<div class="">
4747
{{ extensions.join(", ") }}
@@ -151,14 +151,12 @@ const errorFlashing = ref(false)
151151
watch(files, () => {
152152
emits("input", files.map(entry => entry.file))
153153
})
154-
watch(errors, (newVal, oldVal) => {
154+
watch(errors, () => {
155155
if (errors.length > 0) {
156156
errorFlashing.value = true
157157
setTimeout(() => {
158158
errorFlashing.value = false
159159
}, 500)
160-
}
161-
if (newVal.length !== oldVal.length) {
162160
emits("errors", errors)
163161
}
164162
})
@@ -182,8 +180,8 @@ const props = withDefaults(defineProps<Props>(), {
182180
compact: false,
183181
})
184182
185-
const mimeTypes = computed(() => props.formats.filter(_ => !_.startsWith(".")))
186-
const extensions = computed(() => props.formats.filter(_ => _.startsWith(".")))
183+
const mimeTypes = computed(() => props.formats?.filter(_ => !_.startsWith(".")) ?? [])
184+
const extensions = computed(() => props.formats?.filter(_ => _.startsWith(".")) ?? [])
187185
188186
const getSrc = (file: File) => {
189187
const src = URL.createObjectURL(file)
@@ -201,10 +199,11 @@ const inputFile = async (e: InputEvent): Promise<void | boolean> => {
201199
const errs = []
202200
for (const file of el.value!.files) {
203201
const isImg = file.type.startsWith("image")
204-
202+
203+
const byPassValidation = props.formats.length === 0
205204
const isValidMimeType = mimeTypes.value.find(_ => _.endsWith("/*") ? file.type.startsWith(_.slice(0, -2)) : _ === file.type) !== undefined
206205
const isValidExtension = extensions.value.find(_ => file.name.endsWith(_)) !== undefined
207-
if (!isValidMimeType || !isValidExtension) {
206+
if (!byPassValidation && (!isValidMimeType || !isValidExtension)) {
208207
const extension = file.name.match(/.*(\..*)/)?.[1] ?? "Unknown"
209208
const type = file.type === "" ? "" : ` (${file.type})`
210209
const message = `File type ${extension}${type} is not allowed. Allowed file types are: ${extensionsList.value}.`
@@ -247,7 +246,11 @@ type RealProps =
247246
& LinkableByIdProps
248247
& {
249248
multiple?: boolean
250-
/** A list of extensions or mime types to add to the input's accept. Basic validations are done so that files match an extension and mimeType, but note that a file could still be lying, all files should be validated server side.*/
249+
/**
250+
* A list of extensions or mime types to add to the input's accept. Basic validations are done so that files match an extension and mimeType, but note that a file could still be lying, all files should be validated server side.
251+
*
252+
* Pass an empty array to allow any filetype.
253+
*/
251254
formats?: string[]
252255
compact?: boolean
253256
}

0 commit comments

Comments
 (0)