@masterteam/structure-builder 0.0.41 → 0.0.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, input, Component, ChangeDetectionStrategy, output, viewChild, model, contentChild, computed, signal, effect } from '@angular/core';
2
+ import { inject, input, Component, ChangeDetectionStrategy, output, viewChild, model, contentChild, computed, signal, effect, untracked } from '@angular/core';
3
3
  import * as i3 from '@jsverse/transloco';
4
4
  import { TranslocoModule, TranslocoService } from '@jsverse/transloco';
5
5
  import * as i1 from '@angular/common';
@@ -32,7 +32,7 @@ class NodeFormDialogComponent {
32
32
  dynamicFormControl = new FormControl();
33
33
  nodeData = {};
34
34
  formSchema;
35
- data = input(null, ...(ngDevMode ? [{ debugName: "data" }] : []));
35
+ data = input(null, ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
36
36
  ngOnInit() {
37
37
  this.nodeData = this.data()?.node ?? {};
38
38
  this.formSchema = this.data()?.formSchema ?? [];
@@ -67,10 +67,10 @@ class NodeFormDialogComponent {
67
67
  onCancel() {
68
68
  this.ref.close();
69
69
  }
70
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: NodeFormDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
71
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: NodeFormDialogComponent, isStandalone: true, selector: "mt-node-form-dialog", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div [class]=\"[modalService.contentClass, 'p-4']\">\r\n @if (this.data()?.template) {\r\n <ng-container\r\n *ngTemplateOutlet=\"data().template; context: templateContext\"\r\n ></ng-container>\r\n } @else {\r\n @if (nodeData) {\r\n <mt-dynamic-form\r\n [formConfig]=\"formSchema\"\r\n [formControl]=\"dynamicFormControl\"\r\n ></mt-dynamic-form>\r\n }\r\n }\r\n</div>\r\n<div [class]=\"modalService.footerClass\">\r\n <mt-button\r\n [label]=\"'structureBuilder.cancel' | transloco\"\r\n severity=\"secondary\"\r\n (onClick)=\"onCancel()\"\r\n >\r\n </mt-button>\r\n @if (showSaveButton()) {\r\n <mt-button\r\n [disabled]=\"disableSaveButton()\"\r\n [label]=\"'structureBuilder.saveChanges' | transloco\"\r\n severity=\"primary\"\r\n (onClick)=\"onSave()\"\r\n >\r\n </mt-button>\r\n }\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig", "forcedHiddenFieldKeys", "preserveForcedHiddenValues", "visibleSectionKeys"], outputs: ["runtimeMessagesChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i3.TranslocoPipe, name: "transloco" }] });
70
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NodeFormDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
71
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: NodeFormDialogComponent, isStandalone: true, selector: "mt-node-form-dialog", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div [class]=\"[modalService.contentClass, 'p-4']\">\r\n @if (this.data()?.template) {\r\n <ng-container\r\n *ngTemplateOutlet=\"data().template; context: templateContext\"\r\n ></ng-container>\r\n } @else {\r\n @if (nodeData) {\r\n <mt-dynamic-form\r\n [formConfig]=\"formSchema\"\r\n [formControl]=\"dynamicFormControl\"\r\n ></mt-dynamic-form>\r\n }\r\n }\r\n</div>\r\n<div [class]=\"modalService.footerClass\">\r\n <mt-button\r\n [label]=\"'structureBuilder.cancel' | transloco\"\r\n severity=\"secondary\"\r\n (onClick)=\"onCancel()\"\r\n >\r\n </mt-button>\r\n @if (showSaveButton()) {\r\n <mt-button\r\n [disabled]=\"disableSaveButton()\"\r\n [label]=\"'structureBuilder.saveChanges' | transloco\"\r\n severity=\"primary\"\r\n (onClick)=\"onSave()\"\r\n >\r\n </mt-button>\r\n }\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig", "forcedHiddenFieldKeys", "preserveForcedHiddenValues", "visibleSectionKeys"], outputs: ["runtimeMessagesChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i3.TranslocoPipe, name: "transloco" }] });
72
72
  }
73
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: NodeFormDialogComponent, decorators: [{
73
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NodeFormDialogComponent, decorators: [{
74
74
  type: Component,
75
75
  args: [{ selector: 'mt-node-form-dialog', standalone: true, imports: [
76
76
  CommonModule,
@@ -84,7 +84,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
84
84
  class ConnectionFormDialogComponent {
85
85
  modalService = inject(ModalService);
86
86
  ref = inject(ModalRef);
87
- data = input(null, ...(ngDevMode ? [{ debugName: "data" }] : []));
87
+ data = input(null, ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
88
88
  defaultToolbarTabs = [
89
89
  'functions',
90
90
  'properties',
@@ -120,10 +120,10 @@ class ConnectionFormDialogComponent {
120
120
  onCancel() {
121
121
  this.ref.close();
122
122
  }
123
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ConnectionFormDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
124
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: ConnectionFormDialogComponent, isStandalone: true, selector: "mt-connection-form-dialog", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\r\n [class]=\"\r\n modalService.contentClass +\r\n ' max-h-[80vh] overflow-x-hidden overflow-y-auto p-4'\r\n \"\r\n>\r\n <div class=\"space-y-6\">\r\n @if (formSchema?.sections?.length > 0) {\r\n <mt-dynamic-form\r\n class=\"block\"\r\n [formConfig]=\"formSchema\"\r\n [formControl]=\"dynamicFormControl\"\r\n ></mt-dynamic-form>\r\n }\r\n\r\n @if (formulaSchemaId) {\r\n <mt-card [title]=\"'structureBuilder.formula' | transloco\">\r\n <mt-formula-builder\r\n [formControl]=\"formulaControl\"\r\n [levelSchemaId]=\"formulaSchemaId\"\r\n [toolbarTabs]=\"formulaConfig.toolbarTabs ?? defaultToolbarTabs\"\r\n [codeOnly]=\"formulaConfig.codeOnly ?? false\"\r\n [hideToolbar]=\"formulaConfig.hideToolbar ?? false\"\r\n [hideStatusBar]=\"formulaConfig.hideStatusBar ?? false\"\r\n [isProcessBuilder]=\"formulaConfig.isProcessBuilder ?? false\"\r\n />\r\n </mt-card>\r\n }\r\n </div>\r\n</div>\r\n\r\n<div [class]=\"modalService.footerClass\">\r\n <mt-button\r\n [label]=\"'structureBuilder.cancel' | transloco\"\r\n severity=\"secondary\"\r\n (onClick)=\"onCancel()\"\r\n >\r\n </mt-button>\r\n <mt-button\r\n [disabled]=\"!dynamicFormControl.valid\"\r\n [label]=\"'structureBuilder.saveChanges' | transloco\"\r\n severity=\"primary\"\r\n (onClick)=\"onSave()\"\r\n >\r\n </mt-button>\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig", "forcedHiddenFieldKeys", "preserveForcedHiddenValues", "visibleSectionKeys"], outputs: ["runtimeMessagesChange"] }, { kind: "component", type: FormulaBuilder, selector: "mt-formula-builder", inputs: ["propertiesByPath", "levelSchemaId", "templateId", "placeholder", "hideToolbar", "hideStatusBar", "toolbarTabs", "codeOnly", "isProcessBuilder"], outputs: ["validationChange", "tokensChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i3.TranslocoPipe, name: "transloco" }] });
123
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ConnectionFormDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
124
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: ConnectionFormDialogComponent, isStandalone: true, selector: "mt-connection-form-dialog", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\r\n [class]=\"\r\n modalService.contentClass +\r\n ' max-h-[80vh] overflow-x-hidden overflow-y-auto p-4'\r\n \"\r\n>\r\n <div class=\"space-y-6\">\r\n @if (formSchema?.sections?.length > 0) {\r\n <mt-dynamic-form\r\n class=\"block\"\r\n [formConfig]=\"formSchema\"\r\n [formControl]=\"dynamicFormControl\"\r\n ></mt-dynamic-form>\r\n }\r\n\r\n @if (formulaSchemaId) {\r\n <mt-card [title]=\"'structureBuilder.formula' | transloco\">\r\n <mt-formula-builder\r\n [formControl]=\"formulaControl\"\r\n [levelSchemaId]=\"formulaSchemaId\"\r\n [toolbarTabs]=\"formulaConfig.toolbarTabs ?? defaultToolbarTabs\"\r\n [codeOnly]=\"formulaConfig.codeOnly ?? false\"\r\n [hideToolbar]=\"formulaConfig.hideToolbar ?? false\"\r\n [hideStatusBar]=\"formulaConfig.hideStatusBar ?? false\"\r\n [isProcessBuilder]=\"formulaConfig.isProcessBuilder ?? false\"\r\n />\r\n </mt-card>\r\n }\r\n </div>\r\n</div>\r\n\r\n<div [class]=\"modalService.footerClass\">\r\n <mt-button\r\n [label]=\"'structureBuilder.cancel' | transloco\"\r\n severity=\"secondary\"\r\n (onClick)=\"onCancel()\"\r\n >\r\n </mt-button>\r\n <mt-button\r\n [disabled]=\"!dynamicFormControl.valid\"\r\n [label]=\"'structureBuilder.saveChanges' | transloco\"\r\n severity=\"primary\"\r\n (onClick)=\"onSave()\"\r\n >\r\n </mt-button>\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: DynamicForm, selector: "mt-dynamic-form", inputs: ["formConfig", "forcedHiddenFieldKeys", "preserveForcedHiddenValues", "visibleSectionKeys"], outputs: ["runtimeMessagesChange"] }, { kind: "component", type: FormulaBuilder, selector: "mt-formula-builder", inputs: ["propertiesByPath", "levelSchemaId", "moduleId", "contextEntityTypeKey", "templateId", "placeholder", "hideToolbar", "hideStatusBar", "toolbarTabs", "codeOnly", "isProcessBuilder"], outputs: ["validationChange", "tokensChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i3.TranslocoPipe, name: "transloco" }] });
125
125
  }
126
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ConnectionFormDialogComponent, decorators: [{
126
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ConnectionFormDialogComponent, decorators: [{
127
127
  type: Component,
128
128
  args: [{ selector: 'mt-connection-form-dialog', standalone: true, imports: [
129
129
  CommonModule,
@@ -137,7 +137,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
137
137
  }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] } });
138
138
 
139
139
  class Toolbar {
140
- size = input(...(ngDevMode ? [undefined, { debugName: "size" }] : []));
140
+ size = input(...(ngDevMode ? [undefined, { debugName: "size" }] : /* istanbul ignore next */ []));
141
141
  builderComponent = inject(StructureBuilder);
142
142
  onZoomIn() {
143
143
  this.builderComponent.fZoomDirective()?.zoomIn();
@@ -156,10 +156,10 @@ class Toolbar {
156
156
  autoLayout() {
157
157
  this.builderComponent.maybeAutoLayout();
158
158
  }
159
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: Toolbar, deps: [], target: i0.ɵɵFactoryTarget.Component });
160
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.3", type: Toolbar, isStandalone: true, selector: "mt-toolbar", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mt-button\r\n (onClick)=\"autoLayout()\"\r\n class=\"bg-content rounded-(--p-button-border-radius)\"\r\n size=\"size()\"\r\n variant=\"outlined\"\r\n severity=\"secondary\"\r\n icon=\"arrow.refresh-cw-05\"\r\n></mt-button>\r\n\r\n<mt-buttongroup class=\"bg-content rounded-(--p-button-border-radius)\">\r\n <mt-button\r\n (onClick)=\"onZoomOut()\"\r\n size=\"size()\"\r\n variant=\"outlined\"\r\n severity=\"secondary\"\r\n icon=\"general.minus\"\r\n ></mt-button>\r\n <mt-button\r\n (onClick)=\"onZoomIn()\"\r\n size=\"size()\"\r\n variant=\"outlined\"\r\n severity=\"secondary\"\r\n icon=\"general.plus\"\r\n ></mt-button>\r\n <mt-button\r\n (onClick)=\"onFitToScreen()\"\r\n size=\"size()\"\r\n variant=\"outlined\"\r\n severity=\"secondary\"\r\n icon=\"layout.grid-02\"\r\n ></mt-button>\r\n</mt-buttongroup>\r\n", styles: [":host{display:flex;justify-content:flex-end;align-items:center;position:absolute;gap:calc(var(--spacing) * 2);inset-inline-end:calc(var(--spacing) * 4);bottom:calc(var(--spacing) * 4)}\n"], dependencies: [{ kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ButtonGroup, selector: "mt-buttonGroup, mt-buttongroup, mt-button-group" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
159
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: Toolbar, deps: [], target: i0.ɵɵFactoryTarget.Component });
160
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.8", type: Toolbar, isStandalone: true, selector: "mt-toolbar", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mt-button\r\n (onClick)=\"autoLayout()\"\r\n class=\"bg-content rounded-(--p-button-border-radius)\"\r\n size=\"size()\"\r\n variant=\"outlined\"\r\n severity=\"secondary\"\r\n icon=\"arrow.refresh-cw-05\"\r\n></mt-button>\r\n\r\n<mt-buttongroup class=\"bg-content rounded-(--p-button-border-radius)\">\r\n <mt-button\r\n (onClick)=\"onZoomOut()\"\r\n size=\"size()\"\r\n variant=\"outlined\"\r\n severity=\"secondary\"\r\n icon=\"general.minus\"\r\n ></mt-button>\r\n <mt-button\r\n (onClick)=\"onZoomIn()\"\r\n size=\"size()\"\r\n variant=\"outlined\"\r\n severity=\"secondary\"\r\n icon=\"general.plus\"\r\n ></mt-button>\r\n <mt-button\r\n (onClick)=\"onFitToScreen()\"\r\n size=\"size()\"\r\n variant=\"outlined\"\r\n severity=\"secondary\"\r\n icon=\"layout.grid-02\"\r\n ></mt-button>\r\n</mt-buttongroup>\r\n", styles: [":host{display:flex;justify-content:flex-end;align-items:center;position:absolute;gap:calc(var(--spacing) * 2);inset-inline-end:calc(var(--spacing) * 4);bottom:calc(var(--spacing) * 4)}\n"], dependencies: [{ kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ButtonGroup, selector: "mt-buttonGroup, mt-buttongroup, mt-button-group" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
161
161
  }
162
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: Toolbar, decorators: [{
162
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: Toolbar, decorators: [{
163
163
  type: Component,
164
164
  args: [{ selector: 'mt-toolbar', imports: [Button, ButtonGroup], changeDetection: ChangeDetectionStrategy.OnPush, template: "<mt-button\r\n (onClick)=\"autoLayout()\"\r\n class=\"bg-content rounded-(--p-button-border-radius)\"\r\n size=\"size()\"\r\n variant=\"outlined\"\r\n severity=\"secondary\"\r\n icon=\"arrow.refresh-cw-05\"\r\n></mt-button>\r\n\r\n<mt-buttongroup class=\"bg-content rounded-(--p-button-border-radius)\">\r\n <mt-button\r\n (onClick)=\"onZoomOut()\"\r\n size=\"size()\"\r\n variant=\"outlined\"\r\n severity=\"secondary\"\r\n icon=\"general.minus\"\r\n ></mt-button>\r\n <mt-button\r\n (onClick)=\"onZoomIn()\"\r\n size=\"size()\"\r\n variant=\"outlined\"\r\n severity=\"secondary\"\r\n icon=\"general.plus\"\r\n ></mt-button>\r\n <mt-button\r\n (onClick)=\"onFitToScreen()\"\r\n size=\"size()\"\r\n variant=\"outlined\"\r\n severity=\"secondary\"\r\n icon=\"layout.grid-02\"\r\n ></mt-button>\r\n</mt-buttongroup>\r\n", styles: [":host{display:flex;justify-content:flex-end;align-items:center;position:absolute;gap:calc(var(--spacing) * 2);inset-inline-end:calc(var(--spacing) * 4);bottom:calc(var(--spacing) * 4)}\n"] }]
165
165
  }], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
@@ -185,6 +185,10 @@ const CONFIGURATION = {
185
185
  inputSide: 'top',
186
186
  },
187
187
  };
188
+ const VERTICAL_CONNECTOR_SIDES = ['top', 'bottom'];
189
+ const HORIZONTAL_CONNECTOR_SIDES = ['left', 'right'];
190
+ const CONNECTOR_ID_SEPARATOR = '__sb-connector__';
191
+ const STRUCTURE_BUILDER_CONNECTOR_SUFFIX = /__sb-connector__(input|output)__(top|bottom|left|right)$/;
188
192
  class StructureBuilder {
189
193
  dialogService = inject(DialogService);
190
194
  drawerService = inject(DrawerService);
@@ -193,53 +197,56 @@ class StructureBuilder {
193
197
  dir = inject(Directionality, { optional: true });
194
198
  nodeActionsEvent = output();
195
199
  action = output();
196
- availableNodes = input([], ...(ngDevMode ? [{ debugName: "availableNodes" }] : []));
197
- fCanvas = viewChild(FCanvasComponent, ...(ngDevMode ? [{ debugName: "fCanvas" }] : []));
198
- fFlowComponent = viewChild(FFlowComponent, ...(ngDevMode ? [{ debugName: "fFlowComponent" }] : []));
199
- fCanvasComponent = viewChild(FCanvasComponent, ...(ngDevMode ? [{ debugName: "fCanvasComponent" }] : []));
200
- fZoomDirective = viewChild(FZoomDirective, ...(ngDevMode ? [{ debugName: "fZoomDirective" }] : []));
201
- nodeForm = input({ sections: [] }, ...(ngDevMode ? [{ debugName: "nodeForm" }] : []));
202
- nodeDialogFooterConfig = input(null, ...(ngDevMode ? [{ debugName: "nodeDialogFooterConfig" }] : []));
203
- connectionForm = input({ sections: [] }, ...(ngDevMode ? [{ debugName: "connectionForm" }] : []));
204
- connectionFormulaSchemaId = input(undefined, ...(ngDevMode ? [{ debugName: "connectionFormulaSchemaId" }] : []));
205
- connectionFormulaConfig = input(null, ...(ngDevMode ? [{ debugName: "connectionFormulaConfig" }] : []));
206
- nodeActions = input([], ...(ngDevMode ? [{ debugName: "nodeActions" }] : []));
200
+ availableNodes = input([], ...(ngDevMode ? [{ debugName: "availableNodes" }] : /* istanbul ignore next */ []));
201
+ fCanvas = viewChild(FCanvasComponent, ...(ngDevMode ? [{ debugName: "fCanvas" }] : /* istanbul ignore next */ []));
202
+ fFlowComponent = viewChild(FFlowComponent, ...(ngDevMode ? [{ debugName: "fFlowComponent" }] : /* istanbul ignore next */ []));
203
+ fCanvasComponent = viewChild(FCanvasComponent, ...(ngDevMode ? [{ debugName: "fCanvasComponent" }] : /* istanbul ignore next */ []));
204
+ fZoomDirective = viewChild(FZoomDirective, ...(ngDevMode ? [{ debugName: "fZoomDirective" }] : /* istanbul ignore next */ []));
205
+ nodeForm = input({ sections: [] }, ...(ngDevMode ? [{ debugName: "nodeForm" }] : /* istanbul ignore next */ []));
206
+ nodeDialogFooterConfig = input(null, ...(ngDevMode ? [{ debugName: "nodeDialogFooterConfig" }] : /* istanbul ignore next */ []));
207
+ connectionForm = input({ sections: [] }, ...(ngDevMode ? [{ debugName: "connectionForm" }] : /* istanbul ignore next */ []));
208
+ connectionFormulaSchemaId = input(undefined, ...(ngDevMode ? [{ debugName: "connectionFormulaSchemaId" }] : /* istanbul ignore next */ []));
209
+ connectionFormulaConfig = input(null, ...(ngDevMode ? [{ debugName: "connectionFormulaConfig" }] : /* istanbul ignore next */ []));
210
+ nodeActions = input([], ...(ngDevMode ? [{ debugName: "nodeActions" }] : /* istanbul ignore next */ []));
207
211
  nodeFields = input({
208
212
  id: 'id',
209
213
  name: 'name',
210
214
  icon: 'icon',
211
215
  color: 'color',
212
- }, ...(ngDevMode ? [{ debugName: "nodeFields" }] : []));
213
- isAutoLayout = input(true, ...(ngDevMode ? [{ debugName: "isAutoLayout" }] : []));
214
- readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : []));
215
- addModalType = input('dialog', ...(ngDevMode ? [{ debugName: "addModalType" }] : []));
216
- updateModalType = input('drawer', ...(ngDevMode ? [{ debugName: "updateModalType" }] : []));
217
- addModalStyleClass = input('!w-[35rem]', ...(ngDevMode ? [{ debugName: "addModalStyleClass" }] : []));
218
- updateModalStyleClass = input('!w-[35rem]', ...(ngDevMode ? [{ debugName: "updateModalStyleClass" }] : []));
219
- addModalHeader = input('', ...(ngDevMode ? [{ debugName: "addModalHeader" }] : []));
220
- updateModalHeader = input('', ...(ngDevMode ? [{ debugName: "updateModalHeader" }] : []));
221
- appendTo = input('', ...(ngDevMode ? [{ debugName: "appendTo" }] : []));
222
- availableTabsClass = input('', ...(ngDevMode ? [{ debugName: "availableTabsClass" }] : []));
223
- layoutDirection = input(Direction.TOP_TO_BOTTOM, ...(ngDevMode ? [{ debugName: "layoutDirection" }] : []));
224
- nodes = model([], ...(ngDevMode ? [{ debugName: "nodes" }] : []));
225
- connections = model([], ...(ngDevMode ? [{ debugName: "connections" }] : []));
226
- nodeDialogTemplate = contentChild('nodeDialog', ...(ngDevMode ? [{ debugName: "nodeDialogTemplate" }] : []));
227
- nodeTemplate = input(null, ...(ngDevMode ? [{ debugName: "nodeTemplate" }] : []));
228
- nodeTemplateContent = contentChild('nodeTemplate', ...(ngDevMode ? [{ debugName: "nodeTemplateContent" }] : []));
229
- effectiveNodeTemplate = computed(() => this.nodeTemplate() || this.nodeTemplateContent() || null, ...(ngDevMode ? [{ debugName: "effectiveNodeTemplate" }] : []));
230
- contentDirection = computed(() => this.dir?.value ?? 'ltr', ...(ngDevMode ? [{ debugName: "contentDirection" }] : []));
231
- collapsedConnectionIds = signal(new Set(), ...(ngDevMode ? [{ debugName: "collapsedConnectionIds" }] : []));
232
- activeTab = signal('0', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
216
+ }, ...(ngDevMode ? [{ debugName: "nodeFields" }] : /* istanbul ignore next */ []));
217
+ isAutoLayout = input(true, ...(ngDevMode ? [{ debugName: "isAutoLayout" }] : /* istanbul ignore next */ []));
218
+ readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
219
+ addModalType = input('dialog', ...(ngDevMode ? [{ debugName: "addModalType" }] : /* istanbul ignore next */ []));
220
+ updateModalType = input('drawer', ...(ngDevMode ? [{ debugName: "updateModalType" }] : /* istanbul ignore next */ []));
221
+ addModalStyleClass = input('!w-[35rem]', ...(ngDevMode ? [{ debugName: "addModalStyleClass" }] : /* istanbul ignore next */ []));
222
+ updateModalStyleClass = input('!w-[35rem]', ...(ngDevMode ? [{ debugName: "updateModalStyleClass" }] : /* istanbul ignore next */ []));
223
+ addModalHeader = input('', ...(ngDevMode ? [{ debugName: "addModalHeader" }] : /* istanbul ignore next */ []));
224
+ updateModalHeader = input('', ...(ngDevMode ? [{ debugName: "updateModalHeader" }] : /* istanbul ignore next */ []));
225
+ appendTo = input('', ...(ngDevMode ? [{ debugName: "appendTo" }] : /* istanbul ignore next */ []));
226
+ availableTabsClass = input('', ...(ngDevMode ? [{ debugName: "availableTabsClass" }] : /* istanbul ignore next */ []));
227
+ layoutDirection = input(Direction.TOP_TO_BOTTOM, ...(ngDevMode ? [{ debugName: "layoutDirection" }] : /* istanbul ignore next */ []));
228
+ nodes = model([], ...(ngDevMode ? [{ debugName: "nodes" }] : /* istanbul ignore next */ []));
229
+ connections = model([], ...(ngDevMode ? [{ debugName: "connections" }] : /* istanbul ignore next */ []));
230
+ nodeDialogTemplate = contentChild('nodeDialog', ...(ngDevMode ? [{ debugName: "nodeDialogTemplate" }] : /* istanbul ignore next */ []));
231
+ nodeTemplate = input(null, ...(ngDevMode ? [{ debugName: "nodeTemplate" }] : /* istanbul ignore next */ []));
232
+ nodeTemplateContent = contentChild('nodeTemplate', ...(ngDevMode ? [{ debugName: "nodeTemplateContent" }] : /* istanbul ignore next */ []));
233
+ effectiveNodeTemplate = computed(() => this.nodeTemplate() || this.nodeTemplateContent() || null, ...(ngDevMode ? [{ debugName: "effectiveNodeTemplate" }] : /* istanbul ignore next */ []));
234
+ contentDirection = computed(() => this.dir?.value ?? 'ltr', ...(ngDevMode ? [{ debugName: "contentDirection" }] : /* istanbul ignore next */ []));
235
+ collapsedConnectionIds = signal(new Set(), ...(ngDevMode ? [{ debugName: "collapsedConnectionIds" }] : /* istanbul ignore next */ []));
236
+ activeTab = signal('0', ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
233
237
  eMarkerType = EFMarkerType;
234
- effectiveDirection = computed(() => this.resolveDirection(this.layoutDirection()), ...(ngDevMode ? [{ debugName: "effectiveDirection" }] : []));
235
- configuration = computed(() => CONFIGURATION[this.effectiveDirection()], ...(ngDevMode ? [{ debugName: "configuration" }] : []));
238
+ effectiveDirection = computed(() => this.resolveDirection(this.layoutDirection()), ...(ngDevMode ? [{ debugName: "effectiveDirection" }] : /* istanbul ignore next */ []));
239
+ configuration = computed(() => CONFIGURATION[this.effectiveDirection()], ...(ngDevMode ? [{ debugName: "configuration" }] : /* istanbul ignore next */ []));
240
+ nodeConnectorSides = computed(() => this.effectiveDirection() === Direction.TOP_TO_BOTTOM
241
+ ? VERTICAL_CONNECTOR_SIDES
242
+ : HORIZONTAL_CONNECTOR_SIDES, ...(ngDevMode ? [{ debugName: "nodeConnectorSides" }] : /* istanbul ignore next */ []));
236
243
  nodeActionHandler = (action, node) => {
237
244
  this.buttonAction(action, node);
238
245
  };
239
246
  getFilteredNodeActions = (node) => this.readonly()
240
247
  ? []
241
248
  : this.nodeActions().filter((action) => !action.condition || action.condition(node));
242
- positions = signal({}, ...(ngDevMode ? [{ debugName: "positions" }] : []));
249
+ positions = signal({}, ...(ngDevMode ? [{ debugName: "positions" }] : /* istanbul ignore next */ []));
243
250
  dialogRef;
244
251
  fields = computed(() => {
245
252
  const inputFields = this.nodeFields();
@@ -249,7 +256,7 @@ class StructureBuilder {
249
256
  icon: inputFields.icon || 'icon',
250
257
  color: inputFields.color || 'color',
251
258
  };
252
- }, ...(ngDevMode ? [{ debugName: "fields" }] : []));
259
+ }, ...(ngDevMode ? [{ debugName: "fields" }] : /* istanbul ignore next */ []));
253
260
  availableTabs = computed(() => {
254
261
  const tabsSet = new Set();
255
262
  this.availableNodes().forEach((node) => {
@@ -258,7 +265,7 @@ class StructureBuilder {
258
265
  }
259
266
  });
260
267
  return Array.from(tabsSet).sort();
261
- }, ...(ngDevMode ? [{ debugName: "availableTabs" }] : []));
268
+ }, ...(ngDevMode ? [{ debugName: "availableTabs" }] : /* istanbul ignore next */ []));
262
269
  currentTabNodes = computed(() => {
263
270
  const tabs = this.availableTabs();
264
271
  const currentTabIndex = parseInt(this.activeTab());
@@ -266,7 +273,7 @@ class StructureBuilder {
266
273
  return [];
267
274
  const currentTab = tabs[currentTabIndex];
268
275
  return this.availableNodes().filter((node) => node.tab.includes(currentTab));
269
- }, ...(ngDevMode ? [{ debugName: "currentTabNodes" }] : []));
276
+ }, ...(ngDevMode ? [{ debugName: "currentTabNodes" }] : /* istanbul ignore next */ []));
270
277
  nodesWithComputedProps = computed(() => {
271
278
  const fields = this.fields();
272
279
  const pos = this.positions();
@@ -288,12 +295,29 @@ class StructureBuilder {
288
295
  configuration,
289
296
  };
290
297
  });
291
- }, ...(ngDevMode ? [{ debugName: "nodesWithComputedProps" }] : []));
298
+ }, ...(ngDevMode ? [{ debugName: "nodesWithComputedProps" }] : /* istanbul ignore next */ []));
299
+ nodePositionsById = computed(() => this.nodesWithComputedProps().reduce((positions, node) => {
300
+ positions[node._computedId] = {
301
+ x: node.configuration?.x ?? 0,
302
+ y: node.configuration?.y ?? 0,
303
+ };
304
+ return positions;
305
+ }, {}), ...(ngDevMode ? [{ debugName: "nodePositionsById" }] : /* istanbul ignore next */ []));
292
306
  connectionsComputed = computed(() => this.connections()?.map((c) => ({
293
307
  ...c,
294
- from: String(c.from),
295
- to: String(c.to),
296
- })), ...(ngDevMode ? [{ debugName: "connectionsComputed" }] : []));
308
+ from: this.extractNodeId(String(c.from)),
309
+ to: this.extractNodeId(String(c.to)),
310
+ })), ...(ngDevMode ? [{ debugName: "connectionsComputed" }] : /* istanbul ignore next */ []));
311
+ renderedConnections = computed(() => this.connectionsComputed().map((connection) => {
312
+ const { inputSide, outputSide } = this.resolveConnectionConnectorSides(connection);
313
+ return {
314
+ ...connection,
315
+ _inputConnectorId: this.createConnectorId(connection.to, 'input', inputSide),
316
+ _inputSide: inputSide,
317
+ _outputConnectorId: this.createConnectorId(connection.from, 'output', outputSide),
318
+ _outputSide: outputSide,
319
+ };
320
+ }), ...(ngDevMode ? [{ debugName: "renderedConnections" }] : /* istanbul ignore next */ []));
297
321
  coreFields = computed(() => {
298
322
  const fields = this.fields();
299
323
  return new Set([
@@ -304,7 +328,7 @@ class StructureBuilder {
304
328
  '_computedIcon',
305
329
  '_computedColor',
306
330
  ]);
307
- }, ...(ngDevMode ? [{ debugName: "coreFields" }] : []));
331
+ }, ...(ngDevMode ? [{ debugName: "coreFields" }] : /* istanbul ignore next */ []));
308
332
  constructor() {
309
333
  effect(() => {
310
334
  const direction = this.effectiveDirection();
@@ -366,14 +390,16 @@ class StructureBuilder {
366
390
  if (this.readonly()) {
367
391
  return;
368
392
  }
393
+ const sourceId = this.extractNodeId(event.sourceId ?? event.fOutputId ?? '');
394
+ const targetId = this.extractNodeId(event.targetId ?? event.fInputId ?? '');
395
+ if (!sourceId || !targetId) {
396
+ return;
397
+ }
369
398
  const newConnection = {
370
399
  id: this.generateConnectionId(),
371
- from: event.fOutputId,
372
- to: event.fInputId,
400
+ from: sourceId,
401
+ to: targetId,
373
402
  };
374
- if (!event.fInputId || !event.fOutputId) {
375
- return;
376
- }
377
403
  const exists = this.connectionsComputed().some((conn) => conn.from === newConnection.from && conn.to === newConnection.to);
378
404
  if (!exists) {
379
405
  if (this.connectionForm()?.sections.length > 0 ||
@@ -525,6 +551,7 @@ class StructureBuilder {
525
551
  updateGraph(graph, direction) {
526
552
  graph.setGraph({ rankdir: direction });
527
553
  const SIZE = { width: 300, height: 200 };
554
+ const nodePositions = untracked(this.nodePositionsById);
528
555
  const nodeIds = this.nodes()
529
556
  .map((node) => this.getNestedValue(node, this.fields().id))
530
557
  .filter((nodeId) => nodeId !== null && nodeId !== undefined && `${nodeId}` !== '')
@@ -540,7 +567,8 @@ class StructureBuilder {
540
567
  connection.from !== connection.to);
541
568
  if (validConnections.length > 0) {
542
569
  validConnections.forEach((connection) => {
543
- graph.setEdge(connection.from, connection.to, {});
570
+ const [layoutSourceId, layoutTargetId] = this.resolveLayoutEdge(connection, direction, nodePositions);
571
+ graph.setEdge(layoutSourceId, layoutTargetId, {});
544
572
  });
545
573
  }
546
574
  else if (nodeIds.length > 1) {
@@ -578,8 +606,8 @@ class StructureBuilder {
578
606
  generateConnectionId() {
579
607
  return `conn-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
580
608
  }
581
- extractNodeId(connectionEndId) {
582
- return (connectionEndId || '').replace(/-(in|out)$/, '');
609
+ createConnectorId(nodeId, role, side) {
610
+ return `${nodeId}${CONNECTOR_ID_SEPARATOR}${role}__${side}`;
583
611
  }
584
612
  resolveDirection(layoutDirection) {
585
613
  if (layoutDirection === Direction.LEFT_TO_RIGHT) {
@@ -616,10 +644,54 @@ class StructureBuilder {
616
644
  }
617
645
  return visited;
618
646
  }
619
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: StructureBuilder, deps: [], target: i0.ɵɵFactoryTarget.Component });
620
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: StructureBuilder, isStandalone: true, selector: "mt-structure-builder", inputs: { availableNodes: { classPropertyName: "availableNodes", publicName: "availableNodes", isSignal: true, isRequired: false, transformFunction: null }, nodeForm: { classPropertyName: "nodeForm", publicName: "nodeForm", isSignal: true, isRequired: false, transformFunction: null }, nodeDialogFooterConfig: { classPropertyName: "nodeDialogFooterConfig", publicName: "nodeDialogFooterConfig", isSignal: true, isRequired: false, transformFunction: null }, connectionForm: { classPropertyName: "connectionForm", publicName: "connectionForm", isSignal: true, isRequired: false, transformFunction: null }, connectionFormulaSchemaId: { classPropertyName: "connectionFormulaSchemaId", publicName: "connectionFormulaSchemaId", isSignal: true, isRequired: false, transformFunction: null }, connectionFormulaConfig: { classPropertyName: "connectionFormulaConfig", publicName: "connectionFormulaConfig", isSignal: true, isRequired: false, transformFunction: null }, nodeActions: { classPropertyName: "nodeActions", publicName: "nodeActions", isSignal: true, isRequired: false, transformFunction: null }, nodeFields: { classPropertyName: "nodeFields", publicName: "nodeFields", isSignal: true, isRequired: false, transformFunction: null }, isAutoLayout: { classPropertyName: "isAutoLayout", publicName: "isAutoLayout", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, addModalType: { classPropertyName: "addModalType", publicName: "addModalType", isSignal: true, isRequired: false, transformFunction: null }, updateModalType: { classPropertyName: "updateModalType", publicName: "updateModalType", isSignal: true, isRequired: false, transformFunction: null }, addModalStyleClass: { classPropertyName: "addModalStyleClass", publicName: "addModalStyleClass", isSignal: true, isRequired: false, transformFunction: null }, updateModalStyleClass: { classPropertyName: "updateModalStyleClass", publicName: "updateModalStyleClass", isSignal: true, isRequired: false, transformFunction: null }, addModalHeader: { classPropertyName: "addModalHeader", publicName: "addModalHeader", isSignal: true, isRequired: false, transformFunction: null }, updateModalHeader: { classPropertyName: "updateModalHeader", publicName: "updateModalHeader", isSignal: true, isRequired: false, transformFunction: null }, appendTo: { classPropertyName: "appendTo", publicName: "appendTo", isSignal: true, isRequired: false, transformFunction: null }, availableTabsClass: { classPropertyName: "availableTabsClass", publicName: "availableTabsClass", isSignal: true, isRequired: false, transformFunction: null }, layoutDirection: { classPropertyName: "layoutDirection", publicName: "layoutDirection", isSignal: true, isRequired: false, transformFunction: null }, nodes: { classPropertyName: "nodes", publicName: "nodes", isSignal: true, isRequired: false, transformFunction: null }, connections: { classPropertyName: "connections", publicName: "connections", isSignal: true, isRequired: false, transformFunction: null }, nodeTemplate: { classPropertyName: "nodeTemplate", publicName: "nodeTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { nodeActionsEvent: "nodeActionsEvent", action: "action", nodes: "nodesChange", connections: "connectionsChange" }, host: { classAttribute: "flex h-full bg-surface-200 dark:bg-surface-700 relative rounded-2xl overflow-hidden" }, providers: [DialogService], queries: [{ propertyName: "nodeDialogTemplate", first: true, predicate: ["nodeDialog"], descendants: true, isSignal: true }, { propertyName: "nodeTemplateContent", first: true, predicate: ["nodeTemplate"], descendants: true, isSignal: true }], viewQueries: [{ propertyName: "fCanvas", first: true, predicate: FCanvasComponent, descendants: true, isSignal: true }, { propertyName: "fFlowComponent", first: true, predicate: FFlowComponent, descendants: true, isSignal: true }, { propertyName: "fCanvasComponent", first: true, predicate: FCanvasComponent, descendants: true, isSignal: true }, { propertyName: "fZoomDirective", first: true, predicate: FZoomDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<!-- structure-builder.html -->\r\n@if (!readonly() && availableTabs().length > 0) {\r\n <mt-card\r\n class=\"absolute ms-4 mt-4 z-1 h-[calc(100%---spacing(8))] w-1/5 min-w-xs\"\r\n >\r\n <ng-template #headless>\r\n <!-- Header -->\r\n <div class=\"flex items-center justify-between px-4 pt-5\">\r\n <h3 class=\"text-xl font-semibold\">\r\n {{ \"structureBuilder.levelTemplates\" | transloco }}\r\n </h3>\r\n </div>\r\n\r\n <!-- Tabs using PrimeNG -->\r\n <p-tabs\r\n [(value)]=\"activeTab\"\r\n styleClass=\"structure-tabs \"\r\n class=\"h-full overflow-hidden\"\r\n >\r\n <p-tablist>\r\n @for (tab of availableTabs(); track tab; let i = $index) {\r\n <p-tab [value]=\"i.toString()\">{{ tab | titlecase }}</p-tab>\r\n }\r\n </p-tablist>\r\n <p-tabpanels class=\"bg-transparent! p-0! overflow-auto\">\r\n @for (tab of availableTabs(); track tab; let i = $index) {\r\n <p-tabpanel [value]=\"i.toString()\">\r\n <p class=\"text-xs text-muted py-3 px-4\">\r\n {{ \"structureBuilder.dragToAdd\" | transloco }}\r\n </p>\r\n\r\n <!-- Node List -->\r\n <div class=\"space-y-1 px-4\">\r\n @for (node of currentTabNodes(); track node.id) {\r\n <div\r\n fExternalItem\r\n [fData]=\"node\"\r\n class=\"group select-none relative flex items-center gap-3 py-3 px-4 hover:bg-emphasis hover:border-solid transition-colors rounded-lg border-1 border-dashed border-color border-surface-300 dark:border-surface-500 cursor-move transition-colors\"\r\n >\r\n <!-- Node Icon with color -->\r\n <div class=\"text-primary text-lg\">\r\n <mt-icon [icon]=\"node.icon || 'general.box'\"></mt-icon>\r\n </div>\r\n\r\n <!-- Node Name -->\r\n <span class=\"text-base font-medium flex-1\">{{\r\n node.label\r\n }}</span>\r\n <mt-icon class=\"text-lg\" icon=\"general.menu-05\"></mt-icon>\r\n </div>\r\n }\r\n\r\n @if (currentTabNodes().length === 0) {\r\n <div class=\"text-center py-8 text-gray-400\">\r\n <p class=\"text-sm\">\r\n {{\r\n \"structureBuilder.allItemsInUse\"\r\n | transloco: { tab: tab }\r\n }}\r\n </p>\r\n </div>\r\n }\r\n </div>\r\n </p-tabpanel>\r\n }\r\n </p-tabpanels>\r\n </p-tabs>\r\n </ng-template>\r\n </mt-card>\r\n} @else if (!readonly() && availableNodes().length > 0) {\r\n <div [ngClass]=\"availableTabsClass() || 'absolute top-4 start-4 z-1 w-64'\">\r\n <mt-card [title]=\"'structureBuilder.steps' | transloco\">\r\n <div class=\"flex flex-col gap-2\">\r\n @for (node of availableNodes(); track node.id) {\r\n <div\r\n fExternalItem\r\n [fData]=\"node\"\r\n class=\"group select-none relative flex items-center gap-3 py-3 px-4 hover:bg-emphasis hover:border-solid transition-colors rounded-lg border-1 border-dashed border-color border-surface-300 dark:border-surface-500 cursor-move bg-content\"\r\n >\r\n <!-- Node Icon with color -->\r\n <div class=\"text-primary text-lg\">\r\n <mt-icon [icon]=\"node.icon || 'general.box'\"></mt-icon>\r\n </div>\r\n\r\n <!-- Node Name -->\r\n <span class=\"text-base font-medium flex-1\">{{ node.label }}</span>\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n </div>\r\n}\r\n<!-- Left Sidebar -->\r\n\r\n<!-- Main Canvas Area -->\r\n<div class=\"flex-1 z-0 relative\">\r\n <ng-content select=\"[flowContent]\"></ng-content>\r\n\r\n <f-flow\r\n fDraggable\r\n dir=\"ltr\"\r\n (fLoaded)=\"onLoaded()\"\r\n (fCreateNode)=\"onCreateNode($event)\"\r\n (fCreateConnection)=\"onCreateConnection($event)\"\r\n class=\"size-full\"\r\n >\r\n <f-background>\r\n <f-circle-pattern color=\"#b5b5b5\"></f-circle-pattern>\r\n </f-background>\r\n <f-canvas fZoom [fZoomMinimum]=\"0.1\" [fZoomMaximum]=\"2\">\r\n <f-connection-for-create fBehavior=\"floating\" fType=\"straight\">\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.START\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.END\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n </f-connection-for-create>\r\n <f-snap-connection\r\n fBehavior=\"fixed\"\r\n fType=\"segment\"\r\n class=\"z-1\"\r\n [fSnapThreshold]=\"100\"\r\n >\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.START\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.END\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n </f-snap-connection>\r\n\r\n <f-connection-for-create></f-connection-for-create>\r\n\r\n <!-- Enhanced Connections with Edit Button -->\r\n @for (connection of connectionsComputed(); track connection.id) {\r\n <f-connection\r\n [fReassignDisabled]=\"true\"\r\n [fOutputId]=\"connection.from\"\r\n [fInputId]=\"connection.to\"\r\n fBehavior=\"fixed\"\r\n fType=\"segment\"\r\n [ngClass]=\"{ 'connection-loading': connection.loading, 'z-1': true }\"\r\n >\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.START\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.END\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.SELECTED_START\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.SELECTED_END\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n @if (!readonly()) {\r\n <div\r\n fConnectionCenter\r\n class=\"flex items-center gap-1 bg-content rounded-md p-1 shadow-sm\"\r\n >\r\n @if (!connection.loading) {\r\n <mt-button\r\n size=\"small\"\r\n variant=\"text\"\r\n [icon]=\"'general.edit-05'\"\r\n (click)=\"openConnectionDialog(connection)\"\r\n >\r\n </mt-button>\r\n <mt-button\r\n size=\"small\"\r\n variant=\"text\"\r\n severity=\"danger\"\r\n [icon]=\"'general.trash-01'\"\r\n (click)=\"removeConnection(connection)\"\r\n >\r\n </mt-button>\r\n } @else {\r\n <mt-button\r\n size=\"small\"\r\n variant=\"text\"\r\n [icon]=\"'general.loading-01'\"\r\n >\r\n </mt-button>\r\n }\r\n </div>\r\n }\r\n </f-connection>\r\n }\r\n\r\n <!-- Enhanced Nodes with Edit Button -->\r\n @for (node of nodesWithComputedProps(); track node._computedId) {\r\n <mt-card\r\n fNode\r\n fDragHandle\r\n [fNodePosition]=\"{\r\n x: node.configuration?.x || 200,\r\n y: node.configuration?.y || 100,\r\n }\"\r\n (fNodePositionChange)=\"onNodePositionChange($event, node._computedId)\"\r\n [style.--node-data-border-color]=\"node._computedColor\"\r\n >\r\n <ng-template #headless>\r\n @if (!node.loading) {\r\n <div [attr.dir]=\"contentDirection()\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"\r\n effectiveNodeTemplate() || defaultNodeTemplate\r\n \"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: node,\r\n node: node,\r\n actions: getFilteredNodeActions(node),\r\n onAction: nodeActionHandler,\r\n dir: contentDirection(),\r\n }\"\r\n >\r\n </ng-container>\r\n </div>\r\n <div\r\n fNodeInput\r\n [fInputId]=\"node._computedId\"\r\n [fInputConnectableSide]=\"configuration().inputSide\"\r\n [fInputMultiple]=\"true\"\r\n [ngClass]=\"configuration().inputSide\"\r\n ></div>\r\n\r\n <div\r\n fNodeOutput\r\n [fOutputId]=\"node._computedId\"\r\n [fOutputConnectableSide]=\"configuration().outputSide\"\r\n [isSelfConnectable]=\"false\"\r\n [fOutputMultiple]=\"true\"\r\n [ngClass]=\"configuration().outputSide\"\r\n class=\"bg-surface-50 dark:bg-surface-900\"\r\n ></div>\r\n } @else {\r\n <p-skeleton height=\"10rem\" width=\"15rem\" />\r\n }\r\n\r\n <!-- Node Header with Edit Button -->\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n <ng-template\r\n #defaultNodeTemplate\r\n let-node\r\n let-actions=\"actions\"\r\n let-onAction=\"onAction\"\r\n >\r\n <div\r\n class=\"flex flex-col items-center min-w-3xs gap-2 px-3 py-4 rounded-t-2xl bg-white dark:bg-surface-800 border-(--p-content-border-color)\"\r\n >\r\n @if (node._computedIcon) {\r\n <mt-icon\r\n class=\"text-2xl text-primary\"\r\n [icon]=\"node._computedIcon\"\r\n />\r\n }\r\n <div>{{ node._computedName }}</div>\r\n </div>\r\n <div\r\n class=\"flex justify-center pt-3 mb-4 gap-2 bg-surface-50 dark:bg-surface-900\"\r\n >\r\n @for (action of actions; track action.key) {\r\n <mt-button\r\n [size]=\"action?.size || 'small'\"\r\n [variant]=\"action?.variant\"\r\n [icon]=\"action?.icon\"\r\n [tooltip]=\"action?.tooltip\"\r\n [severity]=\"action?.severity\"\r\n (onClick)=\"onAction(action, node)\"\r\n >\r\n </mt-button>\r\n }\r\n </div>\r\n </ng-template>\r\n </f-canvas>\r\n </f-flow>\r\n</div>\r\n@if (!readonly()) {\r\n <mt-toolbar />\r\n}\r\n", styles: ["::ng-deep :root{--background-element-color: rgba(0, 0, 0, .1);--selection-area-color: rgba(100, 108, 255, .14);--disabled-color: #e2e2e2;--node-background-color: #ffffff;--node-background-color-inverse: #000000;--node-border-radius: 2px;--node-border-color: rgba(60, 60, 67, .36);--node-selected-border-color: #3451b2;--node-color: rgba(60, 60, 67, .78);--node-shadow: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--connection-color: var(--p-text-color);--snap-connection-color: var(--p-text-muted-color);--connection-gradient-1: #b8272c;--connection-gradient-2: #30a46c;--outlet-color: #3451b2;--input-output-color: rgba(60, 60, 67, .78);--minimap-background-color: #ffffff;--minimap-node-color: rgba(60, 60, 67);--minimap-node-selected-color: var(--p-primary-color);--minimap-view-color: rgba(100, 108, 255, .14)}::ng-deep :root.dark{--background-element-color: rgba(255, 255, 255, .1);--selection-area-color: rgba(100, 108, 255, .16);--disabled-color: #2c2c2e;--node-background-color: #000000;--node-background-color-inverse: #ffffff;--node-border-radius: 2px;--node-border-color: rgba(235, 235, 245, .38);--node-selected-border-color: #a8b1ff;--node-color: rgba(235, 235, 245, .6);--node-shadow: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--connection-color: rgba(235, 235, 245, 1);--snap-connection-color: rgba(235, 235, 245, .2);--connection-gradient-1: #f66f81;--connection-gradient-2: #298459;--outlet-color: #a8b1ff;--input-output-color: rgba(235, 235, 245, .6);--minimap-background-color: #1b1b1f;--minimap-node-color: rgba(255, 255, 245, .86);--minimap-node-selected-color: #a8b1ff;--minimap-view-color: rgba(100, 108, 255, .16)}::ng-deep :root{--form-field-text-color: var(--node-color);--form-field-background: var(--minimap-view-color);--form-field-panel-shadow: var(--shadow-4);--form-field-panel-background: var(--node-background-color);--form-field-active-color: var(--minimap-node-selected-color)}::ng-deep f-flow .f-connection{cursor:pointer}::ng-deep f-flow .f-connection .f-connection-drag-handle{fill:transparent}::ng-deep f-flow .f-connection .f-connection-selection{fill:none}::ng-deep f-flow .f-connection .f-connection-path{fill:none;stroke:var(--connection-color);stroke-width:2}::ng-deep f-flow .f-connection .f-connection-marker{fill:var(--connection-color)}::ng-deep f-flow .f-connection .f-marker path,::ng-deep f-flow .f-connection .f-marker circle{fill:var(--connection-color)}::ng-deep f-flow .f-connection .f-connection-text,::ng-deep f-flow .f-connection .f-connection-center{fill:var(--connection-color);color:var(--connection-color)}::ng-deep f-flow .f-connection.f-snap-connection .f-connection-path{stroke:var(--snap-connection-color)}::ng-deep f-flow .f-connection .f-connection-center{display:none}::ng-deep f-flow .f-connection.connection-loading .f-connection-center{display:block}::ng-deep f-flow .f-connection.f-selected .f-connection-center{display:block}::ng-deep f-flow .f-connection.f-selected .f-connection-path{stroke:var(--minimap-node-selected-color)}::ng-deep f-flow .f-connection.f-selected .f-marker path,::ng-deep f-flow .f-connection.f-selected .f-marker circle{fill:var(--p-primary-color);stroke:var(--minimap-node-selected-color)}::ng-deep f-flow .f-connection .f-connection-selection{fill:none;stroke:transparent;stroke-width:20;cursor:pointer}::ng-deep f-flow .f-connection:hover .f-connection-selection{stroke:var(--p-primary-color);opacity:.1}::ng-deep f-flow .f-connection.f-snap-connection .f-connection-path{stroke:var(--snap-connection-color);stroke-width:2px}::ng-deep f-flow .f-connection.f-snap-connection .f-marker path,::ng-deep f-flow .f-connection.f-snap-connection .f-marker circle{fill:var(--snap-connection-color)}::ng-deep f-flow .f-connection.f-snap-connection .f-connection-selection{fill:transparent!important;stroke:transparent!important}::ng-deep f-flow .f-connection.f-connection-for-create .f-connection-selection{fill:transparent!important;stroke:transparent!important}::ng-deep f-flow .f-connection-for-create{pointer-events:none}::ng-deep f-flow .f-connection-for-create .f-connection .f-connection-path{stroke:var(--snap-connection-color);stroke-width:3px;stroke-dasharray:8,4;animation:connection-dash 1s linear infinite}::ng-deep f-flow .f-connection-for-create .f-connection .f-marker path,::ng-deep f-flow .f-connection-for-create .f-connection .f-marker circle{fill:var(--snap-connection-color)}@keyframes connection-dash{to{stroke-dashoffset:-12}}::ng-deep f-flow{direction:ltr}.f-node-input:not(.f-node),.f-node-output:not(.f-node){position:absolute;border-radius:0 0 1rem 1rem}.f-node-input:not(.f-node):hover,.f-node-output:not(.f-node):hover{border:.5px dashed var(--p-primary-color)}.f-node-input:not(.f-node).top,.f-node-input:not(.f-node).bottom,.f-node-output:not(.f-node).top,.f-node-output:not(.f-node).bottom{width:100%;height:16px;left:0}.f-node-input:not(.f-node).top,.f-node-output:not(.f-node).top{top:0}.f-node-input:not(.f-node).bottom,.f-node-output:not(.f-node).bottom{bottom:0}.f-node-input:not(.f-node).left,.f-node-input:not(.f-node).right,.f-node-output:not(.f-node).left,.f-node-output:not(.f-node).right{width:16px;height:100%;top:0}.f-node-input:not(.f-node).left,.f-node-output:not(.f-node).left{left:0;border-radius:1rem 0 0 1rem}.f-node-input:not(.f-node).right,.f-node-output:not(.f-node).right{right:0;border-radius:0 1rem 1rem 0}.f-node-input:not(.f-node).f-node-output-not-connectable,.f-node-input:not(.f-node).f-node-input-not-connectable,.f-node-output:not(.f-node).f-node-output-not-connectable,.f-node-output:not(.f-node).f-node-input-not-connectable{background-color:var(--disabled-color)}.f-node-input:not(.f-node){border-radius:4px}.f-node-input,.f-node-output{z-index:10;pointer-events:all}.examples-toolbar{display:flex;justify-content:flex-end;align-items:center;flex-wrap:wrap;gap:8px;position:absolute;right:16px;top:16px}.examples-toolbar button{font-weight:500;border:none;border-radius:2px;padding:4px 8px;line-height:normal}.f-node:before{content:\"\";position:absolute;width:100%;height:4rem;border-radius:var(--radius-2xl);z-index:-1;top:-.25rem;background-color:var(--node-data-border-color)}.connection-center{display:flex;gap:8px;background:var(--node-background-color);border:1px solid var(--node-border-color);border-radius:4px;padding:4px;box-shadow:var(--node-shadow)}.connection-center .connection-edit-btn,.connection-center .connection-delete-btn{background:none;border:none;width:24px;height:24px;border-radius:4px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s ease}.connection-center .connection-edit-btn:hover,.connection-center .connection-delete-btn:hover{background-color:var(--minimap-view-color)}.connection-center .connection-edit-btn{color:var(--minimap-node-selected-color)}.connection-center .connection-delete-btn{color:#ef4444}.node-edit-btn,.node-delete-btn{background:none;border:none;width:32px;height:32px;border-radius:6px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s ease}.node-edit-btn:hover,.node-delete-btn:hover{background-color:var(--minimap-view-color)}.node-edit-btn{color:var(--minimap-node-selected-color)}.node-delete-btn{color:#ef4444}.node-properties{max-height:200px;overflow-y:auto}.node-properties .property-item{display:flex;justify-content:space-between;padding:4px 0;border-bottom:1px solid var(--node-border-color);font-size:12px}.node-properties .property-item .property-key{font-weight:600;color:var(--node-color);margin-right:8px}.node-properties .property-item .property-value{color:var(--minimap-node-selected-color);word-break:break-word}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: FFlowModule }, { kind: "component", type: i2$1.FFlowComponent, selector: "f-flow", inputs: ["fFlowId"], outputs: ["fLoaded"] }, { kind: "component", type: i2$1.FCanvasComponent, selector: "f-canvas", inputs: ["position", "scale", "debounceTime"], outputs: ["fCanvasChange"] }, { kind: "component", type: i2$1.FBackgroundComponent, selector: "f-background" }, { kind: "component", type: i2$1.FCirclePatternComponent, selector: "f-circle-pattern", inputs: ["id", "color", "radius"] }, { kind: "directive", type: i2$1.FZoomDirective, selector: "f-canvas[fZoom]", inputs: ["fZoom", "fWheelTrigger", "fDblClickTrigger", "fZoomMinimum", "fZoomMaximum", "fZoomStep", "fZoomDblClickStep"], exportAs: ["fComponent"] }, { kind: "directive", type: i2$1.FExternalItemDirective, selector: "[fExternalItem]", inputs: ["fExternalItemId", "fData", "fDisabled", "fPreview", "fPreviewMatchSize", "fPlaceholder"] }, { kind: "component", type: i2$1.FConnectionComponent, selector: "f-connection", inputs: ["fConnectionId", "fText", "fTextStartOffset", "fOutputId", "fInputId", "fRadius", "fOffset", "fBehavior", "fType", "fSelectionDisabled", "fReassignableStart", "fReassignDisabled", "fInputSide", "fOutputSide"], exportAs: ["fComponent"] }, { kind: "directive", type: i2$1.FConnectionCenterDirective, selector: "[fConnectionCenter]", inputs: ["fConnectionCenter"] }, { kind: "component", type: i2$1.FConnectionForCreateComponent, selector: "f-connection-for-create", inputs: ["fRadius", "fOffset", "fBehavior", "fType", "fInputSide", "fOutputSide"] }, { kind: "directive", type: i2$1.FMarkerDirective, selector: "svg[fMarker]", inputs: ["width", "height", "refX", "refY", "type", "orient", "markerUnits"] }, { kind: "component", type: i2$1.FSnapConnectionComponent, selector: "f-snap-connection", inputs: ["fSnapThreshold", "fRadius", "fOffset", "fBehavior", "fType", "fInputSide", "fOutputSide"] }, { kind: "directive", type: i2$1.FNodeInputDirective, selector: "[fNodeInput]", inputs: ["fInputId", "fInputCategory", "fInputMultiple", "fInputDisabled", "fInputConnectableSide"], exportAs: ["fNodeInput"] }, { kind: "directive", type: i2$1.FNodeOutputDirective, selector: "[fNodeOutput]", inputs: ["fOutputId", "fOutputMultiple", "fOutputDisabled", "fOutputConnectableSide", "isSelfConnectable", "fCanBeConnectedInputs"], exportAs: ["fNodeOutput"] }, { kind: "directive", type: i2$1.FNodeDirective, selector: "[fNode]", inputs: ["fNodeId", "fNodeParentId", "fNodePosition", "fNodeSize", "fNodeRotate", "fConnectOnNode", "fMinimapClass", "fNodeDraggingDisabled", "fNodeSelectionDisabled", "fIncludePadding", "fAutoExpandOnChildHit", "fAutoSizeToFitChildren"], outputs: ["fNodePositionChange", "fNodeSizeChange", "fNodeRotateChange"], exportAs: ["fComponent"] }, { kind: "directive", type: i2$1.FDragHandleDirective, selector: "[fDragHandle]" }, { kind: "directive", type: i2$1.FDraggableDirective, selector: "f-flow[fDraggable]", inputs: ["fDraggableDisabled", "fMultiSelectTrigger", "fReassignConnectionTrigger", "fCreateConnectionTrigger", "fNodeResizeTrigger", "fNodeRotateTrigger", "fNodeMoveTrigger", "fCanvasMoveTrigger", "fExternalItemTrigger", "fEmitOnNodeIntersect", "vCellSize", "hCellSize", "fCellSizeWhileDragging"], outputs: ["fSelectionChange", "fNodeIntersectedWithConnections", "fCreateNode", "fMoveNodes", "fReassignConnection", "fCreateConnection", "fDropToGroup", "fDragStarted", "fDragEnded"], exportAs: ["fDraggable"] }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i3$1.Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: i3$1.TabPanels, selector: "p-tabpanels" }, { kind: "component", type: i3$1.TabPanel, selector: "p-tabpanel", inputs: ["lazy", "value"], outputs: ["valueChange"] }, { kind: "component", type: i3$1.TabList, selector: "p-tablist" }, { kind: "component", type: i3$1.Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Toolbar, selector: "mt-toolbar", inputs: ["size"] }, { kind: "component", type: Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i1.TitleCasePipe, name: "titlecase" }, { kind: "pipe", type: i3.TranslocoPipe, name: "transloco" }] });
647
+ extractNodeId(connectionEndId) {
648
+ return (connectionEndId || '')
649
+ .replace(STRUCTURE_BUILDER_CONNECTOR_SUFFIX, '')
650
+ .replace(/-(in|out)$/, '');
651
+ }
652
+ resolveConnectionConnectorSides(connection) {
653
+ const sourcePosition = this.nodePositionsById()[connection.from];
654
+ const targetPosition = this.nodePositionsById()[connection.to];
655
+ const direction = this.effectiveDirection();
656
+ if (!sourcePosition || !targetPosition) {
657
+ return {
658
+ inputSide: this.configuration().inputSide,
659
+ outputSide: this.configuration().outputSide,
660
+ };
661
+ }
662
+ if (direction === Direction.TOP_TO_BOTTOM) {
663
+ return sourcePosition.y <= targetPosition.y
664
+ ? { inputSide: 'top', outputSide: 'bottom' }
665
+ : { inputSide: 'bottom', outputSide: 'top' };
666
+ }
667
+ return sourcePosition.x >= targetPosition.x
668
+ ? { inputSide: 'right', outputSide: 'left' }
669
+ : { inputSide: 'left', outputSide: 'right' };
670
+ }
671
+ resolveLayoutEdge(connection, direction, nodePositions) {
672
+ const sourcePosition = nodePositions[connection.from];
673
+ const targetPosition = nodePositions[connection.to];
674
+ if (!sourcePosition || !targetPosition) {
675
+ return [connection.from, connection.to];
676
+ }
677
+ if (direction === Direction.TOP_TO_BOTTOM) {
678
+ return sourcePosition.y <= targetPosition.y
679
+ ? [connection.from, connection.to]
680
+ : [connection.to, connection.from];
681
+ }
682
+ if (direction === Direction.RIGHT_TO_LEFT) {
683
+ return sourcePosition.x >= targetPosition.x
684
+ ? [connection.from, connection.to]
685
+ : [connection.to, connection.from];
686
+ }
687
+ return sourcePosition.x <= targetPosition.x
688
+ ? [connection.from, connection.to]
689
+ : [connection.to, connection.from];
690
+ }
691
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: StructureBuilder, deps: [], target: i0.ɵɵFactoryTarget.Component });
692
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: StructureBuilder, isStandalone: true, selector: "mt-structure-builder", inputs: { availableNodes: { classPropertyName: "availableNodes", publicName: "availableNodes", isSignal: true, isRequired: false, transformFunction: null }, nodeForm: { classPropertyName: "nodeForm", publicName: "nodeForm", isSignal: true, isRequired: false, transformFunction: null }, nodeDialogFooterConfig: { classPropertyName: "nodeDialogFooterConfig", publicName: "nodeDialogFooterConfig", isSignal: true, isRequired: false, transformFunction: null }, connectionForm: { classPropertyName: "connectionForm", publicName: "connectionForm", isSignal: true, isRequired: false, transformFunction: null }, connectionFormulaSchemaId: { classPropertyName: "connectionFormulaSchemaId", publicName: "connectionFormulaSchemaId", isSignal: true, isRequired: false, transformFunction: null }, connectionFormulaConfig: { classPropertyName: "connectionFormulaConfig", publicName: "connectionFormulaConfig", isSignal: true, isRequired: false, transformFunction: null }, nodeActions: { classPropertyName: "nodeActions", publicName: "nodeActions", isSignal: true, isRequired: false, transformFunction: null }, nodeFields: { classPropertyName: "nodeFields", publicName: "nodeFields", isSignal: true, isRequired: false, transformFunction: null }, isAutoLayout: { classPropertyName: "isAutoLayout", publicName: "isAutoLayout", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, addModalType: { classPropertyName: "addModalType", publicName: "addModalType", isSignal: true, isRequired: false, transformFunction: null }, updateModalType: { classPropertyName: "updateModalType", publicName: "updateModalType", isSignal: true, isRequired: false, transformFunction: null }, addModalStyleClass: { classPropertyName: "addModalStyleClass", publicName: "addModalStyleClass", isSignal: true, isRequired: false, transformFunction: null }, updateModalStyleClass: { classPropertyName: "updateModalStyleClass", publicName: "updateModalStyleClass", isSignal: true, isRequired: false, transformFunction: null }, addModalHeader: { classPropertyName: "addModalHeader", publicName: "addModalHeader", isSignal: true, isRequired: false, transformFunction: null }, updateModalHeader: { classPropertyName: "updateModalHeader", publicName: "updateModalHeader", isSignal: true, isRequired: false, transformFunction: null }, appendTo: { classPropertyName: "appendTo", publicName: "appendTo", isSignal: true, isRequired: false, transformFunction: null }, availableTabsClass: { classPropertyName: "availableTabsClass", publicName: "availableTabsClass", isSignal: true, isRequired: false, transformFunction: null }, layoutDirection: { classPropertyName: "layoutDirection", publicName: "layoutDirection", isSignal: true, isRequired: false, transformFunction: null }, nodes: { classPropertyName: "nodes", publicName: "nodes", isSignal: true, isRequired: false, transformFunction: null }, connections: { classPropertyName: "connections", publicName: "connections", isSignal: true, isRequired: false, transformFunction: null }, nodeTemplate: { classPropertyName: "nodeTemplate", publicName: "nodeTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { nodeActionsEvent: "nodeActionsEvent", action: "action", nodes: "nodesChange", connections: "connectionsChange" }, host: { classAttribute: "flex h-full bg-surface-200 dark:bg-surface-700 relative rounded-2xl overflow-hidden" }, providers: [DialogService], queries: [{ propertyName: "nodeDialogTemplate", first: true, predicate: ["nodeDialog"], descendants: true, isSignal: true }, { propertyName: "nodeTemplateContent", first: true, predicate: ["nodeTemplate"], descendants: true, isSignal: true }], viewQueries: [{ propertyName: "fCanvas", first: true, predicate: FCanvasComponent, descendants: true, isSignal: true }, { propertyName: "fFlowComponent", first: true, predicate: FFlowComponent, descendants: true, isSignal: true }, { propertyName: "fCanvasComponent", first: true, predicate: FCanvasComponent, descendants: true, isSignal: true }, { propertyName: "fZoomDirective", first: true, predicate: FZoomDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<!-- structure-builder.html -->\r\n@if (!readonly() && availableTabs().length > 0) {\r\n <mt-card\r\n class=\"absolute ms-4 mt-4 z-1 h-[calc(100%---spacing(8))] w-1/5 min-w-xs\"\r\n >\r\n <ng-template #headless>\r\n <!-- Header -->\r\n <div class=\"flex items-center justify-between px-4 pt-5\">\r\n <h3 class=\"text-xl font-semibold\">\r\n {{ \"structureBuilder.levelTemplates\" | transloco }}\r\n </h3>\r\n </div>\r\n\r\n <!-- Tabs using PrimeNG -->\r\n <p-tabs\r\n [(value)]=\"activeTab\"\r\n styleClass=\"structure-tabs \"\r\n class=\"h-full overflow-hidden\"\r\n >\r\n <p-tablist>\r\n @for (tab of availableTabs(); track tab; let i = $index) {\r\n <p-tab [value]=\"i.toString()\">{{ tab | titlecase }}</p-tab>\r\n }\r\n </p-tablist>\r\n <p-tabpanels class=\"bg-transparent! p-0! overflow-auto\">\r\n @for (tab of availableTabs(); track tab; let i = $index) {\r\n <p-tabpanel [value]=\"i.toString()\">\r\n <p class=\"text-xs text-muted py-3 px-4\">\r\n {{ \"structureBuilder.dragToAdd\" | transloco }}\r\n </p>\r\n\r\n <!-- Node List -->\r\n <div class=\"space-y-1 px-4\">\r\n @for (node of currentTabNodes(); track node.id) {\r\n <div\r\n fExternalItem\r\n [fData]=\"node\"\r\n style=\"display: flex\"\r\n class=\"group select-none relative flex items-center gap-3 py-3 px-4 hover:bg-emphasis hover:border-solid transition-colors rounded-lg border-1 border-dashed border-color border-surface-300 dark:border-surface-500 cursor-move transition-colors\"\r\n >\r\n <!-- Node Icon with color -->\r\n <div class=\"text-primary text-lg\">\r\n <mt-icon [icon]=\"node.icon || 'general.box'\"></mt-icon>\r\n </div>\r\n\r\n <!-- Node Name -->\r\n <span class=\"text-base font-medium flex-1\">{{\r\n node.label\r\n }}</span>\r\n <mt-icon class=\"text-lg\" icon=\"general.menu-05\"></mt-icon>\r\n </div>\r\n }\r\n\r\n @if (currentTabNodes().length === 0) {\r\n <div class=\"text-center py-8 text-gray-400\">\r\n <p class=\"text-sm\">\r\n {{\r\n \"structureBuilder.allItemsInUse\"\r\n | transloco: { tab: tab }\r\n }}\r\n </p>\r\n </div>\r\n }\r\n </div>\r\n </p-tabpanel>\r\n }\r\n </p-tabpanels>\r\n </p-tabs>\r\n </ng-template>\r\n </mt-card>\r\n} @else if (!readonly() && availableNodes().length > 0) {\r\n <div [ngClass]=\"availableTabsClass() || 'absolute top-4 start-4 z-1 w-64'\">\r\n <mt-card [title]=\"'structureBuilder.steps' | transloco\">\r\n <div class=\"flex flex-col gap-2\">\r\n @for (node of availableNodes(); track node.id) {\r\n <div\r\n fExternalItem\r\n [fData]=\"node\"\r\n style=\"display: flex\"\r\n class=\"group select-none relative flex items-center gap-3 py-3 px-4 hover:bg-emphasis hover:border-solid transition-colors rounded-lg border-1 border-dashed border-color border-surface-300 dark:border-surface-500 cursor-move bg-content\"\r\n >\r\n <!-- Node Icon with color -->\r\n <div class=\"text-primary text-lg\">\r\n <mt-icon [icon]=\"node.icon || 'general.box'\"></mt-icon>\r\n </div>\r\n\r\n <!-- Node Name -->\r\n <span class=\"text-base font-medium flex-1\">{{ node.label }}</span>\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n </div>\r\n}\r\n<!-- Left Sidebar -->\r\n\r\n<!-- Main Canvas Area -->\r\n<div class=\"flex-1 z-0 relative\">\r\n <ng-content select=\"[flowContent]\"></ng-content>\r\n\r\n <f-flow\r\n fDraggable\r\n dir=\"ltr\"\r\n (fLoaded)=\"onLoaded()\"\r\n (fCreateNode)=\"onCreateNode($event)\"\r\n (fCreateConnection)=\"onCreateConnection($event)\"\r\n class=\"size-full\"\r\n >\r\n <f-background>\r\n <f-circle-pattern color=\"#b5b5b5\"></f-circle-pattern>\r\n </f-background>\r\n <f-canvas fZoom [fZoomMinimum]=\"0.1\" [fZoomMaximum]=\"2\">\r\n <f-connection-for-create fBehavior=\"floating\" fType=\"straight\">\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.START\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.END\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n </f-connection-for-create>\r\n <f-snap-connection\r\n fBehavior=\"fixed\"\r\n fType=\"segment\"\r\n class=\"z-1\"\r\n [fSnapThreshold]=\"100\"\r\n >\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.START\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.END\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n </f-snap-connection>\r\n\r\n <f-connection-for-create></f-connection-for-create>\r\n\r\n <!-- Enhanced Connections with Edit Button -->\r\n @for (connection of renderedConnections(); track connection.id) {\r\n <f-connection\r\n [fReassignDisabled]=\"true\"\r\n [fOutputId]=\"connection._outputConnectorId\"\r\n [fInputId]=\"connection._inputConnectorId\"\r\n [fOutputSide]=\"connection._outputSide\"\r\n [fInputSide]=\"connection._inputSide\"\r\n fBehavior=\"fixed\"\r\n fType=\"segment\"\r\n [ngClass]=\"{ 'connection-loading': connection.loading, 'z-1': true }\"\r\n >\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.START\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.END\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.SELECTED_START\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.SELECTED_END\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n @if (!readonly()) {\r\n <div\r\n fConnectionContent\r\n class=\"flex items-center gap-1 bg-content rounded-md p-1 shadow-sm\"\r\n >\r\n @if (!connection.loading) {\r\n <mt-button\r\n size=\"small\"\r\n variant=\"text\"\r\n [icon]=\"'general.edit-05'\"\r\n (click)=\"openConnectionDialog(connection)\"\r\n >\r\n </mt-button>\r\n <mt-button\r\n size=\"small\"\r\n variant=\"text\"\r\n severity=\"danger\"\r\n [icon]=\"'general.trash-01'\"\r\n (click)=\"removeConnection(connection)\"\r\n >\r\n </mt-button>\r\n } @else {\r\n <mt-button\r\n size=\"small\"\r\n variant=\"text\"\r\n [icon]=\"'general.loading-01'\"\r\n >\r\n </mt-button>\r\n }\r\n </div>\r\n }\r\n </f-connection>\r\n }\r\n\r\n <!-- Enhanced Nodes with Edit Button -->\r\n @for (node of nodesWithComputedProps(); track node._computedId) {\r\n <mt-card\r\n fNode\r\n fDragHandle\r\n [fNodePosition]=\"{\r\n x: node.configuration?.x || 200,\r\n y: node.configuration?.y || 100,\r\n }\"\r\n (fNodePositionChange)=\"onNodePositionChange($event, node._computedId)\"\r\n [style.--node-data-border-color]=\"node._computedColor\"\r\n >\r\n <ng-template #headless>\r\n @if (!node.loading) {\r\n <div [attr.dir]=\"contentDirection()\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"\r\n effectiveNodeTemplate() || defaultNodeTemplate\r\n \"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: node,\r\n node: node,\r\n actions: getFilteredNodeActions(node),\r\n onAction: nodeActionHandler,\r\n dir: contentDirection(),\r\n }\"\r\n >\r\n </ng-container>\r\n </div>\r\n @for (side of nodeConnectorSides(); track side) {\r\n <div\r\n fNodeInput\r\n [fInputId]=\"\r\n createConnectorId(node._computedId, 'input', side)\r\n \"\r\n [fInputConnectableSide]=\"side\"\r\n [fInputMultiple]=\"true\"\r\n class=\"sb-connector sb-connector-input\"\r\n [class.top]=\"side === 'top'\"\r\n [class.bottom]=\"side === 'bottom'\"\r\n [class.left]=\"side === 'left'\"\r\n [class.right]=\"side === 'right'\"\r\n ></div>\r\n\r\n <div\r\n fNodeOutput\r\n [fOutputId]=\"\r\n createConnectorId(node._computedId, 'output', side)\r\n \"\r\n [fOutputConnectableSide]=\"side\"\r\n [isSelfConnectable]=\"false\"\r\n [fOutputMultiple]=\"true\"\r\n class=\"sb-connector sb-connector-output bg-surface-50 dark:bg-surface-900\"\r\n [class.top]=\"side === 'top'\"\r\n [class.bottom]=\"side === 'bottom'\"\r\n [class.left]=\"side === 'left'\"\r\n [class.right]=\"side === 'right'\"\r\n ></div>\r\n }\r\n } @else {\r\n <p-skeleton height=\"10rem\" width=\"15rem\" />\r\n }\r\n\r\n <!-- Node Header with Edit Button -->\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n <ng-template\r\n #defaultNodeTemplate\r\n let-node\r\n let-actions=\"actions\"\r\n let-onAction=\"onAction\"\r\n >\r\n <div\r\n class=\"flex flex-col items-center min-w-3xs gap-2 px-3 py-4 rounded-t-2xl bg-white dark:bg-surface-800 border-(--p-content-border-color)\"\r\n >\r\n @if (node._computedIcon) {\r\n <mt-icon\r\n class=\"text-2xl text-primary\"\r\n [icon]=\"node._computedIcon\"\r\n />\r\n }\r\n <div>{{ node._computedName }}</div>\r\n </div>\r\n <div\r\n class=\"flex justify-center pt-3 mb-4 gap-2 bg-surface-50 dark:bg-surface-900\"\r\n >\r\n @for (action of actions; track action.key) {\r\n <mt-button\r\n [size]=\"action?.size || 'small'\"\r\n [variant]=\"action?.variant\"\r\n [icon]=\"action?.icon\"\r\n [tooltip]=\"action?.tooltip\"\r\n [severity]=\"action?.severity\"\r\n (onClick)=\"onAction(action, node)\"\r\n >\r\n </mt-button>\r\n }\r\n </div>\r\n </ng-template>\r\n </f-canvas>\r\n </f-flow>\r\n</div>\r\n@if (!readonly()) {\r\n <mt-toolbar />\r\n}\r\n", styles: ["::ng-deep :root{--background-element-color: rgba(0, 0, 0, .1);--selection-area-color: rgba(100, 108, 255, .14);--disabled-color: #e2e2e2;--node-background-color: #ffffff;--node-background-color-inverse: #000000;--node-border-radius: 2px;--node-border-color: rgba(60, 60, 67, .36);--node-selected-border-color: #3451b2;--node-color: rgba(60, 60, 67, .78);--node-shadow: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--connection-color: var(--p-text-color);--snap-connection-color: var(--p-text-muted-color);--connection-gradient-1: #b8272c;--connection-gradient-2: #30a46c;--outlet-color: #3451b2;--input-output-color: rgba(60, 60, 67, .78);--minimap-background-color: #ffffff;--minimap-node-color: rgba(60, 60, 67);--minimap-node-selected-color: var(--p-primary-color);--minimap-view-color: rgba(100, 108, 255, .14)}::ng-deep :root.dark{--background-element-color: rgba(255, 255, 255, .1);--selection-area-color: rgba(100, 108, 255, .16);--disabled-color: #2c2c2e;--node-background-color: #000000;--node-background-color-inverse: #ffffff;--node-border-radius: 2px;--node-border-color: rgba(235, 235, 245, .38);--node-selected-border-color: #a8b1ff;--node-color: rgba(235, 235, 245, .6);--node-shadow: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--connection-color: rgba(235, 235, 245, 1);--snap-connection-color: rgba(235, 235, 245, .2);--connection-gradient-1: #f66f81;--connection-gradient-2: #298459;--outlet-color: #a8b1ff;--input-output-color: rgba(235, 235, 245, .6);--minimap-background-color: #1b1b1f;--minimap-node-color: rgba(255, 255, 245, .86);--minimap-node-selected-color: #a8b1ff;--minimap-view-color: rgba(100, 108, 255, .16)}::ng-deep :root{--form-field-text-color: var(--node-color);--form-field-background: var(--minimap-view-color);--form-field-panel-shadow: var(--shadow-4);--form-field-panel-background: var(--node-background-color);--form-field-active-color: var(--minimap-node-selected-color)}::ng-deep f-flow .f-connection{cursor:pointer}::ng-deep f-flow .f-connection .f-connection-drag-handle{fill:transparent}::ng-deep f-flow .f-connection .f-connection-selection{fill:none}::ng-deep f-flow .f-connection .f-connection-path{fill:none;stroke:var(--connection-color);stroke-width:2}::ng-deep f-flow .f-connection .f-connection-marker{fill:var(--connection-color)}::ng-deep f-flow .f-connection .f-marker path,::ng-deep f-flow .f-connection .f-marker circle{fill:var(--connection-color)}::ng-deep f-flow .f-connection .f-connection-text,::ng-deep f-flow .f-connection .f-connection-center,::ng-deep f-flow .f-connection .f-connection-content{fill:var(--connection-color);color:var(--connection-color)}::ng-deep f-flow .f-connection.f-snap-connection .f-connection-path{stroke:var(--snap-connection-color)}::ng-deep f-flow .f-connection .f-connection-center,::ng-deep f-flow .f-connection .f-connection-content{display:none}::ng-deep f-flow .f-connection.connection-loading .f-connection-center,::ng-deep f-flow .f-connection.connection-loading .f-connection-content{display:block}::ng-deep f-flow .f-connection.f-selected .f-connection-center,::ng-deep f-flow .f-connection.f-selected .f-connection-content{display:block}::ng-deep f-flow .f-connection.f-selected .f-connection-path{stroke:var(--minimap-node-selected-color)}::ng-deep f-flow .f-connection.f-selected .f-marker path,::ng-deep f-flow .f-connection.f-selected .f-marker circle{fill:var(--p-primary-color);stroke:var(--minimap-node-selected-color)}::ng-deep f-flow .f-connection .f-connection-selection{fill:none;stroke:transparent;stroke-width:20;cursor:pointer}::ng-deep f-flow .f-connection:hover .f-connection-selection{stroke:var(--p-primary-color);opacity:.1}::ng-deep f-flow .f-connection.f-snap-connection .f-connection-path{stroke:var(--snap-connection-color);stroke-width:2px}::ng-deep f-flow .f-connection.f-snap-connection .f-marker path,::ng-deep f-flow .f-connection.f-snap-connection .f-marker circle{fill:var(--snap-connection-color)}::ng-deep f-flow .f-connection.f-snap-connection .f-connection-selection{fill:transparent!important;stroke:transparent!important}::ng-deep f-flow .f-connection.f-connection-for-create .f-connection-selection{fill:transparent!important;stroke:transparent!important}::ng-deep f-flow .f-connection-for-create{pointer-events:none}::ng-deep f-flow .f-connection-for-create .f-connection .f-connection-path{stroke:var(--snap-connection-color);stroke-width:3px;stroke-dasharray:8,4;animation:connection-dash 1s linear infinite}::ng-deep f-flow .f-connection-for-create .f-connection .f-marker path,::ng-deep f-flow .f-connection-for-create .f-connection .f-marker circle{fill:var(--snap-connection-color)}@keyframes connection-dash{to{stroke-dashoffset:-12}}::ng-deep f-flow{direction:ltr}.f-node-input:not(.f-node),.f-node-output:not(.f-node){position:absolute}.f-node-input:not(.f-node):hover,.f-node-output:not(.f-node):hover{border:.5px dashed var(--p-primary-color)}.f-node-input:not(.f-node).top,.f-node-input:not(.f-node).bottom,.f-node-output:not(.f-node).top,.f-node-output:not(.f-node).bottom{width:100%;height:16px;left:0}.f-node-input:not(.f-node).top,.f-node-output:not(.f-node).top{top:0;border-radius:1rem 1rem 0 0}.f-node-input:not(.f-node).bottom,.f-node-output:not(.f-node).bottom{bottom:0;border-radius:0 0 1rem 1rem}.f-node-input:not(.f-node).left,.f-node-input:not(.f-node).right,.f-node-output:not(.f-node).left,.f-node-output:not(.f-node).right{width:16px;height:100%;top:0}.f-node-input:not(.f-node).left,.f-node-output:not(.f-node).left{left:0;border-radius:1rem 0 0 1rem}.f-node-input:not(.f-node).right,.f-node-output:not(.f-node).right{right:0;border-radius:0 1rem 1rem 0}.f-node-input:not(.f-node).f-node-output-not-connectable,.f-node-input:not(.f-node).f-node-input-not-connectable,.f-node-output:not(.f-node).f-node-output-not-connectable,.f-node-output:not(.f-node).f-node-input-not-connectable{background-color:var(--disabled-color)}.sb-connector-input,.sb-connector-output{background-color:transparent!important}.f-node-input:not(.f-node){border-radius:4px}.f-node-input,.f-node-output{z-index:10;pointer-events:all}.examples-toolbar{display:flex;justify-content:flex-end;align-items:center;flex-wrap:wrap;gap:8px;position:absolute;right:16px;top:16px}.examples-toolbar button{font-weight:500;border:none;border-radius:2px;padding:4px 8px;line-height:normal}.f-node:before{content:\"\";position:absolute;width:100%;height:4rem;border-radius:var(--radius-2xl);z-index:-1;top:-.25rem;background-color:var(--node-data-border-color)}.connection-center{display:flex;gap:8px;background:var(--node-background-color);border:1px solid var(--node-border-color);border-radius:4px;padding:4px;box-shadow:var(--node-shadow)}.connection-center .connection-edit-btn,.connection-center .connection-delete-btn{background:none;border:none;width:24px;height:24px;border-radius:4px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s ease}.connection-center .connection-edit-btn:hover,.connection-center .connection-delete-btn:hover{background-color:var(--minimap-view-color)}.connection-center .connection-edit-btn{color:var(--minimap-node-selected-color)}.connection-center .connection-delete-btn{color:#ef4444}.node-edit-btn,.node-delete-btn{background:none;border:none;width:32px;height:32px;border-radius:6px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s ease}.node-edit-btn:hover,.node-delete-btn:hover{background-color:var(--minimap-view-color)}.node-edit-btn{color:var(--minimap-node-selected-color)}.node-delete-btn{color:#ef4444}.node-properties{max-height:200px;overflow-y:auto}.node-properties .property-item{display:flex;justify-content:space-between;padding:4px 0;border-bottom:1px solid var(--node-border-color);font-size:12px}.node-properties .property-item .property-key{font-weight:600;color:var(--node-color);margin-right:8px}.node-properties .property-item .property-value{color:var(--minimap-node-selected-color);word-break:break-word}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: FFlowModule }, { kind: "component", type: i2$1.FFlowComponent, selector: "f-flow", inputs: ["fFlowId", "fCache"], outputs: ["fLoaded"] }, { kind: "component", type: i2$1.FCanvasComponent, selector: "f-canvas", inputs: ["position", "scale", "debounceTime"], outputs: ["fCanvasChange"] }, { kind: "component", type: i2$1.FBackgroundComponent, selector: "f-background" }, { kind: "component", type: i2$1.FCirclePatternComponent, selector: "f-circle-pattern", inputs: ["id", "color", "radius"] }, { kind: "directive", type: i2$1.FZoomDirective, selector: "f-canvas[fZoom]", inputs: ["fZoom", "fWheelTrigger", "fDblClickTrigger", "fZoomMinimum", "fZoomMaximum", "fZoomStep", "fZoomDblClickStep"] }, { kind: "directive", type: i2$1.FExternalItem, selector: "[fExternalItem]", inputs: ["fExternalItemId", "fData", "fDisabled", "fPreview", "fPreviewMatchSize", "fPlaceholder"], outputs: ["fPreviewChange", "fPlaceholderChange"] }, { kind: "directive", type: i2$1.FConnectionContent, selector: "[fConnectionContent]", inputs: ["position", "offset", "align"] }, { kind: "directive", type: i2$1.FConnectionMarker, selector: "svg[fMarker]", inputs: ["width", "height", "refX", "refY", "type", "orient", "markerUnits"] }, { kind: "component", type: i2$1.FConnectionComponent, selector: "f-connection", inputs: ["fConnectionId", "fOutputId", "fInputId", "fRadius", "fOffset", "fBehavior", "fType", "fSelectionDisabled", "fReassignableStart", "fReassignDisabled", "fInputSide", "fOutputSide"], exportAs: ["fComponent"] }, { kind: "component", type: i2$1.FConnectionForCreateComponent, selector: "f-connection-for-create", inputs: ["fRadius", "fOffset", "fBehavior", "fType", "fInputSide", "fOutputSide"] }, { kind: "component", type: i2$1.FSnapConnectionComponent, selector: "f-snap-connection", inputs: ["fSnapThreshold", "fRadius", "fOffset", "fBehavior", "fType", "fInputSide", "fOutputSide"] }, { kind: "directive", type: i2$1.FNodeInputDirective, selector: "[fNodeInput]", inputs: ["fInputId", "fInputCategory", "fInputMultiple", "fInputDisabled", "fInputConnectableSide"], exportAs: ["fNodeInput"] }, { kind: "directive", type: i2$1.FNodeOutputDirective, selector: "[fNodeOutput]", inputs: ["fOutputId", "fOutputMultiple", "fOutputDisabled", "fOutputConnectableSide", "isSelfConnectable", "fCanBeConnectedInputs"], exportAs: ["fNodeOutput"] }, { kind: "directive", type: i2$1.FNodeDirective, selector: "[fNode]", inputs: ["fNodeId", "fNodeParentId", "fNodePosition", "fNodeSize", "fNodeRotate", "fConnectOnNode", "fMinimapClass", "fNodeDraggingDisabled", "fNodeSelectionDisabled", "fIncludePadding", "fAutoExpandOnChildHit", "fAutoSizeToFitChildren"], outputs: ["fNodePositionChange", "fNodeSizeChange", "fNodeRotateChange"], exportAs: ["fComponent"] }, { kind: "directive", type: i2$1.FDragHandleDirective, selector: "[fDragHandle]" }, { kind: "directive", type: i2$1.FDraggableDirective, selector: "f-flow[fDraggable]", inputs: ["fDraggableDisabled", "fMultiSelectTrigger", "fReassignConnectionTrigger", "fCreateConnectionTrigger", "fConnectionWaypointsTrigger", "fMoveControlPointTrigger", "fNodeResizeTrigger", "fNodeRotateTrigger", "fNodeMoveTrigger", "fCanvasMoveTrigger", "fExternalItemTrigger", "fEmitOnNodeIntersect", "vCellSize", "hCellSize", "fCellSizeWhileDragging"], outputs: ["fSelectionChange", "fNodeIntersectedWithConnections", "fNodeConnectionsIntersection", "fCreateNode", "fMoveNodes", "fReassignConnection", "fCreateConnection", "fConnectionWaypointsChanged", "fDropToGroup", "fDragStarted", "fDragEnded"], exportAs: ["fDraggable"] }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i3$1.Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: i3$1.TabPanels, selector: "p-tabpanels" }, { kind: "component", type: i3$1.TabPanel, selector: "p-tabpanel", inputs: ["lazy", "value"], outputs: ["valueChange"] }, { kind: "component", type: i3$1.TabList, selector: "p-tablist" }, { kind: "component", type: i3$1.Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Toolbar, selector: "mt-toolbar", inputs: ["size"] }, { kind: "component", type: Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i1.TitleCasePipe, name: "titlecase" }, { kind: "pipe", type: i3.TranslocoPipe, name: "transloco" }] });
621
693
  }
622
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: StructureBuilder, decorators: [{
694
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: StructureBuilder, decorators: [{
623
695
  type: Component,
624
696
  args: [{ selector: 'mt-structure-builder', standalone: true, imports: [
625
697
  CommonModule,
@@ -634,7 +706,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
634
706
  TranslocoModule,
635
707
  ], providers: [DialogService], host: {
636
708
  class: 'flex h-full bg-surface-200 dark:bg-surface-700 relative rounded-2xl overflow-hidden',
637
- }, template: "<!-- structure-builder.html -->\r\n@if (!readonly() && availableTabs().length > 0) {\r\n <mt-card\r\n class=\"absolute ms-4 mt-4 z-1 h-[calc(100%---spacing(8))] w-1/5 min-w-xs\"\r\n >\r\n <ng-template #headless>\r\n <!-- Header -->\r\n <div class=\"flex items-center justify-between px-4 pt-5\">\r\n <h3 class=\"text-xl font-semibold\">\r\n {{ \"structureBuilder.levelTemplates\" | transloco }}\r\n </h3>\r\n </div>\r\n\r\n <!-- Tabs using PrimeNG -->\r\n <p-tabs\r\n [(value)]=\"activeTab\"\r\n styleClass=\"structure-tabs \"\r\n class=\"h-full overflow-hidden\"\r\n >\r\n <p-tablist>\r\n @for (tab of availableTabs(); track tab; let i = $index) {\r\n <p-tab [value]=\"i.toString()\">{{ tab | titlecase }}</p-tab>\r\n }\r\n </p-tablist>\r\n <p-tabpanels class=\"bg-transparent! p-0! overflow-auto\">\r\n @for (tab of availableTabs(); track tab; let i = $index) {\r\n <p-tabpanel [value]=\"i.toString()\">\r\n <p class=\"text-xs text-muted py-3 px-4\">\r\n {{ \"structureBuilder.dragToAdd\" | transloco }}\r\n </p>\r\n\r\n <!-- Node List -->\r\n <div class=\"space-y-1 px-4\">\r\n @for (node of currentTabNodes(); track node.id) {\r\n <div\r\n fExternalItem\r\n [fData]=\"node\"\r\n class=\"group select-none relative flex items-center gap-3 py-3 px-4 hover:bg-emphasis hover:border-solid transition-colors rounded-lg border-1 border-dashed border-color border-surface-300 dark:border-surface-500 cursor-move transition-colors\"\r\n >\r\n <!-- Node Icon with color -->\r\n <div class=\"text-primary text-lg\">\r\n <mt-icon [icon]=\"node.icon || 'general.box'\"></mt-icon>\r\n </div>\r\n\r\n <!-- Node Name -->\r\n <span class=\"text-base font-medium flex-1\">{{\r\n node.label\r\n }}</span>\r\n <mt-icon class=\"text-lg\" icon=\"general.menu-05\"></mt-icon>\r\n </div>\r\n }\r\n\r\n @if (currentTabNodes().length === 0) {\r\n <div class=\"text-center py-8 text-gray-400\">\r\n <p class=\"text-sm\">\r\n {{\r\n \"structureBuilder.allItemsInUse\"\r\n | transloco: { tab: tab }\r\n }}\r\n </p>\r\n </div>\r\n }\r\n </div>\r\n </p-tabpanel>\r\n }\r\n </p-tabpanels>\r\n </p-tabs>\r\n </ng-template>\r\n </mt-card>\r\n} @else if (!readonly() && availableNodes().length > 0) {\r\n <div [ngClass]=\"availableTabsClass() || 'absolute top-4 start-4 z-1 w-64'\">\r\n <mt-card [title]=\"'structureBuilder.steps' | transloco\">\r\n <div class=\"flex flex-col gap-2\">\r\n @for (node of availableNodes(); track node.id) {\r\n <div\r\n fExternalItem\r\n [fData]=\"node\"\r\n class=\"group select-none relative flex items-center gap-3 py-3 px-4 hover:bg-emphasis hover:border-solid transition-colors rounded-lg border-1 border-dashed border-color border-surface-300 dark:border-surface-500 cursor-move bg-content\"\r\n >\r\n <!-- Node Icon with color -->\r\n <div class=\"text-primary text-lg\">\r\n <mt-icon [icon]=\"node.icon || 'general.box'\"></mt-icon>\r\n </div>\r\n\r\n <!-- Node Name -->\r\n <span class=\"text-base font-medium flex-1\">{{ node.label }}</span>\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n </div>\r\n}\r\n<!-- Left Sidebar -->\r\n\r\n<!-- Main Canvas Area -->\r\n<div class=\"flex-1 z-0 relative\">\r\n <ng-content select=\"[flowContent]\"></ng-content>\r\n\r\n <f-flow\r\n fDraggable\r\n dir=\"ltr\"\r\n (fLoaded)=\"onLoaded()\"\r\n (fCreateNode)=\"onCreateNode($event)\"\r\n (fCreateConnection)=\"onCreateConnection($event)\"\r\n class=\"size-full\"\r\n >\r\n <f-background>\r\n <f-circle-pattern color=\"#b5b5b5\"></f-circle-pattern>\r\n </f-background>\r\n <f-canvas fZoom [fZoomMinimum]=\"0.1\" [fZoomMaximum]=\"2\">\r\n <f-connection-for-create fBehavior=\"floating\" fType=\"straight\">\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.START\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.END\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n </f-connection-for-create>\r\n <f-snap-connection\r\n fBehavior=\"fixed\"\r\n fType=\"segment\"\r\n class=\"z-1\"\r\n [fSnapThreshold]=\"100\"\r\n >\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.START\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.END\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n </f-snap-connection>\r\n\r\n <f-connection-for-create></f-connection-for-create>\r\n\r\n <!-- Enhanced Connections with Edit Button -->\r\n @for (connection of connectionsComputed(); track connection.id) {\r\n <f-connection\r\n [fReassignDisabled]=\"true\"\r\n [fOutputId]=\"connection.from\"\r\n [fInputId]=\"connection.to\"\r\n fBehavior=\"fixed\"\r\n fType=\"segment\"\r\n [ngClass]=\"{ 'connection-loading': connection.loading, 'z-1': true }\"\r\n >\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.START\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.END\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.SELECTED_START\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.SELECTED_END\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n @if (!readonly()) {\r\n <div\r\n fConnectionCenter\r\n class=\"flex items-center gap-1 bg-content rounded-md p-1 shadow-sm\"\r\n >\r\n @if (!connection.loading) {\r\n <mt-button\r\n size=\"small\"\r\n variant=\"text\"\r\n [icon]=\"'general.edit-05'\"\r\n (click)=\"openConnectionDialog(connection)\"\r\n >\r\n </mt-button>\r\n <mt-button\r\n size=\"small\"\r\n variant=\"text\"\r\n severity=\"danger\"\r\n [icon]=\"'general.trash-01'\"\r\n (click)=\"removeConnection(connection)\"\r\n >\r\n </mt-button>\r\n } @else {\r\n <mt-button\r\n size=\"small\"\r\n variant=\"text\"\r\n [icon]=\"'general.loading-01'\"\r\n >\r\n </mt-button>\r\n }\r\n </div>\r\n }\r\n </f-connection>\r\n }\r\n\r\n <!-- Enhanced Nodes with Edit Button -->\r\n @for (node of nodesWithComputedProps(); track node._computedId) {\r\n <mt-card\r\n fNode\r\n fDragHandle\r\n [fNodePosition]=\"{\r\n x: node.configuration?.x || 200,\r\n y: node.configuration?.y || 100,\r\n }\"\r\n (fNodePositionChange)=\"onNodePositionChange($event, node._computedId)\"\r\n [style.--node-data-border-color]=\"node._computedColor\"\r\n >\r\n <ng-template #headless>\r\n @if (!node.loading) {\r\n <div [attr.dir]=\"contentDirection()\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"\r\n effectiveNodeTemplate() || defaultNodeTemplate\r\n \"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: node,\r\n node: node,\r\n actions: getFilteredNodeActions(node),\r\n onAction: nodeActionHandler,\r\n dir: contentDirection(),\r\n }\"\r\n >\r\n </ng-container>\r\n </div>\r\n <div\r\n fNodeInput\r\n [fInputId]=\"node._computedId\"\r\n [fInputConnectableSide]=\"configuration().inputSide\"\r\n [fInputMultiple]=\"true\"\r\n [ngClass]=\"configuration().inputSide\"\r\n ></div>\r\n\r\n <div\r\n fNodeOutput\r\n [fOutputId]=\"node._computedId\"\r\n [fOutputConnectableSide]=\"configuration().outputSide\"\r\n [isSelfConnectable]=\"false\"\r\n [fOutputMultiple]=\"true\"\r\n [ngClass]=\"configuration().outputSide\"\r\n class=\"bg-surface-50 dark:bg-surface-900\"\r\n ></div>\r\n } @else {\r\n <p-skeleton height=\"10rem\" width=\"15rem\" />\r\n }\r\n\r\n <!-- Node Header with Edit Button -->\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n <ng-template\r\n #defaultNodeTemplate\r\n let-node\r\n let-actions=\"actions\"\r\n let-onAction=\"onAction\"\r\n >\r\n <div\r\n class=\"flex flex-col items-center min-w-3xs gap-2 px-3 py-4 rounded-t-2xl bg-white dark:bg-surface-800 border-(--p-content-border-color)\"\r\n >\r\n @if (node._computedIcon) {\r\n <mt-icon\r\n class=\"text-2xl text-primary\"\r\n [icon]=\"node._computedIcon\"\r\n />\r\n }\r\n <div>{{ node._computedName }}</div>\r\n </div>\r\n <div\r\n class=\"flex justify-center pt-3 mb-4 gap-2 bg-surface-50 dark:bg-surface-900\"\r\n >\r\n @for (action of actions; track action.key) {\r\n <mt-button\r\n [size]=\"action?.size || 'small'\"\r\n [variant]=\"action?.variant\"\r\n [icon]=\"action?.icon\"\r\n [tooltip]=\"action?.tooltip\"\r\n [severity]=\"action?.severity\"\r\n (onClick)=\"onAction(action, node)\"\r\n >\r\n </mt-button>\r\n }\r\n </div>\r\n </ng-template>\r\n </f-canvas>\r\n </f-flow>\r\n</div>\r\n@if (!readonly()) {\r\n <mt-toolbar />\r\n}\r\n", styles: ["::ng-deep :root{--background-element-color: rgba(0, 0, 0, .1);--selection-area-color: rgba(100, 108, 255, .14);--disabled-color: #e2e2e2;--node-background-color: #ffffff;--node-background-color-inverse: #000000;--node-border-radius: 2px;--node-border-color: rgba(60, 60, 67, .36);--node-selected-border-color: #3451b2;--node-color: rgba(60, 60, 67, .78);--node-shadow: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--connection-color: var(--p-text-color);--snap-connection-color: var(--p-text-muted-color);--connection-gradient-1: #b8272c;--connection-gradient-2: #30a46c;--outlet-color: #3451b2;--input-output-color: rgba(60, 60, 67, .78);--minimap-background-color: #ffffff;--minimap-node-color: rgba(60, 60, 67);--minimap-node-selected-color: var(--p-primary-color);--minimap-view-color: rgba(100, 108, 255, .14)}::ng-deep :root.dark{--background-element-color: rgba(255, 255, 255, .1);--selection-area-color: rgba(100, 108, 255, .16);--disabled-color: #2c2c2e;--node-background-color: #000000;--node-background-color-inverse: #ffffff;--node-border-radius: 2px;--node-border-color: rgba(235, 235, 245, .38);--node-selected-border-color: #a8b1ff;--node-color: rgba(235, 235, 245, .6);--node-shadow: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--connection-color: rgba(235, 235, 245, 1);--snap-connection-color: rgba(235, 235, 245, .2);--connection-gradient-1: #f66f81;--connection-gradient-2: #298459;--outlet-color: #a8b1ff;--input-output-color: rgba(235, 235, 245, .6);--minimap-background-color: #1b1b1f;--minimap-node-color: rgba(255, 255, 245, .86);--minimap-node-selected-color: #a8b1ff;--minimap-view-color: rgba(100, 108, 255, .16)}::ng-deep :root{--form-field-text-color: var(--node-color);--form-field-background: var(--minimap-view-color);--form-field-panel-shadow: var(--shadow-4);--form-field-panel-background: var(--node-background-color);--form-field-active-color: var(--minimap-node-selected-color)}::ng-deep f-flow .f-connection{cursor:pointer}::ng-deep f-flow .f-connection .f-connection-drag-handle{fill:transparent}::ng-deep f-flow .f-connection .f-connection-selection{fill:none}::ng-deep f-flow .f-connection .f-connection-path{fill:none;stroke:var(--connection-color);stroke-width:2}::ng-deep f-flow .f-connection .f-connection-marker{fill:var(--connection-color)}::ng-deep f-flow .f-connection .f-marker path,::ng-deep f-flow .f-connection .f-marker circle{fill:var(--connection-color)}::ng-deep f-flow .f-connection .f-connection-text,::ng-deep f-flow .f-connection .f-connection-center{fill:var(--connection-color);color:var(--connection-color)}::ng-deep f-flow .f-connection.f-snap-connection .f-connection-path{stroke:var(--snap-connection-color)}::ng-deep f-flow .f-connection .f-connection-center{display:none}::ng-deep f-flow .f-connection.connection-loading .f-connection-center{display:block}::ng-deep f-flow .f-connection.f-selected .f-connection-center{display:block}::ng-deep f-flow .f-connection.f-selected .f-connection-path{stroke:var(--minimap-node-selected-color)}::ng-deep f-flow .f-connection.f-selected .f-marker path,::ng-deep f-flow .f-connection.f-selected .f-marker circle{fill:var(--p-primary-color);stroke:var(--minimap-node-selected-color)}::ng-deep f-flow .f-connection .f-connection-selection{fill:none;stroke:transparent;stroke-width:20;cursor:pointer}::ng-deep f-flow .f-connection:hover .f-connection-selection{stroke:var(--p-primary-color);opacity:.1}::ng-deep f-flow .f-connection.f-snap-connection .f-connection-path{stroke:var(--snap-connection-color);stroke-width:2px}::ng-deep f-flow .f-connection.f-snap-connection .f-marker path,::ng-deep f-flow .f-connection.f-snap-connection .f-marker circle{fill:var(--snap-connection-color)}::ng-deep f-flow .f-connection.f-snap-connection .f-connection-selection{fill:transparent!important;stroke:transparent!important}::ng-deep f-flow .f-connection.f-connection-for-create .f-connection-selection{fill:transparent!important;stroke:transparent!important}::ng-deep f-flow .f-connection-for-create{pointer-events:none}::ng-deep f-flow .f-connection-for-create .f-connection .f-connection-path{stroke:var(--snap-connection-color);stroke-width:3px;stroke-dasharray:8,4;animation:connection-dash 1s linear infinite}::ng-deep f-flow .f-connection-for-create .f-connection .f-marker path,::ng-deep f-flow .f-connection-for-create .f-connection .f-marker circle{fill:var(--snap-connection-color)}@keyframes connection-dash{to{stroke-dashoffset:-12}}::ng-deep f-flow{direction:ltr}.f-node-input:not(.f-node),.f-node-output:not(.f-node){position:absolute;border-radius:0 0 1rem 1rem}.f-node-input:not(.f-node):hover,.f-node-output:not(.f-node):hover{border:.5px dashed var(--p-primary-color)}.f-node-input:not(.f-node).top,.f-node-input:not(.f-node).bottom,.f-node-output:not(.f-node).top,.f-node-output:not(.f-node).bottom{width:100%;height:16px;left:0}.f-node-input:not(.f-node).top,.f-node-output:not(.f-node).top{top:0}.f-node-input:not(.f-node).bottom,.f-node-output:not(.f-node).bottom{bottom:0}.f-node-input:not(.f-node).left,.f-node-input:not(.f-node).right,.f-node-output:not(.f-node).left,.f-node-output:not(.f-node).right{width:16px;height:100%;top:0}.f-node-input:not(.f-node).left,.f-node-output:not(.f-node).left{left:0;border-radius:1rem 0 0 1rem}.f-node-input:not(.f-node).right,.f-node-output:not(.f-node).right{right:0;border-radius:0 1rem 1rem 0}.f-node-input:not(.f-node).f-node-output-not-connectable,.f-node-input:not(.f-node).f-node-input-not-connectable,.f-node-output:not(.f-node).f-node-output-not-connectable,.f-node-output:not(.f-node).f-node-input-not-connectable{background-color:var(--disabled-color)}.f-node-input:not(.f-node){border-radius:4px}.f-node-input,.f-node-output{z-index:10;pointer-events:all}.examples-toolbar{display:flex;justify-content:flex-end;align-items:center;flex-wrap:wrap;gap:8px;position:absolute;right:16px;top:16px}.examples-toolbar button{font-weight:500;border:none;border-radius:2px;padding:4px 8px;line-height:normal}.f-node:before{content:\"\";position:absolute;width:100%;height:4rem;border-radius:var(--radius-2xl);z-index:-1;top:-.25rem;background-color:var(--node-data-border-color)}.connection-center{display:flex;gap:8px;background:var(--node-background-color);border:1px solid var(--node-border-color);border-radius:4px;padding:4px;box-shadow:var(--node-shadow)}.connection-center .connection-edit-btn,.connection-center .connection-delete-btn{background:none;border:none;width:24px;height:24px;border-radius:4px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s ease}.connection-center .connection-edit-btn:hover,.connection-center .connection-delete-btn:hover{background-color:var(--minimap-view-color)}.connection-center .connection-edit-btn{color:var(--minimap-node-selected-color)}.connection-center .connection-delete-btn{color:#ef4444}.node-edit-btn,.node-delete-btn{background:none;border:none;width:32px;height:32px;border-radius:6px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s ease}.node-edit-btn:hover,.node-delete-btn:hover{background-color:var(--minimap-view-color)}.node-edit-btn{color:var(--minimap-node-selected-color)}.node-delete-btn{color:#ef4444}.node-properties{max-height:200px;overflow-y:auto}.node-properties .property-item{display:flex;justify-content:space-between;padding:4px 0;border-bottom:1px solid var(--node-border-color);font-size:12px}.node-properties .property-item .property-key{font-weight:600;color:var(--node-color);margin-right:8px}.node-properties .property-item .property-value{color:var(--minimap-node-selected-color);word-break:break-word}\n"] }]
709
+ }, template: "<!-- structure-builder.html -->\r\n@if (!readonly() && availableTabs().length > 0) {\r\n <mt-card\r\n class=\"absolute ms-4 mt-4 z-1 h-[calc(100%---spacing(8))] w-1/5 min-w-xs\"\r\n >\r\n <ng-template #headless>\r\n <!-- Header -->\r\n <div class=\"flex items-center justify-between px-4 pt-5\">\r\n <h3 class=\"text-xl font-semibold\">\r\n {{ \"structureBuilder.levelTemplates\" | transloco }}\r\n </h3>\r\n </div>\r\n\r\n <!-- Tabs using PrimeNG -->\r\n <p-tabs\r\n [(value)]=\"activeTab\"\r\n styleClass=\"structure-tabs \"\r\n class=\"h-full overflow-hidden\"\r\n >\r\n <p-tablist>\r\n @for (tab of availableTabs(); track tab; let i = $index) {\r\n <p-tab [value]=\"i.toString()\">{{ tab | titlecase }}</p-tab>\r\n }\r\n </p-tablist>\r\n <p-tabpanels class=\"bg-transparent! p-0! overflow-auto\">\r\n @for (tab of availableTabs(); track tab; let i = $index) {\r\n <p-tabpanel [value]=\"i.toString()\">\r\n <p class=\"text-xs text-muted py-3 px-4\">\r\n {{ \"structureBuilder.dragToAdd\" | transloco }}\r\n </p>\r\n\r\n <!-- Node List -->\r\n <div class=\"space-y-1 px-4\">\r\n @for (node of currentTabNodes(); track node.id) {\r\n <div\r\n fExternalItem\r\n [fData]=\"node\"\r\n style=\"display: flex\"\r\n class=\"group select-none relative flex items-center gap-3 py-3 px-4 hover:bg-emphasis hover:border-solid transition-colors rounded-lg border-1 border-dashed border-color border-surface-300 dark:border-surface-500 cursor-move transition-colors\"\r\n >\r\n <!-- Node Icon with color -->\r\n <div class=\"text-primary text-lg\">\r\n <mt-icon [icon]=\"node.icon || 'general.box'\"></mt-icon>\r\n </div>\r\n\r\n <!-- Node Name -->\r\n <span class=\"text-base font-medium flex-1\">{{\r\n node.label\r\n }}</span>\r\n <mt-icon class=\"text-lg\" icon=\"general.menu-05\"></mt-icon>\r\n </div>\r\n }\r\n\r\n @if (currentTabNodes().length === 0) {\r\n <div class=\"text-center py-8 text-gray-400\">\r\n <p class=\"text-sm\">\r\n {{\r\n \"structureBuilder.allItemsInUse\"\r\n | transloco: { tab: tab }\r\n }}\r\n </p>\r\n </div>\r\n }\r\n </div>\r\n </p-tabpanel>\r\n }\r\n </p-tabpanels>\r\n </p-tabs>\r\n </ng-template>\r\n </mt-card>\r\n} @else if (!readonly() && availableNodes().length > 0) {\r\n <div [ngClass]=\"availableTabsClass() || 'absolute top-4 start-4 z-1 w-64'\">\r\n <mt-card [title]=\"'structureBuilder.steps' | transloco\">\r\n <div class=\"flex flex-col gap-2\">\r\n @for (node of availableNodes(); track node.id) {\r\n <div\r\n fExternalItem\r\n [fData]=\"node\"\r\n style=\"display: flex\"\r\n class=\"group select-none relative flex items-center gap-3 py-3 px-4 hover:bg-emphasis hover:border-solid transition-colors rounded-lg border-1 border-dashed border-color border-surface-300 dark:border-surface-500 cursor-move bg-content\"\r\n >\r\n <!-- Node Icon with color -->\r\n <div class=\"text-primary text-lg\">\r\n <mt-icon [icon]=\"node.icon || 'general.box'\"></mt-icon>\r\n </div>\r\n\r\n <!-- Node Name -->\r\n <span class=\"text-base font-medium flex-1\">{{ node.label }}</span>\r\n </div>\r\n }\r\n </div>\r\n </mt-card>\r\n </div>\r\n}\r\n<!-- Left Sidebar -->\r\n\r\n<!-- Main Canvas Area -->\r\n<div class=\"flex-1 z-0 relative\">\r\n <ng-content select=\"[flowContent]\"></ng-content>\r\n\r\n <f-flow\r\n fDraggable\r\n dir=\"ltr\"\r\n (fLoaded)=\"onLoaded()\"\r\n (fCreateNode)=\"onCreateNode($event)\"\r\n (fCreateConnection)=\"onCreateConnection($event)\"\r\n class=\"size-full\"\r\n >\r\n <f-background>\r\n <f-circle-pattern color=\"#b5b5b5\"></f-circle-pattern>\r\n </f-background>\r\n <f-canvas fZoom [fZoomMinimum]=\"0.1\" [fZoomMaximum]=\"2\">\r\n <f-connection-for-create fBehavior=\"floating\" fType=\"straight\">\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.START\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.END\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n </f-connection-for-create>\r\n <f-snap-connection\r\n fBehavior=\"fixed\"\r\n fType=\"segment\"\r\n class=\"z-1\"\r\n [fSnapThreshold]=\"100\"\r\n >\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.START\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.END\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n </f-snap-connection>\r\n\r\n <f-connection-for-create></f-connection-for-create>\r\n\r\n <!-- Enhanced Connections with Edit Button -->\r\n @for (connection of renderedConnections(); track connection.id) {\r\n <f-connection\r\n [fReassignDisabled]=\"true\"\r\n [fOutputId]=\"connection._outputConnectorId\"\r\n [fInputId]=\"connection._inputConnectorId\"\r\n [fOutputSide]=\"connection._outputSide\"\r\n [fInputSide]=\"connection._inputSide\"\r\n fBehavior=\"fixed\"\r\n fType=\"segment\"\r\n [ngClass]=\"{ 'connection-loading': connection.loading, 'z-1': true }\"\r\n >\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.START\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.END\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.SELECTED_START\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n <svg\r\n viewBox=\"0 0 12 12\"\r\n fMarker\r\n [type]=\"eMarkerType.SELECTED_END\"\r\n [height]=\"12\"\r\n [width]=\"12\"\r\n [refX]=\"6\"\r\n [refY]=\"6\"\r\n >\r\n <circle\r\n cx=\"6\"\r\n cy=\"6\"\r\n r=\"3\"\r\n stroke=\"none\"\r\n fill=\"currentColor\"\r\n ></circle>\r\n </svg>\r\n @if (!readonly()) {\r\n <div\r\n fConnectionContent\r\n class=\"flex items-center gap-1 bg-content rounded-md p-1 shadow-sm\"\r\n >\r\n @if (!connection.loading) {\r\n <mt-button\r\n size=\"small\"\r\n variant=\"text\"\r\n [icon]=\"'general.edit-05'\"\r\n (click)=\"openConnectionDialog(connection)\"\r\n >\r\n </mt-button>\r\n <mt-button\r\n size=\"small\"\r\n variant=\"text\"\r\n severity=\"danger\"\r\n [icon]=\"'general.trash-01'\"\r\n (click)=\"removeConnection(connection)\"\r\n >\r\n </mt-button>\r\n } @else {\r\n <mt-button\r\n size=\"small\"\r\n variant=\"text\"\r\n [icon]=\"'general.loading-01'\"\r\n >\r\n </mt-button>\r\n }\r\n </div>\r\n }\r\n </f-connection>\r\n }\r\n\r\n <!-- Enhanced Nodes with Edit Button -->\r\n @for (node of nodesWithComputedProps(); track node._computedId) {\r\n <mt-card\r\n fNode\r\n fDragHandle\r\n [fNodePosition]=\"{\r\n x: node.configuration?.x || 200,\r\n y: node.configuration?.y || 100,\r\n }\"\r\n (fNodePositionChange)=\"onNodePositionChange($event, node._computedId)\"\r\n [style.--node-data-border-color]=\"node._computedColor\"\r\n >\r\n <ng-template #headless>\r\n @if (!node.loading) {\r\n <div [attr.dir]=\"contentDirection()\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"\r\n effectiveNodeTemplate() || defaultNodeTemplate\r\n \"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: node,\r\n node: node,\r\n actions: getFilteredNodeActions(node),\r\n onAction: nodeActionHandler,\r\n dir: contentDirection(),\r\n }\"\r\n >\r\n </ng-container>\r\n </div>\r\n @for (side of nodeConnectorSides(); track side) {\r\n <div\r\n fNodeInput\r\n [fInputId]=\"\r\n createConnectorId(node._computedId, 'input', side)\r\n \"\r\n [fInputConnectableSide]=\"side\"\r\n [fInputMultiple]=\"true\"\r\n class=\"sb-connector sb-connector-input\"\r\n [class.top]=\"side === 'top'\"\r\n [class.bottom]=\"side === 'bottom'\"\r\n [class.left]=\"side === 'left'\"\r\n [class.right]=\"side === 'right'\"\r\n ></div>\r\n\r\n <div\r\n fNodeOutput\r\n [fOutputId]=\"\r\n createConnectorId(node._computedId, 'output', side)\r\n \"\r\n [fOutputConnectableSide]=\"side\"\r\n [isSelfConnectable]=\"false\"\r\n [fOutputMultiple]=\"true\"\r\n class=\"sb-connector sb-connector-output bg-surface-50 dark:bg-surface-900\"\r\n [class.top]=\"side === 'top'\"\r\n [class.bottom]=\"side === 'bottom'\"\r\n [class.left]=\"side === 'left'\"\r\n [class.right]=\"side === 'right'\"\r\n ></div>\r\n }\r\n } @else {\r\n <p-skeleton height=\"10rem\" width=\"15rem\" />\r\n }\r\n\r\n <!-- Node Header with Edit Button -->\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n <ng-template\r\n #defaultNodeTemplate\r\n let-node\r\n let-actions=\"actions\"\r\n let-onAction=\"onAction\"\r\n >\r\n <div\r\n class=\"flex flex-col items-center min-w-3xs gap-2 px-3 py-4 rounded-t-2xl bg-white dark:bg-surface-800 border-(--p-content-border-color)\"\r\n >\r\n @if (node._computedIcon) {\r\n <mt-icon\r\n class=\"text-2xl text-primary\"\r\n [icon]=\"node._computedIcon\"\r\n />\r\n }\r\n <div>{{ node._computedName }}</div>\r\n </div>\r\n <div\r\n class=\"flex justify-center pt-3 mb-4 gap-2 bg-surface-50 dark:bg-surface-900\"\r\n >\r\n @for (action of actions; track action.key) {\r\n <mt-button\r\n [size]=\"action?.size || 'small'\"\r\n [variant]=\"action?.variant\"\r\n [icon]=\"action?.icon\"\r\n [tooltip]=\"action?.tooltip\"\r\n [severity]=\"action?.severity\"\r\n (onClick)=\"onAction(action, node)\"\r\n >\r\n </mt-button>\r\n }\r\n </div>\r\n </ng-template>\r\n </f-canvas>\r\n </f-flow>\r\n</div>\r\n@if (!readonly()) {\r\n <mt-toolbar />\r\n}\r\n", styles: ["::ng-deep :root{--background-element-color: rgba(0, 0, 0, .1);--selection-area-color: rgba(100, 108, 255, .14);--disabled-color: #e2e2e2;--node-background-color: #ffffff;--node-background-color-inverse: #000000;--node-border-radius: 2px;--node-border-color: rgba(60, 60, 67, .36);--node-selected-border-color: #3451b2;--node-color: rgba(60, 60, 67, .78);--node-shadow: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--connection-color: var(--p-text-color);--snap-connection-color: var(--p-text-muted-color);--connection-gradient-1: #b8272c;--connection-gradient-2: #30a46c;--outlet-color: #3451b2;--input-output-color: rgba(60, 60, 67, .78);--minimap-background-color: #ffffff;--minimap-node-color: rgba(60, 60, 67);--minimap-node-selected-color: var(--p-primary-color);--minimap-view-color: rgba(100, 108, 255, .14)}::ng-deep :root.dark{--background-element-color: rgba(255, 255, 255, .1);--selection-area-color: rgba(100, 108, 255, .16);--disabled-color: #2c2c2e;--node-background-color: #000000;--node-background-color-inverse: #ffffff;--node-border-radius: 2px;--node-border-color: rgba(235, 235, 245, .38);--node-selected-border-color: #a8b1ff;--node-color: rgba(235, 235, 245, .6);--node-shadow: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--connection-color: rgba(235, 235, 245, 1);--snap-connection-color: rgba(235, 235, 245, .2);--connection-gradient-1: #f66f81;--connection-gradient-2: #298459;--outlet-color: #a8b1ff;--input-output-color: rgba(235, 235, 245, .6);--minimap-background-color: #1b1b1f;--minimap-node-color: rgba(255, 255, 245, .86);--minimap-node-selected-color: #a8b1ff;--minimap-view-color: rgba(100, 108, 255, .16)}::ng-deep :root{--form-field-text-color: var(--node-color);--form-field-background: var(--minimap-view-color);--form-field-panel-shadow: var(--shadow-4);--form-field-panel-background: var(--node-background-color);--form-field-active-color: var(--minimap-node-selected-color)}::ng-deep f-flow .f-connection{cursor:pointer}::ng-deep f-flow .f-connection .f-connection-drag-handle{fill:transparent}::ng-deep f-flow .f-connection .f-connection-selection{fill:none}::ng-deep f-flow .f-connection .f-connection-path{fill:none;stroke:var(--connection-color);stroke-width:2}::ng-deep f-flow .f-connection .f-connection-marker{fill:var(--connection-color)}::ng-deep f-flow .f-connection .f-marker path,::ng-deep f-flow .f-connection .f-marker circle{fill:var(--connection-color)}::ng-deep f-flow .f-connection .f-connection-text,::ng-deep f-flow .f-connection .f-connection-center,::ng-deep f-flow .f-connection .f-connection-content{fill:var(--connection-color);color:var(--connection-color)}::ng-deep f-flow .f-connection.f-snap-connection .f-connection-path{stroke:var(--snap-connection-color)}::ng-deep f-flow .f-connection .f-connection-center,::ng-deep f-flow .f-connection .f-connection-content{display:none}::ng-deep f-flow .f-connection.connection-loading .f-connection-center,::ng-deep f-flow .f-connection.connection-loading .f-connection-content{display:block}::ng-deep f-flow .f-connection.f-selected .f-connection-center,::ng-deep f-flow .f-connection.f-selected .f-connection-content{display:block}::ng-deep f-flow .f-connection.f-selected .f-connection-path{stroke:var(--minimap-node-selected-color)}::ng-deep f-flow .f-connection.f-selected .f-marker path,::ng-deep f-flow .f-connection.f-selected .f-marker circle{fill:var(--p-primary-color);stroke:var(--minimap-node-selected-color)}::ng-deep f-flow .f-connection .f-connection-selection{fill:none;stroke:transparent;stroke-width:20;cursor:pointer}::ng-deep f-flow .f-connection:hover .f-connection-selection{stroke:var(--p-primary-color);opacity:.1}::ng-deep f-flow .f-connection.f-snap-connection .f-connection-path{stroke:var(--snap-connection-color);stroke-width:2px}::ng-deep f-flow .f-connection.f-snap-connection .f-marker path,::ng-deep f-flow .f-connection.f-snap-connection .f-marker circle{fill:var(--snap-connection-color)}::ng-deep f-flow .f-connection.f-snap-connection .f-connection-selection{fill:transparent!important;stroke:transparent!important}::ng-deep f-flow .f-connection.f-connection-for-create .f-connection-selection{fill:transparent!important;stroke:transparent!important}::ng-deep f-flow .f-connection-for-create{pointer-events:none}::ng-deep f-flow .f-connection-for-create .f-connection .f-connection-path{stroke:var(--snap-connection-color);stroke-width:3px;stroke-dasharray:8,4;animation:connection-dash 1s linear infinite}::ng-deep f-flow .f-connection-for-create .f-connection .f-marker path,::ng-deep f-flow .f-connection-for-create .f-connection .f-marker circle{fill:var(--snap-connection-color)}@keyframes connection-dash{to{stroke-dashoffset:-12}}::ng-deep f-flow{direction:ltr}.f-node-input:not(.f-node),.f-node-output:not(.f-node){position:absolute}.f-node-input:not(.f-node):hover,.f-node-output:not(.f-node):hover{border:.5px dashed var(--p-primary-color)}.f-node-input:not(.f-node).top,.f-node-input:not(.f-node).bottom,.f-node-output:not(.f-node).top,.f-node-output:not(.f-node).bottom{width:100%;height:16px;left:0}.f-node-input:not(.f-node).top,.f-node-output:not(.f-node).top{top:0;border-radius:1rem 1rem 0 0}.f-node-input:not(.f-node).bottom,.f-node-output:not(.f-node).bottom{bottom:0;border-radius:0 0 1rem 1rem}.f-node-input:not(.f-node).left,.f-node-input:not(.f-node).right,.f-node-output:not(.f-node).left,.f-node-output:not(.f-node).right{width:16px;height:100%;top:0}.f-node-input:not(.f-node).left,.f-node-output:not(.f-node).left{left:0;border-radius:1rem 0 0 1rem}.f-node-input:not(.f-node).right,.f-node-output:not(.f-node).right{right:0;border-radius:0 1rem 1rem 0}.f-node-input:not(.f-node).f-node-output-not-connectable,.f-node-input:not(.f-node).f-node-input-not-connectable,.f-node-output:not(.f-node).f-node-output-not-connectable,.f-node-output:not(.f-node).f-node-input-not-connectable{background-color:var(--disabled-color)}.sb-connector-input,.sb-connector-output{background-color:transparent!important}.f-node-input:not(.f-node){border-radius:4px}.f-node-input,.f-node-output{z-index:10;pointer-events:all}.examples-toolbar{display:flex;justify-content:flex-end;align-items:center;flex-wrap:wrap;gap:8px;position:absolute;right:16px;top:16px}.examples-toolbar button{font-weight:500;border:none;border-radius:2px;padding:4px 8px;line-height:normal}.f-node:before{content:\"\";position:absolute;width:100%;height:4rem;border-radius:var(--radius-2xl);z-index:-1;top:-.25rem;background-color:var(--node-data-border-color)}.connection-center{display:flex;gap:8px;background:var(--node-background-color);border:1px solid var(--node-border-color);border-radius:4px;padding:4px;box-shadow:var(--node-shadow)}.connection-center .connection-edit-btn,.connection-center .connection-delete-btn{background:none;border:none;width:24px;height:24px;border-radius:4px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s ease}.connection-center .connection-edit-btn:hover,.connection-center .connection-delete-btn:hover{background-color:var(--minimap-view-color)}.connection-center .connection-edit-btn{color:var(--minimap-node-selected-color)}.connection-center .connection-delete-btn{color:#ef4444}.node-edit-btn,.node-delete-btn{background:none;border:none;width:32px;height:32px;border-radius:6px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s ease}.node-edit-btn:hover,.node-delete-btn:hover{background-color:var(--minimap-view-color)}.node-edit-btn{color:var(--minimap-node-selected-color)}.node-delete-btn{color:#ef4444}.node-properties{max-height:200px;overflow-y:auto}.node-properties .property-item{display:flex;justify-content:space-between;padding:4px 0;border-bottom:1px solid var(--node-border-color);font-size:12px}.node-properties .property-item .property-key{font-weight:600;color:var(--node-color);margin-right:8px}.node-properties .property-item .property-value{color:var(--minimap-node-selected-color);word-break:break-word}\n"] }]
638
710
  }], ctorParameters: () => [], propDecorators: { nodeActionsEvent: [{ type: i0.Output, args: ["nodeActionsEvent"] }], action: [{ type: i0.Output, args: ["action"] }], availableNodes: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableNodes", required: false }] }], fCanvas: [{ type: i0.ViewChild, args: [i0.forwardRef(() => FCanvasComponent), { isSignal: true }] }], fFlowComponent: [{ type: i0.ViewChild, args: [i0.forwardRef(() => FFlowComponent), { isSignal: true }] }], fCanvasComponent: [{ type: i0.ViewChild, args: [i0.forwardRef(() => FCanvasComponent), { isSignal: true }] }], fZoomDirective: [{ type: i0.ViewChild, args: [i0.forwardRef(() => FZoomDirective), { isSignal: true }] }], nodeForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeForm", required: false }] }], nodeDialogFooterConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeDialogFooterConfig", required: false }] }], connectionForm: [{ type: i0.Input, args: [{ isSignal: true, alias: "connectionForm", required: false }] }], connectionFormulaSchemaId: [{ type: i0.Input, args: [{ isSignal: true, alias: "connectionFormulaSchemaId", required: false }] }], connectionFormulaConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "connectionFormulaConfig", required: false }] }], nodeActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeActions", required: false }] }], nodeFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeFields", required: false }] }], isAutoLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "isAutoLayout", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], addModalType: [{ type: i0.Input, args: [{ isSignal: true, alias: "addModalType", required: false }] }], updateModalType: [{ type: i0.Input, args: [{ isSignal: true, alias: "updateModalType", required: false }] }], addModalStyleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "addModalStyleClass", required: false }] }], updateModalStyleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "updateModalStyleClass", required: false }] }], addModalHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "addModalHeader", required: false }] }], updateModalHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "updateModalHeader", required: false }] }], appendTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "appendTo", required: false }] }], availableTabsClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableTabsClass", required: false }] }], layoutDirection: [{ type: i0.Input, args: [{ isSignal: true, alias: "layoutDirection", required: false }] }], nodes: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodes", required: false }] }, { type: i0.Output, args: ["nodesChange"] }], connections: [{ type: i0.Input, args: [{ isSignal: true, alias: "connections", required: false }] }, { type: i0.Output, args: ["connectionsChange"] }], nodeDialogTemplate: [{ type: i0.ContentChild, args: ['nodeDialog', { isSignal: true }] }], nodeTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeTemplate", required: false }] }], nodeTemplateContent: [{ type: i0.ContentChild, args: ['nodeTemplate', { isSignal: true }] }] } });
639
711
 
640
712
  /*