UNPKG

@inkline/inkline

Version:

Inkline is the Vue.js UI/UX Library built for creating your next design system

211 lines (192 loc) 5.46 kB
import { defineComponent } from 'vue'; import { getValueByPath, setValueByPath, setValuesAlongPath, clone, uid } from '@inkline/inkline/helpers'; import { colorVariantClass, defaultPropValue, sizePropValidator, FormComponentMixin } from '@inkline/inkline/mixins'; import { validate } from '@inkline/inkline/validation'; import { Classes, InputElementEvent } from '@inkline/inkline/types'; /** * Slot for default card content * @name default * @kind slot */ const componentName = 'IForm'; export default defineComponent({ name: componentName, mixins: [ FormComponentMixin ], provide () { return { form: this }; }, inheritAttrs: false, props: { /** * The color variant of the form * @type light | dark * @default light * @name color */ color: { type: String, default: '' }, /** * The disabled state of the form * @type Boolean * @default false * @name disabled */ disabled: { type: Boolean, default: false }, /** * Display the form as inline * @type Boolean * @default false * @name inline */ inline: { type: Boolean, default: false }, /** * The loading state of the form * @type Boolean * @default false * @name loading */ loading: { type: Boolean, default: false }, /** * The unique identifier of the form * @type String * @default uid() * @name name */ name: { type: String, default () { return uid('form'); } }, /** * Used to set the form schema * @type Boolean * @default false * @name modelValue */ modelValue: { type: Object, default: () => null }, /** * The readonly state of the form * @type Boolean * @default false * @name readonly */ readonly: { type: Boolean, default: false }, /** * The size variant of the form * @type sm | md | lg * @default md * @name size */ size: { type: String, default: defaultPropValue<string>(componentName, 'size'), validator: sizePropValidator } }, emits: [ /** * Event emitted for setting the modelValue schema * @event update:modelValue */ 'update:modelValue', /** * Event emitted for submitting the form * @event submit */ 'submit' ], computed: { classes (): Classes { return { ...colorVariantClass(this), [`-${this.size}`]: Boolean(this.size), '-disabled': this.isDisabled, '-readonly': this.isReadonly, '-inline': this.inline }; }, schema (): any { if (this.modelValue) { return this.modelValue; } return getValueByPath((this as any).formGroup.schema || (this as any).form.schema || {}, this.name); } }, methods: { onBlur (name: string, event: InputElementEvent) { this.parent.onBlur?.(this.name ? `${this.name}.${name}` : name, event); if (this.modelValue) { let schema = clone(this.modelValue); schema = setValuesAlongPath(schema, name, { untouched: false, touched: true }); if (this.shouldValidate(name, 'blur')) { schema = validate(schema); } this.$emit('update:modelValue', schema); } }, onInput (name: string, value: any) { this.parent.onInput?.(this.name ? `${this.name}.${name}` : name, value); if (this.modelValue) { let schema = this.modelValue; schema = setValueByPath(schema, name, 'value', value); schema = setValuesAlongPath(schema, name, { pristine: false, dirty: true }); if (this.shouldValidate(name, 'input')) { schema = validate(schema); } this.$emit('update:modelValue', schema); } }, onSubmit (event: InputElementEvent) { event.preventDefault(); if (this.modelValue) { let schema = clone(this.modelValue); schema = validate(schema); this.$emit('update:modelValue', schema); if (schema.invalid) { return; } } this.$emit('submit', event); }, shouldValidate (path: string, eventName: string): boolean { const targetSchema = getValueByPath(this.modelValue, path); const events = targetSchema.validateOn ? [].concat(targetSchema.validateOn) : this.$inkline.options.validateOn; return events!.includes(eventName); } } });