// eslint-disable-next-line max-classes-per-file import { VNode, VNodeChildren, VNodeData } from 'vue/types/vnode'; import { Component as VueComponent, RenderContext, AsyncComponent } from 'vue/types/options'; import { JsonSchema } from './jsonschema'; export interface Dict extends Record {} export type Scalar = boolean | number | null | string; export type SchemaType = 'object' | 'array' | 'string' | 'number' | 'integer' | 'boolean' | 'null'; export type ParserKind = SchemaType | 'enum' | 'list' | 'textarea' | 'image' | 'file' | 'password'; export type ScalarKind = 'string' | 'password' | 'number' | 'integer' | 'null' | 'boolean' | 'hidden' | 'textarea' | 'image' | 'file' | 'radio' | 'checkbox'; export type ItemKind = 'enum' | 'list'; export type FieldKind = SchemaType | ScalarKind | ItemKind; export type ComponentsType = 'form' | 'message' | 'button' | 'helper' | FieldKind; export type Component = string | VueComponent | AsyncComponent; export interface Attributes { id: string; name?: string; type?: string; readonly?: boolean; required?: boolean; disabled?: boolean; 'aria-required'?: 'true'; [key: string]: any; } export interface AriaAttributes extends Attributes { readonly 'aria-labelledby'?: string; readonly 'aria-describedby'?: string; } export interface LabelAttributes { id?: string; for: string; [key: string]: any; } export interface HelperAttributes { id?: string; [key: string]: any; } export interface InputAttributes extends Attributes { type: string; value: string; } export interface StateAttributes extends InputAttributes { type: Type | 'radio'; checked: boolean; } export type RadioAttributes = StateAttributes<'radio'>; export type CheckboxAttributes = StateAttributes<'checkbox'>; export interface NumberAttributes extends InputAttributes { type: 'number' | 'radio'; min?: number; max?: number; step?: number; } export interface NullAttributes extends InputAttributes { type: 'hidden'; value: '\u0000'; } export interface StringAttributes extends InputAttributes { type: 'text' | 'date' | 'datetime-local' | 'email' | 'idn-email' | 'time' | 'url' | 'radio' | 'file'; minlength?: number; maxlength?: number; pattern?: string; accept?: string; } export enum MessageType { Info = 0, Success = 1, Warining = 2, Error = 3 } export interface Message { type?: MessageType; text: string; } interface GenericField { id: string; key: string; name?: string; isRoot: boolean; schema: JsonSchema; required: boolean; hasChildren: boolean; initialValue: TModel; value: TModel; readonly messages: Required[]; clear(): void; // clear field reset(): void; // reset initial field value addMessage(message: string, type?: MessageType): void; clearMessages(recursive?: boolean): void; } export interface Field< TKind extends FieldKind, TDescriptor extends IUIDescriptor = IUIDescriptor, TAttributes extends Attributes = Attributes, TModel = any > extends GenericField { kind: TKind; deep: number; parent?: Field; root: Field; attrs: TAttributes; descriptor: TDescriptor; readonly messages: Required[]; // Value setValue(value: TModel, emitChange?: boolean): void; commit(): void; // Rendering requestRender(): void; } export interface ScalarField< TKind extends ScalarKind = ScalarKind, TAttributes extends Attributes = Attributes, TModel extends Scalar | unknown = unknown > extends Field { hasChildren: false; } export interface BooleanField extends ScalarField<'boolean', CheckboxAttributes, boolean> { toggle: () => void; } export type CheckboxField = ScalarField<'checkbox', CheckboxAttributes, unknown>; export type NumberField = ScalarField<'number', NumberAttributes, number>; export type NullField = ScalarField<'null', NullAttributes, null>; export type StringField = ScalarField<'string', StringAttributes, string>; export type RadioField = ScalarField<'radio', RadioAttributes, string>; export type InputField = BooleanField | NumberField | NullField | StringField | RadioField; export type UnknowField = Field; export interface SetField< TKind extends FieldKind, TSetDescriptor extends ISetDescriptor, TModel, TChildField extends UnknowField, TAttributes extends Attributes = Attributes, > extends Field { hasChildren: true; fields: Dict; children: TChildField[]; /** * @param {string} path - The path of the requested field. * It's formated as JavaScript property access * notation (e.g., ".userProp.addressesProp[1].nameProp") */ getField: (path: string) => UnknowField | null; } export type UnknowSetField = SetField; export interface EnumField extends SetField<'enum', IEnumDescriptor, unknown, RadioField> { } export interface ArrayItemField extends Field { buttons: { moveUp: ActionButton; moveDown: ActionButton; delete: ActionButton; }; } export type ActionPushTrigger = () => void; export type ActionMoveTrigger = () => ArrayItemField | undefined; export type ActionDeleteTrigger = () => ArrayItemField | undefined; export interface ActionButton { disabled: boolean; trigger: T; } export interface ArrayField extends SetField<'array', IArrayDescriptor, any[], ArrayItemField> { uniqueItems: boolean; sortable: boolean; pushButton: ActionButton; minItems: number; // default value: Number.MAX_SAFE_INTEGER maxItems: number; // default value: 1 if the field is required, 0 otherwise /** * Add a new item value and return `true` if succeed, else return `false` */ addItemValue: (itemValue: any) => boolean; } export interface ListItemModel { value: string; selected: boolean; } export interface ListField extends Field<'enum', IListDescriptor, Attributes> { items: ListItemModel[]; hasChildren: false; } export interface ObjectFieldChild extends Field { property: string; } export interface ObjectField extends SetField<'object', IObjectDescriptor, Dict, ObjectFieldChild> { } export type ValidatorFunction = (field: T) => Promise; export interface ParserOptions< TModel, TField extends Field = UnknowField, TDescriptor extends DescriptorDefinition = DescriptorDefinition > { kind?: FieldKind; readonly key?: string; readonly schema: JsonSchema; readonly model?: TModel; readonly name?: string; readonly id?: string; readonly required?: boolean; readonly descriptor?: TDescriptor; components?: IComponents; readonly bracketedObjectInputName?: boolean; onChange?: (value: TModel, field: TField) => void; validator?: ValidatorFunction; requestRender?: (updatedFields: Field[]) => void; } export type UnknowParser = IParser; export interface IParser< TModel, TField extends Field = any, TDescriptor extends DescriptorDefinition = DescriptorDefinition > { readonly id: string; readonly isRoot: boolean; readonly options: ParserOptions; readonly parent?: UnknowParser; readonly root: UnknowParser; readonly initialValue: TModel | unknown; model: TModel; rawValue: TModel; readonly kind: string; readonly field: TField; readonly schema: JsonSchema; parse: () => void; reset: () => void; clear: () => void; isEmpty: (data?: TModel) => boolean; requestRender: (fields?: UnknowField[]) => void; } export interface ISetParser< TModel, TField extends SetField, TDescriptor extends DescriptorDefinition = DescriptorDefinition > extends IParser { } export interface DescriptorProperties { readonly labelAttrs: LabelAttributes; readonly helperAttrs: HelperAttributes; readonly components: IComponents; readonly definition: TDescriptor; } export interface IUIDescriptor< TDescriptor extends DescriptorDefinition = DescriptorDefinition > extends Required, DescriptorProperties { } export interface IScalarDescriptor extends DescriptorProperties, Required {} export interface IObjectDescriptor extends DescriptorProperties, Required { readonly childrenGroups: IObjectGroupItem[]; } export interface IObjectChildDescriptor extends IUIDescriptor {} export interface IObjectGroupItem { id: string; label?: string; children: ObjectFieldChild[]; } export interface IArrayChildDescriptor extends IUIDescriptor { buttons: ArrayItemButton[]; } export interface IArrayDescriptor extends DescriptorProperties, Required { readonly children: IArrayChildDescriptor[]; readonly pushButton: PushButtonDescriptor; } export type IEnumItemDescriptor = IUIDescriptor; export type ISetDescriptor = IEnumDescriptor | IArrayDescriptor | IObjectDescriptor; export interface IItemsUIDescriptor< T extends Field, S extends Field, D extends DescriptorDefinition = DescriptorDefinition > extends IUIDescriptor {} export interface IEnumDescriptor extends IItemsUIDescriptor { readonly children: IEnumItemDescriptor[]; } export interface IListDescriptor extends IItemsUIDescriptor { readonly options: ListFieldItemDescriptor[]; } export interface ListFieldItemDescriptor extends ListItemModel { label: string; } export type SetDescriptor = EnumDescriptor | ArrayDescriptor | ObjectDescriptor; export type DescriptorInstance = ScalarDescriptor | SetDescriptor | ListDescriptor; export interface DescriptorDefinition { kind?: TKind; label?: string; helper?: string; visible?: boolean; // by default true. If false, component will be ignored on rendering component?: Component; attrs?: { [attr: string]: string; }; props?: { [prop: string]: unknown; }; } /** * Describe scalar types like: string, password, number, integer, * boolean, null, hidden field, textarea element, image and file * inputs, radio and checkbox elements */ export interface ScalarDescriptor extends DescriptorDefinition { } /** * Use to describe grouped object properties */ export interface ObjectGroupDescriptor extends DescriptorDefinition { properties: string[]; } /** * Describe JSON Schema with type `object` */ export interface ObjectDescriptor extends DescriptorDefinition { layout?: Component; // default: 'fieldset' properties?: { [schemaProperty: string]: DescriptorInstance; }; order?: string[]; groups?: { [groupId: string]: ObjectGroupDescriptor; }; } /** * Describe JSON Schema with key `enum` */ export interface ItemsDescriptor extends DescriptorDefinition { items?: { [itemValue: string]: ScalarDescriptor; }; } /** * Describe HTML Radio Elements */ export interface EnumDescriptor extends ItemsDescriptor<'enum'> { layout?: Component; // default: 'fieldset' } /** * Describe HTML Select Element */ export interface ListDescriptor extends ItemsDescriptor<'list'> { } /** * Describe buttons for array schema */ export interface ButtonDescriptor extends Partial> { type: T; label: string; tooltip?: string; visible?: boolean; component?: Component; } export type PushButtonDescriptor = ButtonDescriptor<'push', ActionPushTrigger>; export type MoveUpButtonDescriptor = ButtonDescriptor<'moveUp', ActionPushTrigger>; export type MoveDownButtonDescriptor = ButtonDescriptor<'moveDown', ActionPushTrigger>; export type DeleteButtonDescriptor = ButtonDescriptor<'delete', ActionPushTrigger>; export type UnknownButtonDescriptor = ButtonDescriptor; export type ArrayItemButton = MoveUpButtonDescriptor | MoveDownButtonDescriptor | DeleteButtonDescriptor | UnknownButtonDescriptor; /** * Describe JSON Schema with type `array` */ export interface ArrayDescriptor extends DescriptorDefinition { layout?: Component; // default: 'fieldset' items?: DescriptorInstance[] | DescriptorInstance; pushButton: PushButtonDescriptor | null; buttons: ArrayItemButton[]; } /** * Custom Components API */ export interface IComponents { set(kind: ComponentsType, component: Component): void; get(kind: ComponentsType, fallbackComponent?: Component): Component; } export declare class Components implements IComponents { set(kind: ComponentsType, component: Component): void; get(kind: ComponentsType, fallbackComponent?: Component): Component; } export declare class NativeComponents extends Components {} /** * FormSchema API */ export interface CreateElement { (tag?: Component, children?: VNodeChildren): VNode; (tag?: Component, data?: VNodeData, children?: VNodeChildren): VNode; } export interface ElementProps> { field: T; } export interface SubmitEvent extends Event { field: UnknowField; } export interface ButtonElementProps extends ElementProps { button: UnknownButtonDescriptor; } export interface FunctionalComponentOptions { name?: string; functional: true; render?(this: undefined, createElement: CreateElement, context: RenderContext): VNode | VNode[]; } export type ArrayButtonComponent = FunctionalComponentOptions; export type MessageComponent = FunctionalComponentOptions>; export type ArrayComponent = FunctionalComponentOptions>; export type BooleanComponent = FunctionalComponentOptions>; export type InputComponent = FunctionalComponentOptions>; export type StateComponent = FunctionalComponentOptions>; export type FieldComponent = FunctionalComponentOptions>; export type FieldsetComponent = FunctionalComponentOptions>; export type HelperComponent = FunctionalComponentOptions>; export type ListComponent = FunctionalComponentOptions>; export type TextareaComponent = FunctionalComponentOptions>; export interface InputEvent extends Event { readonly target: any; }