import { inject, ref, computed, type InjectionKey, type Ref, type ComputedRef } from 'vue' import { type UseEventBusReturn, useDebounceFn } from '@vueuse/core' import type { FormFieldProps } from '../types' import type { FormEvent, FormInputEvents, FormFieldInjectedOptions, FormInjectedOptions } from '../types/form' import type { GetObjectField } from '../types/utils' type Props = { id?: string name?: string size?: GetObjectField color?: GetObjectField eagerValidation?: boolean legend?: string highlight?: boolean disabled?: boolean } export const formOptionsInjectionKey: InjectionKey> = Symbol('nuxt-ui.form-options') export const formBusInjectionKey: InjectionKey> = Symbol('nuxt-ui.form-events') export const formFieldInjectionKey: InjectionKey>> = Symbol('nuxt-ui.form-field') export const formInputsInjectionKey: InjectionKey>> = Symbol('nuxt-ui.form-inputs') export function useFormField(props?: Props) { const formOptions = inject(formOptionsInjectionKey, undefined) const formBus = inject(formBusInjectionKey, undefined) const formField = inject(formFieldInjectionKey, undefined) const formInputs = inject(formInputsInjectionKey, undefined) if (formField) { if (props?.id) { // Updates for="..." attribute on label if props.id is provided formField.value.id = props?.id } if (formInputs && formField.value.name) { formInputs.value[formField.value.name] = formField.value.id } } const blurred = ref(false) function emitFormEvent(type: FormInputEvents, name?: string) { if (formBus && formField && name) { formBus.emit({ type, name }) } } function emitFormBlur() { emitFormEvent('blur', formField?.value.name) blurred.value = true } function emitFormChange() { emitFormEvent('change', formField?.value.name) } const emitFormInput = useDebounceFn( () => { emitFormEvent('input', formField?.value.name) }, formField?.value.validateOnInputDelay ?? formOptions?.value.validateOnInputDelay ?? 0 ) return { id: computed(() => props?.id ?? formField?.value.id), name: computed(() => props?.name ?? formField?.value.name), size: computed(() => props?.size ?? formField?.value.size), color: computed(() => formField?.value.error ? 'error' : props?.color), highlight: computed(() => formField?.value.error ? true : props?.highlight), disabled: computed(() => formOptions?.value.disabled || props?.disabled), emitFormBlur, emitFormInput, emitFormChange } }