@masterteam/form-builder 0.0.32 → 0.0.33

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.
@@ -1649,6 +1649,7 @@ class FBSection {
1649
1649
  expanded = signal(true, ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
1650
1650
  // Form groups cache for dynamic fields
1651
1651
  formGroupsCache = new Map();
1652
+ translatableViewTypes = new Set(['Text', 'LongText']);
1652
1653
  constructor() {
1653
1654
  // Cleanup stale form groups when fields change
1654
1655
  effect(() => {
@@ -1662,25 +1663,65 @@ class FBSection {
1662
1663
  }
1663
1664
  getFormGroup(field) {
1664
1665
  let fg = this.formGroupsCache.get(field.id);
1666
+ const controlNames = this.getFieldControlNames(field);
1665
1667
  if (fg) {
1666
- // Check if field name changed
1667
- if (!fg.contains(field.name)) {
1668
- const oldKey = Object.keys(fg.controls)[0];
1669
- const value = oldKey ? fg.get(oldKey)?.value : field.data?.data;
1670
- fg = new FormGroup({
1671
- [field.name]: new FormControl(value),
1672
- });
1668
+ const existingKeys = Object.keys(fg.controls);
1669
+ const hasSameControls = existingKeys.length === controlNames.length &&
1670
+ controlNames.every((key) => fg?.contains(key));
1671
+ if (!hasSameControls) {
1672
+ fg = this.createFieldFormGroup(field, controlNames);
1673
1673
  this.formGroupsCache.set(field.id, fg);
1674
1674
  }
1675
1675
  }
1676
1676
  else {
1677
- fg = new FormGroup({
1678
- [field.name]: new FormControl(field.data?.data),
1679
- });
1677
+ fg = this.createFieldFormGroup(field, controlNames);
1680
1678
  this.formGroupsCache.set(field.id, fg);
1681
1679
  }
1682
1680
  return fg;
1683
1681
  }
1682
+ getTranslatableFieldControls(field) {
1683
+ return [
1684
+ {
1685
+ key: this.getTranslatableControlName(field, 'en'),
1686
+ config: this.getFieldConfig(field, 'English'),
1687
+ },
1688
+ {
1689
+ key: this.getTranslatableControlName(field, 'ar'),
1690
+ config: this.getFieldConfig(field, 'Arabic'),
1691
+ },
1692
+ ];
1693
+ }
1694
+ isTranslatableTextField(field) {
1695
+ const prop = field.property ?? field.data;
1696
+ return (prop?.isTranslatable === true &&
1697
+ this.translatableViewTypes.has(prop?.viewType ?? field.type));
1698
+ }
1699
+ createFieldFormGroup(field, controlNames) {
1700
+ const initialValue = field.data?.data;
1701
+ const value = initialValue && typeof initialValue === 'object' ? initialValue : {};
1702
+ const controls = controlNames.reduce((acc, key) => {
1703
+ const language = key.endsWith('-en')
1704
+ ? 'en'
1705
+ : key.endsWith('-ar')
1706
+ ? 'ar'
1707
+ : null;
1708
+ acc[key] = new FormControl(language ? value?.[language] : initialValue);
1709
+ return acc;
1710
+ }, {});
1711
+ return new FormGroup(controls);
1712
+ }
1713
+ getFieldControlNames(field) {
1714
+ if (this.isTranslatableTextField(field)) {
1715
+ return [
1716
+ this.getTranslatableControlName(field, 'en'),
1717
+ this.getTranslatableControlName(field, 'ar'),
1718
+ ];
1719
+ }
1720
+ return [field.name];
1721
+ }
1722
+ getTranslatableControlName(field, lang) {
1723
+ return `${field.id}-${lang}`;
1724
+ }
1684
1725
  toggleExpanded() {
1685
1726
  this.expanded.update((v) => !v);
1686
1727
  }
@@ -1734,6 +1775,9 @@ class FBSection {
1734
1775
  });
1735
1776
  }
1736
1777
  getFieldColSpan(field) {
1778
+ if (this.isTranslatableTextField(field)) {
1779
+ return this.getTranslatableFieldGroupColSpan(field);
1780
+ }
1737
1781
  switch (field.width) {
1738
1782
  case '100':
1739
1783
  return 'col-span-12';
@@ -1745,6 +1789,18 @@ class FBSection {
1745
1789
  return 'col-span-12';
1746
1790
  }
1747
1791
  }
1792
+ getTranslatableFieldControlColSpan(field) {
1793
+ if (field.width === '100') {
1794
+ return 'col-span-12';
1795
+ }
1796
+ return 'col-span-12 md:col-span-6';
1797
+ }
1798
+ getTranslatableFieldGroupColSpan(field) {
1799
+ if (field.width === '25') {
1800
+ return 'col-span-12 sm:col-span-6';
1801
+ }
1802
+ return 'col-span-12';
1803
+ }
1748
1804
  getFieldType(field) {
1749
1805
  const typeMap = {
1750
1806
  User: 'select',
@@ -1771,9 +1827,13 @@ class FBSection {
1771
1827
  };
1772
1828
  return typeMap[field.type] ?? 'text';
1773
1829
  }
1774
- getFieldConfig(field) {
1830
+ getFieldConfig(field, languageLabel) {
1775
1831
  const type = this.getFieldType(field);
1776
- const base = { readonly: true, type };
1832
+ const base = {
1833
+ readonly: true,
1834
+ type,
1835
+ label: languageLabel ? `${field.name} (${languageLabel})` : undefined,
1836
+ };
1777
1837
  if (type === 'schema-connection') {
1778
1838
  const prop = field.property;
1779
1839
  base['configuration'] = prop ? (prop['configuration'] ?? {}) : {};
@@ -1781,7 +1841,7 @@ class FBSection {
1781
1841
  return base;
1782
1842
  }
1783
1843
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FBSection, deps: [], target: i0.ɵɵFactoryTarget.Component });
1784
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: FBSection, isStandalone: true, selector: "mt-fb-section", inputs: { section: { classPropertyName: "section", publicName: "section", isSignal: true, isRequired: true, transformFunction: null }, sectionsCount: { classPropertyName: "sectionsCount", publicName: "sectionsCount", 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 }, connectedDropLists: { classPropertyName: "connectedDropLists", publicName: "connectedDropLists", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onFieldDrop: "onFieldDrop" }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div class=\"flex flex-col\">\r\n <div\r\n cdkDragHandle\r\n [class]=\"\r\n 'flex items-center justify-between gap-3 rounded-xl bg-primary px-3 py-3 text-primary-contrast' +\r\n (isManageProperties() ? '' : ' cursor-grab active:cursor-grabbing')\r\n \"\r\n >\r\n <div class=\"flex min-w-0 items-center gap-3\">\r\n <mt-icon\r\n class=\"shrink-0 cursor-pointer text-2xl transition-[rotate]\"\r\n [class.rotate-180]=\"expanded()\"\r\n icon=\"arrow.chevron-down\"\r\n (click)=\"toggleExpanded()\"\r\n ></mt-icon>\r\n\r\n <span class=\"truncate font-semibold\">\r\n {{ sectionName() }}\r\n </span>\r\n @if (!isManageProperties()) {\r\n <mt-icon\r\n class=\"text-lg cursor-pointer\"\r\n icon=\"general.edit-02\"\r\n (click)=\"editSection($event)\"\r\n [mtTooltip]=\"t('edit-section')\"\r\n ></mt-icon>\r\n }\r\n </div>\r\n <span></span>\r\n </div>\r\n @if (expanded()) {\r\n <div\r\n cdkDropList\r\n [id]=\"section().id\"\r\n cdkDropListOrientation=\"mixed\"\r\n [cdkDropListData]=\"displayFields()\"\r\n [cdkDropListConnectedTo]=\"connectedDropLists()\"\r\n [cdkDropListDisabled]=\"isManageProperties()\"\r\n [cdkDropListEnterPredicate]=\"fieldsDropPredicate\"\r\n (cdkDropListDropped)=\"onDrop($event)\"\r\n class=\"grid grid-cols-12 gap-4 relative py-2\"\r\n [class.min-h-27]=\"displayFields().length === 0\"\r\n >\r\n @for (field of displayFields(); track field.id) {\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"field\"\r\n [cdkDragDisabled]=\"\r\n isManageProperties() || field._pending || field._deleting\r\n \"\r\n [class]=\"\r\n getFieldColSpan(field) +\r\n (isManageProperties()\r\n ? ''\r\n : ' cursor-grab active:cursor-grabbing')\r\n \"\r\n >\r\n <div\r\n *cdkDragPlaceholder\r\n [class]=\"\r\n 'h-full min-h-27 bg-black/10 rounded-lg ' +\r\n getFieldColSpan(field)\r\n \"\r\n ></div>\r\n @if (field._pending) {\r\n <!-- Skeleton for pending field -->\r\n <mt-card class=\"h-full animate-pulse\">\r\n <div class=\"flex flex-col gap-3 sm:flex-row\">\r\n <div class=\"flex-1 space-y-3\">\r\n <div class=\"h-4 bg-surface-200 rounded w-1/3\"></div>\r\n <div class=\"h-10 bg-surface-200 rounded\"></div>\r\n </div>\r\n <div class=\"flex shrink-0 flex-row gap-1 sm:flex-col\">\r\n <div class=\"h-8 w-8 bg-surface-200 rounded\"></div>\r\n <div class=\"h-8 w-8 bg-surface-200 rounded\"></div>\r\n </div>\r\n </div>\r\n </mt-card>\r\n } @else {\r\n <mt-card\r\n class=\"h-full relative transition-all duration-200\"\r\n [class.opacity-50]=\"field._deleting\"\r\n >\r\n @if (field._deleting) {\r\n <div\r\n class=\"absolute inset-0 flex items-center justify-center bg-white/50 rounded-xl z-10\"\r\n >\r\n <div\r\n class=\"animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full\"\r\n ></div>\r\n </div>\r\n }\r\n <div class=\"flex flex-col gap-3 sm:flex-row\">\r\n <div class=\"min-w-0 flex-1\">\r\n <form [formGroup]=\"getFormGroup(field)\">\r\n <div\r\n class=\"mb-2 flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-4\"\r\n >\r\n <div class=\"min-w-0 break-words font-semibold\">\r\n {{ field.name }}\r\n </div>\r\n @if (isManageProperties()) {\r\n <div\r\n class=\"flex flex-wrap items-center gap-1.5 sm:ms-auto\"\r\n >\r\n @if (field.isRead === false) {\r\n <span\r\n class=\"text-xs font-medium text-red-500 bg-red-50 px-1.5 py-0.5 rounded\"\r\n >\r\n {{ t(\"hidden\") }}\r\n </span>\r\n } @else if (field.isWrite === false) {\r\n <span\r\n class=\"text-xs font-medium text-amber-600 bg-amber-50 px-1.5 py-0.5 rounded\"\r\n >\r\n {{ t(\"read-only\") }}\r\n </span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"transition-all duration-200\"\r\n [class.opacity-40]=\"\r\n isManageProperties() && field.isRead === false\r\n \"\r\n [class.blur-[1px]]=\"\r\n isManageProperties() && field.isRead === false\r\n \"\r\n >\r\n <mt-dynamic-field\r\n [fieldName]=\"field.name\"\r\n [fieldConfig]=\"getFieldConfig(field)\"\r\n />\r\n </div>\r\n </form>\r\n </div>\r\n <div\r\n class=\"flex shrink-0 flex-row gap-1 self-end sm:flex-col sm:self-start\"\r\n >\r\n <mt-button\r\n size=\"small\"\r\n icon=\"general.settings-01\"\r\n [tooltip]=\"t('edit-field')\"\r\n [variant]=\"'outlined'\"\r\n [disabled]=\"field._deleting\"\r\n (onClick)=\"editField(field)\"\r\n ></mt-button>\r\n @if (!isManageProperties()) {\r\n <mt-button\r\n size=\"small\"\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [variant]=\"'outlined'\"\r\n [tooltip]=\"t('remove-field')\"\r\n [disabled]=\"field._deleting\"\r\n (onClick)=\"removeField($event, field)\"\r\n ></mt-button>\r\n }\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n } @empty {\r\n <mt-card class=\"absolute inset-0 top-4\" paddingless>\r\n <div class=\"size-full p-4\">\r\n <div\r\n class=\"flex h-full items-center justify-center gap-4 rounded-xl border-1 border-primary bg-primary-50 px-4 text-center text-primary\"\r\n >\r\n <mt-icon icon=\"editor.move\" class=\"text-3xl\" />\r\n <span>{{ t(\"drag-from-the-side\") }}</span>\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "directive", type: 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: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: 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: CdkDragPlaceholder, selector: "ng-template[cdkDragPlaceholder]", inputs: ["data"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: DynamicField, selector: "mt-dynamic-field", inputs: ["fieldConfig", "fieldName"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: Tooltip, selector: "[mtTooltip]" }] });
1844
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: FBSection, isStandalone: true, selector: "mt-fb-section", inputs: { section: { classPropertyName: "section", publicName: "section", isSignal: true, isRequired: true, transformFunction: null }, sectionsCount: { classPropertyName: "sectionsCount", publicName: "sectionsCount", 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 }, connectedDropLists: { classPropertyName: "connectedDropLists", publicName: "connectedDropLists", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onFieldDrop: "onFieldDrop" }, ngImport: i0, template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div class=\"flex flex-col\">\r\n <div\r\n cdkDragHandle\r\n [class]=\"\r\n 'flex items-center justify-between gap-3 rounded-xl bg-primary px-3 py-3 text-primary-contrast' +\r\n (isManageProperties() ? '' : ' cursor-grab active:cursor-grabbing')\r\n \"\r\n >\r\n <div class=\"flex min-w-0 items-center gap-3\">\r\n <mt-icon\r\n class=\"shrink-0 cursor-pointer text-2xl transition-[rotate]\"\r\n [class.rotate-180]=\"expanded()\"\r\n icon=\"arrow.chevron-down\"\r\n (click)=\"toggleExpanded()\"\r\n ></mt-icon>\r\n\r\n <span class=\"truncate font-semibold\">\r\n {{ sectionName() }}\r\n </span>\r\n @if (!isManageProperties()) {\r\n <mt-icon\r\n class=\"text-lg cursor-pointer\"\r\n icon=\"general.edit-02\"\r\n (click)=\"editSection($event)\"\r\n [mtTooltip]=\"t('edit-section')\"\r\n ></mt-icon>\r\n }\r\n </div>\r\n <span></span>\r\n </div>\r\n @if (expanded()) {\r\n <div\r\n cdkDropList\r\n [id]=\"section().id\"\r\n cdkDropListOrientation=\"mixed\"\r\n [cdkDropListData]=\"displayFields()\"\r\n [cdkDropListConnectedTo]=\"connectedDropLists()\"\r\n [cdkDropListDisabled]=\"isManageProperties()\"\r\n [cdkDropListEnterPredicate]=\"fieldsDropPredicate\"\r\n (cdkDropListDropped)=\"onDrop($event)\"\r\n class=\"grid grid-cols-12 gap-4 relative py-2\"\r\n [class.min-h-27]=\"displayFields().length === 0\"\r\n >\r\n @for (field of displayFields(); track field.id) {\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"field\"\r\n [cdkDragDisabled]=\"\r\n isManageProperties() || field._pending || field._deleting\r\n \"\r\n [class]=\"\r\n getFieldColSpan(field) +\r\n (isManageProperties()\r\n ? ''\r\n : ' cursor-grab active:cursor-grabbing')\r\n \"\r\n >\r\n <div\r\n *cdkDragPlaceholder\r\n [class]=\"\r\n 'h-full min-h-27 bg-black/10 rounded-lg ' +\r\n getFieldColSpan(field)\r\n \"\r\n ></div>\r\n @if (field._pending) {\r\n <!-- Skeleton for pending field -->\r\n <mt-card class=\"h-full animate-pulse\">\r\n <div class=\"flex flex-col gap-3 sm:flex-row\">\r\n <div class=\"flex-1 space-y-3\">\r\n <div class=\"h-4 bg-surface-200 rounded w-1/3\"></div>\r\n <div class=\"h-10 bg-surface-200 rounded\"></div>\r\n </div>\r\n <div class=\"flex shrink-0 flex-row gap-1 sm:flex-col\">\r\n <div class=\"h-8 w-8 bg-surface-200 rounded\"></div>\r\n <div class=\"h-8 w-8 bg-surface-200 rounded\"></div>\r\n </div>\r\n </div>\r\n </mt-card>\r\n } @else {\r\n <mt-card\r\n class=\"h-full relative transition-all duration-200\"\r\n [class.opacity-50]=\"field._deleting\"\r\n >\r\n @if (field._deleting) {\r\n <div\r\n class=\"absolute inset-0 flex items-center justify-center bg-white/50 rounded-xl z-10\"\r\n >\r\n <div\r\n class=\"animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full\"\r\n ></div>\r\n </div>\r\n }\r\n <div class=\"flex flex-col gap-3 sm:flex-row\">\r\n <div class=\"min-w-0 flex-1\">\r\n <form [formGroup]=\"getFormGroup(field)\">\r\n <div\r\n class=\"mb-2 flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-4\"\r\n >\r\n <div class=\"min-w-0 break-words font-semibold\">\r\n {{ field.name }}\r\n </div>\r\n @if (isManageProperties()) {\r\n <div\r\n class=\"flex flex-wrap items-center gap-1.5 sm:ms-auto\"\r\n >\r\n @if (field.isRead === false) {\r\n <span\r\n class=\"text-xs font-medium text-red-500 bg-red-50 px-1.5 py-0.5 rounded\"\r\n >\r\n {{ t(\"hidden\") }}\r\n </span>\r\n } @else if (field.isWrite === false) {\r\n <span\r\n class=\"text-xs font-medium text-amber-600 bg-amber-50 px-1.5 py-0.5 rounded\"\r\n >\r\n {{ t(\"read-only\") }}\r\n </span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"transition-all duration-200\"\r\n [class.opacity-40]=\"\r\n isManageProperties() && field.isRead === false\r\n \"\r\n [class.blur-[1px]]=\"\r\n isManageProperties() && field.isRead === false\r\n \"\r\n >\r\n @if (isTranslatableTextField(field)) {\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n @for (\r\n control of getTranslatableFieldControls(field);\r\n track control.key\r\n ) {\r\n <div\r\n [class]=\"\r\n getTranslatableFieldControlColSpan(field)\r\n \"\r\n >\r\n <mt-dynamic-field\r\n [fieldName]=\"control.key\"\r\n [fieldConfig]=\"control.config\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <mt-dynamic-field\r\n [fieldName]=\"field.name\"\r\n [fieldConfig]=\"getFieldConfig(field)\"\r\n />\r\n }\r\n </div>\r\n </form>\r\n </div>\r\n <div\r\n class=\"flex shrink-0 flex-row gap-1 self-end sm:flex-col sm:self-start\"\r\n >\r\n <mt-button\r\n size=\"small\"\r\n icon=\"general.settings-01\"\r\n [tooltip]=\"t('edit-field')\"\r\n [variant]=\"'outlined'\"\r\n [disabled]=\"field._deleting\"\r\n (onClick)=\"editField(field)\"\r\n ></mt-button>\r\n @if (!isManageProperties()) {\r\n <mt-button\r\n size=\"small\"\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [variant]=\"'outlined'\"\r\n [tooltip]=\"t('remove-field')\"\r\n [disabled]=\"field._deleting\"\r\n (onClick)=\"removeField($event, field)\"\r\n ></mt-button>\r\n }\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n } @empty {\r\n <mt-card class=\"absolute inset-0 top-4\" paddingless>\r\n <div class=\"size-full p-4\">\r\n <div\r\n class=\"flex h-full items-center justify-center gap-4 rounded-xl border-1 border-primary bg-primary-50 px-4 text-center text-primary\"\r\n >\r\n <mt-icon icon=\"editor.move\" class=\"text-3xl\" />\r\n <span>{{ t(\"drag-from-the-side\") }}</span>\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</ng-container>\r\n", dependencies: [{ kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "directive", type: 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: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: 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: CdkDragPlaceholder, selector: "ng-template[cdkDragPlaceholder]", inputs: ["data"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: DynamicField, selector: "mt-dynamic-field", inputs: ["fieldConfig", "fieldName"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: Tooltip, selector: "[mtTooltip]" }] });
1785
1845
  }
1786
1846
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FBSection, decorators: [{
1787
1847
  type: Component,
@@ -1797,7 +1857,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
1797
1857
  DynamicField,
1798
1858
  ReactiveFormsModule,
1799
1859
  Tooltip,
1800
- ], template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div class=\"flex flex-col\">\r\n <div\r\n cdkDragHandle\r\n [class]=\"\r\n 'flex items-center justify-between gap-3 rounded-xl bg-primary px-3 py-3 text-primary-contrast' +\r\n (isManageProperties() ? '' : ' cursor-grab active:cursor-grabbing')\r\n \"\r\n >\r\n <div class=\"flex min-w-0 items-center gap-3\">\r\n <mt-icon\r\n class=\"shrink-0 cursor-pointer text-2xl transition-[rotate]\"\r\n [class.rotate-180]=\"expanded()\"\r\n icon=\"arrow.chevron-down\"\r\n (click)=\"toggleExpanded()\"\r\n ></mt-icon>\r\n\r\n <span class=\"truncate font-semibold\">\r\n {{ sectionName() }}\r\n </span>\r\n @if (!isManageProperties()) {\r\n <mt-icon\r\n class=\"text-lg cursor-pointer\"\r\n icon=\"general.edit-02\"\r\n (click)=\"editSection($event)\"\r\n [mtTooltip]=\"t('edit-section')\"\r\n ></mt-icon>\r\n }\r\n </div>\r\n <span></span>\r\n </div>\r\n @if (expanded()) {\r\n <div\r\n cdkDropList\r\n [id]=\"section().id\"\r\n cdkDropListOrientation=\"mixed\"\r\n [cdkDropListData]=\"displayFields()\"\r\n [cdkDropListConnectedTo]=\"connectedDropLists()\"\r\n [cdkDropListDisabled]=\"isManageProperties()\"\r\n [cdkDropListEnterPredicate]=\"fieldsDropPredicate\"\r\n (cdkDropListDropped)=\"onDrop($event)\"\r\n class=\"grid grid-cols-12 gap-4 relative py-2\"\r\n [class.min-h-27]=\"displayFields().length === 0\"\r\n >\r\n @for (field of displayFields(); track field.id) {\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"field\"\r\n [cdkDragDisabled]=\"\r\n isManageProperties() || field._pending || field._deleting\r\n \"\r\n [class]=\"\r\n getFieldColSpan(field) +\r\n (isManageProperties()\r\n ? ''\r\n : ' cursor-grab active:cursor-grabbing')\r\n \"\r\n >\r\n <div\r\n *cdkDragPlaceholder\r\n [class]=\"\r\n 'h-full min-h-27 bg-black/10 rounded-lg ' +\r\n getFieldColSpan(field)\r\n \"\r\n ></div>\r\n @if (field._pending) {\r\n <!-- Skeleton for pending field -->\r\n <mt-card class=\"h-full animate-pulse\">\r\n <div class=\"flex flex-col gap-3 sm:flex-row\">\r\n <div class=\"flex-1 space-y-3\">\r\n <div class=\"h-4 bg-surface-200 rounded w-1/3\"></div>\r\n <div class=\"h-10 bg-surface-200 rounded\"></div>\r\n </div>\r\n <div class=\"flex shrink-0 flex-row gap-1 sm:flex-col\">\r\n <div class=\"h-8 w-8 bg-surface-200 rounded\"></div>\r\n <div class=\"h-8 w-8 bg-surface-200 rounded\"></div>\r\n </div>\r\n </div>\r\n </mt-card>\r\n } @else {\r\n <mt-card\r\n class=\"h-full relative transition-all duration-200\"\r\n [class.opacity-50]=\"field._deleting\"\r\n >\r\n @if (field._deleting) {\r\n <div\r\n class=\"absolute inset-0 flex items-center justify-center bg-white/50 rounded-xl z-10\"\r\n >\r\n <div\r\n class=\"animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full\"\r\n ></div>\r\n </div>\r\n }\r\n <div class=\"flex flex-col gap-3 sm:flex-row\">\r\n <div class=\"min-w-0 flex-1\">\r\n <form [formGroup]=\"getFormGroup(field)\">\r\n <div\r\n class=\"mb-2 flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-4\"\r\n >\r\n <div class=\"min-w-0 break-words font-semibold\">\r\n {{ field.name }}\r\n </div>\r\n @if (isManageProperties()) {\r\n <div\r\n class=\"flex flex-wrap items-center gap-1.5 sm:ms-auto\"\r\n >\r\n @if (field.isRead === false) {\r\n <span\r\n class=\"text-xs font-medium text-red-500 bg-red-50 px-1.5 py-0.5 rounded\"\r\n >\r\n {{ t(\"hidden\") }}\r\n </span>\r\n } @else if (field.isWrite === false) {\r\n <span\r\n class=\"text-xs font-medium text-amber-600 bg-amber-50 px-1.5 py-0.5 rounded\"\r\n >\r\n {{ t(\"read-only\") }}\r\n </span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"transition-all duration-200\"\r\n [class.opacity-40]=\"\r\n isManageProperties() && field.isRead === false\r\n \"\r\n [class.blur-[1px]]=\"\r\n isManageProperties() && field.isRead === false\r\n \"\r\n >\r\n <mt-dynamic-field\r\n [fieldName]=\"field.name\"\r\n [fieldConfig]=\"getFieldConfig(field)\"\r\n />\r\n </div>\r\n </form>\r\n </div>\r\n <div\r\n class=\"flex shrink-0 flex-row gap-1 self-end sm:flex-col sm:self-start\"\r\n >\r\n <mt-button\r\n size=\"small\"\r\n icon=\"general.settings-01\"\r\n [tooltip]=\"t('edit-field')\"\r\n [variant]=\"'outlined'\"\r\n [disabled]=\"field._deleting\"\r\n (onClick)=\"editField(field)\"\r\n ></mt-button>\r\n @if (!isManageProperties()) {\r\n <mt-button\r\n size=\"small\"\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [variant]=\"'outlined'\"\r\n [tooltip]=\"t('remove-field')\"\r\n [disabled]=\"field._deleting\"\r\n (onClick)=\"removeField($event, field)\"\r\n ></mt-button>\r\n }\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n } @empty {\r\n <mt-card class=\"absolute inset-0 top-4\" paddingless>\r\n <div class=\"size-full p-4\">\r\n <div\r\n class=\"flex h-full items-center justify-center gap-4 rounded-xl border-1 border-primary bg-primary-50 px-4 text-center text-primary\"\r\n >\r\n <mt-icon icon=\"editor.move\" class=\"text-3xl\" />\r\n <span>{{ t(\"drag-from-the-side\") }}</span>\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</ng-container>\r\n" }]
1860
+ ], template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div class=\"flex flex-col\">\r\n <div\r\n cdkDragHandle\r\n [class]=\"\r\n 'flex items-center justify-between gap-3 rounded-xl bg-primary px-3 py-3 text-primary-contrast' +\r\n (isManageProperties() ? '' : ' cursor-grab active:cursor-grabbing')\r\n \"\r\n >\r\n <div class=\"flex min-w-0 items-center gap-3\">\r\n <mt-icon\r\n class=\"shrink-0 cursor-pointer text-2xl transition-[rotate]\"\r\n [class.rotate-180]=\"expanded()\"\r\n icon=\"arrow.chevron-down\"\r\n (click)=\"toggleExpanded()\"\r\n ></mt-icon>\r\n\r\n <span class=\"truncate font-semibold\">\r\n {{ sectionName() }}\r\n </span>\r\n @if (!isManageProperties()) {\r\n <mt-icon\r\n class=\"text-lg cursor-pointer\"\r\n icon=\"general.edit-02\"\r\n (click)=\"editSection($event)\"\r\n [mtTooltip]=\"t('edit-section')\"\r\n ></mt-icon>\r\n }\r\n </div>\r\n <span></span>\r\n </div>\r\n @if (expanded()) {\r\n <div\r\n cdkDropList\r\n [id]=\"section().id\"\r\n cdkDropListOrientation=\"mixed\"\r\n [cdkDropListData]=\"displayFields()\"\r\n [cdkDropListConnectedTo]=\"connectedDropLists()\"\r\n [cdkDropListDisabled]=\"isManageProperties()\"\r\n [cdkDropListEnterPredicate]=\"fieldsDropPredicate\"\r\n (cdkDropListDropped)=\"onDrop($event)\"\r\n class=\"grid grid-cols-12 gap-4 relative py-2\"\r\n [class.min-h-27]=\"displayFields().length === 0\"\r\n >\r\n @for (field of displayFields(); track field.id) {\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"field\"\r\n [cdkDragDisabled]=\"\r\n isManageProperties() || field._pending || field._deleting\r\n \"\r\n [class]=\"\r\n getFieldColSpan(field) +\r\n (isManageProperties()\r\n ? ''\r\n : ' cursor-grab active:cursor-grabbing')\r\n \"\r\n >\r\n <div\r\n *cdkDragPlaceholder\r\n [class]=\"\r\n 'h-full min-h-27 bg-black/10 rounded-lg ' +\r\n getFieldColSpan(field)\r\n \"\r\n ></div>\r\n @if (field._pending) {\r\n <!-- Skeleton for pending field -->\r\n <mt-card class=\"h-full animate-pulse\">\r\n <div class=\"flex flex-col gap-3 sm:flex-row\">\r\n <div class=\"flex-1 space-y-3\">\r\n <div class=\"h-4 bg-surface-200 rounded w-1/3\"></div>\r\n <div class=\"h-10 bg-surface-200 rounded\"></div>\r\n </div>\r\n <div class=\"flex shrink-0 flex-row gap-1 sm:flex-col\">\r\n <div class=\"h-8 w-8 bg-surface-200 rounded\"></div>\r\n <div class=\"h-8 w-8 bg-surface-200 rounded\"></div>\r\n </div>\r\n </div>\r\n </mt-card>\r\n } @else {\r\n <mt-card\r\n class=\"h-full relative transition-all duration-200\"\r\n [class.opacity-50]=\"field._deleting\"\r\n >\r\n @if (field._deleting) {\r\n <div\r\n class=\"absolute inset-0 flex items-center justify-center bg-white/50 rounded-xl z-10\"\r\n >\r\n <div\r\n class=\"animate-spin h-6 w-6 border-2 border-primary border-t-transparent rounded-full\"\r\n ></div>\r\n </div>\r\n }\r\n <div class=\"flex flex-col gap-3 sm:flex-row\">\r\n <div class=\"min-w-0 flex-1\">\r\n <form [formGroup]=\"getFormGroup(field)\">\r\n <div\r\n class=\"mb-2 flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-4\"\r\n >\r\n <div class=\"min-w-0 break-words font-semibold\">\r\n {{ field.name }}\r\n </div>\r\n @if (isManageProperties()) {\r\n <div\r\n class=\"flex flex-wrap items-center gap-1.5 sm:ms-auto\"\r\n >\r\n @if (field.isRead === false) {\r\n <span\r\n class=\"text-xs font-medium text-red-500 bg-red-50 px-1.5 py-0.5 rounded\"\r\n >\r\n {{ t(\"hidden\") }}\r\n </span>\r\n } @else if (field.isWrite === false) {\r\n <span\r\n class=\"text-xs font-medium text-amber-600 bg-amber-50 px-1.5 py-0.5 rounded\"\r\n >\r\n {{ t(\"read-only\") }}\r\n </span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"transition-all duration-200\"\r\n [class.opacity-40]=\"\r\n isManageProperties() && field.isRead === false\r\n \"\r\n [class.blur-[1px]]=\"\r\n isManageProperties() && field.isRead === false\r\n \"\r\n >\r\n @if (isTranslatableTextField(field)) {\r\n <div class=\"grid grid-cols-12 gap-3\">\r\n @for (\r\n control of getTranslatableFieldControls(field);\r\n track control.key\r\n ) {\r\n <div\r\n [class]=\"\r\n getTranslatableFieldControlColSpan(field)\r\n \"\r\n >\r\n <mt-dynamic-field\r\n [fieldName]=\"control.key\"\r\n [fieldConfig]=\"control.config\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <mt-dynamic-field\r\n [fieldName]=\"field.name\"\r\n [fieldConfig]=\"getFieldConfig(field)\"\r\n />\r\n }\r\n </div>\r\n </form>\r\n </div>\r\n <div\r\n class=\"flex shrink-0 flex-row gap-1 self-end sm:flex-col sm:self-start\"\r\n >\r\n <mt-button\r\n size=\"small\"\r\n icon=\"general.settings-01\"\r\n [tooltip]=\"t('edit-field')\"\r\n [variant]=\"'outlined'\"\r\n [disabled]=\"field._deleting\"\r\n (onClick)=\"editField(field)\"\r\n ></mt-button>\r\n @if (!isManageProperties()) {\r\n <mt-button\r\n size=\"small\"\r\n icon=\"general.trash-01\"\r\n severity=\"danger\"\r\n [variant]=\"'outlined'\"\r\n [tooltip]=\"t('remove-field')\"\r\n [disabled]=\"field._deleting\"\r\n (onClick)=\"removeField($event, field)\"\r\n ></mt-button>\r\n }\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n } @empty {\r\n <mt-card class=\"absolute inset-0 top-4\" paddingless>\r\n <div class=\"size-full p-4\">\r\n <div\r\n class=\"flex h-full items-center justify-center gap-4 rounded-xl border-1 border-primary bg-primary-50 px-4 text-center text-primary\"\r\n >\r\n <mt-icon icon=\"editor.move\" class=\"text-3xl\" />\r\n <span>{{ t(\"drag-from-the-side\") }}</span>\r\n </div>\r\n </div>\r\n </mt-card>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</ng-container>\r\n" }]
1801
1861
  }], ctorParameters: () => [], propDecorators: { section: [{ type: i0.Input, args: [{ isSignal: true, alias: "section", required: true }] }], sectionsCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "sectionsCount", required: false }] }], allSections: [{ type: i0.Input, args: [{ isSignal: true, alias: "allSections", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], connectedDropLists: [{ type: i0.Input, args: [{ isSignal: true, alias: "connectedDropLists", required: false }] }], onFieldDrop: [{ type: i0.Output, args: ["onFieldDrop"] }] } });
1802
1862
 
1803
1863
  class FBPreviewForm {
@@ -2041,7 +2101,7 @@ class FBValidationRuleForm {
2041
2101
  this.saveError.set(message);
2042
2102
  }
2043
2103
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FBValidationRuleForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
2044
- 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'\">\n <div\n [class]=\"[\n modalService.contentClass,\n 'min-w-0',\n 'p-4',\n 'overflow-y-hidden!',\n 'max-[640px]:p-3',\n ]\"\n >\n <div class=\"mt-4 flex h-full min-h-0 flex-col gap-4 overflow-y-auto pb-10\">\n <mt-formula-builder\n [placeholder]=\"t('validation-formula-placeholder')\"\n [formControl]=\"formulaControl\"\n [levelSchemaId]=\"builderSchemaId()\"\n [moduleId]=\"builderModuleId()\"\n [contextEntityTypeKey]=\"builderContextEntityTypeKey()\"\n [propertiesByPath]=\"formulaPropertiesByPath()\"\n (validationChange)=\"onFormulaValidationChange($event)\"\n />\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <mt-text-field\n [label]=\"t('message-en')\"\n [placeholder]=\"t('message-en')\"\n [formControl]=\"messageEnControl\"\n />\n <mt-text-field\n [label]=\"t('message-ar')\"\n [placeholder]=\"t('message-ar')\"\n [formControl]=\"messageArControl\"\n />\n </div>\n <mt-radio-cards-field\n [label]=\"t('severity')\"\n [hint]=\"t('severity-hint')\"\n [options]=\"severityOptions()\"\n [formControl]=\"severityControl\"\n />\n @if (saveError(); as error) {\n <div\n class=\"rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700\"\n >\n {{ error }}\n </div>\n }\n </div>\n </div>\n\n <div\n [class]=\"[\n modalService.footerClass,\n '!h-auto',\n 'min-h-0',\n 'flex-col',\n 'gap-2',\n 'sm:flex-row',\n 'sm:items-center',\n 'sm:justify-end',\n ]\"\n >\n <mt-button\n [label]=\"t('cancel')\"\n variant=\"outlined\"\n [disabled]=\"submitting()\"\n styleClass=\"w-full sm:w-auto\"\n (onClick)=\"onCancel()\"\n />\n <mt-button\n [label]=\"t('save')\"\n severity=\"primary\"\n [loading]=\"submitting()\"\n [disabled]=\"!canSave()\"\n styleClass=\"w-full sm:w-auto\"\n (onClick)=\"onSave()\"\n />\n </div>\n</ng-container>\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: RadioCardsField, selector: "mt-radio-cards-field", inputs: ["circle", "label", "hint", "readonly", "required", "color", "size", "optionLabel", "optionValue", "options"] }, { kind: "component", type: FormulaBuilder, selector: "mt-formula-builder", inputs: ["propertiesByPath", "levelSchemaId", "moduleId", "contextEntityTypeKey", "templateId", "placeholder", "hideToolbar", "hideStatusBar", "toolbarTabs", "codeOnly", "isProcessBuilder"], outputs: ["validationChange", "tokensChange"] }] });
2104
+ 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'\">\n <div\n [class]=\"[\n modalService.contentClass,\n 'min-w-0',\n 'p-4',\n 'overflow-y-hidden!',\n 'max-[640px]:p-3',\n ]\"\n >\n <div class=\"mt-4 flex h-full min-h-0 flex-col gap-4 overflow-y-auto pb-10\">\n <mt-formula-builder\n [placeholder]=\"t('validation-formula-placeholder')\"\n [formControl]=\"formulaControl\"\n [levelSchemaId]=\"builderSchemaId()\"\n [moduleId]=\"builderModuleId()\"\n [contextEntityTypeKey]=\"builderContextEntityTypeKey()\"\n [propertiesByPath]=\"formulaPropertiesByPath()\"\n (validationChange)=\"onFormulaValidationChange($event)\"\n />\n <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <mt-text-field\n [label]=\"t('message-en')\"\n [placeholder]=\"t('message-en')\"\n [formControl]=\"messageEnControl\"\n />\n <mt-text-field\n [label]=\"t('message-ar')\"\n [placeholder]=\"t('message-ar')\"\n [formControl]=\"messageArControl\"\n />\n </div>\n <mt-radio-cards-field\n [label]=\"t('severity')\"\n [hint]=\"t('severity-hint')\"\n [options]=\"severityOptions()\"\n [formControl]=\"severityControl\"\n />\n @if (saveError(); as error) {\n <div\n class=\"rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700\"\n >\n {{ error }}\n </div>\n }\n </div>\n </div>\n\n <div\n [class]=\"[\n modalService.footerClass,\n '!h-auto',\n 'min-h-0',\n 'flex-col',\n 'gap-2',\n 'sm:flex-row',\n 'sm:items-center',\n 'sm:justify-end',\n ]\"\n >\n <mt-button\n [label]=\"t('cancel')\"\n variant=\"outlined\"\n [disabled]=\"submitting()\"\n styleClass=\"w-full sm:w-auto\"\n (onClick)=\"onCancel()\"\n />\n <mt-button\n [label]=\"t('save')\"\n severity=\"primary\"\n [loading]=\"submitting()\"\n [disabled]=\"!canSave()\"\n styleClass=\"w-full sm:w-auto\"\n (onClick)=\"onSave()\"\n />\n </div>\n</ng-container>\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", "maxLength", "icon", "iconPosition"] }, { kind: "component", type: RadioCardsField, selector: "mt-radio-cards-field", inputs: ["circle", "label", "hint", "readonly", "required", "color", "size", "optionLabel", "optionValue", "options"] }, { kind: "component", type: FormulaBuilder, selector: "mt-formula-builder", inputs: ["propertiesByPath", "levelSchemaId", "moduleId", "contextEntityTypeKey", "templateId", "placeholder", "hideToolbar", "hideStatusBar", "toolbarTabs", "codeOnly", "isProcessBuilder"], outputs: ["validationChange", "tokensChange"] }] });
2045
2105
  }
2046
2106
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FBValidationRuleForm, decorators: [{
2047
2107
  type: Component,
@@ -2420,7 +2480,9 @@ class FormBuilder {
2420
2480
  return sections.map((section) => ({
2421
2481
  ...section,
2422
2482
  fields: section.fields.map((field) => {
2423
- const prop = propsMap.get(field.propertyKey) ?? field.property;
2483
+ const prop = propsMap.get(field.propertyKey) ??
2484
+ field.property ??
2485
+ field.propertyMetadata;
2424
2486
  return {
2425
2487
  ...field,
2426
2488
  name: this.resolvePropertyName(prop, field.propertyKey, lang),
@@ -2917,7 +2979,7 @@ class FormBuilder {
2917
2979
  }
2918
2980
  noReturnPredicate = () => false;
2919
2981
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FormBuilder, deps: [], target: i0.ɵɵFactoryTarget.Component });
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"] }] });
2982
+ 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 cdkScrollable\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 cdkScrollable\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 [cdkDropListAutoScrollStep]=\"16\"\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", "maxLength", "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.ɵɵCdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }, { 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"] }] });
2921
2983
  }
2922
2984
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FormBuilder, decorators: [{
2923
2985
  type: Component,
@@ -2935,7 +2997,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
2935
2997
  FBSection,
2936
2998
  DragDropModule,
2937
2999
  Icon,
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"] }]
3000
+ ], template: "<ng-container *transloco=\"let t; prefix: 'formBuilder'\">\r\n <div\r\n cdkScrollable\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 cdkScrollable\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 [cdkDropListAutoScrollStep]=\"16\"\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
3001
  }], 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 }] }] } });
2940
3002
 
2941
3003
  /*