Files
speckle-server/packages/frontend-2/lib/form/composables/textInput.ts
T
Kristaps Fabians Geikins f80a7189a0 chore(fe2): upgrade to nuxt 3.8.2 (#1887)
* chore(fe2): upgrade to nuxt 3.8.2

* fix tailwind-theme build

* readme update

* removing storybook from fe2 :(

* fix(fe2): codegen schema url resolution
2023-11-29 10:22:17 +02:00

117 lines
3.0 KiB
TypeScript

import { useField } from 'vee-validate'
import type { RuleExpression } from 'vee-validate'
import type { Ref, ToRefs } from 'vue'
import type { Nullable } from '@speckle/shared'
import { nanoid } from 'nanoid'
/**
* Common setup for text input & textarea fields
*/
export function useTextInputCore(params: {
props: ToRefs<{
name: string
help?: string
label?: string
showLabel?: boolean
rules?: RuleExpression<string>
validateOnMount?: boolean
validateOnValueUpdate?: boolean
modelValue?: string
autoFocus?: boolean
showClear?: boolean
useLabelInErrors?: boolean
hideErrorMessage?: boolean
}>
emit: {
(e: 'change', val: { event?: Event; value: string }): void
(e: 'clear'): void
}
inputEl: Ref<Nullable<HTMLInputElement | HTMLTextAreaElement>>
}) {
const { props, inputEl, emit } = params
const { value, errorMessage: error } = useField(props.name, props.rules, {
validateOnMount: unref(props.validateOnMount),
validateOnValueUpdate: unref(props.validateOnValueUpdate),
initialValue: unref(props.modelValue) || undefined
})
const labelClasses = computed(() => {
const classParts = ['block label text-foreground-2 mb-2']
if (!unref(props.showLabel)) {
classParts.push('sr-only')
}
return classParts.join(' ')
})
const coreClasses = computed(() => {
const classParts = [
'block w-full rounded focus:outline-none bg-foundation-page text-foreground transition-all',
'disabled:cursor-not-allowed disabled:bg-foundation-disabled disabled:text-disabled-muted',
'placeholder:text-foreground-2'
]
if (error.value) {
classParts.push(
'border-2 border-danger text-danger-darker focus:border-danger focus:ring-danger'
)
} else {
classParts.push('border-0 focus:ring-2 focus:ring-outline-2')
}
return classParts.join(' ')
})
const internalHelpTipId = ref(nanoid())
const title = computed(() => unref(props.label) || unref(props.name))
const errorMessage = computed(() => {
const base = error.value
if (!base || !unref(props.useLabelInErrors)) return base
return base.replace('Value', title.value)
})
const hideHelpTip = computed(
() => errorMessage.value && unref(props.hideErrorMessage)
)
const helpTip = computed(() => errorMessage.value || unref(props.help))
const hasHelpTip = computed(() => !!helpTip.value)
const helpTipId = computed(() =>
hasHelpTip.value ? `${unref(props.name)}-${internalHelpTipId.value}` : undefined
)
const helpTipClasses = computed((): string =>
error.value ? 'text-danger' : 'text-foreground-2'
)
const focus = () => {
inputEl.value?.focus()
}
const clear = () => {
value.value = ''
emit('change', { value: '' })
emit('clear')
}
onMounted(() => {
if (unref(props.autoFocus)) {
focus()
}
})
return {
coreClasses,
title,
value,
helpTipId,
helpTipClasses,
helpTip,
hideHelpTip,
errorMessage,
clear,
focus,
labelClasses
}
}