Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
<template>
<main>
Vue-Tailwind
</main>
<main>Vue-Tailwind</main>
</template>
79 changes: 79 additions & 0 deletions src/components/DxhFileInput.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<template>
<label :for="id" class="block">
<span>{{ label }}</span>
<div class="relative">
<input
:id="id"
:key="fileInputKey"
type="file"
:accept="accept"
:placeholder="placeholder"
:hint="hint"
:disabled="disabled"
:readonly="readonly"
:required="required"
:autofocus="autofocus"
:clearable="clearable"
:multiple="multiple"
class="w-full border px-2 py-1 rounded"
@focus="$emit('focus')"
@blur="$emit('blur')"
@change="handleFileChange"
/>
<div
v-if="clearable && isClear"
class="absolute right-2 top-0 bottom-0 cursor-pointer flex items-center h-full"
>
<slot name="clear" :onClick="clearFile">
<svg
class="inline"
xmlns="http://www.w3.org/2000/svg"
height="14px"
viewBox="0 0 512 512"
@click.stop.prevent="clearFile"
>
<path
d="M256 48a208 208 0 1 1 0 416 208 208 0 1 1 0-416zm0 464A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM175 175c-9.4 9.4-9.4 24.6 0 33.9l47 47-47 47c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l47-47 47 47c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-47-47 47-47c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0l-47 47-47-47c-9.4-9.4-24.6-9.4-33.9 0z"
/>
</svg>
</slot>
</div>
</div>
<p v-if="hint">{{ hint }}</p>
</label>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const isClear = ref(false)
interface props {
modelValue?: any
accept?: string
label?: string
id?: string
placeholder?: string
hint?: string
disabled?: boolean
readonly?: boolean
autofocus?: boolean
required?: boolean
clearable?: boolean
multiple?: boolean
}
const { multiple } = defineProps<props>()
const emit = defineEmits(['focus', 'blur', 'enter', 'update:modelValue'])

const fileInputKey = ref(0)

const handleFileChange = (event: any) => {
emit('update:modelValue', event)
isClear.value = true
}

const clearFile = () => {
fileInputKey.value += 1
emit('update:modelValue', '')
isClear.value = false
}
</script>
35 changes: 35 additions & 0 deletions src/components/__tests__/DxhFileInput.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { describe, it, expect, beforeEach } from 'vitest'
import { mount } from '@vue/test-utils'
import DxhFileInput from '../DxhFileInput.vue'

describe('DxhFileInput', () => {
let wrapper: any

beforeEach(() => {
wrapper = mount(DxhFileInput)
})

it('renders correctly with default props', () => {
expect(wrapper.find('label').exists()).toBe(true)
expect(wrapper.find('input[type="file"]').exists()).toBe(true)
})

it('displays label and placeholder text', async () => {
const label = 'File Input'
const placeholder = 'Choose a file'

await wrapper.setProps({ label, placeholder })

expect(wrapper.find('span').text()).toBe(label)
expect(wrapper.find('input').attributes('placeholder')).toBe(placeholder)
})

it('clears file on clearFile method call', async () => {
await wrapper.setProps({ modelValue: 'test-file.txt' })

await wrapper.vm.clearFile()

expect(wrapper.emitted('update:modelValue')).toBeTruthy()
expect(wrapper.emitted('update:modelValue')[0]).toEqual([''])
})
})
7 changes: 4 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import DButton from "./components/DButton.vue"
import DInput from "./components/DInput.vue"
import DButton from './components/DButton.vue'
import DInput from './components/DInput.vue'
import DxhFileInput from './components/DxhFileInput.vue'

export default {DButton, DInput}
export default { DButton, DInput, DxhFileInput }