mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
refactor: InputItem typing
This commit is contained in:
parent
15b512fa1e
commit
9a48aa1a45
3 changed files with 82 additions and 39 deletions
|
@ -1,63 +1,70 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { inject } from 'vue'
|
import type { BaseValidation } from '@vuelidate/core'
|
||||||
|
import { computed, inject } from 'vue'
|
||||||
|
|
||||||
|
import { ValidationTouchSymbol } from '@/composables/form'
|
||||||
|
import type { BaseItemComputedProps, InputItemProps } from '@/types/form'
|
||||||
|
import { objectGet } from '@/helpers/commons'
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<InputItemProps & BaseItemComputedProps<string | number | null>>(),
|
||||||
modelValue?: string | number | null
|
|
||||||
id?: string
|
|
||||||
placeholder?: string
|
|
||||||
type?: string
|
|
||||||
required?: boolean
|
|
||||||
state?: false | null
|
|
||||||
min?: number
|
|
||||||
max?: number
|
|
||||||
step?: number
|
|
||||||
trim?: boolean
|
|
||||||
autocomplete?: string
|
|
||||||
// FIXME pattern?
|
|
||||||
pattern?: object
|
|
||||||
name?: string
|
|
||||||
}>(),
|
|
||||||
{
|
{
|
||||||
modelValue: null,
|
|
||||||
id: undefined,
|
id: undefined,
|
||||||
|
name: undefined,
|
||||||
placeholder: undefined,
|
placeholder: undefined,
|
||||||
type: 'text',
|
touchKey: undefined,
|
||||||
required: false,
|
autocomplete: undefined,
|
||||||
state: undefined,
|
// pattern: undefined,
|
||||||
min: undefined,
|
|
||||||
max: undefined,
|
|
||||||
step: undefined,
|
step: undefined,
|
||||||
trim: true,
|
trim: true,
|
||||||
autocomplete: undefined,
|
type: 'text',
|
||||||
pattern: undefined,
|
|
||||||
name: undefined,
|
ariaDescribedby: undefined,
|
||||||
|
modelValue: undefined,
|
||||||
|
state: undefined,
|
||||||
|
validation: undefined,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
const emit = defineEmits<{
|
defineEmits<{
|
||||||
'update:modelValue': [value: string | number | null]
|
'update:modelValue': [value: string | number | null]
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const touch = inject('touch')
|
const touch = inject(ValidationTouchSymbol)
|
||||||
|
|
||||||
const autocomplete =
|
const model = defineModel<string | number | null>()
|
||||||
props.autocomplete || props.type === 'password' ? 'new-password' : null
|
|
||||||
|
const autocomplete = computed(() => {
|
||||||
|
const typeToAutocomplete = {
|
||||||
|
password: 'new-password',
|
||||||
|
email: 'email',
|
||||||
|
url: 'url',
|
||||||
|
} as const
|
||||||
|
return props.autocomplete || objectGet(typeToAutocomplete, props.type)
|
||||||
|
})
|
||||||
|
|
||||||
|
const fromValidation = computed(() => {
|
||||||
|
const validation = props?.validation ?? ({} as BaseValidation)
|
||||||
|
return {
|
||||||
|
required: 'required' in validation,
|
||||||
|
min: 'min' in validation ? validation.min.$params.min : undefined,
|
||||||
|
max: 'max' in validation ? validation.max.$params.max : undefined,
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<BFormInput
|
<BFormInput
|
||||||
:modelValue="modelValue"
|
|
||||||
@update:modelValue="emit('update:modelValue', $event)"
|
|
||||||
:id="id"
|
:id="id"
|
||||||
|
v-bind="fromValidation"
|
||||||
|
v-model="model"
|
||||||
|
:name="name"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
:type="type"
|
:autocomplete="autocomplete"
|
||||||
:state="state"
|
|
||||||
:required="required"
|
|
||||||
:min="min"
|
|
||||||
:max="max"
|
|
||||||
:step="step"
|
:step="step"
|
||||||
:trim="trim"
|
:trim="trim"
|
||||||
:autocomplete="autocomplete"
|
:type="type"
|
||||||
@blur="touch(name)"
|
:aria-describedby="ariaDescribedby"
|
||||||
|
:state="state"
|
||||||
|
@blur="touch?.(touchKey)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -29,6 +29,14 @@ export function isObjectLiteral(value) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function objectGet<
|
||||||
|
T extends Obj,
|
||||||
|
K extends keyof T | string,
|
||||||
|
F extends any = undefined,
|
||||||
|
>(obj: T, key: K, fallback?: F) {
|
||||||
|
return (key in obj ? obj[key] : fallback) as K extends keyof T ? T[K] : F
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if value is "empty" (`null`, `undefined`, `''`, `[]`, '{}').
|
* Check if value is "empty" (`null`, `undefined`, `''`, `[]`, '{}').
|
||||||
* Note: `0` is not considered "empty" in that helper.
|
* Note: `0` is not considered "empty" in that helper.
|
||||||
|
|
|
@ -44,3 +44,31 @@ export type FileModelValue = {
|
||||||
current?: boolean
|
current?: boolean
|
||||||
removed?: boolean
|
removed?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type InputItemProps = BaseWritableItemProps & {
|
||||||
|
autocomplete?:
|
||||||
|
| 'off'
|
||||||
|
| 'on'
|
||||||
|
| 'name'
|
||||||
|
| 'email'
|
||||||
|
| 'username'
|
||||||
|
| 'new-password'
|
||||||
|
| 'current-password'
|
||||||
|
| 'url'
|
||||||
|
// pattern?: object
|
||||||
|
// choices?: string[] FIXME rm ?
|
||||||
|
step?: number
|
||||||
|
trim?: boolean
|
||||||
|
type?:
|
||||||
|
| 'color'
|
||||||
|
| 'date'
|
||||||
|
// | 'datetime-local'
|
||||||
|
| 'email'
|
||||||
|
| 'number'
|
||||||
|
| 'password'
|
||||||
|
| 'range'
|
||||||
|
// | 'search'
|
||||||
|
| 'text'
|
||||||
|
| 'time'
|
||||||
|
| 'url'
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue