zgg-ui
Version:
2.0.1 正式版本 基于 Vue 3、UniApp 和 TypeScript 开发的多端适配移动端 UI 组件库,旨在提供丰富的组件集合,帮助开发者快速构建多端响应式的移动应用界面
212 lines (182 loc) • 5.69 kB
text/typescript
import type { SetupContext, InjectionKey } from 'vue'
import { buildProp, definePropType } from '../../libs/utils'
import { castArray } from '../../libs/lodash'
import { computed, inject, ref, unref } from 'vue'
import { useProp } from '../../libs/Hooks/z-use-prop'
import { MaybeRef } from '../../libs/zType'
import type {
RuleItem,
ValidateError,
ValidateFieldsError,
} from '../../libs/async-validator'
import type Form from '../../components/z-form/z-form.vue'
import type FormItem from '../../components/z-form-item/z-form-item.vue'
export type zFormInstance = InstanceType<typeof Form>
export type zFormItemInstance = InstanceType<typeof FormItem>
type formSizeType = 'small' | 'normal' | 'large'
type labelPositionType = 'left' | 'right' | 'top'
type requireAsteriskPositionType = 'left' | 'right'
type FormItemProp = Arrayable<string>
const formItemValidateStates = ['', 'error', 'validating', 'success'] as const
export type FormItemValidateStates = (typeof formItemValidateStates)[number]
type FormProps = {
size?: formSizeType
disabled?: boolean
model?: object
rules?: FormRules
labelPosition?: labelPositionType
requireAsteriskPosition?: requireAsteriskPositionType
labelWidth?: string | number
labelSuffix?: string
statusIcon?: boolean
showMessage?: boolean
validateOnRuleChange?: boolean
hideRequiredAsterisk?: boolean
}
type FormItemProps = {
label?: string
labelWidth?: string | number
labelPosition?: string
prop?: Arrayable<string>
required?: boolean
rules?: Arrayable<FormItemRule>
error?: string
validateStatus?: string
showMessage?: boolean
size?: string
}
type FormEmits = {
validate: (prop: FormItemProp, isValid: boolean, message: string) => boolean
}
export type Arrayable<T> = T | T[]
const formComponentSizes = ['small', 'normal', 'large']
type FormComponentSize = (typeof formComponentSizes)[number]
export interface FormItemRule extends RuleItem {
trigger?: Arrayable<string>
}
export type FormRules = Partial<Record<string, Arrayable<FormItemRule>>>
export type FormValidationResult = Promise<boolean>
export type FormValidationCallback = (
isValid: boolean,
invalidFields?: ValidateFieldsError
) => void
export interface FormValidateFailure {
errors: ValidateError[] | null
fields: ValidateFieldsError
}
export type FormContext = FormProps & {
emits: SetupContext<FormEmits>['emit']
//expose
addField: (field: FormItemContext) => void
removeField: (field: FormItemContext) => void
resetFields: (props?: Arrayable<FormItemProp>) => void
clearValidate: (props?: Arrayable<FormItemProp>) => void
validateField: (
props?: Arrayable<FormItemProp>,
callback?: FormValidationCallback
) => FormValidationResult
}
export interface FormItemContext extends FormItemProps {
size: FormComponentSize
validateState: FormItemValidateStates
hasLabel: boolean
validate: (
trigger: string,
callback?: FormValidationCallback
) => FormValidationResult
resetField: () => void
clearValidate: () => void
}
export const formContextKey: InjectionKey<FormContext> =
Symbol('formContextKey')
export const formItemContextKey: InjectionKey<FormItemContext> =
Symbol('formItemContextKey')
export const filterFields = (
fields: FormItemContext[],
props: Arrayable<FormItemProp>
) => {
const normalized = castArray(props)
return normalized.length > 0
? fields.filter((field) => field.prop && normalized.includes(field.prop))
: fields
}
/* 表单尺寸 */
export const useFormSize = (
fallback?: MaybeRef<FormComponentSize | undefined>,
ignore: Partial<Record<'prop' | 'form' | 'formItem' | 'global', boolean>> = {}
) => {
const emptyRef = ref(undefined)
const size = ignore.prop ? emptyRef : useProp<FormComponentSize>('size')
const form = ignore.form
? { size: undefined }
: inject(formContextKey, undefined)
const formItem = ignore.formItem
? { size: undefined }
: inject(formItemContextKey, undefined)
return computed(
(): FormComponentSize =>
size.value || unref(fallback) || formItem?.size || form?.size || ''
)
}
/* 表单是否禁用 */
export const useFormDisabled = (fallback?: MaybeRef<boolean | undefined>) => {
const disabled = useProp<boolean>('disabled')
const form = inject(formContextKey, undefined)
return computed(
() => disabled.value || unref(fallback) || form?.disabled || false
)
}
export const useFormItem = () => {
const form = inject(formContextKey, undefined)
const formItem = inject(formItemContextKey, undefined)
return {
form,
formItem,
}
}
export type ComponentIndex = string | number
/**
* @description 组件Boolean类型定义
*/
export const useComponentBoolean = buildProp({
type: [Boolean, undefined],
default: undefined,
})
const componentSizes = ['small', 'normal', 'large'] as const
/**
* @description 组件尺寸
*/
export const useComponentSizeProp = buildProp({
type: String,
values: componentSizes,
required: false,
} as const)
/**
* @description 表单组件尺寸
*/
export const useFormSizeProps = buildProp({
type: String,
values: formComponentSizes,
required: false,
} as const)
/**
* @description 组件自定义样式
*/
export const useComponentCustomStyleProp = buildProp({
type: Object,
default: () => ({}),
})
/**
* @description 组件自定义index
*/
export const useComponentIndexProp = buildProp({
type: definePropType<ComponentIndex>([String, Number]),
default: () => Math.floor(Math.random() * 10000),
})
/**
* @description 组件是否开启底部安全区域
*/
export const useComponentSafeAreaInsetBottomProp = buildProp({
type: Boolean,
default: true,
})