@masterteam/form-builder 0.0.28 → 0.0.30
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, Injectable, computed, DestroyRef, input, signal, viewChild, Component, effect, output, viewChildren } from '@angular/core';
|
|
2
|
+
import { inject, Injectable, computed, DestroyRef, input, signal, viewChild, Component, effect, output, viewChildren, booleanAttribute } from '@angular/core';
|
|
3
3
|
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
|
4
4
|
import * as i1$1 from '@angular/common';
|
|
5
5
|
import { CommonModule } from '@angular/common';
|
|
@@ -1429,11 +1429,9 @@ class FBFieldForm {
|
|
|
1429
1429
|
const payload = {
|
|
1430
1430
|
width: widthMap[formValue.size] ?? '100',
|
|
1431
1431
|
};
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
}
|
|
1436
|
-
else {
|
|
1432
|
+
payload['isRead'] = this.isReadControl.value ?? true;
|
|
1433
|
+
payload['isWrite'] = this.isWriteControl.value ?? true;
|
|
1434
|
+
if (!this.isManageProperties()) {
|
|
1437
1435
|
payload['hiddenInCreation'] = formValue.hiddenInCreation ?? false;
|
|
1438
1436
|
payload['hiddenInEditForm'] = formValue.hiddenInEditForm ?? false;
|
|
1439
1437
|
payload['isRequired'] = formValue.isRequired ?? false;
|
|
@@ -1489,7 +1487,7 @@ class FBFieldForm {
|
|
|
1489
1487
|
});
|
|
1490
1488
|
}
|
|
1491
1489
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FBFieldForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1492
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: FBFieldForm, isStandalone: true, selector: "mt-fb-field-form", inputs: { sectionId: { classPropertyName: "sectionId", publicName: "sectionId", isSignal: true, isRequired: false, transformFunction: null }, initialData: { classPropertyName: "initialData", publicName: "initialData", isSignal: true, isRequired: false, transformFunction: null }, allSections: { classPropertyName: "allSections", publicName: "allSections", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div\r\n [class]=\"[\r\n modalService.contentClass,\r\n 'min-w-0',\r\n 'p-4',\r\n 'overflow-y-hidden!',\r\n 'max-[640px]:p-3',\r\n ]\"\r\n >\r\n <div class=\"mt-2 flex h-full min-h-0 flex-col gap-4 overflow-y-auto pb-10\">\r\n <mt-dynamic-form\r\n [formConfig]=\"activeFormConfig()\"\r\n [formControl]=\"formControl\"\r\n >\r\n </mt-dynamic-form>\r\n\r\n
|
|
1490
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: FBFieldForm, isStandalone: true, selector: "mt-fb-field-form", inputs: { sectionId: { classPropertyName: "sectionId", publicName: "sectionId", isSignal: true, isRequired: false, transformFunction: null }, initialData: { classPropertyName: "initialData", publicName: "initialData", isSignal: true, isRequired: false, transformFunction: null }, allSections: { classPropertyName: "allSections", publicName: "allSections", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div\r\n [class]=\"[\r\n modalService.contentClass,\r\n 'min-w-0',\r\n 'p-4',\r\n 'overflow-y-hidden!',\r\n 'max-[640px]:p-3',\r\n ]\"\r\n >\r\n <div class=\"mt-2 flex h-full min-h-0 flex-col gap-4 overflow-y-auto pb-10\">\r\n <mt-dynamic-form\r\n [formConfig]=\"activeFormConfig()\"\r\n [formControl]=\"formControl\"\r\n >\r\n </mt-dynamic-form>\r\n\r\n <!-- isRead Toggle -->\r\n <mt-toggle-field\r\n toggleShape=\"card\"\r\n [label]=\"t('is-read')\"\r\n [descriptionCard]=\"t('is-read-description')\"\r\n icon=\"general.eye\"\r\n [formControl]=\"isReadControl\"\r\n ></mt-toggle-field>\r\n\r\n <!-- isWrite Toggle -->\r\n <mt-toggle-field\r\n toggleShape=\"card\"\r\n [label]=\"t('is-write')\"\r\n [descriptionCard]=\"t('is-write-description')\"\r\n icon=\"general.edit-02\"\r\n [formControl]=\"isWriteControl\"\r\n ></mt-toggle-field>\r\n\r\n @if (!isManageProperties()) {\r\n <!-- Show/Hide Toggle with Set Conditions -->\r\n <mt-toggle-field\r\n toggleShape=\"card\"\r\n [label]=\"t('show-hide')\"\r\n [descriptionCard]=\"t('show-hide-description')\"\r\n icon=\"general.eye\"\r\n [formControl]=\"showHideControl\"\r\n class=\"mt-3\"\r\n >\r\n <ng-template #toggleCardBottom>\r\n @if (showHideControl.value) {\r\n <div class=\"mt-3\">\r\n <mt-button\r\n [label]=\"t('set-conditions')\"\r\n size=\"small\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"onSetConditions()\"\r\n ></mt-button>\r\n </div>\r\n }\r\n </ng-template>\r\n </mt-toggle-field>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div\r\n [class]=\"[\r\n modalService.footerClass,\r\n '!h-auto',\r\n 'min-h-0',\r\n 'flex-col',\r\n 'gap-2',\r\n 'sm:flex-row',\r\n 'sm:items-center',\r\n 'sm:justify-end',\r\n ]\"\r\n >\r\n @if (initialData() && !isManageProperties()) {\r\n <mt-button\r\n [tooltip]=\"t('delete')\"\r\n severity=\"danger\"\r\n [variant]=\"'outlined'\"\r\n icon=\"general.trash-01\"\r\n [loading]=\"deleting()\"\r\n [disabled]=\"submitting()\"\r\n (onClick)=\"onDelete($event)\"\r\n class=\"self-start sm:me-auto\"\r\n ></mt-button>\r\n }\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n variant=\"outlined\"\r\n [disabled]=\"submitting() || deleting()\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"onCancel()\"\r\n >\r\n </mt-button>\r\n <mt-button\r\n [disabled]=\"!formControl.valid || deleting()\"\r\n [label]=\"t('save')\"\r\n severity=\"primary\"\r\n [loading]=\"submitting()\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"onSave()\"\r\n >\r\n </mt-button>\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { 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: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }] });
|
|
1493
1491
|
}
|
|
1494
1492
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FBFieldForm, decorators: [{
|
|
1495
1493
|
type: Component,
|
|
@@ -1499,7 +1497,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
1499
1497
|
DynamicForm,
|
|
1500
1498
|
Button,
|
|
1501
1499
|
ToggleField,
|
|
1502
|
-
], template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div\r\n [class]=\"[\r\n modalService.contentClass,\r\n 'min-w-0',\r\n 'p-4',\r\n 'overflow-y-hidden!',\r\n 'max-[640px]:p-3',\r\n ]\"\r\n >\r\n <div class=\"mt-2 flex h-full min-h-0 flex-col gap-4 overflow-y-auto pb-10\">\r\n <mt-dynamic-form\r\n [formConfig]=\"activeFormConfig()\"\r\n [formControl]=\"formControl\"\r\n >\r\n </mt-dynamic-form>\r\n\r\n
|
|
1500
|
+
], template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div\r\n [class]=\"[\r\n modalService.contentClass,\r\n 'min-w-0',\r\n 'p-4',\r\n 'overflow-y-hidden!',\r\n 'max-[640px]:p-3',\r\n ]\"\r\n >\r\n <div class=\"mt-2 flex h-full min-h-0 flex-col gap-4 overflow-y-auto pb-10\">\r\n <mt-dynamic-form\r\n [formConfig]=\"activeFormConfig()\"\r\n [formControl]=\"formControl\"\r\n >\r\n </mt-dynamic-form>\r\n\r\n <!-- isRead Toggle -->\r\n <mt-toggle-field\r\n toggleShape=\"card\"\r\n [label]=\"t('is-read')\"\r\n [descriptionCard]=\"t('is-read-description')\"\r\n icon=\"general.eye\"\r\n [formControl]=\"isReadControl\"\r\n ></mt-toggle-field>\r\n\r\n <!-- isWrite Toggle -->\r\n <mt-toggle-field\r\n toggleShape=\"card\"\r\n [label]=\"t('is-write')\"\r\n [descriptionCard]=\"t('is-write-description')\"\r\n icon=\"general.edit-02\"\r\n [formControl]=\"isWriteControl\"\r\n ></mt-toggle-field>\r\n\r\n @if (!isManageProperties()) {\r\n <!-- Show/Hide Toggle with Set Conditions -->\r\n <mt-toggle-field\r\n toggleShape=\"card\"\r\n [label]=\"t('show-hide')\"\r\n [descriptionCard]=\"t('show-hide-description')\"\r\n icon=\"general.eye\"\r\n [formControl]=\"showHideControl\"\r\n class=\"mt-3\"\r\n >\r\n <ng-template #toggleCardBottom>\r\n @if (showHideControl.value) {\r\n <div class=\"mt-3\">\r\n <mt-button\r\n [label]=\"t('set-conditions')\"\r\n size=\"small\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"onSetConditions()\"\r\n ></mt-button>\r\n </div>\r\n }\r\n </ng-template>\r\n </mt-toggle-field>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div\r\n [class]=\"[\r\n modalService.footerClass,\r\n '!h-auto',\r\n 'min-h-0',\r\n 'flex-col',\r\n 'gap-2',\r\n 'sm:flex-row',\r\n 'sm:items-center',\r\n 'sm:justify-end',\r\n ]\"\r\n >\r\n @if (initialData() && !isManageProperties()) {\r\n <mt-button\r\n [tooltip]=\"t('delete')\"\r\n severity=\"danger\"\r\n [variant]=\"'outlined'\"\r\n icon=\"general.trash-01\"\r\n [loading]=\"deleting()\"\r\n [disabled]=\"submitting()\"\r\n (onClick)=\"onDelete($event)\"\r\n class=\"self-start sm:me-auto\"\r\n ></mt-button>\r\n }\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n variant=\"outlined\"\r\n [disabled]=\"submitting() || deleting()\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"onCancel()\"\r\n >\r\n </mt-button>\r\n <mt-button\r\n [disabled]=\"!formControl.valid || deleting()\"\r\n [label]=\"t('save')\"\r\n severity=\"primary\"\r\n [loading]=\"submitting()\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"onSave()\"\r\n >\r\n </mt-button>\r\n </div>\r\n</ng-container>\r\n" }]
|
|
1503
1501
|
}], ctorParameters: () => [], propDecorators: { sectionId: [{ type: i0.Input, args: [{ isSignal: true, alias: "sectionId", required: false }] }], initialData: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialData", required: false }] }], allSections: [{ type: i0.Input, args: [{ isSignal: true, alias: "allSections", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }] } });
|
|
1504
1502
|
|
|
1505
1503
|
class FBSectionForm {
|
|
@@ -2046,7 +2044,7 @@ class FBValidationRuleForm {
|
|
|
2046
2044
|
this.saveError.set(message);
|
|
2047
2045
|
}
|
|
2048
2046
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FBValidationRuleForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2049
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: FBValidationRuleForm, isStandalone: true, selector: "mt-fb-validation-rule-form", inputs: { initialData: { classPropertyName: "initialData", publicName: "initialData", isSignal: true, isRequired: false, transformFunction: null }, availableFields: { classPropertyName: "availableFields", publicName: "availableFields", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div\r\n [class]=\"[\r\n modalService.contentClass,\r\n 'min-w-0',\r\n 'p-4',\r\n 'overflow-y-hidden!',\r\n 'max-[640px]:p-3',\r\n ]\"\r\n >\r\n <div class=\"mt-4 flex h-full min-h-0 flex-col gap-4 overflow-y-auto pb-10\">\r\n <mt-formula-builder\r\n [placeholder]=\"t('validation-formula-placeholder')\"\r\n [formControl]=\"formulaControl\"\r\n [levelSchemaId]=\"builderSchemaId()\"\r\n [moduleId]=\"builderModuleId()\"\r\n [contextEntityTypeKey]=\"builderContextEntityTypeKey()\"\r\n [propertiesByPath]=\"formulaPropertiesByPath()\"\r\n
|
|
2047
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: FBValidationRuleForm, isStandalone: true, selector: "mt-fb-validation-rule-form", inputs: { initialData: { classPropertyName: "initialData", publicName: "initialData", isSignal: true, isRequired: false, transformFunction: null }, availableFields: { classPropertyName: "availableFields", publicName: "availableFields", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div\r\n [class]=\"[\r\n modalService.contentClass,\r\n 'min-w-0',\r\n 'p-4',\r\n 'overflow-y-hidden!',\r\n 'max-[640px]:p-3',\r\n ]\"\r\n >\r\n <div class=\"mt-4 flex h-full min-h-0 flex-col gap-4 overflow-y-auto pb-10\">\r\n <mt-formula-builder\r\n [placeholder]=\"t('validation-formula-placeholder')\"\r\n [formControl]=\"formulaControl\"\r\n [levelSchemaId]=\"builderSchemaId()\"\r\n [moduleId]=\"builderModuleId()\"\r\n [contextEntityTypeKey]=\"builderContextEntityTypeKey()\"\r\n [propertiesByPath]=\"formulaPropertiesByPath()\"\r\n (validationChange)=\"onFormulaValidationChange($event)\"\r\n />\r\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\r\n <mt-text-field\r\n [label]=\"t('message-en')\"\r\n [placeholder]=\"t('message-en')\"\r\n [formControl]=\"messageEnControl\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('message-ar')\"\r\n [placeholder]=\"t('message-ar')\"\r\n [formControl]=\"messageArControl\"\r\n />\r\n </div>\r\n <div class=\"grid gap-2\">\r\n <label class=\"text-sm font-medium text-gray-700 dark:text-gray-100\">\r\n {{ t(\"severity\") }}\r\n </label>\r\n <mt-radio-cards\r\n [options]=\"severityOptions()\"\r\n [activeId]=\"severityControl.value\"\r\n (selectionChange)=\"onSeverityChange($event)\"\r\n ></mt-radio-cards>\r\n </div>\r\n @if (saveError(); as error) {\r\n <div\r\n class=\"rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700\"\r\n >\r\n {{ error }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div\r\n [class]=\"[\r\n modalService.footerClass,\r\n '!h-auto',\r\n 'min-h-0',\r\n 'flex-col',\r\n 'gap-2',\r\n 'sm:flex-row',\r\n 'sm:items-center',\r\n 'sm:justify-end',\r\n ]\"\r\n >\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n variant=\"outlined\"\r\n [disabled]=\"submitting()\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"onCancel()\"\r\n />\r\n <mt-button\r\n [label]=\"t('save')\"\r\n severity=\"primary\"\r\n [loading]=\"submitting()\"\r\n [disabled]=\"!canSave()\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"onSave()\"\r\n />\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { 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: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: RadioCards, selector: "mt-radio-cards", inputs: ["circle", "color", "size", "columns", "options", "activeId", "itemTemplate"], outputs: ["optionsChange", "activeIdChange", "selectionChange"] }, { kind: "component", type: FormulaBuilder, selector: "mt-formula-builder", inputs: ["propertiesByPath", "levelSchemaId", "moduleId", "contextEntityTypeKey", "templateId", "placeholder", "hideToolbar", "hideStatusBar", "toolbarTabs", "codeOnly", "isProcessBuilder"], outputs: ["validationChange", "tokensChange"] }] });
|
|
2050
2048
|
}
|
|
2051
2049
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FBValidationRuleForm, decorators: [{
|
|
2052
2050
|
type: Component,
|
|
@@ -2057,7 +2055,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
2057
2055
|
TextField,
|
|
2058
2056
|
RadioCards,
|
|
2059
2057
|
FormulaBuilder,
|
|
2060
|
-
], template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div\r\n [class]=\"[\r\n modalService.contentClass,\r\n 'min-w-0',\r\n 'p-4',\r\n 'overflow-y-hidden!',\r\n 'max-[640px]:p-3',\r\n ]\"\r\n >\r\n <div class=\"mt-4 flex h-full min-h-0 flex-col gap-4 overflow-y-auto pb-10\">\r\n <mt-formula-builder\r\n [placeholder]=\"t('validation-formula-placeholder')\"\r\n [formControl]=\"formulaControl\"\r\n [levelSchemaId]=\"builderSchemaId()\"\r\n [moduleId]=\"builderModuleId()\"\r\n [contextEntityTypeKey]=\"builderContextEntityTypeKey()\"\r\n [propertiesByPath]=\"formulaPropertiesByPath()\"\r\n
|
|
2058
|
+
], template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div\r\n [class]=\"[\r\n modalService.contentClass,\r\n 'min-w-0',\r\n 'p-4',\r\n 'overflow-y-hidden!',\r\n 'max-[640px]:p-3',\r\n ]\"\r\n >\r\n <div class=\"mt-4 flex h-full min-h-0 flex-col gap-4 overflow-y-auto pb-10\">\r\n <mt-formula-builder\r\n [placeholder]=\"t('validation-formula-placeholder')\"\r\n [formControl]=\"formulaControl\"\r\n [levelSchemaId]=\"builderSchemaId()\"\r\n [moduleId]=\"builderModuleId()\"\r\n [contextEntityTypeKey]=\"builderContextEntityTypeKey()\"\r\n [propertiesByPath]=\"formulaPropertiesByPath()\"\r\n (validationChange)=\"onFormulaValidationChange($event)\"\r\n />\r\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\r\n <mt-text-field\r\n [label]=\"t('message-en')\"\r\n [placeholder]=\"t('message-en')\"\r\n [formControl]=\"messageEnControl\"\r\n />\r\n <mt-text-field\r\n [label]=\"t('message-ar')\"\r\n [placeholder]=\"t('message-ar')\"\r\n [formControl]=\"messageArControl\"\r\n />\r\n </div>\r\n <div class=\"grid gap-2\">\r\n <label class=\"text-sm font-medium text-gray-700 dark:text-gray-100\">\r\n {{ t(\"severity\") }}\r\n </label>\r\n <mt-radio-cards\r\n [options]=\"severityOptions()\"\r\n [activeId]=\"severityControl.value\"\r\n (selectionChange)=\"onSeverityChange($event)\"\r\n ></mt-radio-cards>\r\n </div>\r\n @if (saveError(); as error) {\r\n <div\r\n class=\"rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700\"\r\n >\r\n {{ error }}\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div\r\n [class]=\"[\r\n modalService.footerClass,\r\n '!h-auto',\r\n 'min-h-0',\r\n 'flex-col',\r\n 'gap-2',\r\n 'sm:flex-row',\r\n 'sm:items-center',\r\n 'sm:justify-end',\r\n ]\"\r\n >\r\n <mt-button\r\n [label]=\"t('cancel')\"\r\n variant=\"outlined\"\r\n [disabled]=\"submitting()\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"onCancel()\"\r\n />\r\n <mt-button\r\n [label]=\"t('save')\"\r\n severity=\"primary\"\r\n [loading]=\"submitting()\"\r\n [disabled]=\"!canSave()\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"onSave()\"\r\n />\r\n </div>\r\n</ng-container>\r\n" }]
|
|
2061
2059
|
}], ctorParameters: () => [], propDecorators: { initialData: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialData", required: false }] }], availableFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableFields", required: false }] }] } });
|
|
2062
2060
|
|
|
2063
2061
|
class FBValidationRules {
|
|
@@ -2310,6 +2308,8 @@ class FormBuilder {
|
|
|
2310
2308
|
canvasStyleClass = input('', ...(ngDevMode ? [{ debugName: "canvasStyleClass" }] : /* istanbul ignore next */ []));
|
|
2311
2309
|
/** Operating mode: 'builder' (full editor) or 'manageProperties' (read/write permissions only). */
|
|
2312
2310
|
mode = input('builder', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
2311
|
+
/** Controls the draggable properties sidebar independently from the main builder canvas. */
|
|
2312
|
+
showPropertiesSection = input(true, { ...(ngDevMode ? { debugName: "showPropertiesSection" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
2313
2313
|
dialogRef;
|
|
2314
2314
|
// ============================================================================
|
|
2315
2315
|
// Facade State
|
|
@@ -2340,7 +2340,10 @@ class FormBuilder {
|
|
|
2340
2340
|
// Request tracking
|
|
2341
2341
|
initialRequestId = 0;
|
|
2342
2342
|
scopeRequestId = 0;
|
|
2343
|
-
|
|
2343
|
+
lastFormConfigurationContextKey = '';
|
|
2344
|
+
lastResolvedContextKey = '';
|
|
2345
|
+
hasResolvedContextState = false;
|
|
2346
|
+
initialContextStateCleared = false;
|
|
2344
2347
|
// ============================================================================
|
|
2345
2348
|
// Computed Values
|
|
2346
2349
|
// ============================================================================
|
|
@@ -2360,6 +2363,7 @@ class FormBuilder {
|
|
|
2360
2363
|
segments.push(`${type}:${id}`);
|
|
2361
2364
|
return segments.join('/');
|
|
2362
2365
|
}, ...(ngDevMode ? [{ debugName: "contextKey" }] : /* istanbul ignore next */ []));
|
|
2366
|
+
propertiesSectionVisible = computed(() => this.mode() !== 'manageProperties' && this.showPropertiesSection(), ...(ngDevMode ? [{ debugName: "propertiesSectionVisible" }] : /* istanbul ignore next */ []));
|
|
2363
2367
|
usedPropertyKeys = computed(() => {
|
|
2364
2368
|
return new Set(this.sections().flatMap((s) => s.fields.map((f) => f.propertyKey)));
|
|
2365
2369
|
}, ...(ngDevMode ? [{ debugName: "usedPropertyKeys" }] : /* istanbul ignore next */ []));
|
|
@@ -2392,6 +2396,8 @@ class FormBuilder {
|
|
|
2392
2396
|
}, ...(ngDevMode ? [{ debugName: "baseScopeContexts" }] : /* istanbul ignore next */ []));
|
|
2393
2397
|
/** Available scope tabs */
|
|
2394
2398
|
scopeOptions = computed(() => {
|
|
2399
|
+
if (!this.propertiesSectionVisible())
|
|
2400
|
+
return [];
|
|
2395
2401
|
const contexts = this.baseScopeContexts();
|
|
2396
2402
|
return SCOPE_ORDER.filter((s) => (contexts[s] ?? []).length > 0).map((s) => ({
|
|
2397
2403
|
key: s,
|
|
@@ -2399,7 +2405,9 @@ class FormBuilder {
|
|
|
2399
2405
|
}));
|
|
2400
2406
|
}, ...(ngDevMode ? [{ debugName: "scopeOptions" }] : /* istanbul ignore next */ []));
|
|
2401
2407
|
fieldDropListIds = computed(() => this.sections().map((section) => section.id), ...(ngDevMode ? [{ debugName: "fieldDropListIds" }] : /* istanbul ignore next */ []));
|
|
2402
|
-
toolboxDropListIds = computed(() => this.
|
|
2408
|
+
toolboxDropListIds = computed(() => this.propertiesSectionVisible()
|
|
2409
|
+
? this.scopeOptions().map((scope) => `toolbox-${scope.key}`)
|
|
2410
|
+
: [], ...(ngDevMode ? [{ debugName: "toolboxDropListIds" }] : /* istanbul ignore next */ []));
|
|
2403
2411
|
fieldDropListConnections = computed(() => [
|
|
2404
2412
|
...this.fieldDropListIds(),
|
|
2405
2413
|
...this.toolboxDropListIds(),
|
|
@@ -2455,39 +2463,42 @@ class FormBuilder {
|
|
|
2455
2463
|
// Lifecycle
|
|
2456
2464
|
// ============================================================================
|
|
2457
2465
|
constructor() {
|
|
2458
|
-
// Effect: watch
|
|
2466
|
+
// Effect: watch context/sidebar visibility changes and load only data the UI uses.
|
|
2459
2467
|
effect(() => {
|
|
2460
|
-
|
|
2461
|
-
if (key && key !== this.lastContextKey) {
|
|
2462
|
-
this.lastContextKey = key;
|
|
2463
|
-
// In manageProperties mode, load form config AND resolve context for bilingual property names
|
|
2464
|
-
if (this.mode() === 'manageProperties') {
|
|
2465
|
-
this.facade.getFormConfiguration();
|
|
2466
|
-
this.loadInitialContext(key);
|
|
2467
|
-
return;
|
|
2468
|
-
}
|
|
2469
|
-
this.loadInitialContext(key);
|
|
2470
|
-
}
|
|
2468
|
+
this.syncContextData();
|
|
2471
2469
|
}, { allowSignalWrites: true });
|
|
2472
2470
|
}
|
|
2473
2471
|
ngOnInit() {
|
|
2474
|
-
|
|
2472
|
+
this.syncContextData();
|
|
2473
|
+
}
|
|
2474
|
+
syncContextData() {
|
|
2475
2475
|
const key = this.contextKey();
|
|
2476
|
-
if (key
|
|
2477
|
-
this.
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
this.loadInitialContext(key);
|
|
2481
|
-
return;
|
|
2482
|
-
}
|
|
2483
|
-
this.loadInitialContext(key);
|
|
2476
|
+
if (!key) {
|
|
2477
|
+
this.lastFormConfigurationContextKey = '';
|
|
2478
|
+
this.clearInitialContextState();
|
|
2479
|
+
return;
|
|
2484
2480
|
}
|
|
2481
|
+
if (this.mode() === 'manageProperties' &&
|
|
2482
|
+
key !== this.lastFormConfigurationContextKey) {
|
|
2483
|
+
this.lastFormConfigurationContextKey = key;
|
|
2484
|
+
this.facade.getFormConfiguration();
|
|
2485
|
+
}
|
|
2486
|
+
if (!this.propertiesSectionVisible()) {
|
|
2487
|
+
this.clearInitialContextState();
|
|
2488
|
+
return;
|
|
2489
|
+
}
|
|
2490
|
+
if (key === this.lastResolvedContextKey)
|
|
2491
|
+
return;
|
|
2492
|
+
this.lastResolvedContextKey = key;
|
|
2493
|
+
this.loadInitialContext(key);
|
|
2485
2494
|
}
|
|
2486
2495
|
// ============================================================================
|
|
2487
2496
|
// Initial Context Loading
|
|
2488
2497
|
// ============================================================================
|
|
2489
2498
|
loadInitialContext(contextKey) {
|
|
2490
2499
|
const requestId = ++this.initialRequestId;
|
|
2500
|
+
this.hasResolvedContextState = true;
|
|
2501
|
+
this.initialContextStateCleared = false;
|
|
2491
2502
|
this.isContextLoading.set(true);
|
|
2492
2503
|
this.initialContext.set(null);
|
|
2493
2504
|
this.currentProperties.set([]);
|
|
@@ -2511,6 +2522,26 @@ class FormBuilder {
|
|
|
2511
2522
|
this.facade.setProperties(response?.properties ?? []);
|
|
2512
2523
|
});
|
|
2513
2524
|
}
|
|
2525
|
+
clearInitialContextState() {
|
|
2526
|
+
if (this.initialContextStateCleared &&
|
|
2527
|
+
!this.hasResolvedContextState &&
|
|
2528
|
+
!this.lastResolvedContextKey) {
|
|
2529
|
+
return;
|
|
2530
|
+
}
|
|
2531
|
+
if (this.hasResolvedContextState || this.lastResolvedContextKey) {
|
|
2532
|
+
++this.initialRequestId;
|
|
2533
|
+
}
|
|
2534
|
+
++this.scopeRequestId;
|
|
2535
|
+
this.lastResolvedContextKey = '';
|
|
2536
|
+
this.hasResolvedContextState = false;
|
|
2537
|
+
this.initialContextStateCleared = true;
|
|
2538
|
+
this.isContextLoading.set(false);
|
|
2539
|
+
this.initialContext.set(null);
|
|
2540
|
+
this.currentProperties.set([]);
|
|
2541
|
+
this.facade.setProperties([]);
|
|
2542
|
+
this.resetScopeState();
|
|
2543
|
+
this.activeScope.set('Current');
|
|
2544
|
+
}
|
|
2514
2545
|
// ============================================================================
|
|
2515
2546
|
// Tab Change Handler (Called from template)
|
|
2516
2547
|
// ============================================================================
|
|
@@ -2886,7 +2917,7 @@ class FormBuilder {
|
|
|
2886
2917
|
}
|
|
2887
2918
|
noReturnPredicate = () => false;
|
|
2888
2919
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FormBuilder, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2889
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: FormBuilder, isStandalone: true, selector: "mt-form-builder", inputs: { canvasStyleClass: { classPropertyName: "canvasStyleClass", publicName: "canvasStyleClass", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "popovers", predicate: Popover, descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div\r\n class=\"flex h-full w-full gap-7 overflow-hidden max-[1025px]:min-h-0 max-[1025px]:min-w-0 max-[1025px]:flex-col max-[1025px]:gap-4 max-[1025px]:overflow-x-hidden max-[1025px]:overflow-y-auto\"\r\n >\r\n <!-- Properties Sidebar (hidden in manageProperties mode) -->\r\n @if (mode() !== \"manageProperties\") {\r\n <mt-card\r\n class=\"h-full w-1/5 flex flex-col overflow-hidden max-[1025px]:h-auto max-[1025px]:max-h-[42vh] max-[1025px]:min-h-0 max-[1025px]:w-full\"\r\n >\r\n <ng-template #headless>\r\n <!-- Header -->\r\n <h3 class=\"text-xl font-semibold px-4 pt-5\">\r\n {{ t(\"form-elements\") }}\r\n </h3>\r\n\r\n @if (isContextLoading()) {\r\n <!-- Properties Loading Skeleton -->\r\n <div class=\"flex gap-4 py-3 px-5 mt-4\">\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-lg\" />\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"py-4 px-5 space-y-5\">\r\n @for (i of [1, 2, 3, 4, 5, 6]; track i) {\r\n <p-skeleton height=\"3rem\" styleClass=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else if (scopeOptions().length === 0) {\r\n <!-- No Properties State -->\r\n <div class=\"flex-1 flex items-center justify-center p-4\">\r\n <p class=\"text-sm font-semibold text-gray-500\">\r\n {{ t(\"no-data-found\") }}\r\n </p>\r\n </div>\r\n } @else {\r\n <!-- Scope Tabs using PrimeNG -->\r\n <p-tabs\r\n [value]=\"activeScope()\"\r\n (valueChange)=\"onScopeChange($event)\"\r\n styleClass=\"structure-tabs\"\r\n class=\"flex min-h-0 flex-1 flex-col\"\r\n >\r\n <p-tablist class=\"shrink-0 overflow-x-auto\">\r\n @for (scope of scopeOptions(); track scope.key) {\r\n <p-tab [value]=\"scope.key\">{{ scope.label }}</p-tab>\r\n }\r\n </p-tablist>\r\n <p-tabpanels\r\n class=\"!bg-transparent !p-0 !pb-3 flex-1 overflow-hidden\"\r\n >\r\n @for (scope of scopeOptions(); track scope.key) {\r\n <p-tabpanel [value]=\"scope.key\" class=\"h-full flex flex-col\">\r\n @if (scope.key !== \"Current\") {\r\n <div class=\"px-4 pt-3 pb-2\">\r\n <div\r\n class=\"flex flex-col gap-3 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-800/50\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"shrink-0 text-xs font-semibold uppercase tracking-wider text-slate-400\"\r\n >\r\n {{ t(\"path\") }}\r\n </span>\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <span class=\"text-xs font-semibold text-slate-600\">\r\n {{ scope.label }}\r\n </span>\r\n </div>\r\n @if (getScopeBaseContexts(scope.key).length === 0) {\r\n <span class=\"text-xs italic text-slate-400\">\r\n {{ t(\"no-context\") }}\r\n </span>\r\n } @else {\r\n <div class=\"flex flex-col gap-1.5\">\r\n @for (\r\n segment of getScopePath(scope.key);\r\n track $index;\r\n let segmentIndex = $index;\r\n let isLast = $last\r\n ) {\r\n <div\r\n class=\"flex items-center gap-1 py-0.5 px-2 border border-gray-200 rounded bg-white dark:bg-slate-800 dark:border-slate-600\"\r\n >\r\n <div\r\n class=\"flex-1 min-w-0 text-xs font-medium text-slate-600 dark:text-slate-300 truncate cursor-pointer\"\r\n (click)=\"segmentPopover.toggle($event)\"\r\n >\r\n {{\r\n getScopeSegmentLabel(\r\n scope.key,\r\n segmentIndex\r\n )\r\n }}\r\n </div>\r\n <mt-button\r\n type=\"button\"\r\n icon=\"arrow.chevron-down\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"!p-0.5 !min-w-0\"\r\n (onClick)=\"segmentPopover.toggle($event)\"\r\n ></mt-button>\r\n @if (\r\n isLast && canRemoveScopePath(scope.key)\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.trash-01\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n severity=\"danger\"\r\n styleClass=\"!p-0.5 !min-w-0\"\r\n (onClick)=\"removeScopePath(scope.key)\"\r\n ></mt-button>\r\n }\r\n </div>\r\n <p-popover\r\n #segmentPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n [dismissable]=\"true\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n {{ t(\"select\") }}\r\n {{ getTokenLabel(segment.token) }}\r\n </div>\r\n @if (\r\n getScopeSegmentOptions(\r\n scope.key,\r\n segmentIndex\r\n ).length === 0\r\n ) {\r\n <div\r\n class=\"text-xs font-medium text-slate-400\"\r\n >\r\n {{ t(\"no-options\") }}\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n option of getScopeSegmentOptions(\r\n scope.key,\r\n segmentIndex\r\n );\r\n track option.contextKey\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"option.label\"\r\n [icon]=\"\r\n option.contextKey ===\r\n segment.value\r\n ? 'general.check'\r\n : 'general.minus'\r\n \"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onSetScopeSegmentValue(\r\n scope.key,\r\n segmentIndex,\r\n option.contextKey,\r\n segmentPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </p-popover>\r\n }\r\n @if (canAddNextScopeSegment(scope.key)) {\r\n <div class=\"flex items-center gap-2\">\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n severity=\"primary\"\r\n styleClass=\"flex size-7 shrink-0 items-center justify-center rounded-md bg-primary text-xs font-bold text-white hover:opacity-90\"\r\n (onClick)=\"\r\n nextContextPopover.toggle($event)\r\n \"\r\n ></mt-button>\r\n <!-- <span class=\"text-xs text-slate-400\">\r\n {{ t(\"add-segment\") }}\r\n </span> -->\r\n </div>\r\n }\r\n <!-- Popover OUTSIDE the @if block like formula-builder -->\r\n <p-popover\r\n #nextContextPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n [dismissable]=\"true\"\r\n appendTo=\"body\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n {{ t(\"add-segment\") }}\r\n </div>\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n token of getScopeNextTokens(scope.key);\r\n track token\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"getTokenLabel(token)\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onAddScopeSegment(\r\n scope.key,\r\n token,\r\n nextContextPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n </div>\r\n </p-popover>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Node List -->\r\n <div\r\n class=\"flex-1 min-h-0 overflow-y-auto space-y-4 px-4 pb-4 [&_.cdk-drag-placeholder]:hidden\"\r\n [id]=\"'toolbox-' + scope.key\"\r\n cdkDropList\r\n cdkDropListSortingDisabled\r\n [cdkDropListData]=\"getFilteredProperties(scope.key)\"\r\n [cdkDropListConnectedTo]=\"fieldDropListIds()\"\r\n [cdkDropListEnterPredicate]=\"noReturnPredicate\"\r\n >\r\n <!-- Search Field (Sticky) -->\r\n <div\r\n class=\"sticky top-0 bg-surface-0 mb-0 py-3 pb-2 mb-1\"\r\n >\r\n <mt-text-field\r\n [placeholder]=\"t('search-properties')\"\r\n [(ngModel)]=\"searchQuery\"\r\n icon=\"general.search-lg\"\r\n />\r\n </div>\r\n\r\n @if (isScopePropertiesLoading(scope.key)) {\r\n <div class=\"space-y-4\">\r\n @for (i of [1, 2, 3, 4]; track i) {\r\n <p-skeleton height=\"3rem\" styleClass=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else {\r\n @for (\r\n node of getFilteredProperties(scope.key);\r\n track node.key\r\n ) {\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"node\"\r\n class=\"group cursor-move select-none flex items-center gap-3 py-3 px-3 rounded-lg border border-dashed border-surface-300 hover:bg-emphasis dark:border-surface-500 transition-colors\"\r\n >\r\n <div\r\n *cdkDragPlaceholder\r\n class=\"col-span-12 min-h-27 w-full rounded-lg bg-black/10 z-1\"\r\n ></div>\r\n <span\r\n class=\"flex-1 text-start text-base font-medium\"\r\n >{{ getPropertyLabel(node) }}</span\r\n >\r\n\r\n <mt-icon\r\n class=\"text-lg\"\r\n icon=\"general.menu-05\"\r\n ></mt-icon>\r\n </div>\r\n }\r\n\r\n @if (getFilteredProperties(scope.key).length === 0) {\r\n <div class=\"py-8 text-center text-muted-color\">\r\n <p class=\"text-sm\">\r\n @if (searchQuery()) {\r\n {{ t(\"no-data-found\") }}\r\n } @else if (\r\n getScopeProperties(scope.key).length === 0\r\n ) {\r\n {{ t(\"no-properties-available\") }}\r\n } @else {\r\n {{ t(\"all-items-in-use\") }}\r\n }\r\n </p>\r\n </div>\r\n }\r\n }\r\n </div>\r\n </p-tabpanel>\r\n }\r\n </p-tabpanels>\r\n </p-tabs>\r\n }\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n <!-- Main Canvas Area -->\r\n <div\r\n class=\"flex h-full min-w-0 flex-1 gap-4 overflow-y-auto max-[1025px]:h-auto max-[1025px]:min-h-0 max-[1025px]:overflow-visible\"\r\n >\r\n <div\r\n class=\"flex h-full min-w-0 w-full flex-1 flex-col gap-4 max-[1025px]:h-auto\"\r\n [ngClass]=\"canvasStyleClass()\"\r\n >\r\n @if (mode() !== \"manageProperties\") {\r\n <mt-card>\r\n <ng-template #headless>\r\n <div\r\n class=\"flex flex-col gap-3 p-4 sm:flex-row sm:flex-wrap sm:items-center\"\r\n >\r\n <div class=\"w-full sm:w-44\">\r\n <mt-select-field\r\n [label]=\"''\"\r\n [placeholder]=\"''\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n [ngModel]=\"selectedRenderMode()\"\r\n (ngModelChange)=\"onRenderModeChange($event)\"\r\n [options]=\"renderModeOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n optionIcon=\"icon\"\r\n optionIconColor=\"color\"\r\n [optionAvatarShape]=\"'square'\"\r\n [size]=\"'small'\"\r\n [loading]=\"isUpdatingFormSettings()\"\r\n [disabled]=\"\r\n isLoading() ||\r\n isUpdatingFormSettings() ||\r\n !formConfiguration()\r\n \"\r\n />\r\n </div>\r\n <mt-button\r\n icon=\"layout.layout-top\"\r\n [label]=\"t('add-section')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"addSection()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n <mt-button\r\n icon=\"general.eye\"\r\n [label]=\"t('preview')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"openPreview()\"\r\n [disabled]=\"isLoading() || isUpdatingFormSettings()\"\r\n ></mt-button>\r\n <mt-button\r\n [label]=\"t('validation-rules')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"openValidationRules()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n <mt-button\r\n icon=\"finance.credit-card-plus\"\r\n [label]=\"t('reset')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"resetFormConfiguration()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n @if (isLoading()) {\r\n <!-- Form Loading Skeleton -->\r\n @for (i of [1, 2]; track i) {\r\n <mt-card>\r\n <ng-template #headless>\r\n <div class=\"p-4 space-y-4\">\r\n <!-- Section header skeleton -->\r\n <div\r\n class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\"\r\n >\r\n <p-skeleton width=\"10rem\" height=\"1.5rem\" />\r\n <div class=\"flex gap-2\">\r\n <p-skeleton width=\"2rem\" height=\"2rem\" shape=\"circle\" />\r\n <p-skeleton width=\"2rem\" height=\"2rem\" shape=\"circle\" />\r\n </div>\r\n </div>\r\n <!-- Fields skeleton -->\r\n <div class=\"grid grid-cols-12 gap-4\">\r\n <div class=\"col-span-12 sm:col-span-6\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"col-span-12 sm:col-span-6\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"col-span-12\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n }\r\n } @else {\r\n <div\r\n cdkDropList\r\n id=\"sections-list\"\r\n [cdkDropListData]=\"enrichedSections()\"\r\n [cdkDropListDisabled]=\"mode() === 'manageProperties'\"\r\n [cdkDropListEnterPredicate]=\"sectionsDropPredicate\"\r\n (cdkDropListDropped)=\"dropSection($event)\"\r\n class=\"flex flex-col gap-4\"\r\n >\r\n @for (section of enrichedSections(); track section.id) {\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"section\"\r\n [cdkDragDisabled]=\"mode() === 'manageProperties'\"\r\n >\r\n <div\r\n *cdkDragPlaceholder\r\n class=\"min-h-16 rounded-xl border-2 border-dashed border-primary bg-primary-50/40\"\r\n ></div>\r\n <mt-fb-section\r\n [section]=\"section\"\r\n [sectionsCount]=\"enrichedSections().length\"\r\n [allSections]=\"enrichedSections()\"\r\n [mode]=\"mode()\"\r\n [connectedDropLists]=\"fieldDropListConnections()\"\r\n (onFieldDrop)=\"drop($event)\"\r\n >\r\n </mt-fb-section>\r\n </div>\r\n } @empty {\r\n <mt-card>\r\n <div class=\"h-27 p-4\">\r\n <div\r\n class=\"flex justify-center items-center gap-4 h-full border-1 border-primary rounded-xl bg-primary-50 text-primary\"\r\n >\r\n <span>{{ t(\"no-section\") }}</span>\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</ng-container>\r\n", styles: [".cdk-drag{cursor:grab}.cdk-drag:active,.cdk-drag-preview{cursor:grabbing}.cdk-drag-placeholder{opacity:.5}.cdk-drop-list-dragging .cdk-drag{cursor:grabbing}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i3.Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: i3.TabPanels, selector: "p-tabpanels" }, { kind: "component", type: i3.TabPanel, selector: "p-tabpanel", inputs: ["lazy", "value"], outputs: ["valueChange"] }, { kind: "component", type: i3.TabList, selector: "p-tablist" }, { kind: "component", type: i3.Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i4.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i5.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { 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: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: FBSection, selector: "mt-fb-section", inputs: ["section", "sectionsCount", "allSections", "mode", "connectedDropLists"], outputs: ["onFieldDrop"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i6.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i6.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i6.CdkDragPlaceholder, selector: "ng-template[cdkDragPlaceholder]", inputs: ["data"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }] });
|
|
2920
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: FormBuilder, isStandalone: true, selector: "mt-form-builder", inputs: { canvasStyleClass: { classPropertyName: "canvasStyleClass", publicName: "canvasStyleClass", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, showPropertiesSection: { classPropertyName: "showPropertiesSection", publicName: "showPropertiesSection", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "popovers", predicate: Popover, descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div\r\n class=\"flex h-full w-full gap-7 overflow-hidden max-[1025px]:min-h-0 max-[1025px]:min-w-0 max-[1025px]:flex-col max-[1025px]:gap-4 max-[1025px]:overflow-x-hidden max-[1025px]:overflow-y-auto\"\r\n >\r\n <!-- Properties Sidebar -->\r\n @if (propertiesSectionVisible()) {\r\n <mt-card\r\n class=\"h-full w-1/5 flex flex-col overflow-hidden max-[1025px]:h-auto max-[1025px]:max-h-[42vh] max-[1025px]:min-h-0 max-[1025px]:w-full\"\r\n >\r\n <ng-template #headless>\r\n <!-- Header -->\r\n <h3 class=\"text-xl font-semibold px-4 pt-5\">\r\n {{ t(\"form-elements\") }}\r\n </h3>\r\n\r\n @if (isContextLoading()) {\r\n <!-- Properties Loading Skeleton -->\r\n <div class=\"flex gap-4 py-3 px-5 mt-4\">\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-lg\" />\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"py-4 px-5 space-y-5\">\r\n @for (i of [1, 2, 3, 4, 5, 6]; track i) {\r\n <p-skeleton height=\"3rem\" styleClass=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else if (scopeOptions().length === 0) {\r\n <!-- No Properties State -->\r\n <div class=\"flex-1 flex items-center justify-center p-4\">\r\n <p class=\"text-sm font-semibold text-gray-500\">\r\n {{ t(\"no-data-found\") }}\r\n </p>\r\n </div>\r\n } @else {\r\n <!-- Scope Tabs using PrimeNG -->\r\n <p-tabs\r\n [value]=\"activeScope()\"\r\n (valueChange)=\"onScopeChange($event)\"\r\n styleClass=\"structure-tabs\"\r\n class=\"flex min-h-0 flex-1 flex-col\"\r\n >\r\n <p-tablist class=\"shrink-0 overflow-x-auto\">\r\n @for (scope of scopeOptions(); track scope.key) {\r\n <p-tab [value]=\"scope.key\">{{ scope.label }}</p-tab>\r\n }\r\n </p-tablist>\r\n <p-tabpanels\r\n class=\"!bg-transparent !p-0 !pb-3 flex-1 overflow-hidden\"\r\n >\r\n @for (scope of scopeOptions(); track scope.key) {\r\n <p-tabpanel [value]=\"scope.key\" class=\"h-full flex flex-col\">\r\n @if (scope.key !== \"Current\") {\r\n <div class=\"px-4 pt-3 pb-2\">\r\n <div\r\n class=\"flex flex-col gap-3 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-800/50\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"shrink-0 text-xs font-semibold uppercase tracking-wider text-slate-400\"\r\n >\r\n {{ t(\"path\") }}\r\n </span>\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <span class=\"text-xs font-semibold text-slate-600\">\r\n {{ scope.label }}\r\n </span>\r\n </div>\r\n @if (getScopeBaseContexts(scope.key).length === 0) {\r\n <span class=\"text-xs italic text-slate-400\">\r\n {{ t(\"no-context\") }}\r\n </span>\r\n } @else {\r\n <div class=\"flex flex-col gap-1.5\">\r\n @for (\r\n segment of getScopePath(scope.key);\r\n track $index;\r\n let segmentIndex = $index;\r\n let isLast = $last\r\n ) {\r\n <div\r\n class=\"flex items-center gap-1 py-0.5 px-2 border border-gray-200 rounded bg-white dark:bg-slate-800 dark:border-slate-600\"\r\n >\r\n <div\r\n class=\"flex-1 min-w-0 text-xs font-medium text-slate-600 dark:text-slate-300 truncate cursor-pointer\"\r\n (click)=\"segmentPopover.toggle($event)\"\r\n >\r\n {{\r\n getScopeSegmentLabel(\r\n scope.key,\r\n segmentIndex\r\n )\r\n }}\r\n </div>\r\n <mt-button\r\n type=\"button\"\r\n icon=\"arrow.chevron-down\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"!p-0.5 !min-w-0\"\r\n (onClick)=\"segmentPopover.toggle($event)\"\r\n ></mt-button>\r\n @if (\r\n isLast && canRemoveScopePath(scope.key)\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.trash-01\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n severity=\"danger\"\r\n styleClass=\"!p-0.5 !min-w-0\"\r\n (onClick)=\"removeScopePath(scope.key)\"\r\n ></mt-button>\r\n }\r\n </div>\r\n <p-popover\r\n #segmentPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n [dismissable]=\"true\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n {{ t(\"select\") }}\r\n {{ getTokenLabel(segment.token) }}\r\n </div>\r\n @if (\r\n getScopeSegmentOptions(\r\n scope.key,\r\n segmentIndex\r\n ).length === 0\r\n ) {\r\n <div\r\n class=\"text-xs font-medium text-slate-400\"\r\n >\r\n {{ t(\"no-options\") }}\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n option of getScopeSegmentOptions(\r\n scope.key,\r\n segmentIndex\r\n );\r\n track option.contextKey\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"option.label\"\r\n [icon]=\"\r\n option.contextKey ===\r\n segment.value\r\n ? 'general.check'\r\n : 'general.minus'\r\n \"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onSetScopeSegmentValue(\r\n scope.key,\r\n segmentIndex,\r\n option.contextKey,\r\n segmentPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </p-popover>\r\n }\r\n @if (canAddNextScopeSegment(scope.key)) {\r\n <div class=\"flex items-center gap-2\">\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n severity=\"primary\"\r\n styleClass=\"flex size-7 shrink-0 items-center justify-center rounded-md bg-primary text-xs font-bold text-white hover:opacity-90\"\r\n (onClick)=\"\r\n nextContextPopover.toggle($event)\r\n \"\r\n ></mt-button>\r\n <!-- <span class=\"text-xs text-slate-400\">\r\n {{ t(\"add-segment\") }}\r\n </span> -->\r\n </div>\r\n }\r\n <!-- Popover OUTSIDE the @if block like formula-builder -->\r\n <p-popover\r\n #nextContextPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n [dismissable]=\"true\"\r\n appendTo=\"body\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n {{ t(\"add-segment\") }}\r\n </div>\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n token of getScopeNextTokens(scope.key);\r\n track token\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"getTokenLabel(token)\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onAddScopeSegment(\r\n scope.key,\r\n token,\r\n nextContextPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n </div>\r\n </p-popover>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Node List -->\r\n <div\r\n class=\"flex-1 min-h-0 overflow-y-auto space-y-4 px-4 pb-4 [&_.cdk-drag-placeholder]:hidden\"\r\n [id]=\"'toolbox-' + scope.key\"\r\n cdkDropList\r\n cdkDropListSortingDisabled\r\n [cdkDropListData]=\"getFilteredProperties(scope.key)\"\r\n [cdkDropListConnectedTo]=\"fieldDropListIds()\"\r\n [cdkDropListEnterPredicate]=\"noReturnPredicate\"\r\n >\r\n <!-- Search Field (Sticky) -->\r\n <div\r\n class=\"sticky top-0 bg-surface-0 mb-0 py-3 pb-2 mb-1\"\r\n >\r\n <mt-text-field\r\n [placeholder]=\"t('search-properties')\"\r\n [(ngModel)]=\"searchQuery\"\r\n icon=\"general.search-lg\"\r\n />\r\n </div>\r\n\r\n @if (isScopePropertiesLoading(scope.key)) {\r\n <div class=\"space-y-4\">\r\n @for (i of [1, 2, 3, 4]; track i) {\r\n <p-skeleton height=\"3rem\" styleClass=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else {\r\n @for (\r\n node of getFilteredProperties(scope.key);\r\n track node.key\r\n ) {\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"node\"\r\n class=\"group cursor-move select-none flex items-center gap-3 py-3 px-3 rounded-lg border border-dashed border-surface-300 hover:bg-emphasis dark:border-surface-500 transition-colors\"\r\n >\r\n <div\r\n *cdkDragPlaceholder\r\n class=\"col-span-12 min-h-27 w-full rounded-lg bg-black/10 z-1\"\r\n ></div>\r\n <span\r\n class=\"flex-1 text-start text-base font-medium\"\r\n >{{ getPropertyLabel(node) }}</span\r\n >\r\n\r\n <mt-icon\r\n class=\"text-lg\"\r\n icon=\"general.menu-05\"\r\n ></mt-icon>\r\n </div>\r\n }\r\n\r\n @if (getFilteredProperties(scope.key).length === 0) {\r\n <div class=\"py-8 text-center text-muted-color\">\r\n <p class=\"text-sm\">\r\n @if (searchQuery()) {\r\n {{ t(\"no-data-found\") }}\r\n } @else if (\r\n getScopeProperties(scope.key).length === 0\r\n ) {\r\n {{ t(\"no-properties-available\") }}\r\n } @else {\r\n {{ t(\"all-items-in-use\") }}\r\n }\r\n </p>\r\n </div>\r\n }\r\n }\r\n </div>\r\n </p-tabpanel>\r\n }\r\n </p-tabpanels>\r\n </p-tabs>\r\n }\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n <!-- Main Canvas Area -->\r\n <div\r\n class=\"flex h-full min-w-0 flex-1 gap-4 overflow-y-auto max-[1025px]:h-auto max-[1025px]:min-h-0 max-[1025px]:overflow-visible\"\r\n >\r\n <div\r\n class=\"flex h-full min-w-0 w-full flex-1 flex-col gap-4 max-[1025px]:h-auto\"\r\n [ngClass]=\"canvasStyleClass()\"\r\n >\r\n @if (mode() !== \"manageProperties\") {\r\n <mt-card>\r\n <ng-template #headless>\r\n <div\r\n class=\"flex flex-col gap-3 p-4 sm:flex-row sm:flex-wrap sm:items-center\"\r\n >\r\n <div class=\"w-full sm:w-44\">\r\n <mt-select-field\r\n [label]=\"''\"\r\n [placeholder]=\"''\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n [ngModel]=\"selectedRenderMode()\"\r\n (ngModelChange)=\"onRenderModeChange($event)\"\r\n [options]=\"renderModeOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n optionIcon=\"icon\"\r\n optionIconColor=\"color\"\r\n [optionAvatarShape]=\"'square'\"\r\n [size]=\"'small'\"\r\n [loading]=\"isUpdatingFormSettings()\"\r\n [disabled]=\"\r\n isLoading() ||\r\n isUpdatingFormSettings() ||\r\n !formConfiguration()\r\n \"\r\n />\r\n </div>\r\n <mt-button\r\n icon=\"layout.layout-top\"\r\n [label]=\"t('add-section')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"addSection()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n <mt-button\r\n icon=\"general.eye\"\r\n [label]=\"t('preview')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"openPreview()\"\r\n [disabled]=\"isLoading() || isUpdatingFormSettings()\"\r\n ></mt-button>\r\n <mt-button\r\n [label]=\"t('validation-rules')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"openValidationRules()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n <mt-button\r\n icon=\"finance.credit-card-plus\"\r\n [label]=\"t('reset')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"resetFormConfiguration()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n @if (isLoading()) {\r\n <!-- Form Loading Skeleton -->\r\n @for (i of [1, 2]; track i) {\r\n <mt-card>\r\n <ng-template #headless>\r\n <div class=\"p-4 space-y-4\">\r\n <!-- Section header skeleton -->\r\n <div\r\n class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\"\r\n >\r\n <p-skeleton width=\"10rem\" height=\"1.5rem\" />\r\n <div class=\"flex gap-2\">\r\n <p-skeleton width=\"2rem\" height=\"2rem\" shape=\"circle\" />\r\n <p-skeleton width=\"2rem\" height=\"2rem\" shape=\"circle\" />\r\n </div>\r\n </div>\r\n <!-- Fields skeleton -->\r\n <div class=\"grid grid-cols-12 gap-4\">\r\n <div class=\"col-span-12 sm:col-span-6\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"col-span-12 sm:col-span-6\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"col-span-12\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n }\r\n } @else {\r\n <div\r\n cdkDropList\r\n id=\"sections-list\"\r\n [cdkDropListData]=\"enrichedSections()\"\r\n [cdkDropListDisabled]=\"mode() === 'manageProperties'\"\r\n [cdkDropListEnterPredicate]=\"sectionsDropPredicate\"\r\n (cdkDropListDropped)=\"dropSection($event)\"\r\n class=\"flex flex-col gap-4\"\r\n >\r\n @for (section of enrichedSections(); track section.id) {\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"section\"\r\n [cdkDragDisabled]=\"mode() === 'manageProperties'\"\r\n >\r\n <div\r\n *cdkDragPlaceholder\r\n class=\"min-h-16 rounded-xl border-2 border-dashed border-primary bg-primary-50/40\"\r\n ></div>\r\n <mt-fb-section\r\n [section]=\"section\"\r\n [sectionsCount]=\"enrichedSections().length\"\r\n [allSections]=\"enrichedSections()\"\r\n [mode]=\"mode()\"\r\n [connectedDropLists]=\"fieldDropListConnections()\"\r\n (onFieldDrop)=\"drop($event)\"\r\n >\r\n </mt-fb-section>\r\n </div>\r\n } @empty {\r\n <mt-card>\r\n <div class=\"h-27 p-4\">\r\n <div\r\n class=\"flex justify-center items-center gap-4 h-full border-1 border-primary rounded-xl bg-primary-50 text-primary\"\r\n >\r\n <span>{{ t(\"no-section\") }}</span>\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</ng-container>\r\n", styles: [".cdk-drag{cursor:grab}.cdk-drag:active,.cdk-drag-preview{cursor:grabbing}.cdk-drag-placeholder{opacity:.5}.cdk-drop-list-dragging .cdk-drag{cursor:grabbing}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i3.Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: i3.TabPanels, selector: "p-tabpanels" }, { kind: "component", type: i3.TabPanel, selector: "p-tabpanel", inputs: ["lazy", "value"], outputs: ["valueChange"] }, { kind: "component", type: i3.TabList, selector: "p-tablist" }, { kind: "component", type: i3.Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i4.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i5.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { 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: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: FBSection, selector: "mt-fb-section", inputs: ["section", "sectionsCount", "allSections", "mode", "connectedDropLists"], outputs: ["onFieldDrop"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i6.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i6.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i6.CdkDragPlaceholder, selector: "ng-template[cdkDragPlaceholder]", inputs: ["data"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }] });
|
|
2890
2921
|
}
|
|
2891
2922
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FormBuilder, decorators: [{
|
|
2892
2923
|
type: Component,
|
|
@@ -2904,8 +2935,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
2904
2935
|
FBSection,
|
|
2905
2936
|
DragDropModule,
|
|
2906
2937
|
Icon,
|
|
2907
|
-
], template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div\r\n class=\"flex h-full w-full gap-7 overflow-hidden max-[1025px]:min-h-0 max-[1025px]:min-w-0 max-[1025px]:flex-col max-[1025px]:gap-4 max-[1025px]:overflow-x-hidden max-[1025px]:overflow-y-auto\"\r\n >\r\n <!-- Properties Sidebar (hidden in manageProperties mode) -->\r\n @if (mode() !== \"manageProperties\") {\r\n <mt-card\r\n class=\"h-full w-1/5 flex flex-col overflow-hidden max-[1025px]:h-auto max-[1025px]:max-h-[42vh] max-[1025px]:min-h-0 max-[1025px]:w-full\"\r\n >\r\n <ng-template #headless>\r\n <!-- Header -->\r\n <h3 class=\"text-xl font-semibold px-4 pt-5\">\r\n {{ t(\"form-elements\") }}\r\n </h3>\r\n\r\n @if (isContextLoading()) {\r\n <!-- Properties Loading Skeleton -->\r\n <div class=\"flex gap-4 py-3 px-5 mt-4\">\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-lg\" />\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"py-4 px-5 space-y-5\">\r\n @for (i of [1, 2, 3, 4, 5, 6]; track i) {\r\n <p-skeleton height=\"3rem\" styleClass=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else if (scopeOptions().length === 0) {\r\n <!-- No Properties State -->\r\n <div class=\"flex-1 flex items-center justify-center p-4\">\r\n <p class=\"text-sm font-semibold text-gray-500\">\r\n {{ t(\"no-data-found\") }}\r\n </p>\r\n </div>\r\n } @else {\r\n <!-- Scope Tabs using PrimeNG -->\r\n <p-tabs\r\n [value]=\"activeScope()\"\r\n (valueChange)=\"onScopeChange($event)\"\r\n styleClass=\"structure-tabs\"\r\n class=\"flex min-h-0 flex-1 flex-col\"\r\n >\r\n <p-tablist class=\"shrink-0 overflow-x-auto\">\r\n @for (scope of scopeOptions(); track scope.key) {\r\n <p-tab [value]=\"scope.key\">{{ scope.label }}</p-tab>\r\n }\r\n </p-tablist>\r\n <p-tabpanels\r\n class=\"!bg-transparent !p-0 !pb-3 flex-1 overflow-hidden\"\r\n >\r\n @for (scope of scopeOptions(); track scope.key) {\r\n <p-tabpanel [value]=\"scope.key\" class=\"h-full flex flex-col\">\r\n @if (scope.key !== \"Current\") {\r\n <div class=\"px-4 pt-3 pb-2\">\r\n <div\r\n class=\"flex flex-col gap-3 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-800/50\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"shrink-0 text-xs font-semibold uppercase tracking-wider text-slate-400\"\r\n >\r\n {{ t(\"path\") }}\r\n </span>\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <span class=\"text-xs font-semibold text-slate-600\">\r\n {{ scope.label }}\r\n </span>\r\n </div>\r\n @if (getScopeBaseContexts(scope.key).length === 0) {\r\n <span class=\"text-xs italic text-slate-400\">\r\n {{ t(\"no-context\") }}\r\n </span>\r\n } @else {\r\n <div class=\"flex flex-col gap-1.5\">\r\n @for (\r\n segment of getScopePath(scope.key);\r\n track $index;\r\n let segmentIndex = $index;\r\n let isLast = $last\r\n ) {\r\n <div\r\n class=\"flex items-center gap-1 py-0.5 px-2 border border-gray-200 rounded bg-white dark:bg-slate-800 dark:border-slate-600\"\r\n >\r\n <div\r\n class=\"flex-1 min-w-0 text-xs font-medium text-slate-600 dark:text-slate-300 truncate cursor-pointer\"\r\n (click)=\"segmentPopover.toggle($event)\"\r\n >\r\n {{\r\n getScopeSegmentLabel(\r\n scope.key,\r\n segmentIndex\r\n )\r\n }}\r\n </div>\r\n <mt-button\r\n type=\"button\"\r\n icon=\"arrow.chevron-down\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"!p-0.5 !min-w-0\"\r\n (onClick)=\"segmentPopover.toggle($event)\"\r\n ></mt-button>\r\n @if (\r\n isLast && canRemoveScopePath(scope.key)\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.trash-01\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n severity=\"danger\"\r\n styleClass=\"!p-0.5 !min-w-0\"\r\n (onClick)=\"removeScopePath(scope.key)\"\r\n ></mt-button>\r\n }\r\n </div>\r\n <p-popover\r\n #segmentPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n [dismissable]=\"true\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n {{ t(\"select\") }}\r\n {{ getTokenLabel(segment.token) }}\r\n </div>\r\n @if (\r\n getScopeSegmentOptions(\r\n scope.key,\r\n segmentIndex\r\n ).length === 0\r\n ) {\r\n <div\r\n class=\"text-xs font-medium text-slate-400\"\r\n >\r\n {{ t(\"no-options\") }}\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n option of getScopeSegmentOptions(\r\n scope.key,\r\n segmentIndex\r\n );\r\n track option.contextKey\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"option.label\"\r\n [icon]=\"\r\n option.contextKey ===\r\n segment.value\r\n ? 'general.check'\r\n : 'general.minus'\r\n \"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onSetScopeSegmentValue(\r\n scope.key,\r\n segmentIndex,\r\n option.contextKey,\r\n segmentPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </p-popover>\r\n }\r\n @if (canAddNextScopeSegment(scope.key)) {\r\n <div class=\"flex items-center gap-2\">\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n severity=\"primary\"\r\n styleClass=\"flex size-7 shrink-0 items-center justify-center rounded-md bg-primary text-xs font-bold text-white hover:opacity-90\"\r\n (onClick)=\"\r\n nextContextPopover.toggle($event)\r\n \"\r\n ></mt-button>\r\n <!-- <span class=\"text-xs text-slate-400\">\r\n {{ t(\"add-segment\") }}\r\n </span> -->\r\n </div>\r\n }\r\n <!-- Popover OUTSIDE the @if block like formula-builder -->\r\n <p-popover\r\n #nextContextPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n [dismissable]=\"true\"\r\n appendTo=\"body\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n {{ t(\"add-segment\") }}\r\n </div>\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n token of getScopeNextTokens(scope.key);\r\n track token\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"getTokenLabel(token)\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onAddScopeSegment(\r\n scope.key,\r\n token,\r\n nextContextPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n </div>\r\n </p-popover>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Node List -->\r\n <div\r\n class=\"flex-1 min-h-0 overflow-y-auto space-y-4 px-4 pb-4 [&_.cdk-drag-placeholder]:hidden\"\r\n [id]=\"'toolbox-' + scope.key\"\r\n cdkDropList\r\n cdkDropListSortingDisabled\r\n [cdkDropListData]=\"getFilteredProperties(scope.key)\"\r\n [cdkDropListConnectedTo]=\"fieldDropListIds()\"\r\n [cdkDropListEnterPredicate]=\"noReturnPredicate\"\r\n >\r\n <!-- Search Field (Sticky) -->\r\n <div\r\n class=\"sticky top-0 bg-surface-0 mb-0 py-3 pb-2 mb-1\"\r\n >\r\n <mt-text-field\r\n [placeholder]=\"t('search-properties')\"\r\n [(ngModel)]=\"searchQuery\"\r\n icon=\"general.search-lg\"\r\n />\r\n </div>\r\n\r\n @if (isScopePropertiesLoading(scope.key)) {\r\n <div class=\"space-y-4\">\r\n @for (i of [1, 2, 3, 4]; track i) {\r\n <p-skeleton height=\"3rem\" styleClass=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else {\r\n @for (\r\n node of getFilteredProperties(scope.key);\r\n track node.key\r\n ) {\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"node\"\r\n class=\"group cursor-move select-none flex items-center gap-3 py-3 px-3 rounded-lg border border-dashed border-surface-300 hover:bg-emphasis dark:border-surface-500 transition-colors\"\r\n >\r\n <div\r\n *cdkDragPlaceholder\r\n class=\"col-span-12 min-h-27 w-full rounded-lg bg-black/10 z-1\"\r\n ></div>\r\n <span\r\n class=\"flex-1 text-start text-base font-medium\"\r\n >{{ getPropertyLabel(node) }}</span\r\n >\r\n\r\n <mt-icon\r\n class=\"text-lg\"\r\n icon=\"general.menu-05\"\r\n ></mt-icon>\r\n </div>\r\n }\r\n\r\n @if (getFilteredProperties(scope.key).length === 0) {\r\n <div class=\"py-8 text-center text-muted-color\">\r\n <p class=\"text-sm\">\r\n @if (searchQuery()) {\r\n {{ t(\"no-data-found\") }}\r\n } @else if (\r\n getScopeProperties(scope.key).length === 0\r\n ) {\r\n {{ t(\"no-properties-available\") }}\r\n } @else {\r\n {{ t(\"all-items-in-use\") }}\r\n }\r\n </p>\r\n </div>\r\n }\r\n }\r\n </div>\r\n </p-tabpanel>\r\n }\r\n </p-tabpanels>\r\n </p-tabs>\r\n }\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n <!-- Main Canvas Area -->\r\n <div\r\n class=\"flex h-full min-w-0 flex-1 gap-4 overflow-y-auto max-[1025px]:h-auto max-[1025px]:min-h-0 max-[1025px]:overflow-visible\"\r\n >\r\n <div\r\n class=\"flex h-full min-w-0 w-full flex-1 flex-col gap-4 max-[1025px]:h-auto\"\r\n [ngClass]=\"canvasStyleClass()\"\r\n >\r\n @if (mode() !== \"manageProperties\") {\r\n <mt-card>\r\n <ng-template #headless>\r\n <div\r\n class=\"flex flex-col gap-3 p-4 sm:flex-row sm:flex-wrap sm:items-center\"\r\n >\r\n <div class=\"w-full sm:w-44\">\r\n <mt-select-field\r\n [label]=\"''\"\r\n [placeholder]=\"''\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n [ngModel]=\"selectedRenderMode()\"\r\n (ngModelChange)=\"onRenderModeChange($event)\"\r\n [options]=\"renderModeOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n optionIcon=\"icon\"\r\n optionIconColor=\"color\"\r\n [optionAvatarShape]=\"'square'\"\r\n [size]=\"'small'\"\r\n [loading]=\"isUpdatingFormSettings()\"\r\n [disabled]=\"\r\n isLoading() ||\r\n isUpdatingFormSettings() ||\r\n !formConfiguration()\r\n \"\r\n />\r\n </div>\r\n <mt-button\r\n icon=\"layout.layout-top\"\r\n [label]=\"t('add-section')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"addSection()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n <mt-button\r\n icon=\"general.eye\"\r\n [label]=\"t('preview')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"openPreview()\"\r\n [disabled]=\"isLoading() || isUpdatingFormSettings()\"\r\n ></mt-button>\r\n <mt-button\r\n [label]=\"t('validation-rules')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"openValidationRules()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n <mt-button\r\n icon=\"finance.credit-card-plus\"\r\n [label]=\"t('reset')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"resetFormConfiguration()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n @if (isLoading()) {\r\n <!-- Form Loading Skeleton -->\r\n @for (i of [1, 2]; track i) {\r\n <mt-card>\r\n <ng-template #headless>\r\n <div class=\"p-4 space-y-4\">\r\n <!-- Section header skeleton -->\r\n <div\r\n class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\"\r\n >\r\n <p-skeleton width=\"10rem\" height=\"1.5rem\" />\r\n <div class=\"flex gap-2\">\r\n <p-skeleton width=\"2rem\" height=\"2rem\" shape=\"circle\" />\r\n <p-skeleton width=\"2rem\" height=\"2rem\" shape=\"circle\" />\r\n </div>\r\n </div>\r\n <!-- Fields skeleton -->\r\n <div class=\"grid grid-cols-12 gap-4\">\r\n <div class=\"col-span-12 sm:col-span-6\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"col-span-12 sm:col-span-6\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"col-span-12\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n }\r\n } @else {\r\n <div\r\n cdkDropList\r\n id=\"sections-list\"\r\n [cdkDropListData]=\"enrichedSections()\"\r\n [cdkDropListDisabled]=\"mode() === 'manageProperties'\"\r\n [cdkDropListEnterPredicate]=\"sectionsDropPredicate\"\r\n (cdkDropListDropped)=\"dropSection($event)\"\r\n class=\"flex flex-col gap-4\"\r\n >\r\n @for (section of enrichedSections(); track section.id) {\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"section\"\r\n [cdkDragDisabled]=\"mode() === 'manageProperties'\"\r\n >\r\n <div\r\n *cdkDragPlaceholder\r\n class=\"min-h-16 rounded-xl border-2 border-dashed border-primary bg-primary-50/40\"\r\n ></div>\r\n <mt-fb-section\r\n [section]=\"section\"\r\n [sectionsCount]=\"enrichedSections().length\"\r\n [allSections]=\"enrichedSections()\"\r\n [mode]=\"mode()\"\r\n [connectedDropLists]=\"fieldDropListConnections()\"\r\n (onFieldDrop)=\"drop($event)\"\r\n >\r\n </mt-fb-section>\r\n </div>\r\n } @empty {\r\n <mt-card>\r\n <div class=\"h-27 p-4\">\r\n <div\r\n class=\"flex justify-center items-center gap-4 h-full border-1 border-primary rounded-xl bg-primary-50 text-primary\"\r\n >\r\n <span>{{ t(\"no-section\") }}</span>\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</ng-container>\r\n", styles: [".cdk-drag{cursor:grab}.cdk-drag:active,.cdk-drag-preview{cursor:grabbing}.cdk-drag-placeholder{opacity:.5}.cdk-drop-list-dragging .cdk-drag{cursor:grabbing}\n"] }]
|
|
2908
|
-
}], ctorParameters: () => [], propDecorators: { popovers: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => Popover), { isSignal: true }] }], canvasStyleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "canvasStyleClass", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }] } });
|
|
2938
|
+
], template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div\r\n class=\"flex h-full w-full gap-7 overflow-hidden max-[1025px]:min-h-0 max-[1025px]:min-w-0 max-[1025px]:flex-col max-[1025px]:gap-4 max-[1025px]:overflow-x-hidden max-[1025px]:overflow-y-auto\"\r\n >\r\n <!-- Properties Sidebar -->\r\n @if (propertiesSectionVisible()) {\r\n <mt-card\r\n class=\"h-full w-1/5 flex flex-col overflow-hidden max-[1025px]:h-auto max-[1025px]:max-h-[42vh] max-[1025px]:min-h-0 max-[1025px]:w-full\"\r\n >\r\n <ng-template #headless>\r\n <!-- Header -->\r\n <h3 class=\"text-xl font-semibold px-4 pt-5\">\r\n {{ t(\"form-elements\") }}\r\n </h3>\r\n\r\n @if (isContextLoading()) {\r\n <!-- Properties Loading Skeleton -->\r\n <div class=\"flex gap-4 py-3 px-5 mt-4\">\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-lg\" />\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"py-4 px-5 space-y-5\">\r\n @for (i of [1, 2, 3, 4, 5, 6]; track i) {\r\n <p-skeleton height=\"3rem\" styleClass=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else if (scopeOptions().length === 0) {\r\n <!-- No Properties State -->\r\n <div class=\"flex-1 flex items-center justify-center p-4\">\r\n <p class=\"text-sm font-semibold text-gray-500\">\r\n {{ t(\"no-data-found\") }}\r\n </p>\r\n </div>\r\n } @else {\r\n <!-- Scope Tabs using PrimeNG -->\r\n <p-tabs\r\n [value]=\"activeScope()\"\r\n (valueChange)=\"onScopeChange($event)\"\r\n styleClass=\"structure-tabs\"\r\n class=\"flex min-h-0 flex-1 flex-col\"\r\n >\r\n <p-tablist class=\"shrink-0 overflow-x-auto\">\r\n @for (scope of scopeOptions(); track scope.key) {\r\n <p-tab [value]=\"scope.key\">{{ scope.label }}</p-tab>\r\n }\r\n </p-tablist>\r\n <p-tabpanels\r\n class=\"!bg-transparent !p-0 !pb-3 flex-1 overflow-hidden\"\r\n >\r\n @for (scope of scopeOptions(); track scope.key) {\r\n <p-tabpanel [value]=\"scope.key\" class=\"h-full flex flex-col\">\r\n @if (scope.key !== \"Current\") {\r\n <div class=\"px-4 pt-3 pb-2\">\r\n <div\r\n class=\"flex flex-col gap-3 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-800/50\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"shrink-0 text-xs font-semibold uppercase tracking-wider text-slate-400\"\r\n >\r\n {{ t(\"path\") }}\r\n </span>\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <span class=\"text-xs font-semibold text-slate-600\">\r\n {{ scope.label }}\r\n </span>\r\n </div>\r\n @if (getScopeBaseContexts(scope.key).length === 0) {\r\n <span class=\"text-xs italic text-slate-400\">\r\n {{ t(\"no-context\") }}\r\n </span>\r\n } @else {\r\n <div class=\"flex flex-col gap-1.5\">\r\n @for (\r\n segment of getScopePath(scope.key);\r\n track $index;\r\n let segmentIndex = $index;\r\n let isLast = $last\r\n ) {\r\n <div\r\n class=\"flex items-center gap-1 py-0.5 px-2 border border-gray-200 rounded bg-white dark:bg-slate-800 dark:border-slate-600\"\r\n >\r\n <div\r\n class=\"flex-1 min-w-0 text-xs font-medium text-slate-600 dark:text-slate-300 truncate cursor-pointer\"\r\n (click)=\"segmentPopover.toggle($event)\"\r\n >\r\n {{\r\n getScopeSegmentLabel(\r\n scope.key,\r\n segmentIndex\r\n )\r\n }}\r\n </div>\r\n <mt-button\r\n type=\"button\"\r\n icon=\"arrow.chevron-down\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"!p-0.5 !min-w-0\"\r\n (onClick)=\"segmentPopover.toggle($event)\"\r\n ></mt-button>\r\n @if (\r\n isLast && canRemoveScopePath(scope.key)\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.trash-01\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n severity=\"danger\"\r\n styleClass=\"!p-0.5 !min-w-0\"\r\n (onClick)=\"removeScopePath(scope.key)\"\r\n ></mt-button>\r\n }\r\n </div>\r\n <p-popover\r\n #segmentPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n [dismissable]=\"true\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n {{ t(\"select\") }}\r\n {{ getTokenLabel(segment.token) }}\r\n </div>\r\n @if (\r\n getScopeSegmentOptions(\r\n scope.key,\r\n segmentIndex\r\n ).length === 0\r\n ) {\r\n <div\r\n class=\"text-xs font-medium text-slate-400\"\r\n >\r\n {{ t(\"no-options\") }}\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n option of getScopeSegmentOptions(\r\n scope.key,\r\n segmentIndex\r\n );\r\n track option.contextKey\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"option.label\"\r\n [icon]=\"\r\n option.contextKey ===\r\n segment.value\r\n ? 'general.check'\r\n : 'general.minus'\r\n \"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onSetScopeSegmentValue(\r\n scope.key,\r\n segmentIndex,\r\n option.contextKey,\r\n segmentPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </p-popover>\r\n }\r\n @if (canAddNextScopeSegment(scope.key)) {\r\n <div class=\"flex items-center gap-2\">\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n severity=\"primary\"\r\n styleClass=\"flex size-7 shrink-0 items-center justify-center rounded-md bg-primary text-xs font-bold text-white hover:opacity-90\"\r\n (onClick)=\"\r\n nextContextPopover.toggle($event)\r\n \"\r\n ></mt-button>\r\n <!-- <span class=\"text-xs text-slate-400\">\r\n {{ t(\"add-segment\") }}\r\n </span> -->\r\n </div>\r\n }\r\n <!-- Popover OUTSIDE the @if block like formula-builder -->\r\n <p-popover\r\n #nextContextPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n [dismissable]=\"true\"\r\n appendTo=\"body\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n {{ t(\"add-segment\") }}\r\n </div>\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n token of getScopeNextTokens(scope.key);\r\n track token\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"getTokenLabel(token)\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onAddScopeSegment(\r\n scope.key,\r\n token,\r\n nextContextPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n </div>\r\n </p-popover>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Node List -->\r\n <div\r\n class=\"flex-1 min-h-0 overflow-y-auto space-y-4 px-4 pb-4 [&_.cdk-drag-placeholder]:hidden\"\r\n [id]=\"'toolbox-' + scope.key\"\r\n cdkDropList\r\n cdkDropListSortingDisabled\r\n [cdkDropListData]=\"getFilteredProperties(scope.key)\"\r\n [cdkDropListConnectedTo]=\"fieldDropListIds()\"\r\n [cdkDropListEnterPredicate]=\"noReturnPredicate\"\r\n >\r\n <!-- Search Field (Sticky) -->\r\n <div\r\n class=\"sticky top-0 bg-surface-0 mb-0 py-3 pb-2 mb-1\"\r\n >\r\n <mt-text-field\r\n [placeholder]=\"t('search-properties')\"\r\n [(ngModel)]=\"searchQuery\"\r\n icon=\"general.search-lg\"\r\n />\r\n </div>\r\n\r\n @if (isScopePropertiesLoading(scope.key)) {\r\n <div class=\"space-y-4\">\r\n @for (i of [1, 2, 3, 4]; track i) {\r\n <p-skeleton height=\"3rem\" styleClass=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else {\r\n @for (\r\n node of getFilteredProperties(scope.key);\r\n track node.key\r\n ) {\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"node\"\r\n class=\"group cursor-move select-none flex items-center gap-3 py-3 px-3 rounded-lg border border-dashed border-surface-300 hover:bg-emphasis dark:border-surface-500 transition-colors\"\r\n >\r\n <div\r\n *cdkDragPlaceholder\r\n class=\"col-span-12 min-h-27 w-full rounded-lg bg-black/10 z-1\"\r\n ></div>\r\n <span\r\n class=\"flex-1 text-start text-base font-medium\"\r\n >{{ getPropertyLabel(node) }}</span\r\n >\r\n\r\n <mt-icon\r\n class=\"text-lg\"\r\n icon=\"general.menu-05\"\r\n ></mt-icon>\r\n </div>\r\n }\r\n\r\n @if (getFilteredProperties(scope.key).length === 0) {\r\n <div class=\"py-8 text-center text-muted-color\">\r\n <p class=\"text-sm\">\r\n @if (searchQuery()) {\r\n {{ t(\"no-data-found\") }}\r\n } @else if (\r\n getScopeProperties(scope.key).length === 0\r\n ) {\r\n {{ t(\"no-properties-available\") }}\r\n } @else {\r\n {{ t(\"all-items-in-use\") }}\r\n }\r\n </p>\r\n </div>\r\n }\r\n }\r\n </div>\r\n </p-tabpanel>\r\n }\r\n </p-tabpanels>\r\n </p-tabs>\r\n }\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n <!-- Main Canvas Area -->\r\n <div\r\n class=\"flex h-full min-w-0 flex-1 gap-4 overflow-y-auto max-[1025px]:h-auto max-[1025px]:min-h-0 max-[1025px]:overflow-visible\"\r\n >\r\n <div\r\n class=\"flex h-full min-w-0 w-full flex-1 flex-col gap-4 max-[1025px]:h-auto\"\r\n [ngClass]=\"canvasStyleClass()\"\r\n >\r\n @if (mode() !== \"manageProperties\") {\r\n <mt-card>\r\n <ng-template #headless>\r\n <div\r\n class=\"flex flex-col gap-3 p-4 sm:flex-row sm:flex-wrap sm:items-center\"\r\n >\r\n <div class=\"w-full sm:w-44\">\r\n <mt-select-field\r\n [label]=\"''\"\r\n [placeholder]=\"''\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n [ngModel]=\"selectedRenderMode()\"\r\n (ngModelChange)=\"onRenderModeChange($event)\"\r\n [options]=\"renderModeOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n optionIcon=\"icon\"\r\n optionIconColor=\"color\"\r\n [optionAvatarShape]=\"'square'\"\r\n [size]=\"'small'\"\r\n [loading]=\"isUpdatingFormSettings()\"\r\n [disabled]=\"\r\n isLoading() ||\r\n isUpdatingFormSettings() ||\r\n !formConfiguration()\r\n \"\r\n />\r\n </div>\r\n <mt-button\r\n icon=\"layout.layout-top\"\r\n [label]=\"t('add-section')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"addSection()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n <mt-button\r\n icon=\"general.eye\"\r\n [label]=\"t('preview')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"openPreview()\"\r\n [disabled]=\"isLoading() || isUpdatingFormSettings()\"\r\n ></mt-button>\r\n <mt-button\r\n [label]=\"t('validation-rules')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"openValidationRules()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n <mt-button\r\n icon=\"finance.credit-card-plus\"\r\n [label]=\"t('reset')\"\r\n variant=\"outlined\"\r\n severity=\"primary\"\r\n styleClass=\"w-full sm:w-auto\"\r\n (onClick)=\"resetFormConfiguration()\"\r\n [disabled]=\"isLoading()\"\r\n ></mt-button>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n }\r\n\r\n @if (isLoading()) {\r\n <!-- Form Loading Skeleton -->\r\n @for (i of [1, 2]; track i) {\r\n <mt-card>\r\n <ng-template #headless>\r\n <div class=\"p-4 space-y-4\">\r\n <!-- Section header skeleton -->\r\n <div\r\n class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\"\r\n >\r\n <p-skeleton width=\"10rem\" height=\"1.5rem\" />\r\n <div class=\"flex gap-2\">\r\n <p-skeleton width=\"2rem\" height=\"2rem\" shape=\"circle\" />\r\n <p-skeleton width=\"2rem\" height=\"2rem\" shape=\"circle\" />\r\n </div>\r\n </div>\r\n <!-- Fields skeleton -->\r\n <div class=\"grid grid-cols-12 gap-4\">\r\n <div class=\"col-span-12 sm:col-span-6\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"col-span-12 sm:col-span-6\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n <div class=\"col-span-12\">\r\n <p-skeleton height=\"4rem\" styleClass=\"rounded-lg\" />\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n </mt-card>\r\n }\r\n } @else {\r\n <div\r\n cdkDropList\r\n id=\"sections-list\"\r\n [cdkDropListData]=\"enrichedSections()\"\r\n [cdkDropListDisabled]=\"mode() === 'manageProperties'\"\r\n [cdkDropListEnterPredicate]=\"sectionsDropPredicate\"\r\n (cdkDropListDropped)=\"dropSection($event)\"\r\n class=\"flex flex-col gap-4\"\r\n >\r\n @for (section of enrichedSections(); track section.id) {\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"section\"\r\n [cdkDragDisabled]=\"mode() === 'manageProperties'\"\r\n >\r\n <div\r\n *cdkDragPlaceholder\r\n class=\"min-h-16 rounded-xl border-2 border-dashed border-primary bg-primary-50/40\"\r\n ></div>\r\n <mt-fb-section\r\n [section]=\"section\"\r\n [sectionsCount]=\"enrichedSections().length\"\r\n [allSections]=\"enrichedSections()\"\r\n [mode]=\"mode()\"\r\n [connectedDropLists]=\"fieldDropListConnections()\"\r\n (onFieldDrop)=\"drop($event)\"\r\n >\r\n </mt-fb-section>\r\n </div>\r\n } @empty {\r\n <mt-card>\r\n <div class=\"h-27 p-4\">\r\n <div\r\n class=\"flex justify-center items-center gap-4 h-full border-1 border-primary rounded-xl bg-primary-50 text-primary\"\r\n >\r\n <span>{{ t(\"no-section\") }}</span>\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</ng-container>\r\n", styles: [".cdk-drag{cursor:grab}.cdk-drag:active,.cdk-drag-preview{cursor:grabbing}.cdk-drag-placeholder{opacity:.5}.cdk-drop-list-dragging .cdk-drag{cursor:grabbing}\n"] }]
|
|
2939
|
+
}], ctorParameters: () => [], propDecorators: { popovers: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => Popover), { isSignal: true }] }], canvasStyleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "canvasStyleClass", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], showPropertiesSection: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPropertiesSection", required: false }] }] } });
|
|
2909
2940
|
|
|
2910
2941
|
/*
|
|
2911
2942
|
* Public API Surface of form-builder
|