2023-07-25 19:19:27 +02:00
|
|
|
<script setup lang="ts">
|
|
|
|
import { useField } from 'vee-validate'
|
|
|
|
import { formGroupExtras } from '@/composables/form'
|
|
|
|
|
|
|
|
const props = defineProps<{
|
|
|
|
name: string
|
|
|
|
label: string
|
|
|
|
icon?: string
|
|
|
|
description?: string
|
2023-07-26 04:08:17 +02:00
|
|
|
row?: boolean
|
2023-07-25 19:19:27 +02:00
|
|
|
}>()
|
|
|
|
|
|
|
|
const { errorMessage } = useField(() => props.name)
|
|
|
|
const invalid = computed(() => !!errorMessage.value)
|
|
|
|
const describedBy = computed(() => {
|
|
|
|
return (
|
|
|
|
[
|
|
|
|
props.description ? props.name + '__description' : null,
|
|
|
|
invalid.value ? props.name + '__feedback_invalid' : null,
|
|
|
|
]
|
|
|
|
.filter((x) => x)
|
|
|
|
.join(' ') || undefined
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
provide(formGroupExtras, {
|
|
|
|
describedBy,
|
|
|
|
invalid,
|
|
|
|
})
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
|
|
|
<div>
|
|
|
|
<div
|
|
|
|
role="group"
|
|
|
|
:aria-invalid="invalid"
|
2023-07-26 04:08:17 +02:00
|
|
|
:class="{ 'is-invalid': invalid, 'flex-col': !row }"
|
2023-07-25 19:19:27 +02:00
|
|
|
class="flex"
|
|
|
|
>
|
|
|
|
<slot name="label">
|
2023-07-26 04:08:17 +02:00
|
|
|
<label :id="name + '__label'" :for="name" class="block ml-1 mb-2">
|
2023-07-25 19:19:27 +02:00
|
|
|
<Icon
|
|
|
|
v-if="icon"
|
|
|
|
:name="icon"
|
|
|
|
size="2em"
|
|
|
|
aria-hidden="true"
|
|
|
|
class="m-2"
|
|
|
|
/>
|
|
|
|
<span :class="{ 'sr-only': !!icon }">{{ label }}</span>
|
|
|
|
</label>
|
|
|
|
</slot>
|
|
|
|
|
|
|
|
<div>
|
|
|
|
<slot name="default" />
|
|
|
|
|
|
|
|
<div
|
|
|
|
v-show="invalid"
|
|
|
|
:id="name + '__feedback_invalid'"
|
|
|
|
tabindex="-1"
|
|
|
|
aria-live="assertive"
|
|
|
|
aria-atomic="true"
|
|
|
|
class="text-error mt-1"
|
|
|
|
>
|
|
|
|
{{ errorMessage }}
|
|
|
|
</div>
|
|
|
|
<small
|
|
|
|
v-if="description"
|
|
|
|
:id="name + '__description'"
|
|
|
|
tabindex="-1"
|
|
|
|
class="block text-gray-400 mt-1"
|
|
|
|
>
|
|
|
|
{{ description }}
|
|
|
|
</small>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|