@ngx-dynamic-components/tools
Version:
@ngx-dynamic-components/tools is Angular 7+ library what contains a core interfaces to build a configuration driven web pages.
495 lines (486 loc) • 41.9 kB
JavaScript
import * as i0 from '@angular/core';
import { Component, Input, ViewChild, HostBinding, EventEmitter, Output, HostListener, NgModule } from '@angular/core';
import * as i1 from '@angular/common';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import * as i8 from 'angular-split';
import { AngularSplitModule } from 'angular-split';
import { MatToolbarModule } from '@angular/material/toolbar';
import * as i2$1 from '@angular/material/button';
import { MatButtonModule } from '@angular/material/button';
import * as i4 from '@angular/material/tabs';
import { MatTabsModule } from '@angular/material/tabs';
import { MatDividerModule } from '@angular/material/divider';
import * as i5 from '@angular/material/card';
import { MatCardModule } from '@angular/material/card';
import * as i3 from '@angular/material/icon';
import { MatIconModule } from '@angular/material/icon';
import * as i4$1 from '@angular/material/tooltip';
import { MatTooltipModule } from '@angular/material/tooltip';
import * as i5$1 from '@angular/material/input';
import { MatInputModule } from '@angular/material/input';
import * as i6 from '@angular/material/form-field';
import { MatFormFieldModule } from '@angular/material/form-field';
import * as i1$1 from '@angular/material/dialog';
import { MatDialogModule } from '@angular/material/dialog';
import * as i3$1 from '@angular/material/list';
import { MatListModule } from '@angular/material/list';
import * as i2 from '@ngx-dynamic-components/core';
import { getComponentById, formatObjToJsonStr, CoreService, DynamicComponentsCoreModule } from '@ngx-dynamic-components/core';
import { DynamicComponentsBootstrapModule } from '@ngx-dynamic-components/bootstrap';
import { debounceTime, map } from 'rxjs/operators';
import { fromEvent } from 'rxjs';
import { edit } from 'ace-builds';
import { jsPython } from 'jspython-interpreter';
// eslint-disable-next-line no-shadow
var Layout;
(function (Layout) {
Layout["horizontal"] = "horizontal";
Layout["vertical"] = "vertical";
})(Layout || (Layout = {}));
class PreviewEditorComponent {
scripts;
initUiModel;
initDataModel;
title;
uiModelEl;
uiModelJSONEl;
scriptsEl;
dataModelEl;
dynamicComponent;
flex = 'initial';
dataModel;
dataModelCopy;
uiModel;
uiModelEditor;
uiModelJSONEditor;
dataModelEditor;
scriptsEditor;
interpreter;
editorOptions = {
language: 'json',
automaticLayout: true,
};
direction = Layout.horizontal;
codeSize = 50;
async eventHandlers({ eventName, rootUIModel, parameters = null, sender, eventHandler }) {
if (!this.interpreter) {
return;
}
if (this.interpreter.hasFunction(this.scripts, eventHandler)) {
try {
if (parameters) {
parameters[parameters.argsKey] = parameters.argsValue;
}
const res = await this.interpreter.evaluate(this.scripts, {
rootUIModel,
dataModel: this.dataModel,
...parameters,
}, eventHandler);
sender?.setEventHandlerResult(eventName, res);
}
catch (e) {
alert(`${e.message}`);
}
}
}
ngOnInit() {
this.interpreter = jsPython();
this.interpreter.addFunction('getComponentById', (uiModel, id) => getComponentById(uiModel, id));
this.interpreter.addFunction('alert', (msg) => alert(msg));
this.interpreter.assignGlobalContext({});
this.uiModel = this.initUiModel;
this.dataModel = this.initDataModel;
}
ngAfterViewInit() {
this.onDataModelChange(this.dynamicComponent.dataModel);
this.initUIPreview();
}
toggleSourceCode() {
this.codeSize = !this.codeSize ? 50 : 0;
}
toggleLayout() {
this.direction =
this.direction === Layout.horizontal
? Layout.vertical
: Layout.horizontal;
}
get isHorizontal() {
return this.direction === Layout.horizontal;
}
onRendered(data) {
console.log('rendered', data);
}
onDataModelChange(data) {
if (data && this.dataModelEditor) {
this.dataModelEditor.setValue(formatObjToJsonStr(data));
}
else if (this.uiModelEditor) {
this.uiModelEditor.setValue(formatObjToJsonStr(this.uiModel));
}
}
resize() {
this.scriptsEditor.resize();
this.uiModelEditor.resize();
this.uiModelJSONEditor.resize();
this.dataModelEditor.resize();
}
initUIPreview() {
if (this.uiModelEl) {
this.uiModelJSONEditor = edit(this.uiModelJSONEl.nativeElement, {
mode: 'ace/mode/json',
autoScrollEditorIntoView: true,
tabSize: 2,
useSoftTabs: true,
readOnly: true,
});
this.setJSONEditor(this.initUiModel);
this.initEditor('uiModel', this.uiModelEl, this.initUiModel, 'ace/mode/xml').pipe(debounceTime(500)).subscribe((uiModel) => {
this.dynamicComponent.containerRef.clear();
this.setJSONEditor(uiModel);
this.refreshPreview(uiModel, this.dataModel);
});
this.initEditor('dataModel', this.dataModelEl, this.initDataModel).subscribe((dataModel) => this.refreshPreview(this.uiModel, dataModel ? JSON.parse(dataModel) : dataModel));
this.initEditor('scripts', this.scriptsEl, this.scripts, 'ace/mode/python').subscribe((sc) => (this.scripts = sc));
}
}
setJSONEditor(uiModel) {
const res = CoreService.parseXMLModel(uiModel);
this.uiModelJSONEditor.setValue(formatObjToJsonStr(res), -1);
this.uiModelJSONEditor.resize();
}
refreshPreview(uiModel, dataModel) {
this.uiModel = uiModel;
this.dataModelCopy = JSON.parse(JSON.stringify(dataModel));
}
// eslint-disable-next-line max-len
initEditor(name, element, value, mode = 'ace/mode/json') {
const editor = edit(element.nativeElement, {
mode,
autoScrollEditorIntoView: true,
value: formatObjToJsonStr(value),
tabSize: 2,
useSoftTabs: true,
indentedSoftWrap: true,
});
editor.setOptions({
enableBasicAutocompletion: true,
enableSnippets: false,
enableLiveAutocompletion: true,
});
this[`${name}Editor`] = editor;
return fromEvent(editor, 'change').pipe(map(() => editor.getValue()));
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: PreviewEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.6", type: PreviewEditorComponent, selector: "dc-preview-editor", inputs: { scripts: "scripts", initUiModel: "initUiModel", initDataModel: "initDataModel", title: "title" }, host: { properties: { "style.flex": "this.flex" } }, viewQueries: [{ propertyName: "uiModelEl", first: true, predicate: ["uiModelEl"], descendants: true }, { propertyName: "uiModelJSONEl", first: true, predicate: ["uiModelJSONEl"], descendants: true }, { propertyName: "scriptsEl", first: true, predicate: ["scriptsEl"], descendants: true }, { propertyName: "dataModelEl", first: true, predicate: ["dataModelEl"], descendants: true }, { propertyName: "dynamicComponent", first: true, predicate: ["dynamicComponent"], descendants: true }], ngImport: i0, template: "<mat-card *ngIf=\"initUiModel\" class=\"h-100 preview-card d-flex flex-column\">\r\n <mat-card-header>\r\n <span class=\"flex-fill align-self-center\">{{title}}</span>\r\n <button mat-icon-button *ngIf=\"codeSize\" (click)=\"toggleLayout()\"\r\n [matTooltip]=\"(isHorizontal ? 'Vertical' : 'Horizontal') + ' layout'\">\r\n <mat-icon>{{isHorizontal ? 'vertical_split' : 'horizontal_split'}}</mat-icon>\r\n </button>\r\n <button mat-icon-button matTooltip=\"Source code\" (click)=\"toggleSourceCode()\">\r\n <mat-icon>code</mat-icon>\r\n </button>\r\n </mat-card-header>\r\n <mat-card-content class=\"h-100\">\r\n <as-split [useTransition]=\"true\" [direction]=\"direction\" unit=\"percent\" [gutterSize]=\"codeSize ? 11 : 0\">\r\n <as-split-area #area0=\"asSplitArea\" class=\"d-flex\" [size]=\"codeSize\">\r\n <mat-tab-group class=\"w-100 ui-model-tab\">\r\n <mat-tab label=\"UI Model\">\r\n <mat-tab-group class=\"w-100 h-100\" headerPosition=\"below\">\r\n <mat-tab label=\"XML\">\r\n <div #uiModelEl class=\"h-100\"></div>\r\n </mat-tab>\r\n <mat-tab label=\"JSON\">\r\n <div #uiModelJSONEl class=\"h-100\"></div>\r\n </mat-tab>\r\n </mat-tab-group>\r\n </mat-tab>\r\n <mat-tab label=\"Scripts\">\r\n <div #scriptsEl class=\"h-100\"></div>\r\n </mat-tab>\r\n <mat-tab label=\"Data Model\">\r\n <div #dataModelEl class=\"h-100\"></div>\r\n </mat-tab>\r\n </mat-tab-group>\r\n </as-split-area>\r\n <as-split-area [size]=\"100 - codeSize\" #area1=\"asSplitArea\">\r\n <div class=\"preview\">\r\n <ngx-dynamic-component class=\"d-block\" *ngIf=\"uiModel\" #dynamicComponent\r\n [xmlUIModel]='uiModel'\r\n [dataModel]='dataModel'\r\n (render)='onRendered($event)'\r\n (changedDataModel)=\"onDataModelChange($event)\"\r\n (eventHandlers)=\"eventHandlers($event)\"></ngx-dynamic-component>\r\n </div>\r\n </as-split-area>\r\n </as-split>\r\n </mat-card-content>\r\n</mat-card>\r\n", styles: [":host{display:flex}::ng-deep mat-card .mat-card-header-text{margin:0}::ng-deep mat-card .mat-mdc-tab-body-wrapper,::ng-deep mat-card .mat-tab-body-wrapper{display:block;overflow:visible;height:100%;min-height:200px}::ng-deep mat-card .mat-mdc-tab-body-wrapper mat-tab-body,::ng-deep mat-card .mat-tab-body-wrapper mat-tab-body{height:100%}.preview-card mat-card-content ::ng-deep .as-init .as-split-gutter,.preview-card mat-card-content .as-split-area{height:auto}.ui-model-tab ::ng-deep .mat-tab-label{height:24px;font-size:.85rem}mat-card{width:100%;padding:0}mat-card mat-card-header,mat-card mat-card-content{padding:1em}mat-card mat-divider{margin:1em 0;position:static}mat-card mat-card-header{color:#00000080;background:#eeeeee;padding:8px 20px}mat-card mat-card-header mat-icon{cursor:pointer}mat-card mat-card-header h3{margin:0}mat-card .preview{background:#eeeeee;padding:1em}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.NGXDynamicComponent, selector: "ngx-dynamic-component", inputs: ["dataModel", "xmlUIModel"], outputs: ["render", "changedDataModel", "eventHandlers"] }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i4.MatTab, selector: "mat-tab", inputs: ["disabled"], exportAs: ["matTab"] }, { kind: "component", type: i4.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "disableRipple", "fitInkBarToContent", "mat-stretch-tabs"], exportAs: ["matTabGroup"] }, { kind: "component", type: i5.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i5.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i5.MatCardHeader, selector: "mat-card-header" }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: i8.SplitComponent, selector: "as-split", inputs: ["direction", "unit", "gutterSize", "gutterStep", "restrictMove", "useTransition", "disabled", "dir", "gutterDblClickDuration", "gutterClickDeltaPx", "gutterAriaLabel"], outputs: ["transitionEnd", "dragStart", "dragEnd", "gutterClick", "gutterDblClick"], exportAs: ["asSplit"] }, { kind: "directive", type: i8.SplitAreaDirective, selector: "as-split-area, [as-split-area]", inputs: ["order", "size", "minSize", "maxSize", "lockSize", "visible"], exportAs: ["asSplitArea"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: PreviewEditorComponent, decorators: [{
type: Component,
args: [{ selector: 'dc-preview-editor', template: "<mat-card *ngIf=\"initUiModel\" class=\"h-100 preview-card d-flex flex-column\">\r\n <mat-card-header>\r\n <span class=\"flex-fill align-self-center\">{{title}}</span>\r\n <button mat-icon-button *ngIf=\"codeSize\" (click)=\"toggleLayout()\"\r\n [matTooltip]=\"(isHorizontal ? 'Vertical' : 'Horizontal') + ' layout'\">\r\n <mat-icon>{{isHorizontal ? 'vertical_split' : 'horizontal_split'}}</mat-icon>\r\n </button>\r\n <button mat-icon-button matTooltip=\"Source code\" (click)=\"toggleSourceCode()\">\r\n <mat-icon>code</mat-icon>\r\n </button>\r\n </mat-card-header>\r\n <mat-card-content class=\"h-100\">\r\n <as-split [useTransition]=\"true\" [direction]=\"direction\" unit=\"percent\" [gutterSize]=\"codeSize ? 11 : 0\">\r\n <as-split-area #area0=\"asSplitArea\" class=\"d-flex\" [size]=\"codeSize\">\r\n <mat-tab-group class=\"w-100 ui-model-tab\">\r\n <mat-tab label=\"UI Model\">\r\n <mat-tab-group class=\"w-100 h-100\" headerPosition=\"below\">\r\n <mat-tab label=\"XML\">\r\n <div #uiModelEl class=\"h-100\"></div>\r\n </mat-tab>\r\n <mat-tab label=\"JSON\">\r\n <div #uiModelJSONEl class=\"h-100\"></div>\r\n </mat-tab>\r\n </mat-tab-group>\r\n </mat-tab>\r\n <mat-tab label=\"Scripts\">\r\n <div #scriptsEl class=\"h-100\"></div>\r\n </mat-tab>\r\n <mat-tab label=\"Data Model\">\r\n <div #dataModelEl class=\"h-100\"></div>\r\n </mat-tab>\r\n </mat-tab-group>\r\n </as-split-area>\r\n <as-split-area [size]=\"100 - codeSize\" #area1=\"asSplitArea\">\r\n <div class=\"preview\">\r\n <ngx-dynamic-component class=\"d-block\" *ngIf=\"uiModel\" #dynamicComponent\r\n [xmlUIModel]='uiModel'\r\n [dataModel]='dataModel'\r\n (render)='onRendered($event)'\r\n (changedDataModel)=\"onDataModelChange($event)\"\r\n (eventHandlers)=\"eventHandlers($event)\"></ngx-dynamic-component>\r\n </div>\r\n </as-split-area>\r\n </as-split>\r\n </mat-card-content>\r\n</mat-card>\r\n", styles: [":host{display:flex}::ng-deep mat-card .mat-card-header-text{margin:0}::ng-deep mat-card .mat-mdc-tab-body-wrapper,::ng-deep mat-card .mat-tab-body-wrapper{display:block;overflow:visible;height:100%;min-height:200px}::ng-deep mat-card .mat-mdc-tab-body-wrapper mat-tab-body,::ng-deep mat-card .mat-tab-body-wrapper mat-tab-body{height:100%}.preview-card mat-card-content ::ng-deep .as-init .as-split-gutter,.preview-card mat-card-content .as-split-area{height:auto}.ui-model-tab ::ng-deep .mat-tab-label{height:24px;font-size:.85rem}mat-card{width:100%;padding:0}mat-card mat-card-header,mat-card mat-card-content{padding:1em}mat-card mat-divider{margin:1em 0;position:static}mat-card mat-card-header{color:#00000080;background:#eeeeee;padding:8px 20px}mat-card mat-card-header mat-icon{cursor:pointer}mat-card mat-card-header h3{margin:0}mat-card .preview{background:#eeeeee;padding:1em}\n"] }]
}], propDecorators: { scripts: [{
type: Input
}], initUiModel: [{
type: Input
}], initDataModel: [{
type: Input
}], title: [{
type: Input
}], uiModelEl: [{
type: ViewChild,
args: ['uiModelEl']
}], uiModelJSONEl: [{
type: ViewChild,
args: ['uiModelJSONEl']
}], scriptsEl: [{
type: ViewChild,
args: ['scriptsEl']
}], dataModelEl: [{
type: ViewChild,
args: ['dataModelEl']
}], dynamicComponent: [{
type: ViewChild,
args: ['dynamicComponent']
}], flex: [{
type: HostBinding,
args: ['style.flex']
}] } });
class AddDialogComponent {
dialogRef;
categories = [];
constructor(dialogRef) {
this.dialogRef = dialogRef;
}
ngOnInit() {
this.categories = [];
}
selectComponent(item) {
this.dialogRef.close(item.defaultModel || item.example.uiModel || {
type: `${item.packageName}:${item.name}`,
itemProperties: {},
containerProperties: {}
});
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: AddDialogComponent, deps: [{ token: i1$1.MatDialogRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.6", type: AddDialogComponent, selector: "dc-add-dialog", ngImport: i0, template: `
<mat-list role="list" class="components" *ngFor="let cat of categories">
<h3 class="mat-h3">{{cat.name}}</h3>
<mat-list-item role="listitem"
(click)="selectComponent(item)" *ngFor="let item of cat.components">
{{item.name}} - {{item.description}}
</mat-list-item>
</mat-list>
`, isInline: true, styles: [":host{min-width:300px;display:block}mat-list h3{margin:0;text-decoration:underline}.components mat-list-item{height:auto;cursor:pointer}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: i3$1.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i3$1.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: AddDialogComponent, decorators: [{
type: Component,
args: [{ selector: 'dc-add-dialog', template: `
<mat-list role="list" class="components" *ngFor="let cat of categories">
<h3 class="mat-h3">{{cat.name}}</h3>
<mat-list-item role="listitem"
(click)="selectComponent(item)" *ngFor="let item of cat.components">
{{item.name}} - {{item.description}}
</mat-list-item>
</mat-list>
`, styles: [":host{min-width:300px;display:block}mat-list h3{margin:0;text-decoration:underline}.components mat-list-item{height:auto;cursor:pointer}\n"] }]
}], ctorParameters: function () { return [{ type: i1$1.MatDialogRef }]; } });
class PropertiesEditorComponent {
uiModel;
editorContainer;
editBtn;
updatedProperty = new EventEmitter();
itemProperties = [];
properties = [];
showEditor = false;
get positionClass() {
// eslint-disable-next-line no-underscore-dangle
const btnPos = this.editBtn._elementRef.nativeElement.getBoundingClientRect().right;
const docWidth = document.body.offsetWidth;
return docWidth - btnPos < 200 ? 'left' : '';
}
onClick(targetElement) {
if (this.editorContainer) {
const clickedInside = this.editorContainer.nativeElement.contains(targetElement);
// eslint-disable-next-line no-underscore-dangle
if (!clickedInside && this.editBtn._elementRef.nativeElement.contains(targetElement)) {
// Clicked on button.
const itemProps = this.uiModel.itemProperties || {};
this.properties = this.itemProperties.map(({ name }) => {
let value = itemProps[name];
if (value === undefined) {
value = '';
}
else if (typeof value === 'object') {
value = JSON.stringify(value);
}
return { name, value };
});
this.showEditor = true;
}
else if (!clickedInside) {
// Clicked outside.
this.showEditor = false;
this.updatedProperty.emit();
}
}
}
ngOnInit() {
this.itemProperties = CoreService.getComponentProperties(this.uiModel.type);
}
updateProperty(evt, prop) {
try {
// If property value is an object or an array.
this.uiModel.itemProperties[prop] = JSON.parse(evt.target.value);
}
catch {
this.uiModel.itemProperties[prop] = evt.target.value;
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: PropertiesEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.6", type: PropertiesEditorComponent, selector: "dc-properties-editor", inputs: { uiModel: "uiModel" }, outputs: { updatedProperty: "updatedProperty" }, host: { listeners: { "document:click": "onClick($event.target)" } }, viewQueries: [{ propertyName: "editorContainer", first: true, predicate: ["editorContainer"], descendants: true }, { propertyName: "editBtn", first: true, predicate: ["editBtn"], descendants: true }], ngImport: i0, template: `
<button mat-icon-button matTooltip="Edit properties" (click)="showEditor = true" #editBtn>
<mat-icon>edit</mat-icon>
</button>
<div class="editor-container" #editorContainer fxLayout="column" *ngIf="showEditor" [ngClass]="positionClass">
<mat-form-field *ngFor="let property of properties">
<input matInput [placeholder]="property.name" [value]="property.value" (input)="updateProperty($event, property.name)">
</mat-form-field>
</div>
`, isInline: true, styles: [".editor-container{position:absolute;background:white;top:0;left:40px;z-index:3;padding:10px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.editor-container.left{left:-200px}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "directive", type: i5$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: PropertiesEditorComponent, decorators: [{
type: Component,
args: [{ selector: 'dc-properties-editor', template: `
<button mat-icon-button matTooltip="Edit properties" (click)="showEditor = true" #editBtn>
<mat-icon>edit</mat-icon>
</button>
<div class="editor-container" #editorContainer fxLayout="column" *ngIf="showEditor" [ngClass]="positionClass">
<mat-form-field *ngFor="let property of properties">
<input matInput [placeholder]="property.name" [value]="property.value" (input)="updateProperty($event, property.name)">
</mat-form-field>
</div>
`, styles: [".editor-container{position:absolute;background:white;top:0;left:40px;z-index:3;padding:10px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.editor-container.left{left:-200px}\n"] }]
}], propDecorators: { uiModel: [{
type: Input
}], editorContainer: [{
type: ViewChild,
args: ['editorContainer']
}], editBtn: [{
type: ViewChild,
args: ['editBtn']
}], updatedProperty: [{
type: Output
}], onClick: [{
type: HostListener,
args: ['document:click', ['$event.target']]
}] } });
class ControlEditorComponent {
dialog;
uiModel;
uiModelChanged = new EventEmitter();
uiModelRemoved = new EventEmitter();
constructor(dialog) {
this.dialog = dialog;
}
openAddDialog() {
const dialogRef = this.dialog.open(AddDialogComponent);
dialogRef.afterClosed().subscribe(item => {
this.uiModel.children.push(item);
this.uiModelChanged.emit();
});
}
onHover(evt) {
const dragEl = this.getParentDrag(evt.target);
dragEl.classList.add('drag-selected');
}
onMouseLeave(evt) {
const dragEl = this.getParentDrag(evt.target);
dragEl.classList.remove('drag-selected');
}
getDragTooltip() {
return this.uiModel.type === 'material:flex-container' ? 'Drag container' : 'Drag component';
}
getParentDrag(el) {
let dragEl = el;
while (!['item', 'row', 'col-sm'].some(c => Array.from(dragEl.classList).includes(c))) {
dragEl = dragEl.parentNode;
}
return dragEl;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: ControlEditorComponent, deps: [{ token: i1$1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.6", type: ControlEditorComponent, selector: "dc-control-editor", inputs: { uiModel: "uiModel" }, outputs: { uiModelChanged: "uiModelChanged", uiModelRemoved: "uiModelRemoved" }, ngImport: i0, template: `
<dc-properties-editor [uiModel]="uiModel" (updatedProperty)="uiModelChanged.emit()"></dc-properties-editor>
<button mat-icon-button [matTooltip]="getDragTooltip()"
(mouseover)="onHover($event)" (focus)="onHover($event)" (mouseleave)="onMouseLeave($event)" class="handle">
<svg width="24px" fill="currentColor" viewBox="0 0 24 24">
<path d="M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z">
</path>
<path d="M0 0h24v24H0z" fill="none"></path>
</svg>
</button>
<button mat-icon-button class="add-component" matTooltip="Add component" (click)="openAddDialog()">
<mat-icon>add</mat-icon>
</button>
<button mat-icon-button matTooltip="Remove" (click)="uiModelRemoved.emit()">
<mat-icon>clear</mat-icon>
</button>
`, isInline: true, styles: ["::ng-deep .preview dc-container dc-container-row.row{min-height:100px;border:1px dashed rgba(0,0,0,0)}::ng-deep .preview dc-container dc-container-row.row.active{border-color:gray}::ng-deep .preview.edit-mode dc-container dc-container-row.row{border-color:#00000040}::ng-deep .preview.edit-mode dc-container dc-container-row.row>dc-control-editor{left:-50px}::ng-deep .preview.edit-mode dc-container dc-container-row.row>dc-control-editor .handle{display:none}::ng-deep .preview.edit-mode dc-container dc-container-row.row>dc-control-editor .add-component{display:inline-block}::ng-deep .preview.edit-mode dc-container dc-container-row.row .col-sm dc-ui-flex-container+dc-control-editor{left:60px}::ng-deep .preview dc-ui-flex-container .item,::ng-deep .preview dc-container .item,::ng-deep .preview dc-container dc-container-row.row,::ng-deep .preview dc-container dc-container-row.row>div[class*=col-]{position:relative;border:1px dashed rgba(0,0,0,0)}::ng-deep .preview dc-ui-flex-container .item:hover>dc-control-editor,::ng-deep .preview dc-container .item:hover>dc-control-editor,::ng-deep .preview dc-container dc-container-row.row:hover>dc-control-editor,::ng-deep .preview dc-container dc-container-row.row>div[class*=col-]:hover>dc-control-editor{display:block}::ng-deep .preview dc-ui-flex-container .item.drag-selected,::ng-deep .preview dc-container .item.drag-selected,::ng-deep .preview dc-container dc-container-row.row.drag-selected,::ng-deep .preview dc-container dc-container-row.row>div[class*=col-].drag-selected{border-color:gray}::ng-deep .preview dc-ui-flex-container .item.drag-selected dc-control-editor,::ng-deep .preview dc-container .item.drag-selected dc-control-editor,::ng-deep .preview dc-container dc-container-row.row.drag-selected dc-control-editor,::ng-deep .preview dc-container dc-container-row.row>div[class*=col-].drag-selected dc-control-editor{display:block!important}::ng-deep .preview dc-ui-flex-container .item dc-ui-flex-container+dc-control-editor>.handle,::ng-deep .preview dc-container .item dc-ui-flex-container+dc-control-editor>.handle,::ng-deep .preview dc-container dc-container-row.row dc-ui-flex-container+dc-control-editor>.handle,::ng-deep .preview dc-container dc-container-row.row>div[class*=col-] dc-ui-flex-container+dc-control-editor>.handle{color:#000000bf}::ng-deep .preview dc-ui-flex-container .item:hover dc-ui-flex-container+dc-control-editor>.handle,::ng-deep .preview dc-container .item:hover dc-ui-flex-container+dc-control-editor>.handle,::ng-deep .preview dc-container dc-container-row.row:hover dc-ui-flex-container+dc-control-editor>.handle,::ng-deep .preview dc-container dc-container-row.row>div[class*=col-]:hover dc-ui-flex-container+dc-control-editor>.handle{color:#000c}::ng-deep .preview dc-ui-flex-container .item dc-ui-flex-container+dc-control-editor,::ng-deep .preview dc-container .item dc-ui-flex-container+dc-control-editor,::ng-deep .preview dc-container dc-container-row.row dc-ui-flex-container+dc-control-editor,::ng-deep .preview dc-container dc-container-row.row>div[class*=col-] dc-ui-flex-container+dc-control-editor{left:-50px}::ng-deep .preview dc-container.container dc-container-row.row>dc-control-editor{left:-50px}::ng-deep .gu-mirror{position:fixed!important;margin:0!important;z-index:9999!important;opacity:.8;-ms-filter:\"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)\";filter:alpha(opacity=80);pointer-events:none;box-sizing:border-box;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f;background:#eeeeee}::ng-deep .gu-mirror>dc-control-editor{display:block!important}::ng-deep .gu-mirror>dc-ui-flex-container+dc-control-editor{left:-50px}::ng-deep .gu-hide{left:-9999px!important}::ng-deep .gu-unselectable{-webkit-user-select:none!important;-moz-user-select:none!important;user-select:none!important}::ng-deep .gu-transit{position:relative;transition:transform .25s cubic-bezier(0,0,.2,1)}::ng-deep .gu-transit:after{content:\" \";top:0;display:block;position:absolute;background:#ccc;width:100%;height:100%;z-index:1}::ng-deep .gu-transit dc-control-editor{display:none!important}:host{position:absolute;color:#00000080;top:0;right:0;z-index:2;max-width:105px;display:none;background:rgba(0,0,0,.25);border-radius:4px}:host:hover{cursor:move;color:#000000bf}:host ::ng-deep button{height:35px;line-height:35px;width:35px}:host .add-component{display:none}\n"], dependencies: [{ kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: PropertiesEditorComponent, selector: "dc-properties-editor", inputs: ["uiModel"], outputs: ["updatedProperty"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: ControlEditorComponent, decorators: [{
type: Component,
args: [{ selector: 'dc-control-editor', template: `
<dc-properties-editor [uiModel]="uiModel" (updatedProperty)="uiModelChanged.emit()"></dc-properties-editor>
<button mat-icon-button [matTooltip]="getDragTooltip()"
(mouseover)="onHover($event)" (focus)="onHover($event)" (mouseleave)="onMouseLeave($event)" class="handle">
<svg width="24px" fill="currentColor" viewBox="0 0 24 24">
<path d="M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z">
</path>
<path d="M0 0h24v24H0z" fill="none"></path>
</svg>
</button>
<button mat-icon-button class="add-component" matTooltip="Add component" (click)="openAddDialog()">
<mat-icon>add</mat-icon>
</button>
<button mat-icon-button matTooltip="Remove" (click)="uiModelRemoved.emit()">
<mat-icon>clear</mat-icon>
</button>
`, styles: ["::ng-deep .preview dc-container dc-container-row.row{min-height:100px;border:1px dashed rgba(0,0,0,0)}::ng-deep .preview dc-container dc-container-row.row.active{border-color:gray}::ng-deep .preview.edit-mode dc-container dc-container-row.row{border-color:#00000040}::ng-deep .preview.edit-mode dc-container dc-container-row.row>dc-control-editor{left:-50px}::ng-deep .preview.edit-mode dc-container dc-container-row.row>dc-control-editor .handle{display:none}::ng-deep .preview.edit-mode dc-container dc-container-row.row>dc-control-editor .add-component{display:inline-block}::ng-deep .preview.edit-mode dc-container dc-container-row.row .col-sm dc-ui-flex-container+dc-control-editor{left:60px}::ng-deep .preview dc-ui-flex-container .item,::ng-deep .preview dc-container .item,::ng-deep .preview dc-container dc-container-row.row,::ng-deep .preview dc-container dc-container-row.row>div[class*=col-]{position:relative;border:1px dashed rgba(0,0,0,0)}::ng-deep .preview dc-ui-flex-container .item:hover>dc-control-editor,::ng-deep .preview dc-container .item:hover>dc-control-editor,::ng-deep .preview dc-container dc-container-row.row:hover>dc-control-editor,::ng-deep .preview dc-container dc-container-row.row>div[class*=col-]:hover>dc-control-editor{display:block}::ng-deep .preview dc-ui-flex-container .item.drag-selected,::ng-deep .preview dc-container .item.drag-selected,::ng-deep .preview dc-container dc-container-row.row.drag-selected,::ng-deep .preview dc-container dc-container-row.row>div[class*=col-].drag-selected{border-color:gray}::ng-deep .preview dc-ui-flex-container .item.drag-selected dc-control-editor,::ng-deep .preview dc-container .item.drag-selected dc-control-editor,::ng-deep .preview dc-container dc-container-row.row.drag-selected dc-control-editor,::ng-deep .preview dc-container dc-container-row.row>div[class*=col-].drag-selected dc-control-editor{display:block!important}::ng-deep .preview dc-ui-flex-container .item dc-ui-flex-container+dc-control-editor>.handle,::ng-deep .preview dc-container .item dc-ui-flex-container+dc-control-editor>.handle,::ng-deep .preview dc-container dc-container-row.row dc-ui-flex-container+dc-control-editor>.handle,::ng-deep .preview dc-container dc-container-row.row>div[class*=col-] dc-ui-flex-container+dc-control-editor>.handle{color:#000000bf}::ng-deep .preview dc-ui-flex-container .item:hover dc-ui-flex-container+dc-control-editor>.handle,::ng-deep .preview dc-container .item:hover dc-ui-flex-container+dc-control-editor>.handle,::ng-deep .preview dc-container dc-container-row.row:hover dc-ui-flex-container+dc-control-editor>.handle,::ng-deep .preview dc-container dc-container-row.row>div[class*=col-]:hover dc-ui-flex-container+dc-control-editor>.handle{color:#000c}::ng-deep .preview dc-ui-flex-container .item dc-ui-flex-container+dc-control-editor,::ng-deep .preview dc-container .item dc-ui-flex-container+dc-control-editor,::ng-deep .preview dc-container dc-container-row.row dc-ui-flex-container+dc-control-editor,::ng-deep .preview dc-container dc-container-row.row>div[class*=col-] dc-ui-flex-container+dc-control-editor{left:-50px}::ng-deep .preview dc-container.container dc-container-row.row>dc-control-editor{left:-50px}::ng-deep .gu-mirror{position:fixed!important;margin:0!important;z-index:9999!important;opacity:.8;-ms-filter:\"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)\";filter:alpha(opacity=80);pointer-events:none;box-sizing:border-box;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f;background:#eeeeee}::ng-deep .gu-mirror>dc-control-editor{display:block!important}::ng-deep .gu-mirror>dc-ui-flex-container+dc-control-editor{left:-50px}::ng-deep .gu-hide{left:-9999px!important}::ng-deep .gu-unselectable{-webkit-user-select:none!important;-moz-user-select:none!important;user-select:none!important}::ng-deep .gu-transit{position:relative;transition:transform .25s cubic-bezier(0,0,.2,1)}::ng-deep .gu-transit:after{content:\" \";top:0;display:block;position:absolute;background:#ccc;width:100%;height:100%;z-index:1}::ng-deep .gu-transit dc-control-editor{display:none!important}:host{position:absolute;color:#00000080;top:0;right:0;z-index:2;max-width:105px;display:none;background:rgba(0,0,0,.25);border-radius:4px}:host:hover{cursor:move;color:#000000bf}:host ::ng-deep button{height:35px;line-height:35px;width:35px}:host .add-component{display:none}\n"] }]
}], ctorParameters: function () { return [{ type: i1$1.MatDialog }]; }, propDecorators: { uiModel: [{
type: Input
}], uiModelChanged: [{
type: Output
}], uiModelRemoved: [{
type: Output
}] } });
const angularSplitModuleForRoot = AngularSplitModule.forRoot();
class ToolsModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: ToolsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.1.6", ngImport: i0, type: ToolsModule, declarations: [PreviewEditorComponent, ControlEditorComponent, PropertiesEditorComponent, AddDialogComponent], imports: [CommonModule,
DynamicComponentsCoreModule,
DynamicComponentsBootstrapModule,
MatToolbarModule,
MatButtonModule,
MatTabsModule,
MatDividerModule,
MatCardModule,
MatIconModule,
MatTooltipModule,
MatInputModule,
MatFormFieldModule,
MatDialogModule,
MatListModule,
FormsModule,
ReactiveFormsModule, i8.AngularSplitModule], exports: [PreviewEditorComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: ToolsModule, imports: [CommonModule,
DynamicComponentsCoreModule,
DynamicComponentsBootstrapModule,
MatToolbarModule,
MatButtonModule,
MatTabsModule,
MatDividerModule,
MatCardModule,
MatIconModule,
MatTooltipModule,
MatInputModule,
MatFormFieldModule,
MatDialogModule,
MatListModule,
FormsModule,
ReactiveFormsModule,
angularSplitModuleForRoot] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: ToolsModule, decorators: [{
type: NgModule,
args: [{
declarations: [
PreviewEditorComponent, ControlEditorComponent, PropertiesEditorComponent, AddDialogComponent
],
imports: [
CommonModule,
DynamicComponentsCoreModule,
DynamicComponentsBootstrapModule,
MatToolbarModule,
MatButtonModule,
MatTabsModule,
MatDividerModule,
MatCardModule,
MatIconModule,
MatTooltipModule,
MatInputModule,
MatFormFieldModule,
MatDialogModule,
MatListModule,
FormsModule,
ReactiveFormsModule,
angularSplitModuleForRoot
],
exports: [PreviewEditorComponent]
}]
}] });
/*
* Public API Surface of tools
*/
/**
* Generated bundle index. Do not edit.
*/
export { PreviewEditorComponent, ToolsModule, angularSplitModuleForRoot };
//# sourceMappingURL=ngx-dynamic-components-tools.mjs.map