93 lines
2.4 KiB
Vue
93 lines
2.4 KiB
Vue
<template>
|
|
<div :class="['flex flex-row items-center gap-2', wrapperClass]">
|
|
<label
|
|
v-if="label"
|
|
:for="id"
|
|
class="text-xl text-bold flex items-center"
|
|
:class="labelClass"
|
|
>
|
|
<span
|
|
v-if="label">
|
|
{{ label }}
|
|
</span>
|
|
<span
|
|
v-if="code"
|
|
class="text-neutral-600">
|
|
({{ code }})
|
|
</span>
|
|
</label>
|
|
<input
|
|
:id="id"
|
|
type="number"
|
|
:value="modelValue ?? ''"
|
|
:min="min"
|
|
:max="max"
|
|
:step="step"
|
|
:disabled="disabled"
|
|
v-bind="attrs"
|
|
class="border-b border-black text-xl bg-transparent w-12"
|
|
:class="[
|
|
isEmpty ? 'text-neutral-400' : 'text-black',
|
|
disabled ? 'cursor-not-allowed' : 'cursor-text',
|
|
inputClass
|
|
]"
|
|
@keydown="onKeydown"
|
|
@input="onInput"
|
|
>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import {computed, useAttrs} from 'vue'
|
|
|
|
defineOptions({inheritAttrs: false})
|
|
|
|
const props = withDefaults(
|
|
defineProps<{
|
|
id?: string
|
|
label?: string
|
|
code?: string
|
|
modelValue: number | string | null | undefined
|
|
min?: number | string
|
|
max?: number | string
|
|
step?: number | string
|
|
disabled?: boolean
|
|
wrapperClass?: string
|
|
labelClass?: string
|
|
inputClass?: string
|
|
}>(),
|
|
{
|
|
min: undefined,
|
|
max: undefined,
|
|
step: undefined,
|
|
disabled: false,
|
|
wrapperClass: '',
|
|
labelClass: '',
|
|
inputClass: ''
|
|
}
|
|
)
|
|
|
|
const emit = defineEmits<{
|
|
(event: 'update:modelValue', value: number | null): void
|
|
}>()
|
|
|
|
const attrs = useAttrs()
|
|
const isEmpty = computed(() => props.modelValue === null || props.modelValue === undefined || props.modelValue === '')
|
|
|
|
const onInput = (event: Event) => {
|
|
const target = event.target as HTMLInputElement
|
|
if (target.value === '') {
|
|
emit('update:modelValue', null)
|
|
return
|
|
}
|
|
const numeric = Math.max(0, Number(target.value))
|
|
emit('update:modelValue', Number.isNaN(numeric) ? null : numeric)
|
|
}
|
|
|
|
const onKeydown = (event: KeyboardEvent) => {
|
|
if (event.key === '-' || event.key === 'e' || event.key === 'E') {
|
|
event.preventDefault()
|
|
}
|
|
}
|
|
</script>
|