UNPKG

bootstrap-vue-next

Version:

Seamless integration of Vue 3, Bootstrap 5, and TypeScript for modern, type-safe UI development

1 lines 7.8 kB
{"version":3,"file":"useFormInput-CfzQTcFF.mjs","sources":["../src/utils/normalizeInput.ts","../src/composables/useFormInput.ts"],"sourcesContent":["import type {Numberish} from '../types/CommonTypes'\n\nexport const normalizeInput = (\n v: Numberish | null,\n modelModifiers: Record<'number' | 'lazy' | 'trim', true | undefined>\n) => {\n if (v === null) return\n let update = v\n if (modelModifiers.number && typeof update === 'string' && update !== '') {\n const parsed = Number.parseFloat(update)\n update = Number.isNaN(parsed) ? update : parsed\n }\n return update\n}\n","import type {Numberish} from '../types/CommonTypes'\nimport {\n computed,\n inject,\n nextTick,\n onActivated,\n onMounted,\n ref,\n type Ref,\n type ShallowRef,\n} from 'vue'\nimport {useAriaInvalid} from './useAriaInvalid'\nimport {useId} from './useId'\nimport {useFocus, useToNumber} from '@vueuse/core'\nimport type {CommonInputProps} from '../types/FormCommonInputProps'\nimport {formGroupKey} from '../utils/keys'\nimport {useDebounceFn} from '../utils/debounce'\nimport {useStateClass} from './useStateClass'\n\nexport const useFormInput = (\n props: Readonly<CommonInputProps>,\n input:\n | Readonly<ShallowRef<HTMLInputElement | null>>\n | Readonly<ShallowRef<HTMLTextAreaElement | null>>,\n modelValue: Ref<Numberish | null>,\n modelModifiers: Record<'number' | 'lazy' | 'trim', true | undefined>\n) => {\n const forceUpdateKey = ref(0)\n\n const computedId = useId(() => props.id, 'input')\n const debounceNumber = useToNumber(() => props.debounce ?? 0, {nanToZero: true})\n const debounceMaxWaitNumber = useToNumber(() => props.debounceMaxWait ?? Number.NaN)\n\n // This automatically adds the appropriate \"for\" attribute to a BFormGroup label\n const formGroupData = inject(formGroupKey, null)?.(computedId)\n const computedState = computed(() =>\n props.state !== undefined ? props.state : (formGroupData?.state.value ?? null)\n )\n const computedAriaInvalid = useAriaInvalid(() => props.ariaInvalid, computedState)\n const stateClass = useStateClass(computedState)\n\n const internalUpdateModelValue = useDebounceFn(\n (value: Numberish) => {\n modelValue.value = value\n },\n () => (modelModifiers.lazy === true ? 0 : debounceNumber.value),\n {maxWait: () => (modelModifiers.lazy === true ? Number.NaN : debounceMaxWaitNumber.value)}\n )\n\n const updateModelValue = (value: Numberish, force = false, immediate = false) => {\n if (modelModifiers.lazy === true && force === false) return\n if (immediate) {\n modelValue.value = value\n } else {\n internalUpdateModelValue(value)\n }\n }\n\n const {focused} = useFocus(input, {\n initialValue: props.autofocus,\n })\n\n const _formatValue = (value: string, evt: Readonly<Event>, force = false) => {\n if (props.formatter !== undefined && (!props.lazyFormatter || force)) {\n return props.formatter(value, evt)\n }\n return value\n }\n onMounted(() => {\n if (input.value) {\n input.value.value = modelValue.value?.toString() ?? ''\n }\n })\n\n onActivated(() => {\n nextTick(() => {\n if (props.autofocus) {\n focused.value = true\n }\n })\n })\n\n const onInput = (evt: Readonly<Event>) => {\n const {value} = evt.target as HTMLInputElement\n const formattedValue = _formatValue(value, evt)\n if (evt.defaultPrevented) {\n evt.preventDefault()\n return\n }\n\n const nextModel = formattedValue\n\n updateModelValue(nextModel)\n }\n\n const onChange = (evt: Readonly<Event>) => {\n const {value} = evt.target as HTMLInputElement\n const formattedValue = _formatValue(value, evt)\n if (evt.defaultPrevented) {\n evt.preventDefault()\n return\n }\n\n const nextModel = formattedValue\n if (modelValue.value !== nextModel) {\n updateModelValue(formattedValue, true)\n }\n }\n\n const onBlur = (evt: Readonly<FocusEvent>) => {\n if (\n !modelModifiers.lazy &&\n !props.lazyFormatter &&\n !modelModifiers.trim &&\n debounceNumber.value <= 0\n )\n return\n\n const {value} = evt.target as HTMLInputElement\n const formattedValue = _formatValue(value, evt, true)\n\n const nextModel = modelModifiers.trim ? formattedValue.trim() : formattedValue\n const needsForceUpdate = nextModel.length !== formattedValue.length\n // Cancel before modelValue.value comparison and update\n internalUpdateModelValue.cancel()\n if (modelValue.value !== nextModel) {\n updateModelValue(formattedValue, true, true)\n }\n if (modelModifiers.trim && needsForceUpdate) {\n // The value is trimmed but there would still exist some white space\n // So, force update the value. You need to bind this to :key on the input element\n forceUpdateKey.value = forceUpdateKey.value + 1\n }\n }\n\n const focus = () => {\n if (!props.disabled) {\n focused.value = true\n }\n }\n\n const blur = () => {\n if (!props.disabled) {\n focused.value = false\n }\n }\n\n return {\n input,\n computedId,\n computedAriaInvalid,\n onInput,\n onChange,\n onBlur,\n focus,\n blur,\n forceUpdateKey,\n stateClass,\n }\n}\n"],"names":[],"mappings":"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"}