Files
mixtape/zero.Backoffice.UI/app/editor/editor-field.ts
T

200 lines
4.7 KiB
TypeScript
Raw Normal View History

import { Component } from "vue";
import { ZeroEditorField } from "zero/schemas";
2021-12-21 13:58:48 +01:00
import { extendObject } from '../utils/objects';
2021-12-21 00:53:17 +01:00
export declare type BooleanExpression = (model: any, value: any) => boolean;
export const createFieldProxy = (field: ZeroEditorFieldImpl) => new Proxy(field, {
get: function (target: ZeroEditorFieldImpl, prop: string | symbol, receiver: any): any
{
// handle internals
if (prop in target)
{
// @ts-ignore
return target[prop];
2021-12-21 00:53:17 +01:00
}
// handle dynamic fields + extensions
return (args: any) =>
2021-12-21 00:53:17 +01:00
{
target.fieldType = prop;
target.options = args;
2021-12-21 00:53:17 +01:00
return target;
};
}
})// as EditorField;
2021-12-21 13:58:48 +01:00
// @ts-ignore
2021-12-21 00:53:17 +01:00
export class ZeroEditorFieldImpl implements ZeroEditorField
{
path: string;
configuration: ZeroEditorFieldConfiguration;
fieldType: string | symbol;
2021-12-21 00:53:17 +01:00
options?: any;
customComponent?: Component;
2021-12-21 00:53:17 +01:00
constructor(path: string, config?: ZeroEditorFieldConfiguration)
{
this.path = path;
2021-12-21 13:58:48 +01:00
this.configuration = extendObject(createDefaultFieldConfiguration(), config || {}) as ZeroEditorFieldConfiguration;
2021-12-21 00:53:17 +01:00
}
/**
* Set this field as optional
* @param {function|boolean} [condition] - Optionally only require this field when a condition is fulfilled or reset the required state with true/false
*/
setOptional(condition: Function | boolean): ZeroEditorField
{
this.configuration.optional = condition;
return this;
}
/**
* Whether the input next to the headline or below
* @param {boolean} isHorizontal
* @returns {EditorField}
*/
setHorizontal(isHorizontal: boolean): ZeroEditorField
{
this.configuration.horizontal = !isHorizontal;
return this;
}
/**
* Set this field to disabled
*/
setReadonly(condition: Function | boolean): ZeroEditorField
{
this.configuration.readonly = condition;
return this;
}
/**
* Conditionally hide this field
* @param {function} condition - function which returns a boolean and gets passed the current model
*/
setHidden(condition: Function | boolean): ZeroEditorField
{
this.configuration.hidden = condition;
return this;
}
/**
* Set a custom component for a field
* @param {Component} component - The component to render (can be an async component too)
* @param {T} [options] = Custom options to pass to this editor
*/
component(component: Component, options?: any): ZeroEditorField
2021-12-21 00:53:17 +01:00
{
this.customComponent = component;
2021-12-21 00:53:17 +01:00
this.options = options;
return this;
}
2022-01-10 16:13:59 +01:00
/**
* The expression argument is called when the value of the field changes
* @param {function} callback - function which is called
*/
onChange(callback: Function): ZeroEditorField
{
this.configuration.changeHandlers.push(callback);
return this;
}
2021-12-21 00:53:17 +01:00
}
export function createDefaultFieldConfiguration(): ZeroEditorFieldConfiguration
{
return {
optional: false,
readonly: false,
hidden: false,
label: null,
hideLabel: false,
description: null,
helpText: null,
classes: null,
2021-12-21 13:58:48 +01:00
horizontal: false,
2021-12-30 17:09:25 +01:00
sort: 0,
2022-01-10 16:13:59 +01:00
preview: undefined,
changeHandlers: []
2021-12-21 00:53:17 +01:00
} as ZeroEditorFieldConfiguration;
}
export interface ZeroEditorFieldConfiguration
{
/**
* Whether this field is optional or required (additional validation is done on the server)
*/
optional?: Function | boolean;
/**
* Whether this field is readonly and can't be changed
*/
readonly?: Function | boolean;
/**
* Conditionally hide the field
*/
hidden?: Function | boolean;
/**
* A custom label for this field (otherwise it's generated via `onLabelCreate`)
**/
label?: string | null,
/**
* Hide the field label
**/
hideLabel?: boolean,
/**
* A custom description for this field (otherwise it's generated via `onDescriptionCreate`)
**/
description?: string | null,
/**
* Display a help text below the field
**/
helpText?: string | null,
/**
* Append HTML class to the generated property
**/
classes?: string | null,
/**
* Whether to render the label next to the input
**/
2021-12-21 13:58:48 +01:00
horizontal?: boolean,
/**
* Sort order for fields within the editor canvas
**/
2021-12-30 17:09:25 +01:00
sort?: number,
/**
* Sort order for fields within the editor canvas
**/
2022-01-10 16:13:59 +01:00
preview?: ZeroEditorFieldFilterPreview,
/**
* Handlers which get called on value change
**/
changeHandlers?: Array<Function>
2021-12-30 17:09:25 +01:00
}
export interface ZeroEditorFieldFilterPreview
{
/**
* Icon which is displayed next to the filter option
*/
icon?: string;
/**
* Checks whether the selected value for the filter option is valid and if it should be marked as selected
*/
selected?: (value: any, model: any) => boolean;
/**
* Renders the filter value which is previewed
*/
value?: (value: any, model: any) => string;
2021-12-21 00:53:17 +01:00
}