kwikid-forms
Version:
KwikID's JSON Configuration based Forms Renderer and Builder
451 lines • 99.8 kB
JavaScript
import { __decorate } from "tslib";
import { animate, style, transition, trigger } from "@angular/animations";
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from "@angular/core";
import { FormControl, FormGroup } from "@angular/forms";
import { checkObjectKeyExists, getObjectDeepCopy, getObjectValueFromPath, logMethod, mergeObjects, setValueToObjectPath } from "kwikid-toolkit";
import _ from "lodash";
import { Converter } from "../../renderer/config-converter/config-converter";
import { EFormEditorType } from "./builder-form-editor.definitions";
import { findModifiedKeys, getFieldIndex, removeField } from "./builder-form-editor.helper";
import { FIELD_CONFIG, FIELD_PROPERTIES_CONFIG, FIELD_VALIDATORS_CONFIG, NOFIELD_CONFIG, OPTIONS, TABLE_COLUMNS } from "./builder.form-editor.constants";
import * as i0 from "@angular/core";
import * as i1 from "kwikui";
import * as i2 from "./builder.form-editor.service";
import * as i3 from "@angular/common";
import * as i4 from "@angular/forms";
export class KwikIDBuilderFormEditorComponent {
constructor(loaderService, kwikidBuilderFormEditorService) {
this.loaderService = loaderService;
this.kwikidBuilderFormEditorService = kwikidBuilderFormEditorService;
/**
* Components Inputs
*/
this.activeFormConfig = {};
/**
* Component Outputs (Event Emitters)
*/
this.onClickSaveActiveFormConfig = new EventEmitter();
/**
* Component Variables
*/
// Field Editor Variables
this.rows = [];
this.columns = TABLE_COLUMNS;
this.activeFieldConfigEditing = {};
this.showFieldConfigValidatorsConfigEditor = false;
this.activeFieldConfigValidatorsConfig = {};
this.showFieldConfigPropertiesConfigEditor = false;
this.activeFieldConfigPropertiesConfig = {};
this.showFieldConfigOptionsConfigEditor = false;
this.activeFieldConfigOptionsConfig = [];
// General Editor Variables
this.editorTypeOptions = [
{ key: "FIELDS", label: "fields" },
{ key: "NON_FIELDS", label: "other config" }
];
this.activeEditorType = EFormEditorType.FIELDS;
this.activeFormConfig_Fields = [];
this.activeFormConfigNoFields = {};
this.showConfigPreview = false;
// Forms
this.formGroup = new FormGroup({});
// Form Saved State
this.savedConfig = false;
// Dialog
this.dialogOpen = false;
this.dialogError = false;
this.memoizedGetOptions = _.memoize(this.getOptions);
}
markSaved() {
this.savedConfig = true;
}
markUnsaved() {
this.savedConfig = false;
}
showDialog() {
this.dialogOpen = true;
}
hideDialog() {
this.dialogOpen = false;
}
showDialogError() {
this.dialogError = true;
}
hideDialogError() {
this.dialogError = false;
}
/**
* Angular Lifecycle Methods
*/
ngOnChanges(changes) {
const verifyChange = (key) => {
return checkObjectKeyExists(changes, key) && !changes[key].firstChange;
};
if (verifyChange("activeFormConfig")) {
let formConfig = new Converter().convertFormConfig(changes.activeFormConfig.currentValue);
formConfig = new Converter().updateFormConfigProperties(formConfig);
this.activeFormConfig = formConfig;
this.initFormEditor(this.activeFormConfig);
}
}
initFormEditor(activeFormConfig) {
this.toggleLoader(true);
this.activeFormConfig_Fields = getObjectDeepCopy(activeFormConfig.fields);
this.activeFormConfigNoFields = getObjectDeepCopy(activeFormConfig);
delete this.activeFormConfigNoFields.fields;
this.rows = this.activeFormConfig_Fields.map((field) => {
var _a;
return {
key: field.key,
label: field.label,
type: field.type,
disabled: field.disabled,
validators: Object.assign(Object.assign({}, FIELD_VALIDATORS_CONFIG), field.validators),
properties: Object.assign(Object.assign({}, FIELD_PROPERTIES_CONFIG[field.type]), field.properties),
options: (_a = field === null || field === void 0 ? void 0 : field.options) !== null && _a !== void 0 ? _a : []
};
});
this.formGroup = this.kwikidBuilderFormEditorService.createNestedFormGroup(this.rows);
this.toggleLoader(false);
}
/**
* General Editor Common Methods
*/
handleOnClickChangeActiveEditor(editorType) {
this.activeEditorType = editorType;
}
handleOnClickSaveActiveFormConfig() {
this.convertToMinifiedJson();
this.markSaved();
this.onClickSaveActiveFormConfig.emit(getObjectDeepCopy(this.activeFormConfig));
}
/**
* Fields Editor Related Methods
*/
/**
* Methods to handle addition of new field
*/
handleOnClickAddField() {
this.markUnsaved();
this.toggleLoader(true);
const newIndex = this.rows.length;
const fieldConfig = getObjectDeepCopy(mergeObjects(FIELD_CONFIG.text, {
key: String(newIndex)
}));
this.rows[newIndex] = fieldConfig;
const formControl = new FormControl(fieldConfig);
this.formGroup.addControl(String(newIndex), formControl);
this.toggleLoader(false);
}
/**
* Methods to handle editing of field key-values
*/
handleOnClickEditValidators(e) {
const fieldConfig = this.formGroup.getRawValue()[e.index];
const fieldConfigValidators = fieldConfig.validators;
this.activeFieldConfigValidatorsConfig = mergeObjects(FIELD_VALIDATORS_CONFIG, fieldConfigValidators);
this.showFieldConfigValidatorsConfigEditor = true;
this.activeFieldConfigEditing = fieldConfig;
}
handleOnClickEditProperties(e) {
const fieldConfig = this.formGroup.getRawValue()[e.index];
const fieldConfigProperties = fieldConfig.properties;
this.activeFieldConfigPropertiesConfig = mergeObjects(FIELD_PROPERTIES_CONFIG[e.type], fieldConfigProperties);
this.showFieldConfigPropertiesConfigEditor = true;
this.activeFieldConfigEditing = fieldConfig;
}
handleOnClickEditOptions(e) {
const fieldConfig = this.formGroup.getRawValue()[e.index];
const fieldConfigOptions = fieldConfig.options;
this.activeFieldConfigOptionsConfig = mergeObjects([], fieldConfigOptions);
this.showFieldConfigOptionsConfigEditor = true;
this.activeFieldConfigEditing = fieldConfig;
}
/**
* Methods to handle change in input values for Fields Keys
*/
handleOnInput(e) {
this.markUnsaved();
const fieldConfig = this.formGroup.getRawValue()[e.index];
const finalPath = e.path !== "" ? `${e.path}.${e.key}` : e.key;
if (finalPath.includes("disabled")) {
e.value.new = Boolean(e.value.new);
}
let newFieldConfig = setValueToObjectPath(getObjectDeepCopy(fieldConfig), finalPath, e.value.new);
if (finalPath.includes("type")) {
this.toggleLoader(true);
newFieldConfig = setValueToObjectPath(newFieldConfig, "validators", FIELD_VALIDATORS_CONFIG);
newFieldConfig = setValueToObjectPath(newFieldConfig, "properties", FIELD_PROPERTIES_CONFIG[newFieldConfig.type]);
this.toggleLoader(false);
}
this.rows = this.rows.map((row) => {
if (row.key === fieldConfig.key) {
return getObjectDeepCopy(newFieldConfig);
}
return getObjectDeepCopy(row);
});
this.formGroup.controls[e.index].setValue(newFieldConfig, {
emitEvent: false
});
}
handleOnInputFieldConfigValidatorsConfig(e) {
this.markUnsaved();
try {
this.hideDialogError();
const validatorConfig = JSON.parse(e);
const rowIndex = getFieldIndex(this.rows, this.activeFieldConfigEditing.key);
if (rowIndex !== -1) {
this.rows[rowIndex].validators = validatorConfig;
}
this.activeFieldConfigEditing = mergeObjects(this.activeFieldConfigEditing, { validators: validatorConfig });
this.formGroup.controls[rowIndex].setValue(this.activeFieldConfigEditing, {
emitEvent: false
});
}
catch (err) {
this.showDialogError();
}
}
handleOnInputFieldConfigPropertiesConfig(e) {
this.markUnsaved();
try {
this.hideDialogError();
const propertiesConfig = JSON.parse(e);
const rowIndex = getFieldIndex(this.rows, this.activeFieldConfigEditing.key);
if (rowIndex !== -1) {
this.rows[rowIndex].properties = propertiesConfig;
}
this.activeFieldConfigEditing = mergeObjects(this.activeFieldConfigEditing, { properties: propertiesConfig });
this.formGroup.controls[rowIndex].setValue(this.activeFieldConfigEditing, {
emitEvent: false
});
}
catch (err) {
this.showDialogError();
}
}
handleOnInputFieldConfigOptionsConfig(e) {
this.markUnsaved();
try {
this.hideDialogError();
const optionsConfig = JSON.parse(e);
const rowIndex = getFieldIndex(this.rows, this.activeFieldConfigEditing.key);
if (rowIndex !== -1) {
this.rows[rowIndex].options = optionsConfig;
}
this.activeFieldConfigEditing = mergeObjects(this.activeFieldConfigEditing, { options: optionsConfig });
this.formGroup.controls[rowIndex].setValue(this.activeFieldConfigEditing, {
emitEvent: false
});
}
catch (err) {
this.showDialogError();
}
}
/**
* Methods to handle deletion of field
*/
handleOnClickDeleteField(e) {
this.markUnsaved();
this.rows = removeField(this.rows, e.key);
this.formGroup = this.kwikidBuilderFormEditorService.createNestedFormGroup(this.rows);
this.formGroup.updateValueAndValidity();
}
/**
* Non Fields Editor Related Methods
*/
handleOnClickSaveActiveFormConfigNoFields(e) {
this.activeFormConfigNoFields = JSON.parse(e);
}
/**
* Other Component Methods
*/
handleOnClickPreview() {
this.showDialog();
}
toggleLoader(loader) {
if (loader) {
this.loaderService.show({
fullscreen: true,
loaderText: "Please wait"
});
}
else {
this.loaderService.hide();
}
}
closeJSONPopup() {
this.hideDialog();
this.showFieldConfigValidatorsConfigEditor = false;
this.showFieldConfigPropertiesConfigEditor = false;
this.showFieldConfigOptionsConfigEditor = false;
}
/**
* Other Helper Methods
*/
copyToClipboard() {
this.kwikidBuilderFormEditorService.copyToClipboard(this.activeFormConfig);
}
convertToMinifiedJson() {
const fields = [];
for (const field of Object.values(getObjectDeepCopy(this.formGroup.getRawValue()))) {
fields.push(setValueToObjectPath(findModifiedKeys(FIELD_CONFIG[field.type], field, ""), "type", field.type));
}
const activeFormConfigNoFieldsMinified = findModifiedKeys(NOFIELD_CONFIG, getObjectDeepCopy(this.activeFormConfigNoFields), "");
this.activeFormConfig = mergeObjects({}, activeFormConfigNoFieldsMinified, {
fields
});
}
convertToCompleteJson() {
let formConfig = new Converter().convertFormConfig(getObjectDeepCopy(this.activeFormConfig));
formConfig = new Converter().updateFormConfigProperties(formConfig);
this.activeFormConfig = formConfig;
}
downloadJSON() {
this.kwikidBuilderFormEditorService.downloadJSON(this.activeFormConfig);
}
/**
* Misc Methods
*/
getOptions(index, value, key, path) {
if (path.includes("properties")) {
const fieldType = this.rows[index].type;
const finalPath = `${path}['${fieldType}'].${key}`;
return getObjectValueFromPath(OPTIONS, finalPath);
}
const finalPath = path !== "" ? `${path}.${key}` : key;
return getObjectValueFromPath(OPTIONS, finalPath);
}
isOptions(index, value, key, path) {
if (path.includes("properties")) {
const fieldType = this.rows[index].type;
const finalPath = `${path}['${fieldType}'].${key}`;
return Array.isArray(getObjectValueFromPath(OPTIONS, finalPath));
}
const finalPath = path !== "" ? `${path}.${key}` : key;
return Array.isArray(getObjectValueFromPath(OPTIONS, finalPath));
}
isBoolean(value) {
return typeof value === "boolean";
}
isString(value) {
return typeof value === "string";
}
isNumber(value) {
return typeof value === "number";
}
isObject(value) {
return typeof value === "object" && value !== null;
}
/**
* Angular Specific Methods
*/
trackByFn(index, item) {
const key = (item === null || item === void 0 ? void 0 : item.key) || "";
const value = (item === null || item === void 0 ? void 0 : item.value) || "";
if (typeof item === "string") {
return `${String(index)}_${item}_${new Date().getTime()}`;
}
return `${String(index)}_${key}_${value}_${new Date().getTime()}`;
}
}
/** @nocollapse */ KwikIDBuilderFormEditorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: KwikIDBuilderFormEditorComponent, deps: [{ token: i1.KwikUILoaderService }, { token: i2.KwikIDFormBuilderFormEditorService }], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ KwikIDBuilderFormEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.17", type: KwikIDBuilderFormEditorComponent, selector: "kwikid-builder-form-editor", inputs: { activeFormConfig: "activeFormConfig" }, outputs: { onClickSaveActiveFormConfig: "onClickSaveActiveFormConfig" }, usesOnChanges: true, ngImport: i0, template: "<!-- Component Loader -->\n<kwikui-loader></kwikui-loader>\n\n<!-- Component Main View -->\n<div class=\"container\">\n <ng-container *ngIf=\"activeFormConfig; else noFormSelectedTemplate\">\n <header>\n <div>\n Editing Config of Form: <b>{{ activeFormConfig.props.title }}</b>\n </div>\n <div class=\"header-form-editor-btns\">\n <button (click)=\"handleOnClickPreview()\">preview</button>\n <div>Editor Type:</div>\n <select (change)=\"handleOnClickChangeActiveEditor($event.target.value)\">\n <option\n *ngFor=\"let option of editorTypeOptions\"\n [value]=\"option.key\"\n [selected]=\"option.key === activeEditorType\"\n >\n {{ option.label }}\n </option>\n </select>\n </div>\n </header>\n <main>\n <div\n class=\"form-config-fields\"\n *ngIf=\"activeEditorType == 'FIELDS'; else nonFieldsEditorTemplate\"\n >\n <ng-container *ngIf=\"rows.length <= 0\">\n <div class=\"no-fields disclaimer\">\n <div><p>Please add field to get started</p></div>\n <div class=\"icon\"><h1>+</h1></div>\n <button (click)=\"handleOnClickAddField()\">add field</button>\n </div>\n </ng-container>\n <table>\n <thead>\n <tr>\n <th *ngFor=\"let column of columns\">\n {{ column }}\n </th>\n </tr>\n </thead>\n <tbody>\n <ng-container\n *ngFor=\"let row of rows; let i = index; trackBy: trackByFn\"\n >\n <tr>\n <ng-container *ngFor=\"let column of columns; let j = index\">\n <td>\n <div [class]=\"column\">\n <ng-container\n *ngIf=\"\n column !== 'delete' &&\n column !== 'validators' &&\n column !== 'properties' &&\n column !== 'type' &&\n column !== 'disabled' &&\n column !== 'options'\n \"\n [ngTemplateOutlet]=\"getFieldTemplate\"\n [ngTemplateOutletContext]=\"{\n index: i,\n fieldValue: row[column],\n fieldKey: column,\n parentPath: ''\n }\"\n ></ng-container>\n <ng-container *ngIf=\"column === 'type'\">\n <ng-container\n [ngTemplateOutlet]=\"optionFieldTemplate\"\n [ngTemplateOutletContext]=\"{\n index: i,\n key: column,\n value: row[column],\n path: '',\n options: memoizedGetOptions(\n i,\n row[column],\n column,\n ''\n )\n }\"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"column === 'disabled'\">\n <ng-container\n [ngTemplateOutlet]=\"booleanFieldTemplate\"\n [ngTemplateOutletContext]=\"{\n index: i,\n key: column,\n value: row[column],\n path: '',\n options: memoizedGetOptions(\n i,\n row[column],\n column,\n ''\n )\n }\"\n ></ng-container>\n </ng-container>\n <ng-container *ngIf=\"column === 'delete'\">\n <button\n (click)=\"\n handleOnClickDeleteField({\n index: i,\n key: row['key']\n })\n \"\n [disabled]=\"rows.length === 1\"\n >\n delete\n </button>\n </ng-container>\n <ng-container *ngIf=\"column === 'validators'\">\n <button\n (click)=\"\n handleOnClickEditValidators({\n index: i,\n key: row['key'],\n type: row['type']\n })\n \"\n >\n edit\n </button>\n </ng-container>\n <ng-container *ngIf=\"column === 'properties'\">\n <button\n (click)=\"\n handleOnClickEditProperties({\n index: i,\n key: row['key'],\n type: row['type']\n })\n \"\n >\n edit\n </button>\n </ng-container>\n <ng-container\n *ngIf=\"row['type'] === 'radio' && column === 'options'\"\n >\n <button\n (click)=\"\n handleOnClickEditOptions({\n index: i,\n key: row['key'],\n type: row['type']\n })\n \"\n >\n add\n </button>\n </ng-container>\n <ng-container\n *ngIf=\"row['type'] === 'select' && column === 'options'\"\n >\n <button\n (click)=\"\n handleOnClickEditOptions({\n index: i,\n key: row['key'],\n type: row['type']\n })\n \"\n >\n add\n </button>\n </ng-container>\n </div>\n </td>\n </ng-container>\n </tr>\n </ng-container>\n </tbody>\n </table>\n <div class=\"add-field-btn-container\"> </div>\n </div>\n <ng-template #nonFieldsEditorTemplate>\n <div class=\"form-config-no-fields\">\n <div\n class=\"json-editor\"\n contenteditable=\"true\"\n (keyup)=\"\n handleOnClickSaveActiveFormConfigNoFields($event.target.innerHTML)\n \"\n >\n {{ activeFormConfigNoFields | json }}\n </div>\n </div>\n </ng-template>\n </main>\n <footer>\n <button\n *ngIf=\"rows.length > 0\"\n (click)=\"handleOnClickAddField()\"\n >\n add field\n </button>\n <button\n (click)=\"handleOnClickSaveActiveFormConfig()\"\n [class.secondary]=\"!savedConfig\"\n >\n {{ savedConfig ? \"saved\" : \"unsaved\" }}\n </button>\n </footer>\n </ng-container>\n <ng-template #noFormSelectedTemplate>\n <div class=\"no-form-selected disclaimer\">\n <div class=\"icon\"><h1>➦</h1></div>\n <div><p>Please select a form to edit it's fields</p></div>\n </div>\n </ng-template>\n</div>\n\n<!-- Component Dialog -->\n<div\n class=\"modal\"\n [class.error]=\"dialogError === true\"\n *ngIf=\"\n dialogOpen ||\n showFieldConfigValidatorsConfigEditor ||\n showFieldConfigPropertiesConfigEditor ||\n showFieldConfigOptionsConfigEditor\n \"\n [@panelInOut]\n>\n <div class=\"modal-box\">\n <div\n class=\"modal-content\"\n *ngIf=\"dialogOpen\"\n >\n <div class=\"modal-heading\">\n <div class=\"modal-title\">\n {{ activeFormConfig.props.title }}'s Config Preview\n </div>\n <div class=\"modal-actions\">\n <button (click)=\"convertToMinifiedJson()\">minify</button>\n <button (click)=\"convertToCompleteJson()\">full</button>\n <button (click)=\"downloadJSON()\">download</button>\n <button (click)=\"copyToClipboard()\">copy</button>\n <button (click)=\"closeJSONPopup()\">close</button>\n </div>\n </div>\n <div class=\"modal-body\">\n <div class=\"json-editor\">\n <code>{{ activeFormConfig | json }}</code>\n </div>\n </div>\n </div>\n <div\n class=\"modal-content\"\n *ngIf=\"showFieldConfigValidatorsConfigEditor\"\n >\n <div class=\"modal-heading\">\n <div class=\"modal-title\">\n {{ activeFormConfig.props.title }}'s Validator Config Editor\n </div>\n <div class=\"modal-actions\">\n <button (click)=\"closeJSONPopup()\">close</button>\n </div>\n </div>\n <div class=\"modal-body\">\n <div\n class=\"json-editor\"\n contenteditable=\"true\"\n (keyup)=\"\n handleOnInputFieldConfigValidatorsConfig($event.target.innerHTML)\n \"\n >\n {{ this.activeFieldConfigValidatorsConfig | json }}\n </div>\n </div>\n </div>\n <div\n class=\"modal-content\"\n *ngIf=\"showFieldConfigPropertiesConfigEditor\"\n >\n <div class=\"modal-heading\">\n <div class=\"modal-title\">\n {{ activeFormConfig.props.title }}'s Properties Config Editor\n </div>\n <div class=\"modal-actions\">\n <button (click)=\"closeJSONPopup()\">close</button>\n </div>\n </div>\n <div class=\"modal-body\">\n <div\n class=\"json-editor\"\n contenteditable=\"true\"\n (keyup)=\"\n handleOnInputFieldConfigPropertiesConfig($event.target.innerHTML)\n \"\n >\n {{ this.activeFieldConfigPropertiesConfig | json }}\n </div>\n </div>\n </div>\n <div\n class=\"modal-content\"\n *ngIf=\"showFieldConfigOptionsConfigEditor\"\n >\n <div class=\"modal-heading\">\n <div class=\"modal-title\">\n {{ activeFormConfig.props.title }}'s Options Config Editor\n </div>\n <div class=\"modal-actions\">\n <button (click)=\"closeJSONPopup()\">close</button>\n </div>\n </div>\n <div class=\"modal-body\">\n <div\n class=\"json-editor\"\n contenteditable=\"true\"\n (keyup)=\"\n handleOnInputFieldConfigOptionsConfig($event.target.innerHTML)\n \"\n >\n {{ this.activeFieldConfigOptionsConfig | json }}\n </div>\n </div>\n </div>\n </div>\n</div>\n<!-- END -->\n\n<!-- Template for rendering different field types -->\n<!-- General Field Template -->\n<ng-template\n #getFieldTemplate\n let-index=\"index\"\n let-value=\"fieldValue\"\n let-key=\"fieldKey\"\n let-path=\"parentPath\"\n>\n <div>\n <ng-container\n [ngTemplateOutlet]=\"\n isObject(value) ? objectFieldTemplate : notObjectFieldTemplate\n \"\n [ngTemplateOutletContext]=\"{\n index: index,\n fieldValue: value,\n fieldKey: key,\n parentPath: path\n }\"\n >\n </ng-container>\n </div>\n</ng-template>\n\n<!-- Object Type Field Template -->\n<ng-template\n #objectFieldTemplate\n let-index=\"index\"\n let-value=\"fieldValue\"\n let-key=\"fieldKey\"\n let-path=\"parentPath\"\n>\n <ng-container *ngFor=\"let item of value | keyvalue\">\n <ng-container\n [ngTemplateOutlet]=\"getFieldTemplate\"\n [ngTemplateOutletContext]=\"{\n index: index,\n fieldValue: item.value,\n fieldKey: item.key,\n parentPath: path === '' ? key : path + '.' + key\n }\"\n >\n </ng-container>\n </ng-container>\n</ng-template>\n\n<!-- Non Object Type Field Template -->\n<ng-template\n #notObjectFieldTemplate\n let-index=\"index\"\n let-value=\"fieldValue\"\n let-key=\"fieldKey\"\n let-path=\"parentPath\"\n>\n <div>\n <ng-container *ngIf=\"isOptions(index, value, key, path)\">\n <ng-container\n [ngTemplateOutlet]=\"optionFieldTemplate\"\n [ngTemplateOutletContext]=\"{\n index: index,\n key: key,\n value: value,\n path: path,\n options: memoizedGetOptions(index, value, key, path)\n }\"\n ></ng-container>\n </ng-container>\n <ng-container\n *ngIf=\"!isOptions(index, value, key, path) && isString(value)\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n textFieldTemplate;\n context: { index: index, key: key, value: value, path: path }\n \"\n ></ng-container>\n </ng-container>\n <ng-container\n *ngIf=\"!isOptions(index, value, key, path) && isNumber(value)\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n numberFieldTemplate;\n context: { index: index, key: key, value: value, path: path }\n \"\n ></ng-container>\n </ng-container>\n </div>\n</ng-template>\n\n<!-- Non Object Type Field :: Options Field Template -->\n<ng-template\n #optionFieldTemplate\n let-index=\"index\"\n let-key=\"key\"\n let-value=\"value\"\n let-path=\"path\"\n let-options=\"options\"\n>\n <div class=\"field-container options\">\n <select\n (change)=\"\n handleOnInput({\n index,\n key,\n value: { previous: value, new: $event.target.value },\n path\n })\n \"\n >\n <option\n *ngFor=\"let option of options\"\n [value]=\"option\"\n [selected]=\"option === value\"\n >{{ option }}</option\n >\n </select>\n </div>\n</ng-template>\n\n<!-- Non Object Type Field :: Boolean Field Template -->\n<ng-template\n #booleanFieldTemplate\n let-index=\"index\"\n let-key=\"key\"\n let-value=\"value\"\n let-path=\"path\"\n>\n <div class=\"field-container checkbox\">\n <input\n type=\"checkbox\"\n [checked]=\"value\"\n (change)=\"\n handleOnInput({\n index,\n key,\n value: { previous: value, new: $event.target.checked },\n path\n })\n \"\n />\n </div>\n</ng-template>\n\n<!-- Non Object Type Field :: Text Field Template -->\n<ng-template\n #textFieldTemplate\n let-index=\"index\"\n let-key=\"key\"\n let-value=\"value\"\n let-path=\"path\"\n>\n <div class=\"field-container text\">\n <input\n placeholder=\"Enter {{ key }}\"\n type=\"text\"\n [value]=\"value\"\n (blur)=\"\n handleOnInput({\n index,\n key,\n value: { previous: value, new: $event.target.value },\n path\n })\n \"\n />\n </div>\n</ng-template>\n\n<!-- Non Object Type Field :: Number Field Template -->\n<ng-template\n #numberFieldTemplate\n let-index=\"index\"\n let-key=\"key\"\n let-value=\"value\"\n let-path=\"path\"\n>\n <div class=\"field-container number\">\n <input\n placeholder=\"Enter {{ key }}\"\n type=\"number\"\n [value]=\"value\"\n (blur)=\"\n handleOnInput({\n index,\n key,\n value: { previous: value, new: $event.target.value },\n path\n })\n \"\n />\n </div>\n</ng-template>\n<!-- END -->\n", styles: ["::-webkit-scrollbar{width:8px}::-webkit-scrollbar-track{border-radius:10px}::-webkit-scrollbar-thumb{background:lightgray;border-radius:10px}::-webkit-scrollbar-thumb:hover{background:gray}input[type=text],input[type=number]{width:100%;padding:8px 12px;border:1px solid #ccc;border-radius:4px;box-sizing:border-box;appearance:auto!important}input[type=checkbox]{appearance:auto!important;width:1rem;height:1rem}select{width:100%;padding:8px 12px;border:1px solid #ccc;border-radius:4px;box-sizing:border-box}textarea{overflow-wrap:anywhere;resize:none;unicode-bidi:embed;white-space:pre-wrap}button{display:inline-block;padding:8px 12px;background-color:#007bff;color:#fff;text-decoration:none;border-radius:4px;border:none;cursor:pointer}button:hover{background-color:#0069d9}button:active{background-color:#0056b3}button:focus{outline:none}button.secondary{padding:7px 11px;border:1px solid #007bff;background-color:#fff;color:#007bff}button.secondary:hover{background-color:#b7daff}button.secondary:active{background-color:#b7daff}button.secondary:focus{outline:none}.field-container{display:flex}.field-container label{color:gray}.field-container.checkbox{flex-direction:row;align-items:center;justify-content:center;padding:8px 12px;margin:auto}.field-container.options,.field-container.number,.field-container.text{flex-direction:column}.disclaimer{display:flex;flex-direction:column;align-content:center;justify-content:center;align-items:center;color:#121212;width:100%;height:100%}.disclaimer>*:not(:last-child){margin-bottom:1.5rem}.disclaimer .icon{width:3rem;height:3rem;display:flex;flex-direction:row;align-content:center;justify-content:center;align-items:center}.disclaimer.no-form-selected h1{transform:scaleX(-1)}.disclaimer h1{font-size:5rem;font-weight:100}.disclaimer p{font-size:1rem}\n", ":host{all:unset;position:relative;width:100%;height:100%;overflow:auto}.container{display:flex;flex-direction:column;justify-content:space-between;align-items:stretch;height:100%;border:1px solid #ccc}.container header{padding:.5rem;display:flex;flex-direction:row;align-content:center;justify-content:space-between;align-items:center;border-bottom:1px solid #ccc}.container header .header-form-editor-btns{display:flex;flex-direction:row;align-content:center;justify-content:space-between;align-items:center}.container header .header-form-editor-btns>*:not(:last-child){margin-right:1rem}.container main{padding:.5rem;flex-grow:1;overflow:auto;display:flex;flex-direction:row;justify-content:flex-start;align-items:stretch;white-space:nowrap;position:relative}.container main>*:not(:last-child){margin-right:1rem}.container main .no-fields{position:absolute;top:0;left:0;background:white}.container main .form-config-no-fields{overflow:auto;width:100%}.container main .form-config-fields{overflow:auto;width:100%}.container main .form-config-fields .add-field-btn-container{width:100%;text-align:center}.container main .validators,.container main .properties{display:flex;flex-direction:column;justify-content:flex-start;align-items:stretch}.container main .validators>*:not(:last-child),.container main .properties>*:not(:last-child){margin-bottom:.5rem}.container main .input-checkbox-container{display:flex;flex-direction:row}.container footer{padding:.5rem;display:flex;flex-direction:row;justify-content:flex-end;align-items:stretch;border-top:1px solid lightgray}.container footer>*:not(:last-child){margin-right:1rem}.modal{position:absolute;top:0;background-color:#0000004d;width:100%;height:100%;display:flex;justify-content:center;align-items:center;left:0;flex-direction:row}.modal.error{background-color:#ff00004d}.modal-box{width:75%;height:75%;margin:auto;background-color:#fff;border-radius:1rem;box-shadow:#64646f33 0 7px 29px}.modal-content{display:flex;flex-direction:column;align-content:center;justify-content:flex-start;align-items:stretch;width:100%;height:100%}.modal-heading{padding:.5rem 1rem;width:100%;display:flex;flex-direction:row;justify-content:space-between;border-bottom:1px solid lightgray;align-items:center}.modal-title{font-weight:bold;font-size:1rem}.modal-actions{display:flex;flex-direction:row;cursor:pointer}.modal-actions>*:not(:last-child){margin-right:1rem}.modal-body{overflow:auto;flex:1}.modal-body .json-editor{font-family:monospace;white-space:pre-wrap;border:none;padding:0;background-color:#f5f5f5;height:100%;outline:none;overflow:auto}.json-editor{font-family:monospace;white-space:pre-wrap;border:none;padding:0;background-color:#f5f5f5;height:100%;outline:none;overflow:auto}table{width:100%;border-collapse:collapse;margin-bottom:20px}table th,table td{padding:8px;text-align:left;border:1px solid #ccc;vertical-align:top}table th{background-color:#f2f2f2}table tr:nth-child(even){background-color:#f9f9f9}table tr:hover{background-color:#eaeaea}\n"], components: [{ type: i1.KwikUILoaderComponent, selector: "kwikui-loader" }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i4.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { type: i4.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "json": i3.JsonPipe, "keyvalue": i3.KeyValuePipe }, animations: [
trigger("panelInOut", [
transition(":enter", [
style({ transform: "translateY(100%)" }),
animate(150)
]),
transition(":leave", [
animate(100, style({ transform: "translateY(100%)" }))
])
])
], changeDetection: i0.ChangeDetectionStrategy.OnPush });
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "ngOnChanges", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "initFormEditor", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "handleOnClickChangeActiveEditor", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "handleOnClickSaveActiveFormConfig", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "handleOnClickAddField", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "handleOnClickEditValidators", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "handleOnClickEditProperties", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "handleOnClickEditOptions", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "handleOnInput", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "handleOnInputFieldConfigValidatorsConfig", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "handleOnInputFieldConfigPropertiesConfig", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "handleOnInputFieldConfigOptionsConfig", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "handleOnClickDeleteField", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "handleOnClickSaveActiveFormConfigNoFields", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "handleOnClickPreview", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "toggleLoader", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "closeJSONPopup", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "copyToClipboard", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "convertToMinifiedJson", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "convertToCompleteJson", null);
__decorate([
logMethod
], KwikIDBuilderFormEditorComponent.prototype, "downloadJSON", null);
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: KwikIDBuilderFormEditorComponent, decorators: [{
type: Component,
args: [{
selector: "kwikid-builder-form-editor",
templateUrl: "./builder-form-editor.component.html",
styleUrls: ["../shared.scss", "./builder-form-editor.component.scss"],
changeDetection: ChangeDetectionStrategy.OnPush,
animations: [
trigger("panelInOut", [
transition(":enter", [
style({ transform: "translateY(100%)" }),
animate(150)
]),
transition(":leave", [
animate(100, style({ transform: "translateY(100%)" }))
])
])
]
}]
}], ctorParameters: function () { return [{ type: i1.KwikUILoaderService }, { type: i2.KwikIDFormBuilderFormEditorService }]; }, propDecorators: { activeFormConfig: [{
type: Input
}], onClickSaveActiveFormConfig: [{
type: Output
}], ngOnChanges: [], initFormEditor: [], handleOnClickChangeActiveEditor: [], handleOnClickSaveActiveFormConfig: [], handleOnClickAddField: [], handleOnClickEditValidators: [], handleOnClickEditProperties: [], handleOnClickEditOptions: [], handleOnInput: [], handleOnInputFieldConfigValidatorsConfig: [], handleOnInputFieldConfigPropertiesConfig: [], handleOnInputFieldConfigOptionsConfig: [], handleOnClickDeleteField: [], handleOnClickSaveActiveFormConfigNoFields: [], handleOnClickPreview: [], toggleLoader: [], closeJSONPopup: [], copyToClipboard: [], convertToMinifiedJson: [], convertToCompleteJson: [], downloadJSON: [] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGRlci1mb3JtLWVkaXRvci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9rd2lraWQtZm9ybXMvc3JjL2xpYi9idWlsZGVyL2J1aWxkZXItZm9ybS1lZGl0b3IvYnVpbGRlci1mb3JtLWVkaXRvci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9rd2lraWQtZm9ybXMvc3JjL2xpYi9idWlsZGVyL2J1aWxkZXItZm9ybS1lZGl0b3IvYnVpbGRlci1mb3JtLWVkaXRvci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzFFLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBRUwsTUFBTSxFQUVQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEQsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixpQkFBaUIsRUFDakIsc0JBQXNCLEVBQ3RCLFNBQVMsRUFDVCxZQUFZLEVBQ1osb0JBQW9CLEVBQ3JCLE1BQU0sZ0JBQWdCLENBQUM7QUFFeEIsT0FBTyxDQUFDLE1BQU0sUUFBUSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrREFBa0QsQ0FBQztBQUM3RSxPQUFPLEVBQ0wsZUFBZSxFQUVoQixNQUFNLG1DQUFtQyxDQUFDO0FBQzNDLE9BQU8sRUFDTCxnQkFBZ0IsRUFDaEIsYUFBYSxFQUNiLFdBQVcsRUFDWixNQUFNLDhCQUE4QixDQUFDO0FBQ3RDLE9BQU8sRUFDTCxZQUFZLEVBQ1osdUJBQXVCLEVBQ3ZCLHVCQUF1QixFQUN2QixjQUFjLEVBQ2QsT0FBTyxFQUNQ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