@sdcorejs/angular 21.0.1 → 21.0.4

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.
Files changed (142) hide show
  1. package/README.md +22 -4
  2. package/assets/scss/core/_inline-edit.scss +105 -0
  3. package/assets/scss/core/form.scss +15 -0
  4. package/fesm2022/sdcorejs-angular-components-anchor.mjs +9 -9
  5. package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs +111 -24
  6. package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs.map +1 -1
  7. package/fesm2022/sdcorejs-angular-components-avatar.mjs +4 -4
  8. package/fesm2022/sdcorejs-angular-components-avatar.mjs.map +1 -1
  9. package/fesm2022/sdcorejs-angular-components-badge.mjs +3 -3
  10. package/fesm2022/sdcorejs-angular-components-base.mjs +3 -3
  11. package/fesm2022/sdcorejs-angular-components-button.mjs +5 -7
  12. package/fesm2022/sdcorejs-angular-components-button.mjs.map +1 -1
  13. package/fesm2022/sdcorejs-angular-components-chart.mjs +12 -12
  14. package/fesm2022/sdcorejs-angular-components-ckeditor-styles.mjs +3 -3
  15. package/fesm2022/sdcorejs-angular-components-code-editor.mjs +3 -3
  16. package/fesm2022/sdcorejs-angular-components-document-builder.mjs +6 -6
  17. package/fesm2022/sdcorejs-angular-components-editor.mjs +3 -3
  18. package/fesm2022/sdcorejs-angular-components-form-generic.mjs +291 -382
  19. package/fesm2022/sdcorejs-angular-components-form-generic.mjs.map +1 -1
  20. package/fesm2022/sdcorejs-angular-components-history.mjs +7 -7
  21. package/fesm2022/sdcorejs-angular-components-import-excel.mjs +10 -10
  22. package/fesm2022/sdcorejs-angular-components-inform.mjs +6 -6
  23. package/fesm2022/sdcorejs-angular-components-mini-editor.mjs +3 -3
  24. package/fesm2022/sdcorejs-angular-components-modal-resizable.mjs +158 -0
  25. package/fesm2022/sdcorejs-angular-components-modal-resizable.mjs.map +1 -0
  26. package/fesm2022/sdcorejs-angular-components-modal.mjs +3 -3
  27. package/fesm2022/sdcorejs-angular-components-operator.mjs +6 -4
  28. package/fesm2022/sdcorejs-angular-components-operator.mjs.map +1 -1
  29. package/fesm2022/sdcorejs-angular-components-preview.mjs +8 -8
  30. package/fesm2022/sdcorejs-angular-components-preview.mjs.map +1 -1
  31. package/fesm2022/sdcorejs-angular-components-query-bar.mjs +60 -106
  32. package/fesm2022/sdcorejs-angular-components-query-bar.mjs.map +1 -1
  33. package/fesm2022/sdcorejs-angular-components-query-builder.mjs +671 -59
  34. package/fesm2022/sdcorejs-angular-components-query-builder.mjs.map +1 -1
  35. package/fesm2022/sdcorejs-angular-components-quick-action.mjs +3 -3
  36. package/fesm2022/sdcorejs-angular-components-section.mjs +7 -9
  37. package/fesm2022/sdcorejs-angular-components-section.mjs.map +1 -1
  38. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs +5 -7
  39. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs.map +1 -1
  40. package/fesm2022/sdcorejs-angular-components-splitter.mjs +12 -12
  41. package/fesm2022/sdcorejs-angular-components-stepper.mjs +7 -9
  42. package/fesm2022/sdcorejs-angular-components-stepper.mjs.map +1 -1
  43. package/fesm2022/sdcorejs-angular-components-tab-router.mjs +18 -18
  44. package/fesm2022/sdcorejs-angular-components-tab.mjs +7 -9
  45. package/fesm2022/sdcorejs-angular-components-tab.mjs.map +1 -1
  46. package/fesm2022/sdcorejs-angular-components-table.mjs +336 -211
  47. package/fesm2022/sdcorejs-angular-components-table.mjs.map +1 -1
  48. package/fesm2022/sdcorejs-angular-components-upload-file.mjs +29 -18
  49. package/fesm2022/sdcorejs-angular-components-upload-file.mjs.map +1 -1
  50. package/fesm2022/sdcorejs-angular-components-view.mjs +45 -13
  51. package/fesm2022/sdcorejs-angular-components-view.mjs.map +1 -1
  52. package/fesm2022/sdcorejs-angular-components.mjs +1 -0
  53. package/fesm2022/sdcorejs-angular-components.mjs.map +1 -1
  54. package/fesm2022/sdcorejs-angular-directives.mjs +21 -21
  55. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs +35 -10
  56. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs.map +1 -1
  57. package/fesm2022/sdcorejs-angular-forms-checkbox.mjs +11 -6
  58. package/fesm2022/sdcorejs-angular-forms-checkbox.mjs.map +1 -1
  59. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs +15 -10
  60. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs.map +1 -1
  61. package/fesm2022/sdcorejs-angular-forms-chip.mjs +15 -10
  62. package/fesm2022/sdcorejs-angular-forms-chip.mjs.map +1 -1
  63. package/fesm2022/sdcorejs-angular-forms-date-range.mjs +21 -12
  64. package/fesm2022/sdcorejs-angular-forms-date-range.mjs.map +1 -1
  65. package/fesm2022/sdcorejs-angular-forms-date.mjs +29 -17
  66. package/fesm2022/sdcorejs-angular-forms-date.mjs.map +1 -1
  67. package/fesm2022/sdcorejs-angular-forms-datetime.mjs +34 -22
  68. package/fesm2022/sdcorejs-angular-forms-datetime.mjs.map +1 -1
  69. package/fesm2022/sdcorejs-angular-forms-directives.mjs +12 -12
  70. package/fesm2022/sdcorejs-angular-forms-inline-text.mjs +167 -0
  71. package/fesm2022/sdcorejs-angular-forms-inline-text.mjs.map +1 -0
  72. package/fesm2022/sdcorejs-angular-forms-input-color.mjs +7 -5
  73. package/fesm2022/sdcorejs-angular-forms-input-color.mjs.map +1 -1
  74. package/fesm2022/sdcorejs-angular-forms-input-number.mjs +44 -11
  75. package/fesm2022/sdcorejs-angular-forms-input-number.mjs.map +1 -1
  76. package/fesm2022/sdcorejs-angular-forms-input.mjs +38 -12
  77. package/fesm2022/sdcorejs-angular-forms-input.mjs.map +1 -1
  78. package/fesm2022/sdcorejs-angular-forms-label.mjs +3 -3
  79. package/fesm2022/sdcorejs-angular-forms-models.mjs +32 -2
  80. package/fesm2022/sdcorejs-angular-forms-models.mjs.map +1 -1
  81. package/fesm2022/sdcorejs-angular-forms-radio.mjs +11 -6
  82. package/fesm2022/sdcorejs-angular-forms-radio.mjs.map +1 -1
  83. package/fesm2022/sdcorejs-angular-forms-select.mjs +36 -12
  84. package/fesm2022/sdcorejs-angular-forms-select.mjs.map +1 -1
  85. package/fesm2022/sdcorejs-angular-forms-switch.mjs +11 -6
  86. package/fesm2022/sdcorejs-angular-forms-switch.mjs.map +1 -1
  87. package/fesm2022/sdcorejs-angular-forms-textarea.mjs +17 -7
  88. package/fesm2022/sdcorejs-angular-forms-textarea.mjs.map +1 -1
  89. package/fesm2022/sdcorejs-angular-forms.mjs +4 -4
  90. package/fesm2022/sdcorejs-angular-handlers.mjs +3 -3
  91. package/fesm2022/sdcorejs-angular-i18n.mjs +26 -6
  92. package/fesm2022/sdcorejs-angular-i18n.mjs.map +1 -1
  93. package/fesm2022/sdcorejs-angular-interceptors.mjs +6 -6
  94. package/fesm2022/sdcorejs-angular-modules-auth.mjs +9 -9
  95. package/fesm2022/sdcorejs-angular-modules-authom.mjs +7 -7
  96. package/fesm2022/sdcorejs-angular-modules-keycloak.mjs +7 -7
  97. package/fesm2022/sdcorejs-angular-modules-layout.mjs +73 -73
  98. package/fesm2022/sdcorejs-angular-modules-permission.mjs +9 -9
  99. package/fesm2022/sdcorejs-angular-pipes.mjs +14 -14
  100. package/fesm2022/sdcorejs-angular-services-api.mjs +10 -10
  101. package/fesm2022/sdcorejs-angular-services-cache.mjs +3 -3
  102. package/fesm2022/sdcorejs-angular-services-confirm.mjs +6 -6
  103. package/fesm2022/sdcorejs-angular-services-confirm.mjs.map +1 -1
  104. package/fesm2022/sdcorejs-angular-services-docx.mjs +3 -3
  105. package/fesm2022/sdcorejs-angular-services-excel.mjs +3 -3
  106. package/fesm2022/sdcorejs-angular-services-license.mjs +3 -3
  107. package/fesm2022/sdcorejs-angular-services-loading.mjs +3 -3
  108. package/fesm2022/sdcorejs-angular-services-notify.mjs +47 -16
  109. package/fesm2022/sdcorejs-angular-services-notify.mjs.map +1 -1
  110. package/fesm2022/sdcorejs-angular-services-storage.mjs +3 -3
  111. package/package.json +9 -1
  112. package/types/sdcorejs-angular-components-autoid-inspector.d.ts +53 -4
  113. package/types/sdcorejs-angular-components-button.d.ts +1 -2
  114. package/types/sdcorejs-angular-components-form-generic.d.ts +15 -17
  115. package/types/sdcorejs-angular-components-modal-resizable.d.ts +32 -0
  116. package/types/sdcorejs-angular-components-query-builder.d.ts +247 -23
  117. package/types/sdcorejs-angular-components-section.d.ts +1 -2
  118. package/types/sdcorejs-angular-components-side-drawer.d.ts +1 -2
  119. package/types/sdcorejs-angular-components-stepper.d.ts +1 -2
  120. package/types/sdcorejs-angular-components-tab.d.ts +1 -2
  121. package/types/sdcorejs-angular-components-table.d.ts +100 -12
  122. package/types/sdcorejs-angular-components-upload-file.d.ts +2 -0
  123. package/types/sdcorejs-angular-components-view.d.ts +33 -0
  124. package/types/sdcorejs-angular-components.d.ts +1 -0
  125. package/types/sdcorejs-angular-forms-autocomplete.d.ts +16 -3
  126. package/types/sdcorejs-angular-forms-checkbox.d.ts +5 -1
  127. package/types/sdcorejs-angular-forms-chip-calendar.d.ts +5 -2
  128. package/types/sdcorejs-angular-forms-chip.d.ts +5 -2
  129. package/types/sdcorejs-angular-forms-date-range.d.ts +12 -5
  130. package/types/sdcorejs-angular-forms-date.d.ts +14 -5
  131. package/types/sdcorejs-angular-forms-datetime.d.ts +14 -5
  132. package/types/sdcorejs-angular-forms-inline-text.d.ts +80 -0
  133. package/types/sdcorejs-angular-forms-input-color.d.ts +3 -1
  134. package/types/sdcorejs-angular-forms-input-number.d.ts +14 -2
  135. package/types/sdcorejs-angular-forms-input.d.ts +14 -2
  136. package/types/sdcorejs-angular-forms-models.d.ts +40 -2
  137. package/types/sdcorejs-angular-forms-radio.d.ts +5 -2
  138. package/types/sdcorejs-angular-forms-select.d.ts +23 -5
  139. package/types/sdcorejs-angular-forms-switch.d.ts +5 -2
  140. package/types/sdcorejs-angular-forms-textarea.d.ts +9 -2
  141. package/types/sdcorejs-angular-i18n.d.ts +4 -0
  142. package/types/sdcorejs-angular-services-notify.d.ts +17 -0
@@ -11,7 +11,6 @@ import * as i2 from '@angular/material/icon';
11
11
  import { MatIconModule } from '@angular/material/icon';
12
12
  import * as i2$1 from '@angular/material/tooltip';
13
13
  import { MatTooltipModule } from '@angular/material/tooltip';
14
- import { SdBaseSecureComponent } from '@sdcorejs/angular/components/base';
15
14
  import { SdButton } from '@sdcorejs/angular/components/button';
16
15
  import { SdModal } from '@sdcorejs/angular/components/modal';
17
16
  import { SdInput as SdInput$1 } from '@sdcorejs/angular/forms/input';
@@ -745,10 +744,10 @@ class FormGenericService {
745
744
  return '';
746
745
  },
747
746
  };
748
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: FormGenericService, deps: [{ token: SD_FORM_GENERIC_CONFIGURATION, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
749
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: FormGenericService, providedIn: 'root' });
747
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FormGenericService, deps: [{ token: SD_FORM_GENERIC_CONFIGURATION, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
748
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FormGenericService, providedIn: 'root' });
750
749
  }
751
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: FormGenericService, decorators: [{
750
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FormGenericService, decorators: [{
752
751
  type: Injectable,
753
752
  args: [{
754
753
  providedIn: 'root',
@@ -783,10 +782,10 @@ class SdFormRenderService {
783
782
  }
784
783
  return reuslts;
785
784
  };
786
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdFormRenderService, deps: [{ token: ComponentViewedPipe }], target: i0.ɵɵFactoryTarget.Injectable });
787
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdFormRenderService, providedIn: 'root' });
785
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SdFormRenderService, deps: [{ token: ComponentViewedPipe }], target: i0.ɵɵFactoryTarget.Injectable });
786
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SdFormRenderService, providedIn: 'root' });
788
787
  }
789
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdFormRenderService, decorators: [{
788
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SdFormRenderService, decorators: [{
790
789
  type: Injectable,
791
790
  args: [{
792
791
  providedIn: 'root',
@@ -865,11 +864,11 @@ class ComponentViewedPipe {
865
864
  }
866
865
  return '';
867
866
  };
868
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ComponentViewedPipe, deps: [{ token: i1.SdFormatNumberPipe }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Pipe });
869
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: ComponentViewedPipe, isStandalone: true, name: "componentViewed" });
870
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ComponentViewedPipe, providedIn: 'root' });
867
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ComponentViewedPipe, deps: [{ token: i1.SdFormatNumberPipe }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Pipe });
868
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.16", ngImport: i0, type: ComponentViewedPipe, isStandalone: true, name: "componentViewed" });
869
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ComponentViewedPipe, providedIn: 'root' });
871
870
  }
872
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ComponentViewedPipe, decorators: [{
871
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ComponentViewedPipe, decorators: [{
873
872
  type: Pipe,
874
873
  args: [{
875
874
  name: 'componentViewed',
@@ -945,10 +944,10 @@ class WhenExpressionPipe {
945
944
  required: component?.validate?.required || this.#required(component, entity),
946
945
  };
947
946
  }
948
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: WhenExpressionPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
949
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: WhenExpressionPipe, isStandalone: true, name: "whenExpression" });
947
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: WhenExpressionPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
948
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.16", ngImport: i0, type: WhenExpressionPipe, isStandalone: true, name: "whenExpression" });
950
949
  }
951
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: WhenExpressionPipe, decorators: [{
950
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: WhenExpressionPipe, decorators: [{
952
951
  type: Pipe,
953
952
  args: [{
954
953
  name: 'whenExpression',
@@ -1046,11 +1045,11 @@ class ExpressionQueryPipe {
1046
1045
  }
1047
1046
  return this.#generateQuery(condition);
1048
1047
  }
1049
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ExpressionQueryPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1050
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: ExpressionQueryPipe, isStandalone: true, name: "expressionQuery" });
1051
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ExpressionQueryPipe, providedIn: 'root' });
1048
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ExpressionQueryPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1049
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.16", ngImport: i0, type: ExpressionQueryPipe, isStandalone: true, name: "expressionQuery" });
1050
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ExpressionQueryPipe, providedIn: 'root' });
1052
1051
  }
1053
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ExpressionQueryPipe, decorators: [{
1052
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ExpressionQueryPipe, decorators: [{
1054
1053
  type: Pipe,
1055
1054
  args: [{
1056
1055
  name: 'expressionQuery',
@@ -1082,10 +1081,10 @@ class ExpressionViewPipe {
1082
1081
  }
1083
1082
  return `<div class="d-flex flex-row align-items-center" style="gap:8px ;flex-wrap: wrap ;word-wrap: break-word">${results.join('')}</div>`;
1084
1083
  }
1085
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ExpressionViewPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1086
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: ExpressionViewPipe, isStandalone: true, name: "expressionView" });
1084
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ExpressionViewPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1085
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.16", ngImport: i0, type: ExpressionViewPipe, isStandalone: true, name: "expressionView" });
1087
1086
  }
1088
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ExpressionViewPipe, decorators: [{
1087
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ExpressionViewPipe, decorators: [{
1089
1088
  type: Pipe,
1090
1089
  args: [{
1091
1090
  name: 'expressionView',
@@ -1182,11 +1181,11 @@ class ExpressionFeelPipe {
1182
1181
  }
1183
1182
  return result;
1184
1183
  }
1185
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ExpressionFeelPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1186
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: ExpressionFeelPipe, isStandalone: true, name: "expressionFeel" });
1187
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ExpressionFeelPipe, providedIn: 'root' });
1184
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ExpressionFeelPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1185
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.16", ngImport: i0, type: ExpressionFeelPipe, isStandalone: true, name: "expressionFeel" });
1186
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ExpressionFeelPipe, providedIn: 'root' });
1188
1187
  }
1189
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ExpressionFeelPipe, decorators: [{
1188
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ExpressionFeelPipe, decorators: [{
1190
1189
  type: Pipe,
1191
1190
  args: [{
1192
1191
  name: 'expressionFeel',
@@ -1217,10 +1216,10 @@ class HtmlPipe {
1217
1216
  const renderedHtml = StringUtilities.templateToDisplay(content, variables);
1218
1217
  return this.sanitizer.sanitize(SecurityContext.HTML, renderedHtml) || '';
1219
1218
  };
1220
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HtmlPipe, deps: [{ token: i1$1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe });
1221
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: HtmlPipe, isStandalone: true, name: "htmlPipe" });
1219
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: HtmlPipe, deps: [{ token: i1$1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe });
1220
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.16", ngImport: i0, type: HtmlPipe, isStandalone: true, name: "htmlPipe" });
1222
1221
  }
1223
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HtmlPipe, decorators: [{
1222
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: HtmlPipe, decorators: [{
1224
1223
  type: Pipe,
1225
1224
  args: [{
1226
1225
  name: 'htmlPipe',
@@ -1238,10 +1237,10 @@ class HyperlinkPipe {
1238
1237
  }
1239
1238
  return StringUtilities.templateToDisplay(hyperlink, entity);
1240
1239
  };
1241
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HyperlinkPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1242
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: HyperlinkPipe, isStandalone: true, name: "hyperlink" });
1240
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: HyperlinkPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1241
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.16", ngImport: i0, type: HyperlinkPipe, isStandalone: true, name: "hyperlink" });
1243
1242
  }
1244
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HyperlinkPipe, decorators: [{
1243
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: HyperlinkPipe, decorators: [{
1245
1244
  type: Pipe,
1246
1245
  args: [{
1247
1246
  name: 'hyperlink',
@@ -1327,10 +1326,10 @@ class TextfieldComponent {
1327
1326
  this.ref.markForCheck();
1328
1327
  }
1329
1328
  };
1330
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TextfieldComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1331
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: TextfieldComponent, isStandalone: true, selector: "lib-textfield", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"], _validator: ["validator", "_validator"] }, ngImport: i0, template: "@if (component && entity) {\n <sd-input\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [helperText]=\"component.helperText\"\n [name]=\"component.key\"\n [autoId]=\"component.key\"\n [(model)]=\"entity[component.key!]\"\n [required]=\"required\"\n [validator]=\"validator\"\n [maxlength]=\"component.validate?.maxlength\"\n [pattern]=\"component.validate?.pattern\"\n [patternErrorMessage]=\"component.validate?.patternErrorMessage\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed || component.properties?.viewed\"></sd-input>\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1329
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: TextfieldComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1330
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: TextfieldComponent, isStandalone: true, selector: "lib-textfield", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"], _validator: ["validator", "_validator"] }, ngImport: i0, template: "@if (component && entity) {\n <sd-input\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [helperText]=\"component.helperText\"\n [name]=\"component.key\"\n [autoId]=\"component.key\"\n [(model)]=\"entity[component.key!]\"\n [required]=\"required\"\n [validator]=\"validator\"\n [maxlength]=\"component.validate?.maxlength\"\n [pattern]=\"component.validate?.pattern\"\n [patternErrorMessage]=\"component.validate?.patternErrorMessage\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed || component.properties?.viewed\"></sd-input>\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1332
1331
  }
1333
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TextfieldComponent, decorators: [{
1332
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: TextfieldComponent, decorators: [{
1334
1333
  type: Component,
1335
1334
  args: [{ selector: 'lib-textfield', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
1336
1335
  CommonModule,
@@ -1411,10 +1410,10 @@ class TextareaComponent {
1411
1410
  ngOnDestroy() {
1412
1411
  this.#subscription.unsubscribe();
1413
1412
  }
1414
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TextareaComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1415
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: TextareaComponent, isStandalone: true, selector: "lib-textarea", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"] }, ngImport: i0, template: "@if (component && entity) {\n <sd-textarea\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [helperText]=\"component.helperText\"\n [name]=\"component.key\"\n [autoId]=\"component.key\"\n [(model)]=\"entity[component.key!]\"\n [required]=\"required\"\n [maxlength]=\"component.validate?.maxlength\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed || component.properties?.viewed\"></sd-textarea>\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdTextarea, selector: "sd-textarea", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "rows", "hideInlineError", "required", "disabled", "viewed", "autoHeight", "maxlength", "pattern", "validator", "inlineError", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1413
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: TextareaComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1414
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: TextareaComponent, isStandalone: true, selector: "lib-textarea", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"] }, ngImport: i0, template: "@if (component && entity) {\n <sd-textarea\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [helperText]=\"component.helperText\"\n [name]=\"component.key\"\n [autoId]=\"component.key\"\n [(model)]=\"entity[component.key!]\"\n [required]=\"required\"\n [maxlength]=\"component.validate?.maxlength\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed || component.properties?.viewed\"></sd-textarea>\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdTextarea, selector: "sd-textarea", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "rows", "hideInlineError", "required", "disabled", "viewed", "autoHeight", "maxlength", "pattern", "validator", "inlineError", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1416
1415
  }
1417
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TextareaComponent, decorators: [{
1416
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: TextareaComponent, decorators: [{
1418
1417
  type: Component,
1419
1418
  args: [{ selector: 'lib-textarea', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
1420
1419
  CommonModule,
@@ -1492,12 +1491,12 @@ class ChipStringComponent {
1492
1491
  ngOnDestroy() {
1493
1492
  this.#subscription.unsubscribe();
1494
1493
  }
1495
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ChipStringComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1496
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ChipStringComponent, isStandalone: true, selector: "lib-chip-string", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"] }, ngImport: i0, template: "@if (component && entity) {\n @if (viewed || component.properties?.viewed) {\n <div class=\"text-black400\">{{ component.label || component.key }}</div>\n <div class=\"T14M\">{{ entity[component.key!] | componentViewed: entity : component | async }}</div>\n } @else {\n <sd-chip\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [name]=\"component.key\"\n [autoId]=\"component.key\"\n [(model)]=\"entity[component.key!]\"\n [required]=\"required\"\n [disabled]=\"disabled\"></sd-chip>\n }\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdChip, selector: "sd-chip", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "placeholder", "removable", "hideInlineError", "required", "min", "max", "addable", "disabled", "viewed", "hyperlink", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: i1$2.AsyncPipe, name: "async" }, { kind: "pipe", type:
1494
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ChipStringComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1495
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ChipStringComponent, isStandalone: true, selector: "lib-chip-string", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"] }, ngImport: i0, template: "@if (component && entity) {\n @if (viewed || component.properties?.viewed) {\n <div class=\"text-black400\">{{ component.label || component.key }}</div>\n <div class=\"T14M\">{{ entity[component.key!] | componentViewed: entity : component | async }}</div>\n } @else {\n <sd-chip\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [name]=\"component.key\"\n [autoId]=\"component.key\"\n [(model)]=\"entity[component.key!]\"\n [required]=\"required\"\n [disabled]=\"disabled\"></sd-chip>\n }\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdChip, selector: "sd-chip", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "placeholder", "removable", "hideInlineError", "required", "min", "max", "addable", "disabled", "viewed", "hyperlink", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: i1$2.AsyncPipe, name: "async" }, { kind: "pipe", type:
1497
1496
  // Pipe cho phần viewed
1498
1497
  ComponentViewedPipe, name: "componentViewed" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1499
1498
  }
1500
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ChipStringComponent, decorators: [{
1499
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ChipStringComponent, decorators: [{
1501
1500
  type: Component,
1502
1501
  args: [{ selector: 'lib-chip-string', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
1503
1502
  CommonModule,
@@ -1575,12 +1574,12 @@ class ChipCalendarComponent {
1575
1574
  ngOnDestroy() {
1576
1575
  this.#subscription.unsubscribe();
1577
1576
  }
1578
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ChipCalendarComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1579
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ChipCalendarComponent, isStandalone: true, selector: "lib-chip-calendar", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"] }, ngImport: i0, template: "@if (component && entity) {\n @if (viewed || component.properties?.viewed) {\n <div class=\"text-black400\">{{ component.label || component.key }}</div>\n <div class=\"T14M\">{{ entity[component.key!] | componentViewed: entity : component | async }}</div>\n } @else {\n <sd-chip-calendar\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [name]=\"component.key\"\n [autoId]=\"component.key\"\n [(model)]=\"entity[component.key!]\"\n [required]=\"required\"\n [disabled]=\"disabled\"></sd-chip-calendar>\n }\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdChipCalendar, selector: "sd-chip-calendar", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "placeholder", "removable", "hideInlineError", "required", "min", "max", "disabled", "viewed", "hyperlink", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: i1$2.AsyncPipe, name: "async" }, { kind: "pipe", type:
1577
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ChipCalendarComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1578
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ChipCalendarComponent, isStandalone: true, selector: "lib-chip-calendar", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"] }, ngImport: i0, template: "@if (component && entity) {\n @if (viewed || component.properties?.viewed) {\n <div class=\"text-black400\">{{ component.label || component.key }}</div>\n <div class=\"T14M\">{{ entity[component.key!] | componentViewed: entity : component | async }}</div>\n } @else {\n <sd-chip-calendar\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [name]=\"component.key\"\n [autoId]=\"component.key\"\n [(model)]=\"entity[component.key!]\"\n [required]=\"required\"\n [disabled]=\"disabled\"></sd-chip-calendar>\n }\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdChipCalendar, selector: "sd-chip-calendar", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "placeholder", "removable", "hideInlineError", "required", "min", "max", "disabled", "viewed", "hyperlink", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: i1$2.AsyncPipe, name: "async" }, { kind: "pipe", type:
1580
1579
  // Pipe cho phần viewed
1581
1580
  ComponentViewedPipe, name: "componentViewed" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1582
1581
  }
1583
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ChipCalendarComponent, decorators: [{
1582
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ChipCalendarComponent, decorators: [{
1584
1583
  type: Component,
1585
1584
  args: [{ selector: 'lib-chip-calendar', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
1586
1585
  CommonModule,
@@ -1658,12 +1657,12 @@ class NumberComponent {
1658
1657
  ngOnDestroy() {
1659
1658
  this.#subscription.unsubscribe();
1660
1659
  }
1661
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NumberComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1662
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: NumberComponent, isStandalone: true, selector: "lib-number", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"] }, ngImport: i0, template: "@if (component && entity) {\n @if (viewed || component.properties?.viewed) {\n <div class=\"text-secondary\">{{ component.label || component.key }}</div>\n <div class=\"T16M\">{{ entity[component.key!] | componentViewed: entity : component | async }}</div>\n } @else {\n <sd-input-number\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [helperText]=\"component.helperText\"\n [name]=\"component.key\"\n [autoId]=\"component.key\"\n [(model)]=\"entity[component.key!]\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [max]=\"component.validate?.max\"\n [min]=\"component.validate?.min\"\n [viewed]=\"viewed || component.properties?.viewed\"></sd-input-number>\n }\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "pipe", type: i1$2.AsyncPipe, name: "async" }, { kind: "pipe", type:
1660
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: NumberComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1661
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: NumberComponent, isStandalone: true, selector: "lib-number", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"] }, ngImport: i0, template: "@if (component && entity) {\n @if (viewed || component.properties?.viewed) {\n <div class=\"text-secondary\">{{ component.label || component.key }}</div>\n <div class=\"T16M\">{{ entity[component.key!] | componentViewed: entity : component | async }}</div>\n } @else {\n <sd-input-number\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [helperText]=\"component.helperText\"\n [name]=\"component.key\"\n [autoId]=\"component.key\"\n [(model)]=\"entity[component.key!]\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [max]=\"component.validate?.max\"\n [min]=\"component.validate?.min\"\n [viewed]=\"viewed || component.properties?.viewed\"></sd-input-number>\n }\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "pipe", type: i1$2.AsyncPipe, name: "async" }, { kind: "pipe", type:
1663
1662
  // Pipe cho phần viewed
1664
1663
  ComponentViewedPipe, name: "componentViewed" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1665
1664
  }
1666
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NumberComponent, decorators: [{
1665
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: NumberComponent, decorators: [{
1667
1666
  type: Component,
1668
1667
  args: [{ selector: 'lib-number', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
1669
1668
  CommonModule,
@@ -1756,10 +1755,10 @@ class DatetimeComponent {
1756
1755
  this.router.navigate([path], { queryParams });
1757
1756
  }
1758
1757
  };
1759
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: DatetimeComponent, deps: [{ token: i1$3.Router }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1760
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: DatetimeComponent, isStandalone: true, selector: "lib-datetime", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"] }, ngImport: i0, template: "@if (component && entity) {\n @if (subtype === 'date') {\n <sd-date\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [helperText]=\"component.helperText\"\n [name]=\"component.key\"\n [autoId]=\"component.key\"\n [(model)]=\"entity[component.key!]\"\n [required]=\"required\"\n [min]=\"component.validate?.min\"\n [max]=\"component.validate?.max\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed || component.properties?.viewed\"></sd-date>\n } @else {\n <sd-datetime\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [helperText]=\"component.helperText\"\n [name]=\"component.key\"\n [autoId]=\"component.key\"\n [(model)]=\"entity[component.key!]\"\n [required]=\"required\"\n [min]=\"component.validate?.min\"\n [max]=\"component.validate?.max\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed || component.properties?.viewed\"></sd-datetime>\n }\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdDate, selector: "sd-date", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDatetime, selector: "sd-datetime", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "showSeconds", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1758
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: DatetimeComponent, deps: [{ token: i1$3.Router }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1759
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: DatetimeComponent, isStandalone: true, selector: "lib-datetime", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"] }, ngImport: i0, template: "@if (component && entity) {\n @if (subtype === 'date') {\n <sd-date\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [helperText]=\"component.helperText\"\n [name]=\"component.key\"\n [autoId]=\"component.key\"\n [(model)]=\"entity[component.key!]\"\n [required]=\"required\"\n [min]=\"component.validate?.min\"\n [max]=\"component.validate?.max\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed || component.properties?.viewed\"></sd-date>\n } @else {\n <sd-datetime\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [helperText]=\"component.helperText\"\n [name]=\"component.key\"\n [autoId]=\"component.key\"\n [(model)]=\"entity[component.key!]\"\n [required]=\"required\"\n [min]=\"component.validate?.min\"\n [max]=\"component.validate?.max\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed || component.properties?.viewed\"></sd-datetime>\n }\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdDate, selector: "sd-date", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "clearable", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDatetime, selector: "sd-datetime", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "showSeconds", "clearable", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1761
1760
  }
1762
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: DatetimeComponent, decorators: [{
1761
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: DatetimeComponent, decorators: [{
1763
1762
  type: Component,
1764
1763
  args: [{ selector: 'lib-datetime', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
1765
1764
  CommonModule,
@@ -1961,10 +1960,10 @@ class SelectComponent {
1961
1960
  this.router.navigate([path], { queryParams });
1962
1961
  }
1963
1962
  };
1964
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SelectComponent, deps: [{ token: i1$3.Router }, { token: i0.ChangeDetectorRef }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
1965
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: SelectComponent, isStandalone: true, selector: "lib-select", inputs: { setVariables: "setVariables", _form: ["form", "_form"], _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"], _validator: ["validator", "_validator"] }, ngImport: i0, template: "@if (entity && component) {\n <sd-select\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [name]=\"component.key\"\n [autoId]=\"component.key\"\n [(model)]=\"entity[component.key]\"\n [required]=\"required\"\n [validator]=\"validator\"\n [disabled]=\"disabled\"\n [items]=\"items\"\n valueField=\"value\"\n displayField=\"display\"\n disabledField=\"disabled\"\n (sdChange)=\"onChanges()\"\n [multiple]=\"component.properties?.multiple\"\n [viewed]=\"viewed || component.properties?.viewed\"\n [hyperlink]=\"component.properties?.hyperlink | hyperlink: entity\"></sd-select>\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdSelect, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "bare", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "pipe", type: HyperlinkPipe, name: "hyperlink" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1963
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SelectComponent, deps: [{ token: i1$3.Router }, { token: i0.ChangeDetectorRef }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
1964
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: SelectComponent, isStandalone: true, selector: "lib-select", inputs: { setVariables: "setVariables", _form: ["form", "_form"], _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"], _validator: ["validator", "_validator"] }, ngImport: i0, template: "@if (entity && component) {\n <sd-select\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [name]=\"component.key\"\n [autoId]=\"component.key\"\n [(model)]=\"entity[component.key]\"\n [required]=\"required\"\n [validator]=\"validator\"\n [disabled]=\"disabled\"\n [items]=\"items\"\n valueField=\"value\"\n displayField=\"display\"\n disabledField=\"disabled\"\n (sdChange)=\"onChanges()\"\n [multiple]=\"component.properties?.multiple\"\n [viewed]=\"viewed || component.properties?.viewed\"\n [hyperlink]=\"component.properties?.hyperlink | hyperlink: entity\"></sd-select>\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdSelect, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "clearable", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "pipe", type: HyperlinkPipe, name: "hyperlink" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1966
1965
  }
1967
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SelectComponent, decorators: [{
1966
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SelectComponent, decorators: [{
1968
1967
  type: Component,
1969
1968
  args: [{ selector: 'lib-select', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
1970
1969
  CommonModule,
@@ -2095,10 +2094,10 @@ class RadioComponent {
2095
2094
  this.router.navigate([path], { queryParams });
2096
2095
  }
2097
2096
  };
2098
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RadioComponent, deps: [{ token: i1$3.Router }, { token: i0.ChangeDetectorRef }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
2099
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: RadioComponent, isStandalone: true, selector: "lib-radio", inputs: { setVariables: "setVariables", _form: ["form", "_form"], _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"] }, ngImport: i0, template: "@if (entity && component) {\n <sd-radio\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [name]=\"component.key\"\n [autoId]=\"component.key\"\n [(model)]=\"entity[component.key!]\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [items]=\"items\"\n valueField=\"value\"\n displayField=\"display\"\n [display]=\"component.properties?.direction\"\n [viewed]=\"viewed || component.properties?.viewed\"\n [hyperlink]=\"component.properties?.hyperlink | hyperlink: entity\"></sd-radio>\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdRadio, selector: "sd-radio", inputs: ["autoId", "name", "form", "label", "placeholder", "display", "items", "valueField", "displayField", "required", "inlineError", "disabled", "viewed", "color", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "pipe", type: HyperlinkPipe, name: "hyperlink" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2097
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RadioComponent, deps: [{ token: i1$3.Router }, { token: i0.ChangeDetectorRef }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
2098
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: RadioComponent, isStandalone: true, selector: "lib-radio", inputs: { setVariables: "setVariables", _form: ["form", "_form"], _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"] }, ngImport: i0, template: "@if (entity && component) {\n <sd-radio\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [name]=\"component.key\"\n [autoId]=\"component.key\"\n [(model)]=\"entity[component.key!]\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [items]=\"items\"\n valueField=\"value\"\n displayField=\"display\"\n [display]=\"component.properties?.direction\"\n [viewed]=\"viewed || component.properties?.viewed\"\n [hyperlink]=\"component.properties?.hyperlink | hyperlink: entity\"></sd-radio>\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdRadio, selector: "sd-radio", inputs: ["autoId", "name", "form", "label", "placeholder", "display", "items", "valueField", "displayField", "required", "inlineError", "disabled", "viewed", "color", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "pipe", type: HyperlinkPipe, name: "hyperlink" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2100
2099
  }
2101
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RadioComponent, decorators: [{
2100
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RadioComponent, decorators: [{
2102
2101
  type: Component,
2103
2102
  args: [{ selector: 'lib-radio', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
2104
2103
  CommonModule,
@@ -2188,10 +2187,10 @@ class UploadComponent {
2188
2187
  upload = async () => {
2189
2188
  return await this.sdUploadFile?.upload();
2190
2189
  };
2191
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: UploadComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
2192
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: UploadComponent, isStandalone: true, selector: "lib-upload", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"], _validator: ["validator", "_validator"] }, viewQueries: [{ propertyName: "sdUploadFile", first: true, predicate: SdUploadFile, descendants: true }], ngImport: i0, template: "@if (component && entity) {\n @if (viewed || component.properties?.viewed) {\n <div class=\"text-secondary\">{{ component.label || component.key }}</div>\n <sd-upload-file\n [type]=\"component.properties?.type\"\n [form]=\"form\"\n [model]=\"entity[component.key!]\"\n align=\"left\"\n [args]=\"component.properties?.args\"\n disabled\n previewWidth=\"50px\"\n previewHeight=\"50px\"></sd-upload-file>\n } @else {\n <sd-upload-file\n [type]=\"component.properties?.type\"\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [(model)]=\"entity[component.key!]\"\n [max]=\"component.properties?.max\"\n [maxSize]=\"component.properties?.maxSize\"\n [extensions]=\"component.properties?.extensions\"\n [args]=\"component.properties?.args\"\n align=\"left\"\n [required]=\"component.validate?.required || required\"\n [disabled]=\"disabled\"\n previewWidth=\"50px\"\n previewHeight=\"50px\"></sd-upload-file>\n }\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdUploadFile, selector: "sd-upload-file", inputs: ["autoId", "args", "label", "key", "description", "previewWidth", "previewHeight", "align", "upload", "details", "download", "imageValidator", "maxSize", "maxWidth", "maxHeight", "scaleToPixel", "form", "name", "required", "type", "helperText", "max", "maxOfImage", "extensions", "disabled", "model"], outputs: ["loaded", "filesChanged", "modelChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2190
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: UploadComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
2191
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: UploadComponent, isStandalone: true, selector: "lib-upload", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"], _validator: ["validator", "_validator"] }, viewQueries: [{ propertyName: "sdUploadFile", first: true, predicate: SdUploadFile, descendants: true }], ngImport: i0, template: "@if (component && entity) {\n @if (viewed || component.properties?.viewed) {\n <div class=\"text-secondary\">{{ component.label || component.key }}</div>\n <sd-upload-file\n [type]=\"component.properties?.type\"\n [form]=\"form\"\n [model]=\"entity[component.key!]\"\n align=\"left\"\n [args]=\"component.properties?.args\"\n disabled\n previewWidth=\"50px\"\n previewHeight=\"50px\"></sd-upload-file>\n } @else {\n <sd-upload-file\n [type]=\"component.properties?.type\"\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [(model)]=\"entity[component.key!]\"\n [max]=\"component.properties?.max\"\n [maxSize]=\"component.properties?.maxSize\"\n [extensions]=\"component.properties?.extensions\"\n [args]=\"component.properties?.args\"\n align=\"left\"\n [required]=\"component.validate?.required || required\"\n [disabled]=\"disabled\"\n previewWidth=\"50px\"\n previewHeight=\"50px\"></sd-upload-file>\n }\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdUploadFile, selector: "sd-upload-file", inputs: ["autoId", "args", "label", "key", "description", "previewWidth", "previewHeight", "align", "upload", "details", "download", "imageValidator", "maxSize", "maxWidth", "maxHeight", "scaleToPixel", "form", "name", "required", "type", "helperText", "max", "maxOfImage", "extensions", "disabled", "model"], outputs: ["loaded", "filesChanged", "modelChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2193
2192
  }
2194
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: UploadComponent, decorators: [{
2193
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: UploadComponent, decorators: [{
2195
2194
  type: Component,
2196
2195
  args: [{ selector: 'lib-upload', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, SdUploadFile], template: "@if (component && entity) {\n @if (viewed || component.properties?.viewed) {\n <div class=\"text-secondary\">{{ component.label || component.key }}</div>\n <sd-upload-file\n [type]=\"component.properties?.type\"\n [form]=\"form\"\n [model]=\"entity[component.key!]\"\n align=\"left\"\n [args]=\"component.properties?.args\"\n disabled\n previewWidth=\"50px\"\n previewHeight=\"50px\"></sd-upload-file>\n } @else {\n <sd-upload-file\n [type]=\"component.properties?.type\"\n [form]=\"form\"\n [label]=\"component.label || component.key\"\n [(model)]=\"entity[component.key!]\"\n [max]=\"component.properties?.max\"\n [maxSize]=\"component.properties?.maxSize\"\n [extensions]=\"component.properties?.extensions\"\n [args]=\"component.properties?.args\"\n align=\"left\"\n [required]=\"component.validate?.required || required\"\n [disabled]=\"disabled\"\n previewWidth=\"50px\"\n previewHeight=\"50px\"></sd-upload-file>\n }\n}\n", styles: [":host{display:contents;width:100%}\n"] }]
2197
2196
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { setVariables: [{
@@ -2569,12 +2568,12 @@ class TableComponent {
2569
2568
  await Promise.all(this.uploadFiles.map(uploadFile => uploadFile.upload()));
2570
2569
  }
2571
2570
  };
2572
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TableComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
2573
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: TableComponent, isStandalone: true, selector: "lib-table", inputs: { setVariables: "setVariables", form: "form", _component: ["component", "_component"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "table", first: true, predicate: SdTable, descendants: true }, { propertyName: "sideDrawer", first: true, predicate: SdSideDrawer, descendants: true }, { propertyName: "uploadFiles", predicate: SdUploadFile, descendants: true }], ngImport: i0, template: "@if(component && tableOption) {\n <div style=\"width: 100%\">\n <sd-table [option]=\"tableOption\">\n @for(key of imageKeys; track key) {\n <ng-template [sdTableCellDef]=\"key\" let-item=\"item\">\n <sd-upload-file\n type=\"image\"\n [model]=\"item[key]\"\n [args]=\"getArgs(key)\"\n (modelChange)=\"onFileUploadChange(item, key, $event)\"\n align=\"left\"\n disabled\n previewWidth=\"50px\"\n previewHeight=\"50px\"></sd-upload-file>\n </ng-template>\n }\n @for(key of fileKeys; track key) {\n <ng-template [sdTableCellDef]=\"key\" let-item=\"item\">\n <sd-upload-file\n [model]=\"item[key]\"\n [args]=\"getArgs(key)\"\n (modelChange)=\"onFileUploadChange(item, key, $event)\"\n align=\"left\"\n disabled\n previewWidth=\"50px\"\n previewHeight=\"50px\"></sd-upload-file>\n </ng-template>\n }\n </sd-table>\n @if(!viewed && !component.properties?.viewed) {\n <sd-button\n prefixIcon=\"add\"\n color=\"primary\"\n (click)=\"onDetail()\"\n [title]=\"component.properties?.titleButtonCreate || ('core.component.form-builder.add-new' | translate)\"></sd-button>\n }\n @if(!viewed && !component.properties?.viewed) {\n <sd-side-drawer [title]=\"'core.component.form-builder.detail' | translate\" width=\"500px\">\n <div sdTitle>\n <span>{{ 'core.component.form-builder.create-update' | translate }}</span>\n </div>\n <div sdBody class=\"c-table-create-update\">\n @if(!!component.columns?.length) {\n <div class=\"row mx-0\">\n @for(column of component.columns;track column.key) {\n @let validate = formRenderColumn[column.key].validate;\n <div class=\"col-12 px-0 mt-16\">\n @if(column.type === 'string') {\n <sd-input\n [form]=\"form\"\n [label]=\"column.label\"\n [(model)]=\"row[column.key]\"\n [required]=\"validate?.required\"\n [pattern]=\"column.validate?.pattern\"\n [patternErrorMessage]=\"column.validate?.patternErrorMessage\"></sd-input>\n }@else if(column.type === 'number') {\n <sd-input-number\n [form]=\"form\"\n [label]=\"column.label\"\n [(model)]=\"row[column.key]\"\n [required]=\"validate?.required\"\n [min]=\"column.validate?.min\"></sd-input-number>\n }@else if(column.type === 'radio') {\n <sd-radio\n [form]=\"form\"\n [label]=\"column.label\"\n [name]=\"column.key\"\n [items]=\"column.values\"\n valueField=\"value\"\n displayField=\"display\"\n [required]=\"validate?.required\"></sd-radio>\n }@else if(column.type === 'values') {\n <sd-autocomplete\n [form]=\"form\"\n [label]=\"column.label\"\n [(model)]=\"row[column.key]\"\n [items]=\"columnValues[column.key]\"\n valueField=\"value\"\n displayField=\"display\"\n [required]=\"validate?.required\"></sd-autocomplete>\n }@else if(column.type === 'date') {\n <sd-date\n [form]=\"form\"\n [label]=\"column.label\"\n [(model)]=\"row[column.key]\"\n [required]=\"validate?.required\"></sd-date>\n }@else if(column.type === 'datetime') {\n <sd-datetime\n [form]=\"form\"\n [label]=\"column.label\"\n [(model)]=\"row[column.key]\"\n [required]=\"validate?.required\"></sd-datetime>\n }@else if(column.type === 'image') {\n <sd-upload-file\n [label]=\"column.label\"\n type=\"image\"\n [(model)]=\"row[column.key]\"\n [args]=\"column.args\"\n previewWidth=\"50px\"\n previewHeight=\"50px\"\n align=\"left\"></sd-upload-file>\n }@else if (column.type === 'file') {\n <sd-upload-file\n [label]=\"column.label\"\n type=\"file\"\n [(model)]=\"row[column.key]\"\n [args]=\"column.args\"\n previewWidth=\"50px\"\n previewHeight=\"50px\"\n align=\"left\"></sd-upload-file>\n }\n </div>\n }\n </div>\n }\n \n </div>\n <div sdFooter class=\"text-right pr-16\">\n <sd-button [title]=\"'core.component.form-builder.save' | translate\" prefixIcon=\"save\" color=\"primary\" type=\"fill\" (click)=\"onAccept()\"></sd-button>\n </div>\n </sd-side-drawer>\n }\n </div>\n}\n\n", styles: [":host{display:contents}.c-table-create-update{background:#fff;margin:-16px;padding:16px;height:calc(100vh - 97px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdInputNumber$1, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdAutocomplete, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdUploadFile, selector: "sd-upload-file", inputs: ["autoId", "args", "label", "key", "description", "previewWidth", "previewHeight", "align", "upload", "details", "download", "imageValidator", "maxSize", "maxWidth", "maxHeight", "scaleToPixel", "form", "name", "required", "type", "helperText", "max", "maxOfImage", "extensions", "disabled", "model"], outputs: ["loaded", "filesChanged", "modelChange"] }, { kind: "component", type: SdTable, selector: "sd-table", inputs: ["autoId", "option"] }, { kind: "directive", type: SdTableCellDefDirective, selector: "[sdTableCellDef]", inputs: ["sdTableCellDef"] }, { kind: "component", type: SdSideDrawer, selector: "sd-side-drawer", inputs: ["title", "width", "hideClose", "disableBackdropClose", "drawerClass", "autoId"], outputs: ["sdClosed"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdRadio, selector: "sd-radio", inputs: ["autoId", "name", "form", "label", "placeholder", "display", "items", "valueField", "displayField", "required", "inlineError", "disabled", "viewed", "color", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdDate, selector: "sd-date", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDatetime, selector: "sd-datetime", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "showSeconds", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "pipe", type:
2571
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: TableComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
2572
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: TableComponent, isStandalone: true, selector: "lib-table", inputs: { setVariables: "setVariables", form: "form", _component: ["component", "_component"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "table", first: true, predicate: SdTable, descendants: true }, { propertyName: "sideDrawer", first: true, predicate: SdSideDrawer, descendants: true }, { propertyName: "uploadFiles", predicate: SdUploadFile, descendants: true }], ngImport: i0, template: "@if(component && tableOption) {\n <div style=\"width: 100%\">\n <sd-table [option]=\"tableOption\">\n @for(key of imageKeys; track key) {\n <ng-template [sdTableCellDef]=\"key\" let-item=\"item\">\n <sd-upload-file\n type=\"image\"\n [model]=\"item[key]\"\n [args]=\"getArgs(key)\"\n (modelChange)=\"onFileUploadChange(item, key, $event)\"\n align=\"left\"\n disabled\n previewWidth=\"50px\"\n previewHeight=\"50px\"></sd-upload-file>\n </ng-template>\n }\n @for(key of fileKeys; track key) {\n <ng-template [sdTableCellDef]=\"key\" let-item=\"item\">\n <sd-upload-file\n [model]=\"item[key]\"\n [args]=\"getArgs(key)\"\n (modelChange)=\"onFileUploadChange(item, key, $event)\"\n align=\"left\"\n disabled\n previewWidth=\"50px\"\n previewHeight=\"50px\"></sd-upload-file>\n </ng-template>\n }\n </sd-table>\n @if(!viewed && !component.properties?.viewed) {\n <sd-button\n prefixIcon=\"add\"\n color=\"primary\"\n (click)=\"onDetail()\"\n [title]=\"component.properties?.titleButtonCreate || ('core.component.form-builder.add-new' | translate)\"></sd-button>\n }\n @if(!viewed && !component.properties?.viewed) {\n <sd-side-drawer [title]=\"'core.component.form-builder.detail' | translate\" width=\"500px\">\n <div sdTitle>\n <span>{{ 'core.component.form-builder.create-update' | translate }}</span>\n </div>\n <div sdBody class=\"c-table-create-update\">\n @if(!!component.columns?.length) {\n <div class=\"row mx-0\">\n @for(column of component.columns;track column.key) {\n @let validate = formRenderColumn[column.key].validate;\n <div class=\"col-12 px-0 mt-16\">\n @if(column.type === 'string') {\n <sd-input\n [form]=\"form\"\n [label]=\"column.label\"\n [(model)]=\"row[column.key]\"\n [required]=\"validate?.required\"\n [pattern]=\"column.validate?.pattern\"\n [patternErrorMessage]=\"column.validate?.patternErrorMessage\"></sd-input>\n }@else if(column.type === 'number') {\n <sd-input-number\n [form]=\"form\"\n [label]=\"column.label\"\n [(model)]=\"row[column.key]\"\n [required]=\"validate?.required\"\n [min]=\"column.validate?.min\"></sd-input-number>\n }@else if(column.type === 'radio') {\n <sd-radio\n [form]=\"form\"\n [label]=\"column.label\"\n [name]=\"column.key\"\n [items]=\"column.values\"\n valueField=\"value\"\n displayField=\"display\"\n [required]=\"validate?.required\"></sd-radio>\n }@else if(column.type === 'values') {\n <sd-autocomplete\n [form]=\"form\"\n [label]=\"column.label\"\n [(model)]=\"row[column.key]\"\n [items]=\"columnValues[column.key]\"\n valueField=\"value\"\n displayField=\"display\"\n [required]=\"validate?.required\"></sd-autocomplete>\n }@else if(column.type === 'date') {\n <sd-date\n [form]=\"form\"\n [label]=\"column.label\"\n [(model)]=\"row[column.key]\"\n [required]=\"validate?.required\"></sd-date>\n }@else if(column.type === 'datetime') {\n <sd-datetime\n [form]=\"form\"\n [label]=\"column.label\"\n [(model)]=\"row[column.key]\"\n [required]=\"validate?.required\"></sd-datetime>\n }@else if(column.type === 'image') {\n <sd-upload-file\n [label]=\"column.label\"\n type=\"image\"\n [(model)]=\"row[column.key]\"\n [args]=\"column.args\"\n previewWidth=\"50px\"\n previewHeight=\"50px\"\n align=\"left\"></sd-upload-file>\n }@else if (column.type === 'file') {\n <sd-upload-file\n [label]=\"column.label\"\n type=\"file\"\n [(model)]=\"row[column.key]\"\n [args]=\"column.args\"\n previewWidth=\"50px\"\n previewHeight=\"50px\"\n align=\"left\"></sd-upload-file>\n }\n </div>\n }\n </div>\n }\n \n </div>\n <div sdFooter class=\"text-right pr-16\">\n <sd-button [title]=\"'core.component.form-builder.save' | translate\" prefixIcon=\"save\" color=\"primary\" type=\"fill\" (click)=\"onAccept()\"></sd-button>\n </div>\n </sd-side-drawer>\n }\n </div>\n}\n\n", styles: [":host{display:contents}.c-table-create-update{background:#fff;margin:-16px;padding:16px;height:calc(100vh - 97px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdInputNumber$1, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdAutocomplete, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "clearable", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdUploadFile, selector: "sd-upload-file", inputs: ["autoId", "args", "label", "key", "description", "previewWidth", "previewHeight", "align", "upload", "details", "download", "imageValidator", "maxSize", "maxWidth", "maxHeight", "scaleToPixel", "form", "name", "required", "type", "helperText", "max", "maxOfImage", "extensions", "disabled", "model"], outputs: ["loaded", "filesChanged", "modelChange"] }, { kind: "component", type: SdTable, selector: "sd-table", inputs: ["autoId", "option"] }, { kind: "directive", type: SdTableCellDefDirective, selector: "[sdTableCellDef]", inputs: ["sdTableCellDef"] }, { kind: "component", type: SdSideDrawer, selector: "sd-side-drawer", inputs: ["title", "width", "hideClose", "disableBackdropClose", "drawerClass", "autoId"], outputs: ["sdClosed"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdRadio, selector: "sd-radio", inputs: ["autoId", "name", "form", "label", "placeholder", "display", "items", "valueField", "displayField", "required", "inlineError", "disabled", "viewed", "color", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdDate, selector: "sd-date", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "clearable", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDatetime, selector: "sd-datetime", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "showSeconds", "clearable", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "pipe", type:
2574
2573
  // Pipe cho phần viewed
2575
2574
  TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2576
2575
  }
2577
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TableComponent, decorators: [{
2576
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: TableComponent, decorators: [{
2578
2577
  type: Component,
2579
2578
  args: [{ selector: 'lib-table', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
2580
2579
  CommonModule,
@@ -2753,10 +2752,10 @@ class HtmlComponent {
2753
2752
  ngOnDestroy() {
2754
2753
  this.#subscription.unsubscribe();
2755
2754
  }
2756
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HtmlComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
2757
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: HtmlComponent, isStandalone: true, selector: "lib-html", inputs: { setVariables: "setVariables", _form: ["form", "_form"], _entity: ["entity", "_entity"], _hashedValues: ["hashedValues", "_hashedValues"], _component: ["component", "_component"], _viewed: ["viewed", "_viewed"] }, ngImport: i0, template: "@if (component && entity) {\n <div [innerHTML]=\"entity[key] | htmlPipe: entity[key] : component\"></div>\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "pipe", type: HtmlPipe, name: "htmlPipe" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2755
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: HtmlComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
2756
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: HtmlComponent, isStandalone: true, selector: "lib-html", inputs: { setVariables: "setVariables", _form: ["form", "_form"], _entity: ["entity", "_entity"], _hashedValues: ["hashedValues", "_hashedValues"], _component: ["component", "_component"], _viewed: ["viewed", "_viewed"] }, ngImport: i0, template: "@if (component && entity) {\n <div [innerHTML]=\"entity[key] | htmlPipe: entity[key] : component\"></div>\n}\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "pipe", type: HtmlPipe, name: "htmlPipe" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2758
2757
  }
2759
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HtmlComponent, decorators: [{
2758
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: HtmlComponent, decorators: [{
2760
2759
  type: Component,
2761
2760
  args: [{ selector: 'lib-html', changeDetection: ChangeDetectionStrategy.OnPush, imports: [HtmlPipe], template: "@if (component && entity) {\n <div [innerHTML]=\"entity[key] | htmlPipe: entity[key] : component\"></div>\n}\n", styles: [":host{display:contents;width:100%}\n"] }]
2762
2761
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: FormGenericService }], propDecorators: { setVariables: [{
@@ -2823,10 +2822,10 @@ class LibItemComponent {
2823
2822
  await this.itemUpload?.upload?.();
2824
2823
  await this.itemTable?.upload?.();
2825
2824
  };
2826
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: LibItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2827
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: LibItemComponent, isStandalone: true, selector: "lib-item", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"], _validator: ["validator", "_validator"] }, viewQueries: [{ propertyName: "itemUpload", first: true, predicate: UploadComponent, descendants: true }, { propertyName: "itemTable", first: true, predicate: TableComponent, descendants: true }], ngImport: i0, template: "@if (entity && component) {\n @if (component.type === 'textfield') {\n <div [class]=\"col\">\n <lib-textfield\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [entity]=\"entity\"\n [component]=\"component\"\n [validator]=\"validator\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed\"></lib-textfield>\n </div>\n } @else if (component.type === 'textarea') {\n <div [class]=\"col\">\n <lib-textarea\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [entity]=\"entity\"\n [component]=\"component\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed\"></lib-textarea>\n </div>\n } @else if (component.type === 'chip-string') {\n <div [class]=\"col\">\n <lib-chip-string\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [entity]=\"entity\"\n [component]=\"component\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed\"></lib-chip-string>\n </div>\n } @else if (component.type === 'chip-calendar') {\n <div [class]=\"col\">\n <lib-chip-calendar\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [entity]=\"entity\"\n [component]=\"component\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed\"></lib-chip-calendar>\n </div>\n } @else if (component.type === 'number') {\n <div [class]=\"col\">\n <lib-number\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [entity]=\"entity\"\n [component]=\"component\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed\"></lib-number>\n </div>\n }\n @if (component.type === 'select') {\n <div [class]=\"col\">\n <lib-select\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [component]=\"component\"\n [entity]=\"entity\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [validator]=\"validator\"\n [viewed]=\"viewed\"></lib-select>\n </div>\n } @else if (component.type === 'radio') {\n <div [class]=\"col\">\n <lib-radio\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [component]=\"component\"\n [entity]=\"entity\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed\"></lib-radio>\n </div>\n } @else if (component.type === 'datetime') {\n <div [class]=\"col\">\n <lib-datetime\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [entity]=\"entity\"\n [component]=\"component\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed\"></lib-datetime>\n </div>\n } @else if (component.type === 'upload') {\n <div [class]=\"col\">\n <lib-upload\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [component]=\"component\"\n [entity]=\"entity\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [validator]=\"validator\"\n [viewed]=\"viewed\">\n </lib-upload>\n </div>\n } @else if (component.type === 'table') {\n <div [class]=\"col\">\n <lib-table [setVariables]=\"setVariables\" [component]=\"component\" [(model)]=\"entity[component.key!]\" [viewed]=\"viewed\"></lib-table>\n </div>\n } @else if (component.type === 'html') {\n <div [class]=\"col\">\n <lib-html [setVariables]=\"setVariables\" [form]=\"form\" [entity]=\"entity\" [component]=\"component\" [viewed]=\"viewed\"> </lib-html>\n </div>\n } @else if (component.type === 'break') {\n <!-- Break: empty 12-col placeholder \u00E9p xu\u1ED1ng d\u00F2ng. Kh\u00F4ng render g\u00EC runtime. -->\n <div class=\"col-12\" style=\"height: 0;\"></div>\n }\n}\n", styles: [":host{display:contents}\n"], dependencies: [{ kind: "component", type: TextfieldComponent, selector: "lib-textfield", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed", "validator"] }, { kind: "component", type: TextareaComponent, selector: "lib-textarea", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: ChipStringComponent, selector: "lib-chip-string", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: ChipCalendarComponent, selector: "lib-chip-calendar", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: NumberComponent, selector: "lib-number", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: DatetimeComponent, selector: "lib-datetime", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: SelectComponent, selector: "lib-select", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed", "validator"] }, { kind: "component", type: RadioComponent, selector: "lib-radio", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: TableComponent, selector: "lib-table", inputs: ["setVariables", "form", "component", "required", "viewed", "model"], outputs: ["modelChange"] }, { kind: "component", type: UploadComponent, selector: "lib-upload", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed", "validator"] }, { kind: "component", type: HtmlComponent, selector: "lib-html", inputs: ["setVariables", "form", "entity", "hashedValues", "component", "viewed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2825
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: LibItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2826
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: LibItemComponent, isStandalone: true, selector: "lib-item", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"], _validator: ["validator", "_validator"] }, viewQueries: [{ propertyName: "itemUpload", first: true, predicate: UploadComponent, descendants: true }, { propertyName: "itemTable", first: true, predicate: TableComponent, descendants: true }], ngImport: i0, template: "@if (entity && component) {\n @if (component.type === 'textfield') {\n <div [class]=\"col\">\n <lib-textfield\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [entity]=\"entity\"\n [component]=\"component\"\n [validator]=\"validator\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed\"></lib-textfield>\n </div>\n } @else if (component.type === 'textarea') {\n <div [class]=\"col\">\n <lib-textarea\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [entity]=\"entity\"\n [component]=\"component\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed\"></lib-textarea>\n </div>\n } @else if (component.type === 'chip-string') {\n <div [class]=\"col\">\n <lib-chip-string\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [entity]=\"entity\"\n [component]=\"component\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed\"></lib-chip-string>\n </div>\n } @else if (component.type === 'chip-calendar') {\n <div [class]=\"col\">\n <lib-chip-calendar\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [entity]=\"entity\"\n [component]=\"component\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed\"></lib-chip-calendar>\n </div>\n } @else if (component.type === 'number') {\n <div [class]=\"col\">\n <lib-number\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [entity]=\"entity\"\n [component]=\"component\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed\"></lib-number>\n </div>\n }\n @if (component.type === 'select') {\n <div [class]=\"col\">\n <lib-select\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [component]=\"component\"\n [entity]=\"entity\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [validator]=\"validator\"\n [viewed]=\"viewed\"></lib-select>\n </div>\n } @else if (component.type === 'radio') {\n <div [class]=\"col\">\n <lib-radio\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [component]=\"component\"\n [entity]=\"entity\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed\"></lib-radio>\n </div>\n } @else if (component.type === 'datetime') {\n <div [class]=\"col\">\n <lib-datetime\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [entity]=\"entity\"\n [component]=\"component\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [viewed]=\"viewed\"></lib-datetime>\n </div>\n } @else if (component.type === 'upload') {\n <div [class]=\"col\">\n <lib-upload\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [component]=\"component\"\n [entity]=\"entity\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [validator]=\"validator\"\n [viewed]=\"viewed\">\n </lib-upload>\n </div>\n } @else if (component.type === 'table') {\n <div [class]=\"col\">\n <lib-table [setVariables]=\"setVariables\" [component]=\"component\" [(model)]=\"entity[component.key!]\" [viewed]=\"viewed\"></lib-table>\n </div>\n } @else if (component.type === 'html') {\n <div [class]=\"col\">\n <lib-html [setVariables]=\"setVariables\" [form]=\"form\" [entity]=\"entity\" [component]=\"component\" [viewed]=\"viewed\"> </lib-html>\n </div>\n } @else if (component.type === 'break') {\n <!-- Break: empty 12-col placeholder \u00E9p xu\u1ED1ng d\u00F2ng. Kh\u00F4ng render g\u00EC runtime. -->\n <div class=\"col-12\" style=\"height: 0;\"></div>\n }\n}\n", styles: [":host{display:contents}\n"], dependencies: [{ kind: "component", type: TextfieldComponent, selector: "lib-textfield", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed", "validator"] }, { kind: "component", type: TextareaComponent, selector: "lib-textarea", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: ChipStringComponent, selector: "lib-chip-string", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: ChipCalendarComponent, selector: "lib-chip-calendar", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: NumberComponent, selector: "lib-number", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: DatetimeComponent, selector: "lib-datetime", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: SelectComponent, selector: "lib-select", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed", "validator"] }, { kind: "component", type: RadioComponent, selector: "lib-radio", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: TableComponent, selector: "lib-table", inputs: ["setVariables", "form", "component", "required", "viewed", "model"], outputs: ["modelChange"] }, { kind: "component", type: UploadComponent, selector: "lib-upload", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed", "validator"] }, { kind: "component", type: HtmlComponent, selector: "lib-html", inputs: ["setVariables", "form", "entity", "hashedValues", "component", "viewed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2828
2827
  }
2829
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: LibItemComponent, decorators: [{
2828
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: LibItemComponent, decorators: [{
2830
2829
  type: Component,
2831
2830
  args: [{ selector: 'lib-item', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
2832
2831
  TextfieldComponent,
@@ -2914,10 +2913,10 @@ class VariableComponent {
2914
2913
  ngOnDestroy() {
2915
2914
  this.#subscription.unsubscribe();
2916
2915
  }
2917
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: VariableComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
2918
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.15", type: VariableComponent, isStandalone: true, selector: "variable", inputs: { variables: "variables", setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"] }, ngImport: i0, template: "", changeDetection: i0.ChangeDetectionStrategy.OnPush });
2916
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: VariableComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
2917
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: VariableComponent, isStandalone: true, selector: "variable", inputs: { variables: "variables", setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"] }, ngImport: i0, template: "", changeDetection: i0.ChangeDetectionStrategy.OnPush });
2919
2918
  }
2920
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: VariableComponent, decorators: [{
2919
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: VariableComponent, decorators: [{
2921
2920
  type: Component,
2922
2921
  args: [{ selector: 'variable', changeDetection: ChangeDetectionStrategy.OnPush, template: "" }]
2923
2922
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { variables: [{
@@ -2938,7 +2937,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
2938
2937
 
2939
2938
  /* eslint-disable @typescript-eslint/no-explicit-any */
2940
2939
  /* eslint-disable @angular-eslint/no-input-rename */
2941
- class SdFormRender extends SdBaseSecureComponent {
2940
+ class SdFormRender {
2942
2941
  ref;
2943
2942
  formGenericConfiguration;
2944
2943
  formRenderItems = new QueryList();
@@ -2979,7 +2978,6 @@ class SdFormRender extends SdBaseSecureComponent {
2979
2978
  // Các component item của form-render sẽ lắng nghe thay đổi
2980
2979
  setVariables = new Subject();
2981
2980
  constructor(ref, formGenericConfiguration) {
2982
- super();
2983
2981
  this.ref = ref;
2984
2982
  this.formGenericConfiguration = formGenericConfiguration;
2985
2983
  }
@@ -3064,10 +3062,10 @@ class SdFormRender extends SdBaseSecureComponent {
3064
3062
  }
3065
3063
  return messages;
3066
3064
  };
3067
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdFormRender, deps: [{ token: i0.ChangeDetectorRef }, { token: SD_FORM_GENERIC_CONFIGURATION, optional: true }], target: i0.ɵɵFactoryTarget.Component });
3068
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: SdFormRender, isStandalone: true, selector: "sd-form-render", inputs: { form: "form", _configuration: ["configuration", "_configuration"], _default: ["defaultEntity", "_default"], _entity: ["entity", "_entity"], _properties: ["properties", "_properties"], _viewed: ["viewed", "_viewed"] }, viewQueries: [{ propertyName: "formRenderItems", predicate: LibItemComponent, descendants: true }], usesInheritance: true, ngImport: i0, template: "@if (form && loadCompleted && hashedValues) {\n <div class=\"row mx-0\">\n @for (component of configuration.components; track component.id) {\n @let expression = hashedValues | whenExpression: component : formValue;\n @if (!expression.hidden) {\n @if (component.type === 'group') {\n @if (!!component.components.length) {\n <div class=\"col-12 mt-16\">\n <sd-section [title]=\"component.label\" [icon]=\"component.properties.icon\">\n <div class=\"row mx-0\">\n @for (childComponent of component.components; track childComponent.id) {\n @let childExpression = hashedValues | whenExpression: childComponent : formValue;\n @if (!childExpression.hidden) {\n <lib-item\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [entity]=\"entity\"\n [component]=\"childComponent\"\n [required]=\"childExpression.required\"\n [disabled]=\"childExpression.disabled\"\n [viewed]=\"viewed\"></lib-item>\n }\n }\n </div>\n </sd-section>\n </div>\n }\n } @else {\n <lib-item\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [entity]=\"entity\"\n [component]=\"component\"\n [required]=\"expression.required\"\n [disabled]=\"expression.disabled\"\n [viewed]=\"viewed\"></lib-item>\n }\n }\n }\n <variable [variables]=\"configuration.variables\" [setVariables]=\"setVariables\" [form]=\"form\" [entity]=\"entity\" ></variable>\n </div>\n}\n", styles: [":host{display:contents}\n"], dependencies: [{ kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: LibItemComponent, selector: "lib-item", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed", "validator"] }, { kind: "component", type: VariableComponent, selector: "variable", inputs: ["variables", "setVariables", "form", "entity"] }, { kind: "pipe", type: WhenExpressionPipe, name: "whenExpression" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3065
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SdFormRender, deps: [{ token: i0.ChangeDetectorRef }, { token: SD_FORM_GENERIC_CONFIGURATION, optional: true }], target: i0.ɵɵFactoryTarget.Component });
3066
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: SdFormRender, isStandalone: true, selector: "sd-form-render", inputs: { form: "form", _configuration: ["configuration", "_configuration"], _default: ["defaultEntity", "_default"], _entity: ["entity", "_entity"], _properties: ["properties", "_properties"], _viewed: ["viewed", "_viewed"] }, viewQueries: [{ propertyName: "formRenderItems", predicate: LibItemComponent, descendants: true }], ngImport: i0, template: "@if (form && loadCompleted && hashedValues) {\n <div class=\"row mx-0\">\n @for (component of configuration.components; track component.id) {\n @let expression = hashedValues | whenExpression: component : formValue;\n @if (!expression.hidden) {\n @if (component.type === 'group') {\n @if (!!component.components.length) {\n <div class=\"col-12 mt-16\">\n <sd-section [title]=\"component.label\" [icon]=\"component.properties.icon\">\n <div class=\"row mx-0\">\n @for (childComponent of component.components; track childComponent.id) {\n @let childExpression = hashedValues | whenExpression: childComponent : formValue;\n @if (!childExpression.hidden) {\n <lib-item\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [entity]=\"entity\"\n [component]=\"childComponent\"\n [required]=\"childExpression.required\"\n [disabled]=\"childExpression.disabled\"\n [viewed]=\"viewed\"></lib-item>\n }\n }\n </div>\n </sd-section>\n </div>\n }\n } @else {\n <lib-item\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [entity]=\"entity\"\n [component]=\"component\"\n [required]=\"expression.required\"\n [disabled]=\"expression.disabled\"\n [viewed]=\"viewed\"></lib-item>\n }\n }\n }\n <variable [variables]=\"configuration.variables\" [setVariables]=\"setVariables\" [form]=\"form\" [entity]=\"entity\" ></variable>\n </div>\n}\n", styles: [":host{display:contents}\n"], dependencies: [{ kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: LibItemComponent, selector: "lib-item", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed", "validator"] }, { kind: "component", type: VariableComponent, selector: "variable", inputs: ["variables", "setVariables", "form", "entity"] }, { kind: "pipe", type: WhenExpressionPipe, name: "whenExpression" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3069
3067
  }
3070
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdFormRender, decorators: [{
3068
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SdFormRender, decorators: [{
3071
3069
  type: Component,
3072
3070
  args: [{ selector: 'sd-form-render', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdSection, LibItemComponent, WhenExpressionPipe, VariableComponent], template: "@if (form && loadCompleted && hashedValues) {\n <div class=\"row mx-0\">\n @for (component of configuration.components; track component.id) {\n @let expression = hashedValues | whenExpression: component : formValue;\n @if (!expression.hidden) {\n @if (component.type === 'group') {\n @if (!!component.components.length) {\n <div class=\"col-12 mt-16\">\n <sd-section [title]=\"component.label\" [icon]=\"component.properties.icon\">\n <div class=\"row mx-0\">\n @for (childComponent of component.components; track childComponent.id) {\n @let childExpression = hashedValues | whenExpression: childComponent : formValue;\n @if (!childExpression.hidden) {\n <lib-item\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [entity]=\"entity\"\n [component]=\"childComponent\"\n [required]=\"childExpression.required\"\n [disabled]=\"childExpression.disabled\"\n [viewed]=\"viewed\"></lib-item>\n }\n }\n </div>\n </sd-section>\n </div>\n }\n } @else {\n <lib-item\n [setVariables]=\"setVariables\"\n [form]=\"form\"\n [entity]=\"entity\"\n [component]=\"component\"\n [required]=\"expression.required\"\n [disabled]=\"expression.disabled\"\n [viewed]=\"viewed\"></lib-item>\n }\n }\n }\n <variable [variables]=\"configuration.variables\" [setVariables]=\"setVariables\" [form]=\"form\" [entity]=\"entity\" ></variable>\n </div>\n}\n", styles: [":host{display:contents}\n"] }]
3073
3071
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
@@ -3219,10 +3217,10 @@ class ExpressionBuilderComponent {
3219
3217
  condition.value = DateUtilities$1.toFormat(condition.value, 'yyyy/MM/dd HH:mm:00');
3220
3218
  }
3221
3219
  };
3222
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ExpressionBuilderComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
3223
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ExpressionBuilderComponent, isStandalone: true, selector: "expression-builder", inputs: { label: "label", _attributes: ["attributes", "_attributes"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange", sdChange: "sdChange", edit: "edit" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<!--\n FEEL-style expression trigger pill (M3 redesign).\n B\u1EA5m v\u00E0o pill m\u1EDF modal builder hi\u1EC7n t\u1EA1i (onEdit).\n-->\n<div class=\"fb-field\">\n @if (label) {\n <div class=\"fb-field__label\">{{ label }}</div>\n }\n @let exprText = model | expressionQuery;\n <div class=\"fb-expr\" (click)=\"onEdit()\" role=\"button\" tabindex=\"0\">\n <span class=\"fb-expr__badge\">FEEL</span>\n @if (exprText) {\n <span class=\"fb-expr__code mono\">{{ exprText }}</span>\n } @else {\n <span class=\"empty\">{{ 'core.component.form-builder.set-expression' | translate }}</span>\n }\n <button type=\"button\" class=\"fb-icon-btn\" (click)=\"onEdit(); $event.stopPropagation()\" aria-label=\"edit expression\">\n <span class=\"msi\">functions</span>\n </button>\n </div>\n</div>\n@if (expression) {\n <sd-modal [title]=\"'core.component.form-builder.set-expression' | translate\">\n <div class=\"c-builder\">\n <div class=\"d-flex justify-content-end\">\n <sd-button\n prefixIcon=\"calculate\"\n class=\"mr-4\"\n [title]=\"'core.component.form-builder.condition-group' | translate\"\n color=\"primary\"\n (click)=\"addCombinator(expression.conditions)\"></sd-button>\n <sd-button\n prefixIcon=\"add\"\n [title]=\"'core.component.form-builder.condition' | translate\"\n color=\"primary\"\n (click)=\"addCondition(expression.conditions)\"\n type=\"fill\"></sd-button>\n </div>\n <!-- C\u1EA5p 1 -->\n @for (conditionLv1 of expression.conditions; track conditionLv1.key; let idxLv1 = $index) {\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px\">\n <div class=\"c-condition\">\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\n @if (idxLv1 === 0) {\n <div class=\"c-where\">WHERE</div>\n }\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\n @if (idxLv1 === 1) {\n <div class=\"c-select\">\n <sd-select\n size=\"sm\"\n [(model)]=\"expression.combinator\"\n [items]=\"[\n { value: '&&', display: 'AND' },\n { value: '||', display: 'OR' }\n ]\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError=\"\"></sd-select>\n </div>\n }\n </div>\n @if (conditionLv1.type === 'condition') {\n <sd-autocomplete\n size=\"sm\"\n [form]=\"form\"\n style=\"width: 200px\"\n [(model)]=\"conditionLv1.field\"\n [items]=\"attributes\"\n (sdChange)=\"onChangeAttribute(conditionLv1)\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-autocomplete>\n @let fieldAttribute = attribute[conditionLv1.field!];\n <sd-select\n size=\"sm\"\n [form]=\"form\"\n style=\"width: 100px\"\n [(model)]=\"conditionLv1.operator\"\n [items]=\"attributeOperators[fieldAttribute?.type || 'string']\"\n valueField=\"value\"\n displayField=\"display\"\n [disabled]=\"!fieldAttribute?.type\"\n required\n hideInlineError></sd-select>\n @if (\n !!fieldAttribute?.type && conditionLv1.operator && conditionLv1.operator !== 'NULL' && conditionLv1.operator !== 'NOT_NULL'\n ) {\n @if (fieldAttribute.type === 'string') {\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input>\n } @else if (fieldAttribute.type === 'number') {\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"conditionLv1.value\" hideInlineError></sd-input-number>\n <sd-autocomplete\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv1.value\"\n [items]=\"numberAttributes\"\n valueField=\"value\"\n displayField=\"display\"\n hideInlineError></sd-autocomplete>\n } @else if (fieldAttribute.type === 'datetime' && conditionLv1.dayInfo) {\n <sd-select\n size=\"sm\"\n [placeholder]=\"'core.component.form-builder.time' | translate\"\n [form]=\"form\"\n style=\"width: 150px\"\n [items]=\"types\"\n valueField=\"value\"\n displayField=\"display\"\n [(model)]=\"conditionLv1.dayInfo.type\"\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\n required\n hideInlineError>\n </sd-select>\n @if (conditionLv1.dayInfo.type === 'RELATED') {\n <sd-input-number\n size=\"sm\"\n [form]=\"form\"\n style=\"width: 80px\"\n [(model)]=\"conditionLv1.dayInfo.relatedValue\"\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\n [min]=\"1\"\n required\n hideInlineError>\n </sd-input-number>\n <sd-select\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [items]=\"previouses\"\n valueField=\"value\"\n displayField=\"display\"\n [(model)]=\"conditionLv1.dayInfo.related\"\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\n required\n hideInlineError>\n </sd-select>\n } @else if (conditionLv1.dayInfo.type === 'DATETIME') {\n <sd-datetime\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv1.value\"\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\n required\n hideInlineError>\n </sd-datetime>\n } @else if (conditionLv1.dayInfo.type === 'ATTRIBUTE') {\n <sd-autocomplete\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv1.value\"\n [items]=\"dateAttributes\"\n valueField=\"value\"\n displayField=\"display\"\n hideInlineError></sd-autocomplete>\n }\n } @else if (fieldAttribute.type === 'boolean') {\n <sd-select\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv1.value\"\n [items]=\"[\n { value: true, display: fieldAttribute.displayOnTrue },\n { value: false, display: fieldAttribute.displayOnFalse }\n ]\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-select>\n } @else if (fieldAttribute.type === 'values') {\n <sd-autocomplete\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv1.value\"\n [items]=\"fieldAttribute.values\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-autocomplete>\n }\n }\n <sd-button class=\"ml-auto\" prefixIcon=\"delete\" [tooltip]=\"'core.component.form-builder.delete' | translate\" (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\n } @else if (conditionLv1.type === 'combinator') {\n <div class=\"c-builder\">\n <div class=\"d-flex justify-content-end\">\n <sd-button class=\"mr-4\" prefixIcon=\"delete\" [tooltip]=\"'core.component.form-builder.delete' | translate\" (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\n <sd-button\n prefixIcon=\"add\"\n [title]=\"'core.component.form-builder.condition' | translate\"\n size=\"sm\"\n color=\"primary\"\n (click)=\"addCondition(conditionLv1.conditions)\"\n type=\"fill\"></sd-button>\n </div>\n <!-- C\u1EA5p 2 -->\n @for (conditionLv2 of conditionLv1.conditions; track conditionLv2.key; let idxLv2 = $index) {\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px\">\n <div class=\"c-condition\">\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\n @if (idxLv2 === 0) {\n <div class=\"c-where\">WHERE</div>\n }\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\n @if (idxLv2 === 1) {\n <div class=\"c-select\">\n <sd-select\n size=\"sm\"\n [(model)]=\"conditionLv1.combinator\"\n [items]=\"[\n { value: '&&', display: 'AND' },\n { value: '||', display: 'OR' }\n ]\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError=\"\"></sd-select>\n </div>\n }\n </div>\n @if (conditionLv2.type === 'condition') {\n <sd-autocomplete\n size=\"sm\"\n [form]=\"form\"\n style=\"width: 200px\"\n [(model)]=\"conditionLv2.field\"\n [items]=\"attributes\"\n (sdChange)=\"onChangeAttribute(conditionLv2)\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-autocomplete>\n @let fieldAttribute = attribute[conditionLv2.field!];\n <sd-select\n size=\"sm\"\n [form]=\"form\"\n style=\"width: 100px\"\n [(model)]=\"conditionLv2.operator\"\n [items]=\"attributeOperators[fieldAttribute?.type || 'string']\"\n valueField=\"value\"\n displayField=\"display\"\n [disabled]=\"!fieldAttribute?.type\"\n required\n hideInlineError></sd-select>\n @if (\n !!fieldAttribute?.type &&\n conditionLv2.operator &&\n conditionLv2.operator !== 'NULL' &&\n conditionLv2.operator !== 'NOT_NULL'\n ) {\n @if (fieldAttribute.type === 'string') {\n <sd-input\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv2.value\"\n required\n hideInlineError></sd-input>\n } @else if (fieldAttribute.type === 'number') {\n <sd-input-number\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv2.value\"\n hideInlineError></sd-input-number>\n <sd-autocomplete\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv2.value\"\n [items]=\"numberAttributes\"\n valueField=\"value\"\n displayField=\"display\"\n hideInlineError></sd-autocomplete>\n } @else if (fieldAttribute.type === 'datetime' && conditionLv2.dayInfo) {\n <sd-select\n size=\"sm\"\n [form]=\"form\"\n [placeholder]=\"'core.component.form-builder.time' | translate\"\n style=\"width: 150px\"\n [items]=\"types\"\n valueField=\"value\"\n displayField=\"display\"\n [(model)]=\"conditionLv2.dayInfo.type\"\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\n required\n hideInlineError>\n </sd-select>\n @if (conditionLv2.dayInfo.type === 'RELATED') {\n <sd-input-number\n size=\"sm\"\n [form]=\"form\"\n style=\"width: 80px\"\n [(model)]=\"conditionLv2.dayInfo.relatedValue\"\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\n [min]=\"1\"\n required\n hideInlineError>\n </sd-input-number>\n <sd-select\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [items]=\"previouses\"\n valueField=\"value\"\n displayField=\"display\"\n [(model)]=\"conditionLv2.dayInfo.related\"\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\n required\n hideInlineError>\n </sd-select>\n } @else if (conditionLv2.dayInfo.type === 'DATETIME') {\n <sd-datetime\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv2.value\"\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\n required\n hideInlineError>\n </sd-datetime>\n } @else if (conditionLv2.dayInfo.type === 'ATTRIBUTE') {\n <sd-autocomplete\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv2.value\"\n [items]=\"dateAttributes\"\n valueField=\"value\"\n displayField=\"display\"\n hideInlineError></sd-autocomplete>\n }\n } @else if (fieldAttribute.type === 'boolean') {\n <sd-select\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv2.value\"\n [items]=\"[\n { value: true, display: fieldAttribute.displayOnTrue },\n { value: false, display: fieldAttribute.displayOnFalse }\n ]\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-select>\n } @else if (fieldAttribute.type === 'values') {\n <sd-autocomplete\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv2.value\"\n [items]=\"fieldAttribute.values\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-autocomplete>\n }\n }\n <sd-button\n class=\"ml-auto\"\n prefixIcon=\"delete\"\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"remove(conditionLv1.conditions, idxLv1)\"></sd-button>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\n </ng-container>\n </sd-modal>\n}\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect$1, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "bare", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: SdDatetime, selector: "sd-datetime", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "showSeconds", "bare", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "pipe", type: ExpressionQueryPipe, name: "expressionQuery" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3220
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ExpressionBuilderComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
3221
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ExpressionBuilderComponent, isStandalone: true, selector: "expression-builder", inputs: { label: "label", _attributes: ["attributes", "_attributes"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange", sdChange: "sdChange", edit: "edit" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<!--\n FEEL-style expression trigger pill (M3 redesign).\n B\u1EA5m v\u00E0o pill m\u1EDF modal builder hi\u1EC7n t\u1EA1i (onEdit).\n-->\n<div class=\"fb-field\">\n @if (label) {\n <div class=\"fb-field__label\">{{ label }}</div>\n }\n @let exprText = model | expressionQuery;\n <div class=\"fb-expr\" (click)=\"onEdit()\" role=\"button\" tabindex=\"0\">\n <span class=\"fb-expr__badge\">FEEL</span>\n @if (exprText) {\n <span class=\"fb-expr__code mono\">{{ exprText }}</span>\n } @else {\n <span class=\"empty\">{{ 'core.component.form-builder.set-expression' | translate }}</span>\n }\n <button type=\"button\" class=\"fb-icon-btn\" (click)=\"onEdit(); $event.stopPropagation()\" aria-label=\"edit expression\">\n <span class=\"msi\">functions</span>\n </button>\n </div>\n</div>\n@if (expression) {\n <sd-modal [title]=\"'core.component.form-builder.set-expression' | translate\">\n <div class=\"c-builder\">\n <div class=\"d-flex justify-content-end\">\n <sd-button\n prefixIcon=\"calculate\"\n class=\"mr-4\"\n [title]=\"'core.component.form-builder.condition-group' | translate\"\n color=\"primary\"\n (click)=\"addCombinator(expression.conditions)\"></sd-button>\n <sd-button\n prefixIcon=\"add\"\n [title]=\"'core.component.form-builder.condition' | translate\"\n color=\"primary\"\n (click)=\"addCondition(expression.conditions)\"\n type=\"fill\"></sd-button>\n </div>\n <!-- C\u1EA5p 1 -->\n @for (conditionLv1 of expression.conditions; track conditionLv1.key; let idxLv1 = $index) {\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px\">\n <div class=\"c-condition\">\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\n @if (idxLv1 === 0) {\n <div class=\"c-where\">WHERE</div>\n }\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\n @if (idxLv1 === 1) {\n <div class=\"c-select\">\n <sd-select\n size=\"sm\"\n [(model)]=\"expression.combinator\"\n [items]=\"[\n { value: '&&', display: 'AND' },\n { value: '||', display: 'OR' }\n ]\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError=\"\"></sd-select>\n </div>\n }\n </div>\n @if (conditionLv1.type === 'condition') {\n <sd-autocomplete\n size=\"sm\"\n [form]=\"form\"\n style=\"width: 200px\"\n [(model)]=\"conditionLv1.field\"\n [items]=\"attributes\"\n (sdChange)=\"onChangeAttribute(conditionLv1)\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-autocomplete>\n @let fieldAttribute = attribute[conditionLv1.field!];\n <sd-select\n size=\"sm\"\n [form]=\"form\"\n style=\"width: 100px\"\n [(model)]=\"conditionLv1.operator\"\n [items]=\"attributeOperators[fieldAttribute?.type || 'string']\"\n valueField=\"value\"\n displayField=\"display\"\n [disabled]=\"!fieldAttribute?.type\"\n required\n hideInlineError></sd-select>\n @if (\n !!fieldAttribute?.type && conditionLv1.operator && conditionLv1.operator !== 'NULL' && conditionLv1.operator !== 'NOT_NULL'\n ) {\n @if (fieldAttribute.type === 'string') {\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input>\n } @else if (fieldAttribute.type === 'number') {\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"conditionLv1.value\" hideInlineError></sd-input-number>\n <sd-autocomplete\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv1.value\"\n [items]=\"numberAttributes\"\n valueField=\"value\"\n displayField=\"display\"\n hideInlineError></sd-autocomplete>\n } @else if (fieldAttribute.type === 'datetime' && conditionLv1.dayInfo) {\n <sd-select\n size=\"sm\"\n [placeholder]=\"'core.component.form-builder.time' | translate\"\n [form]=\"form\"\n style=\"width: 150px\"\n [items]=\"types\"\n valueField=\"value\"\n displayField=\"display\"\n [(model)]=\"conditionLv1.dayInfo.type\"\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\n required\n hideInlineError>\n </sd-select>\n @if (conditionLv1.dayInfo.type === 'RELATED') {\n <sd-input-number\n size=\"sm\"\n [form]=\"form\"\n style=\"width: 80px\"\n [(model)]=\"conditionLv1.dayInfo.relatedValue\"\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\n [min]=\"1\"\n required\n hideInlineError>\n </sd-input-number>\n <sd-select\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [items]=\"previouses\"\n valueField=\"value\"\n displayField=\"display\"\n [(model)]=\"conditionLv1.dayInfo.related\"\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\n required\n hideInlineError>\n </sd-select>\n } @else if (conditionLv1.dayInfo.type === 'DATETIME') {\n <sd-datetime\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv1.value\"\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\n required\n hideInlineError>\n </sd-datetime>\n } @else if (conditionLv1.dayInfo.type === 'ATTRIBUTE') {\n <sd-autocomplete\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv1.value\"\n [items]=\"dateAttributes\"\n valueField=\"value\"\n displayField=\"display\"\n hideInlineError></sd-autocomplete>\n }\n } @else if (fieldAttribute.type === 'boolean') {\n <sd-select\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv1.value\"\n [items]=\"[\n { value: true, display: fieldAttribute.displayOnTrue },\n { value: false, display: fieldAttribute.displayOnFalse }\n ]\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-select>\n } @else if (fieldAttribute.type === 'values') {\n <sd-autocomplete\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv1.value\"\n [items]=\"fieldAttribute.values\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-autocomplete>\n }\n }\n <sd-button class=\"ml-auto\" prefixIcon=\"delete\" [tooltip]=\"'core.component.form-builder.delete' | translate\" (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\n } @else if (conditionLv1.type === 'combinator') {\n <div class=\"c-builder\">\n <div class=\"d-flex justify-content-end\">\n <sd-button class=\"mr-4\" prefixIcon=\"delete\" [tooltip]=\"'core.component.form-builder.delete' | translate\" (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\n <sd-button\n prefixIcon=\"add\"\n [title]=\"'core.component.form-builder.condition' | translate\"\n size=\"sm\"\n color=\"primary\"\n (click)=\"addCondition(conditionLv1.conditions)\"\n type=\"fill\"></sd-button>\n </div>\n <!-- C\u1EA5p 2 -->\n @for (conditionLv2 of conditionLv1.conditions; track conditionLv2.key; let idxLv2 = $index) {\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px\">\n <div class=\"c-condition\">\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\n @if (idxLv2 === 0) {\n <div class=\"c-where\">WHERE</div>\n }\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\n @if (idxLv2 === 1) {\n <div class=\"c-select\">\n <sd-select\n size=\"sm\"\n [(model)]=\"conditionLv1.combinator\"\n [items]=\"[\n { value: '&&', display: 'AND' },\n { value: '||', display: 'OR' }\n ]\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError=\"\"></sd-select>\n </div>\n }\n </div>\n @if (conditionLv2.type === 'condition') {\n <sd-autocomplete\n size=\"sm\"\n [form]=\"form\"\n style=\"width: 200px\"\n [(model)]=\"conditionLv2.field\"\n [items]=\"attributes\"\n (sdChange)=\"onChangeAttribute(conditionLv2)\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-autocomplete>\n @let fieldAttribute = attribute[conditionLv2.field!];\n <sd-select\n size=\"sm\"\n [form]=\"form\"\n style=\"width: 100px\"\n [(model)]=\"conditionLv2.operator\"\n [items]=\"attributeOperators[fieldAttribute?.type || 'string']\"\n valueField=\"value\"\n displayField=\"display\"\n [disabled]=\"!fieldAttribute?.type\"\n required\n hideInlineError></sd-select>\n @if (\n !!fieldAttribute?.type &&\n conditionLv2.operator &&\n conditionLv2.operator !== 'NULL' &&\n conditionLv2.operator !== 'NOT_NULL'\n ) {\n @if (fieldAttribute.type === 'string') {\n <sd-input\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv2.value\"\n required\n hideInlineError></sd-input>\n } @else if (fieldAttribute.type === 'number') {\n <sd-input-number\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv2.value\"\n hideInlineError></sd-input-number>\n <sd-autocomplete\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv2.value\"\n [items]=\"numberAttributes\"\n valueField=\"value\"\n displayField=\"display\"\n hideInlineError></sd-autocomplete>\n } @else if (fieldAttribute.type === 'datetime' && conditionLv2.dayInfo) {\n <sd-select\n size=\"sm\"\n [form]=\"form\"\n [placeholder]=\"'core.component.form-builder.time' | translate\"\n style=\"width: 150px\"\n [items]=\"types\"\n valueField=\"value\"\n displayField=\"display\"\n [(model)]=\"conditionLv2.dayInfo.type\"\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\n required\n hideInlineError>\n </sd-select>\n @if (conditionLv2.dayInfo.type === 'RELATED') {\n <sd-input-number\n size=\"sm\"\n [form]=\"form\"\n style=\"width: 80px\"\n [(model)]=\"conditionLv2.dayInfo.relatedValue\"\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\n [min]=\"1\"\n required\n hideInlineError>\n </sd-input-number>\n <sd-select\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [items]=\"previouses\"\n valueField=\"value\"\n displayField=\"display\"\n [(model)]=\"conditionLv2.dayInfo.related\"\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\n required\n hideInlineError>\n </sd-select>\n } @else if (conditionLv2.dayInfo.type === 'DATETIME') {\n <sd-datetime\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv2.value\"\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\n required\n hideInlineError>\n </sd-datetime>\n } @else if (conditionLv2.dayInfo.type === 'ATTRIBUTE') {\n <sd-autocomplete\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv2.value\"\n [items]=\"dateAttributes\"\n valueField=\"value\"\n displayField=\"display\"\n hideInlineError></sd-autocomplete>\n }\n } @else if (fieldAttribute.type === 'boolean') {\n <sd-select\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv2.value\"\n [items]=\"[\n { value: true, display: fieldAttribute.displayOnTrue },\n { value: false, display: fieldAttribute.displayOnFalse }\n ]\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-select>\n } @else if (fieldAttribute.type === 'values') {\n <sd-autocomplete\n size=\"sm\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"conditionLv2.value\"\n [items]=\"fieldAttribute.values\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-autocomplete>\n }\n }\n <sd-button\n class=\"ml-auto\"\n prefixIcon=\"delete\"\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"remove(conditionLv1.conditions, idxLv1)\"></sd-button>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\n </ng-container>\n </sd-modal>\n}\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect$1, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "clearable", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "clearable", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: SdDatetime, selector: "sd-datetime", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "showSeconds", "clearable", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "pipe", type: ExpressionQueryPipe, name: "expressionQuery" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3224
3222
  }
3225
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ExpressionBuilderComponent, decorators: [{
3223
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ExpressionBuilderComponent, decorators: [{
3226
3224
  type: Component,
3227
3225
  args: [{ selector: 'expression-builder', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
3228
3226
  SdInput$1,
@@ -3366,10 +3364,10 @@ class AttributeExpression {
3366
3364
  }
3367
3365
  return attributes;
3368
3366
  };
3369
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeExpression, deps: [{ token: i0.ChangeDetectorRef }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
3370
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.15", type: AttributeExpression, isStandalone: true, selector: "attribute-expression", inputs: { components: "components", variables: "variables", label: "label", _model: ["model", "_model"] }, outputs: { modelChange: "modelChange", sdChange: "sdChange" }, ngImport: i0, template: "\n\n<expression-builder class=\"d-block py-8\" [label]=\"label\" [(model)]=\"model\" [attributes]=\"attributes\" (sdChange)=\"onChange($event)\" (edit)=\"onEdit()\"></expression-builder>", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: ExpressionBuilderComponent, selector: "expression-builder", inputs: ["label", "attributes", "model"], outputs: ["modelChange", "sdChange", "edit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3367
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeExpression, deps: [{ token: i0.ChangeDetectorRef }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
3368
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: AttributeExpression, isStandalone: true, selector: "attribute-expression", inputs: { components: "components", variables: "variables", label: "label", _model: ["model", "_model"] }, outputs: { modelChange: "modelChange", sdChange: "sdChange" }, ngImport: i0, template: "\n\n<expression-builder class=\"d-block py-8\" [label]=\"label\" [(model)]=\"model\" [attributes]=\"attributes\" (sdChange)=\"onChange($event)\" (edit)=\"onEdit()\"></expression-builder>", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: ExpressionBuilderComponent, selector: "expression-builder", inputs: ["label", "attributes", "model"], outputs: ["modelChange", "sdChange", "edit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3371
3369
  }
3372
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeExpression, decorators: [{
3370
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeExpression, decorators: [{
3373
3371
  type: Component,
3374
3372
  args: [{ selector: 'attribute-expression', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ExpressionBuilderComponent], template: "\n\n<expression-builder class=\"d-block py-8\" [label]=\"label\" [(model)]=\"model\" [attributes]=\"attributes\" (sdChange)=\"onChange($event)\" (edit)=\"onEdit()\"></expression-builder>", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"] }]
3375
3373
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: FormGenericService }], propDecorators: { components: [{
@@ -3410,10 +3408,10 @@ class AttributeInputNumber {
3410
3408
  onChange = (value) => {
3411
3409
  this.modelChange.emit(value);
3412
3410
  };
3413
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeInputNumber, deps: [], target: i0.ɵɵFactoryTarget.Component });
3414
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.15", type: AttributeInputNumber, isStandalone: true, selector: "attribute-input-number", inputs: { _label: ["label", "_label"], _disabled: ["disabled", "_disabled"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, ngImport: i0, template: "<!-- <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <sd-input-number\n style=\"width: 200px\"\n size=\"sm\"\n [(model)]=\"model\"\n [disabled]=\"disabled\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-input-number>\n</div> -->\n<sd-input-number\n class=\"py-8\"\n size=\"sm\"\n [label]=\"label!\"\n [(model)]=\"model\"\n [disabled]=\"disabled\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-input-number>\n", dependencies: [{ kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }] });
3411
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeInputNumber, deps: [], target: i0.ɵɵFactoryTarget.Component });
3412
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: AttributeInputNumber, isStandalone: true, selector: "attribute-input-number", inputs: { _label: ["label", "_label"], _disabled: ["disabled", "_disabled"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, ngImport: i0, template: "<!-- <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <sd-input-number\n style=\"width: 200px\"\n size=\"sm\"\n [(model)]=\"model\"\n [disabled]=\"disabled\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-input-number>\n</div> -->\n<sd-input-number\n class=\"py-8\"\n size=\"sm\"\n [label]=\"label!\"\n [(model)]=\"model\"\n [disabled]=\"disabled\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-input-number>\n", dependencies: [{ kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }] });
3415
3413
  }
3416
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeInputNumber, decorators: [{
3414
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeInputNumber, decorators: [{
3417
3415
  type: Component,
3418
3416
  args: [{ selector: 'attribute-input-number', imports: [SdInputNumber], template: "<!-- <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <sd-input-number\n style=\"width: 200px\"\n size=\"sm\"\n [(model)]=\"model\"\n [disabled]=\"disabled\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-input-number>\n</div> -->\n<sd-input-number\n class=\"py-8\"\n size=\"sm\"\n [label]=\"label!\"\n [(model)]=\"model\"\n [disabled]=\"disabled\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-input-number>\n" }]
3419
3417
  }], propDecorators: { _label: [{
@@ -3452,10 +3450,10 @@ class AttributeInput {
3452
3450
  this.modelChange.emit(value);
3453
3451
  this.sdChange.emit(value);
3454
3452
  };
3455
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
3456
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.15", type: AttributeInput, isStandalone: true, selector: "attribute-input", inputs: { form: "form", _label: ["label", "_label"], _disabled: ["disabled", "_disabled"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange", sdChange: "sdChange" }, ngImport: i0, template: "<!-- <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <sd-input style=\"width: 200px\" size=\"sm\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-input>\n</div> -->\n<sd-input class=\"py-8\" size=\"sm\" [label]=\"label!\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-input>\n", dependencies: [{ kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }] });
3453
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
3454
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: AttributeInput, isStandalone: true, selector: "attribute-input", inputs: { form: "form", _label: ["label", "_label"], _disabled: ["disabled", "_disabled"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange", sdChange: "sdChange" }, ngImport: i0, template: "<!-- <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <sd-input style=\"width: 200px\" size=\"sm\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-input>\n</div> -->\n<sd-input class=\"py-8\" size=\"sm\" [label]=\"label!\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-input>\n", dependencies: [{ kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }] });
3457
3455
  }
3458
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeInput, decorators: [{
3456
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeInput, decorators: [{
3459
3457
  type: Component,
3460
3458
  args: [{ selector: 'attribute-input', imports: [SdInput$1], template: "<!-- <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <sd-input style=\"width: 200px\" size=\"sm\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-input>\n</div> -->\n<sd-input class=\"py-8\" size=\"sm\" [label]=\"label!\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-input>\n" }]
3461
3459
  }], propDecorators: { form: [{
@@ -3493,10 +3491,10 @@ class AttributeSwitch {
3493
3491
  onChange = (value) => {
3494
3492
  this.modelChange.emit(!!value);
3495
3493
  };
3496
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeSwitch, deps: [], target: i0.ɵɵFactoryTarget.Component });
3497
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.15", type: AttributeSwitch, isStandalone: true, selector: "attribute-switch", inputs: { form: "form", _label: ["label", "_label"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, ngImport: i0, template: "<!-- <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <sd-switch size=\"sm\" [form]=\"form\" [(model)]=\"model\" (sdChange)=\"onChange($event)\" hideInlineError></sd-switch>\n</div> -->\n<sd-select\n class=\"py-8\"\n size=\"sm\"\n [label]=\"label!\"\n [form]=\"form\"\n [(model)]=\"model\"\n valueField=\"value\"\n displayField=\"display\"\n [items]=\"[\n { value: true, display: ('core.confirm.yes-short' | translate) },\n { value: false, display: ('core.confirm.no-short' | translate) }\n ]\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-select>\n", dependencies: [{ kind: "component", type: SdSelect$1, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "bare", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
3494
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeSwitch, deps: [], target: i0.ɵɵFactoryTarget.Component });
3495
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: AttributeSwitch, isStandalone: true, selector: "attribute-switch", inputs: { form: "form", _label: ["label", "_label"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, ngImport: i0, template: "<!-- <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <sd-switch size=\"sm\" [form]=\"form\" [(model)]=\"model\" (sdChange)=\"onChange($event)\" hideInlineError></sd-switch>\n</div> -->\n<sd-select\n class=\"py-8\"\n size=\"sm\"\n [label]=\"label!\"\n [form]=\"form\"\n [(model)]=\"model\"\n valueField=\"value\"\n displayField=\"display\"\n [items]=\"[\n { value: true, display: ('core.confirm.yes-short' | translate) },\n { value: false, display: ('core.confirm.no-short' | translate) }\n ]\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-select>\n", dependencies: [{ kind: "component", type: SdSelect$1, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "clearable", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
3498
3496
  }
3499
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeSwitch, decorators: [{
3497
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeSwitch, decorators: [{
3500
3498
  type: Component,
3501
3499
  args: [{ selector: 'attribute-switch', imports: [SdSelect$1, TranslatePipe], template: "<!-- <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <sd-switch size=\"sm\" [form]=\"form\" [(model)]=\"model\" (sdChange)=\"onChange($event)\" hideInlineError></sd-switch>\n</div> -->\n<sd-select\n class=\"py-8\"\n size=\"sm\"\n [label]=\"label!\"\n [form]=\"form\"\n [(model)]=\"model\"\n valueField=\"value\"\n displayField=\"display\"\n [items]=\"[\n { value: true, display: ('core.confirm.yes-short' | translate) },\n { value: false, display: ('core.confirm.no-short' | translate) }\n ]\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-select>\n" }]
3502
3500
  }], propDecorators: { form: [{
@@ -3533,10 +3531,10 @@ class AttributeTemplate {
3533
3531
  }
3534
3532
  }
3535
3533
  };
3536
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeTemplate, deps: [{ token: SD_FORM_GENERIC_CONFIGURATION, optional: true }], target: i0.ɵɵFactoryTarget.Component });
3537
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: AttributeTemplate, isStandalone: true, selector: "attribute-template", inputs: { _component: ["component", "_component"] }, outputs: { sdChange: "sdChange" }, ngImport: i0, template: "@if (templates.length) {\n <!-- <div class=\"d-flex align-items-center py-4\">\n <div class=\"T14M\" style=\"flex: 1\">D\u1EEF li\u1EC7u m\u1EABu</div>\n <sd-autocomplete\n style=\"width: 200px\"\n size=\"sm\"\n [(model)]=\"component.template\"\n [items]=\"templates\"\n valueField=\"value\"\n displayField=\"display\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-autocomplete>\n </div> -->\n <sd-autocomplete\n class=\"py-8\"\n size=\"sm\"\n [label]=\"'core.component.form-builder.template-data' | translate\"\n [(model)]=\"component.template\"\n [items]=\"templates\"\n valueField=\"value\"\n displayField=\"display\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-autocomplete>\n}\n", dependencies: [{ kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
3534
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeTemplate, deps: [{ token: SD_FORM_GENERIC_CONFIGURATION, optional: true }], target: i0.ɵɵFactoryTarget.Component });
3535
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: AttributeTemplate, isStandalone: true, selector: "attribute-template", inputs: { _component: ["component", "_component"] }, outputs: { sdChange: "sdChange" }, ngImport: i0, template: "@if (templates.length) {\n <!-- <div class=\"d-flex align-items-center py-4\">\n <div class=\"T14M\" style=\"flex: 1\">D\u1EEF li\u1EC7u m\u1EABu</div>\n <sd-autocomplete\n style=\"width: 200px\"\n size=\"sm\"\n [(model)]=\"component.template\"\n [items]=\"templates\"\n valueField=\"value\"\n displayField=\"display\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-autocomplete>\n </div> -->\n <sd-autocomplete\n class=\"py-8\"\n size=\"sm\"\n [label]=\"'core.component.form-builder.template-data' | translate\"\n [(model)]=\"component.template\"\n [items]=\"templates\"\n valueField=\"value\"\n displayField=\"display\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-autocomplete>\n}\n", dependencies: [{ kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "clearable", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
3538
3536
  }
3539
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeTemplate, decorators: [{
3537
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeTemplate, decorators: [{
3540
3538
  type: Component,
3541
3539
  args: [{ selector: 'attribute-template', imports: [SdAutocomplete$1, TranslatePipe], template: "@if (templates.length) {\n <!-- <div class=\"d-flex align-items-center py-4\">\n <div class=\"T14M\" style=\"flex: 1\">D\u1EEF li\u1EC7u m\u1EABu</div>\n <sd-autocomplete\n style=\"width: 200px\"\n size=\"sm\"\n [(model)]=\"component.template\"\n [items]=\"templates\"\n valueField=\"value\"\n displayField=\"display\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-autocomplete>\n </div> -->\n <sd-autocomplete\n class=\"py-8\"\n size=\"sm\"\n [label]=\"'core.component.form-builder.template-data' | translate\"\n [(model)]=\"component.template\"\n [items]=\"templates\"\n valueField=\"value\"\n displayField=\"display\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-autocomplete>\n}\n" }]
3542
3540
  }], ctorParameters: () => [{ type: undefined, decorators: [{
@@ -3574,10 +3572,10 @@ class AttributeTextarea {
3574
3572
  this.modelChange.emit(value);
3575
3573
  this.sdChange.emit(value);
3576
3574
  };
3577
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeTextarea, deps: [], target: i0.ɵɵFactoryTarget.Component });
3578
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.15", type: AttributeTextarea, isStandalone: true, selector: "attribute-textarea", inputs: { form: "form", _label: ["label", "_label"], _disabled: ["disabled", "_disabled"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange", sdChange: "sdChange" }, ngImport: i0, template: "<sd-textarea class=\"py-8\" size=\"sm\" [label]=\"label!\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-textarea>", dependencies: [{ kind: "component", type: SdTextarea, selector: "sd-textarea", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "rows", "hideInlineError", "required", "disabled", "viewed", "autoHeight", "maxlength", "pattern", "validator", "inlineError", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange"] }] });
3575
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeTextarea, deps: [], target: i0.ɵɵFactoryTarget.Component });
3576
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: AttributeTextarea, isStandalone: true, selector: "attribute-textarea", inputs: { form: "form", _label: ["label", "_label"], _disabled: ["disabled", "_disabled"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange", sdChange: "sdChange" }, ngImport: i0, template: "<sd-textarea class=\"py-8\" size=\"sm\" [label]=\"label!\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-textarea>", dependencies: [{ kind: "component", type: SdTextarea, selector: "sd-textarea", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "rows", "hideInlineError", "required", "disabled", "viewed", "autoHeight", "maxlength", "pattern", "validator", "inlineError", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange"] }] });
3579
3577
  }
3580
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeTextarea, decorators: [{
3578
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeTextarea, decorators: [{
3581
3579
  type: Component,
3582
3580
  args: [{ selector: 'attribute-textarea', imports: [SdTextarea], template: "<sd-textarea class=\"py-8\" size=\"sm\" [label]=\"label!\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-textarea>" }]
3583
3581
  }], propDecorators: { form: [{
@@ -3611,10 +3609,10 @@ class BuilderService {
3611
3609
  // Debound 0.2s để tránh trigger liên tục
3612
3610
  return this.#componentChanges.pipe(debounceTime(200));
3613
3611
  }
3614
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: BuilderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3615
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: BuilderService, providedIn: 'root' });
3612
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BuilderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3613
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BuilderService, providedIn: 'root' });
3616
3614
  }
3617
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: BuilderService, decorators: [{
3615
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BuilderService, decorators: [{
3618
3616
  type: Injectable,
3619
3617
  args: [{
3620
3618
  providedIn: 'root',
@@ -3666,10 +3664,10 @@ class TextfieldAttribute {
3666
3664
  this.ref.markForCheck();
3667
3665
  }
3668
3666
  };
3669
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TextfieldAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3670
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: TextfieldAttribute, isStandalone: true, selector: "textfield-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.default-value' | translate\" [(model)]=\"component.defaultValue\"></attribute-input>\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n <attribute-input-number [label]=\"'core.component.form-builder.maxlength' | translate\" [(model)]=\"component.validate!.maxlength\"></attribute-input-number>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n <attribute-input label=\"Expression\" [(model)]=\"component.validate!.pattern\"></attribute-input>\n <attribute-input label=\"Expression message\" [(model)]=\"component.validate!.patternErrorMessage\"></attribute-input>\n </div>\n </details>\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInputNumber, selector: "attribute-input-number", inputs: ["label", "disabled", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3667
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: TextfieldAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3668
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: TextfieldAttribute, isStandalone: true, selector: "textfield-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.default-value' | translate\" [(model)]=\"component.defaultValue\"></attribute-input>\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n <attribute-input-number [label]=\"'core.component.form-builder.maxlength' | translate\" [(model)]=\"component.validate!.maxlength\"></attribute-input-number>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n <attribute-input label=\"Expression\" [(model)]=\"component.validate!.pattern\"></attribute-input>\n <attribute-input label=\"Expression message\" [(model)]=\"component.validate!.patternErrorMessage\"></attribute-input>\n </div>\n </details>\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInputNumber, selector: "attribute-input-number", inputs: ["label", "disabled", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3671
3669
  }
3672
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TextfieldAttribute, decorators: [{
3670
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: TextfieldAttribute, decorators: [{
3673
3671
  type: Component,
3674
3672
  args: [{ selector: 'textfield-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeExpression, AttributeInput, AttributeInputNumber, AttributeSwitch, AttributeTextarea, TranslatePipe], template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.default-value' | translate\" [(model)]=\"component.defaultValue\"></attribute-input>\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n <attribute-input-number [label]=\"'core.component.form-builder.maxlength' | translate\" [(model)]=\"component.validate!.maxlength\"></attribute-input-number>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n <attribute-input label=\"Expression\" [(model)]=\"component.validate!.pattern\"></attribute-input>\n <attribute-input label=\"Expression message\" [(model)]=\"component.validate!.patternErrorMessage\"></attribute-input>\n </div>\n </details>\n}\n" }]
3675
3673
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
@@ -3710,10 +3708,10 @@ class TextFieldControl {
3710
3708
  ngOnDestroy() {
3711
3709
  this.#subscription.unsubscribe();
3712
3710
  }
3713
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TextFieldControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3714
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: TextFieldControl, isStandalone: true, selector: "textfield-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">\n Your input text\n </div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-input\">{{component.defaultValue}}</div>\n </div>\n}\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative;padding:0 8px;color:#bfbfbf}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3711
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: TextFieldControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3712
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: TextFieldControl, isStandalone: true, selector: "textfield-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">\n Your input text\n </div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-input\">{{component.defaultValue}}</div>\n </div>\n}\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative;padding:0 8px;color:#bfbfbf}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3715
3713
  }
3716
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TextFieldControl, decorators: [{
3714
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: TextFieldControl, decorators: [{
3717
3715
  type: Component,
3718
3716
  args: [{ selector: 'textfield-control', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">\n Your input text\n </div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-input\">{{component.defaultValue}}</div>\n </div>\n}\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative;padding:0 8px;color:#bfbfbf}\n"] }]
3719
3717
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
@@ -3766,10 +3764,10 @@ class TextareaAttribute {
3766
3764
  this.ref.markForCheck();
3767
3765
  }
3768
3766
  };
3769
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TextareaAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3770
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: TextareaAttribute, isStandalone: true, selector: "textarea-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n <attribute-input-number [label]=\"'core.component.form-builder.maxlength' | translate\" [(model)]=\"component.validate!.maxlength\"></attribute-input-number>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInputNumber, selector: "attribute-input-number", inputs: ["label", "disabled", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3767
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: TextareaAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3768
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: TextareaAttribute, isStandalone: true, selector: "textarea-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n <attribute-input-number [label]=\"'core.component.form-builder.maxlength' | translate\" [(model)]=\"component.validate!.maxlength\"></attribute-input-number>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInputNumber, selector: "attribute-input-number", inputs: ["label", "disabled", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3771
3769
  }
3772
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TextareaAttribute, decorators: [{
3770
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: TextareaAttribute, decorators: [{
3773
3771
  type: Component,
3774
3772
  args: [{ selector: 'textarea-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeInput, AttributeInputNumber, AttributeSwitch, AttributeExpression, AttributeTextarea, TranslatePipe], template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n <attribute-input-number [label]=\"'core.component.form-builder.maxlength' | translate\" [(model)]=\"component.validate!.maxlength\"></attribute-input-number>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n}\n" }]
3775
3773
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
@@ -3811,10 +3809,10 @@ class TextareaControl {
3811
3809
  ngOnDestroy() {
3812
3810
  this.#subscription.unsubscribe();
3813
3811
  }
3814
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TextareaControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3815
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: TextareaControl, isStandalone: true, selector: "textarea-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">Your input text</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-textarea\"></div>\n </div>\n}\n", styles: [".c-textarea{width:100%;background:#fff;height:100px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3812
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: TextareaControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3813
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: TextareaControl, isStandalone: true, selector: "textarea-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">Your input text</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-textarea\"></div>\n </div>\n}\n", styles: [".c-textarea{width:100%;background:#fff;height:100px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3816
3814
  }
3817
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TextareaControl, decorators: [{
3815
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: TextareaControl, decorators: [{
3818
3816
  type: Component,
3819
3817
  args: [{ selector: 'textarea-control', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">Your input text</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-textarea\"></div>\n </div>\n}\n", styles: [".c-textarea{width:100%;background:#fff;height:100px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}\n"] }]
3820
3818
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
@@ -3851,10 +3849,10 @@ class ChipStringControl {
3851
3849
  ngOnDestroy() {
3852
3850
  this.#subscription.unsubscribe();
3853
3851
  }
3854
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ChipStringControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3855
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ChipStringControl, isStandalone: true, selector: "chip-string-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">One, Two, Three</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-input\">\n <span class=\"c-chip\">One</span>\n <span class=\"c-chip\">Two</span>\n <span class=\"c-chip\">Three</span>\n </div>\n </div>\n}\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}.c-chip{display:inline-block;padding:2px 8px;background:#e0e0e0;border-radius:16px;font-size:13px;line-height:20px;margin:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3852
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ChipStringControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3853
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ChipStringControl, isStandalone: true, selector: "chip-string-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">One, Two, Three</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-input\">\n <span class=\"c-chip\">One</span>\n <span class=\"c-chip\">Two</span>\n <span class=\"c-chip\">Three</span>\n </div>\n </div>\n}\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}.c-chip{display:inline-block;padding:2px 8px;background:#e0e0e0;border-radius:16px;font-size:13px;line-height:20px;margin:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3856
3854
  }
3857
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ChipStringControl, decorators: [{
3855
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ChipStringControl, decorators: [{
3858
3856
  type: Component,
3859
3857
  args: [{ selector: 'chip-string-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule], template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">One, Two, Three</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-input\">\n <span class=\"c-chip\">One</span>\n <span class=\"c-chip\">Two</span>\n <span class=\"c-chip\">Three</span>\n </div>\n </div>\n}\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}.c-chip{display:inline-block;padding:2px 8px;background:#e0e0e0;border-radius:16px;font-size:13px;line-height:20px;margin:2px}\n"] }]
3860
3858
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
@@ -3914,10 +3912,10 @@ class ChipStringAttribute {
3914
3912
  onChanges = () => {
3915
3913
  this.#changes.next();
3916
3914
  };
3917
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ChipStringAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3918
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ChipStringAttribute, isStandalone: true, selector: "chip-string-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n @if (component.properties!.viewed) {\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\n }\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n @if (!component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n }\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3915
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ChipStringAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3916
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ChipStringAttribute, isStandalone: true, selector: "chip-string-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n @if (component.properties!.viewed) {\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\n }\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n @if (!component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n }\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3919
3917
  }
3920
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ChipStringAttribute, decorators: [{
3918
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ChipStringAttribute, decorators: [{
3921
3919
  type: Component,
3922
3920
  args: [{ selector: 'chip-string-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeInput, AttributeSwitch, AttributeExpression, TranslatePipe], template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n @if (component.properties!.viewed) {\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\n }\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n @if (!component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n }\n}\n" }]
3923
3921
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
@@ -3960,10 +3958,10 @@ class ChipCalendarControl {
3960
3958
  ngOnDestroy() {
3961
3959
  this.#subscription.unsubscribe();
3962
3960
  }
3963
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ChipCalendarControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3964
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ChipCalendarControl, isStandalone: true, selector: "chip-calendar-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">One, Two, Three</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-input\">\n <span class=\"c-chip\">One</span>\n <span class=\"c-chip\">Two</span>\n <span class=\"c-chip\">Three</span>\n </div>\n </div>\n}\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}.c-chip{display:inline-block;padding:2px 8px;background:#e0e0e0;border-radius:16px;font-size:13px;line-height:20px;margin:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3961
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ChipCalendarControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3962
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ChipCalendarControl, isStandalone: true, selector: "chip-calendar-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">One, Two, Three</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-input\">\n <span class=\"c-chip\">One</span>\n <span class=\"c-chip\">Two</span>\n <span class=\"c-chip\">Three</span>\n </div>\n </div>\n}\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}.c-chip{display:inline-block;padding:2px 8px;background:#e0e0e0;border-radius:16px;font-size:13px;line-height:20px;margin:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3965
3963
  }
3966
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ChipCalendarControl, decorators: [{
3964
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ChipCalendarControl, decorators: [{
3967
3965
  type: Component,
3968
3966
  args: [{ selector: 'chip-calendar-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule], template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">One, Two, Three</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-input\">\n <span class=\"c-chip\">One</span>\n <span class=\"c-chip\">Two</span>\n <span class=\"c-chip\">Three</span>\n </div>\n </div>\n}\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}.c-chip{display:inline-block;padding:2px 8px;background:#e0e0e0;border-radius:16px;font-size:13px;line-height:20px;margin:2px}\n"] }]
3969
3967
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
@@ -4023,10 +4021,10 @@ class ChipCalendarAttribute {
4023
4021
  onChanges = () => {
4024
4022
  this.#changes.next();
4025
4023
  };
4026
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ChipCalendarAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4027
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ChipCalendarAttribute, isStandalone: true, selector: "chip-calendar-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n @if (component.properties!.viewed) {\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\n }\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n @if (!component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n }\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4024
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ChipCalendarAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4025
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ChipCalendarAttribute, isStandalone: true, selector: "chip-calendar-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n @if (component.properties!.viewed) {\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\n }\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n @if (!component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n }\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4028
4026
  }
4029
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ChipCalendarAttribute, decorators: [{
4027
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ChipCalendarAttribute, decorators: [{
4030
4028
  type: Component,
4031
4029
  args: [{ selector: 'chip-calendar-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeInput, AttributeSwitch, AttributeExpression, TranslatePipe], template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n @if (component.properties!.viewed) {\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\n }\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n @if (!component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n }\n}\n" }]
4032
4030
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
@@ -4089,10 +4087,10 @@ class NumberAttribute {
4089
4087
  this.ref.markForCheck();
4090
4088
  }
4091
4089
  };
4092
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NumberAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4093
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: NumberAttribute, isStandalone: true, selector: "number-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\n </div>\n</details>\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n <attribute-input-number [label]=\"'core.component.form-builder.min' | translate\" [(model)]=\"component.validate!.min\"></attribute-input-number>\n <attribute-input-number [label]=\"'core.component.form-builder.max' | translate\" [(model)]=\"component.validate!.max\"></attribute-input-number>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInputNumber, selector: "attribute-input-number", inputs: ["label", "disabled", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4090
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: NumberAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4091
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: NumberAttribute, isStandalone: true, selector: "number-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\n </div>\n</details>\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n <attribute-input-number [label]=\"'core.component.form-builder.min' | translate\" [(model)]=\"component.validate!.min\"></attribute-input-number>\n <attribute-input-number [label]=\"'core.component.form-builder.max' | translate\" [(model)]=\"component.validate!.max\"></attribute-input-number>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInputNumber, selector: "attribute-input-number", inputs: ["label", "disabled", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4094
4092
  }
4095
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NumberAttribute, decorators: [{
4093
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: NumberAttribute, decorators: [{
4096
4094
  type: Component,
4097
4095
  args: [{ selector: 'number-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeInput, AttributeInputNumber, AttributeSwitch, AttributeExpression, AttributeTextarea, TranslatePipe], template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\n </div>\n</details>\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n <attribute-input-number [label]=\"'core.component.form-builder.min' | translate\" [(model)]=\"component.validate!.min\"></attribute-input-number>\n <attribute-input-number [label]=\"'core.component.form-builder.max' | translate\" [(model)]=\"component.validate!.max\"></attribute-input-number>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n}\n" }]
4098
4096
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
@@ -4136,10 +4134,10 @@ class NumberControl {
4136
4134
  ngOnDestroy() {
4137
4135
  this.#subscription.unsubscribe();
4138
4136
  }
4139
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NumberControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4140
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: NumberControl, isStandalone: true, selector: "number-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">{{number}}</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-input\"></div>\n </div>\n}\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4137
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: NumberControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4138
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: NumberControl, isStandalone: true, selector: "number-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">{{number}}</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-input\"></div>\n </div>\n}\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4141
4139
  }
4142
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NumberControl, decorators: [{
4140
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: NumberControl, decorators: [{
4143
4141
  type: Component,
4144
4142
  args: [{ selector: 'number-control', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">{{number}}</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-input\"></div>\n </div>\n}\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}\n"] }]
4145
4143
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
@@ -4174,10 +4172,10 @@ class DatetimeControl {
4174
4172
  ngOnDestroy() {
4175
4173
  this.#subscription.unsubscribe();
4176
4174
  }
4177
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: DatetimeControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4178
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: DatetimeControl, isStandalone: true, selector: "datetime-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">{{ component.subtype === 'datetime' ? datetime : date }}</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-input\">\n <svg viewBox=\"0 0 24 24\" width=\"24px\" height=\"24px\" fill=\"currentColor\" focusable=\"false\">\n <path\n d=\"M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z\"></path>\n </svg>\n </div>\n </div>\n}\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);position:relative;border-radius:4px}.c-input svg{position:absolute;top:2px;right:3px;color:#999}.label{font-weight:500}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4175
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: DatetimeControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4176
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: DatetimeControl, isStandalone: true, selector: "datetime-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">{{ component.subtype === 'datetime' ? datetime : date }}</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-input\">\n <svg viewBox=\"0 0 24 24\" width=\"24px\" height=\"24px\" fill=\"currentColor\" focusable=\"false\">\n <path\n d=\"M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z\"></path>\n </svg>\n </div>\n </div>\n}\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);position:relative;border-radius:4px}.c-input svg{position:absolute;top:2px;right:3px;color:#999}.label{font-weight:500}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4179
4177
  }
4180
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: DatetimeControl, decorators: [{
4178
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: DatetimeControl, decorators: [{
4181
4179
  type: Component,
4182
4180
  args: [{ selector: 'datetime-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [], template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">{{ component.subtype === 'datetime' ? datetime : date }}</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-input\">\n <svg viewBox=\"0 0 24 24\" width=\"24px\" height=\"24px\" fill=\"currentColor\" focusable=\"false\">\n <path\n d=\"M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z\"></path>\n </svg>\n </div>\n </div>\n}\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);position:relative;border-radius:4px}.c-input svg{position:absolute;top:2px;right:3px;color:#999}.label{font-weight:500}\n"] }]
4183
4181
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
@@ -4222,10 +4220,10 @@ class AttributeSelect {
4222
4220
  this.modelChange.emit(value);
4223
4221
  this.sdChange.emit(value);
4224
4222
  };
4225
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
4226
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.15", type: AttributeSelect, isStandalone: true, selector: "attribute-select", inputs: { form: "form", _label: ["label", "_label"], _disabled: ["disabled", "_disabled"], _multiple: ["multiple", "_multiple"], _items: ["items", "_items"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange", sdChange: "sdChange" }, ngImport: i0, template: "<!-- <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <sd-select\n style=\"width: 200px\"\n size=\"sm\"\n [form]=\"form\"\n [(model)]=\"model\"\n [items]=\"items\"\n valueField=\"value\"\n displayField=\"display\"\n [disabled]=\"disabled\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-select>\n</div> -->\n<sd-select\n class=\"py-8\"\n size=\"sm\"\n [label]=\"label!\"\n [form]=\"form\"\n [(model)]=\"model\"\n [items]=\"items\"\n valueField=\"value\"\n displayField=\"display\"\n [disabled]=\"disabled\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-select>", dependencies: [{ kind: "component", type: SdSelect$1, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "bare", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }] });
4223
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
4224
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: AttributeSelect, isStandalone: true, selector: "attribute-select", inputs: { form: "form", _label: ["label", "_label"], _disabled: ["disabled", "_disabled"], _multiple: ["multiple", "_multiple"], _items: ["items", "_items"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange", sdChange: "sdChange" }, ngImport: i0, template: "<!-- <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <sd-select\n style=\"width: 200px\"\n size=\"sm\"\n [form]=\"form\"\n [(model)]=\"model\"\n [items]=\"items\"\n valueField=\"value\"\n displayField=\"display\"\n [disabled]=\"disabled\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-select>\n</div> -->\n<sd-select\n class=\"py-8\"\n size=\"sm\"\n [label]=\"label!\"\n [form]=\"form\"\n [(model)]=\"model\"\n [items]=\"items\"\n valueField=\"value\"\n displayField=\"display\"\n [disabled]=\"disabled\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-select>", dependencies: [{ kind: "component", type: SdSelect$1, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "clearable", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }] });
4227
4225
  }
4228
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeSelect, decorators: [{
4226
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeSelect, decorators: [{
4229
4227
  type: Component,
4230
4228
  args: [{ selector: 'attribute-select', imports: [SdSelect$1], template: "<!-- <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <sd-select\n style=\"width: 200px\"\n size=\"sm\"\n [form]=\"form\"\n [(model)]=\"model\"\n [items]=\"items\"\n valueField=\"value\"\n displayField=\"display\"\n [disabled]=\"disabled\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-select>\n</div> -->\n<sd-select\n class=\"py-8\"\n size=\"sm\"\n [label]=\"label!\"\n [form]=\"form\"\n [(model)]=\"model\"\n [items]=\"items\"\n valueField=\"value\"\n displayField=\"display\"\n [disabled]=\"disabled\"\n (sdChange)=\"onChange($event)\"\n hideInlineError></sd-select>" }]
4231
4229
  }], propDecorators: { form: [{
@@ -4296,10 +4294,10 @@ class DatetimeAttribute {
4296
4294
  this.ref.markForCheck();
4297
4295
  }
4298
4296
  };
4299
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: DatetimeAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4300
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: DatetimeAttribute, isStandalone: true, selector: "datetime-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n <attribute-select\n [label]=\"'core.component.form-builder.format' | translate\"\n [(model)]=\"component.subtype\"\n [items]=\"[\n { value: 'date', display: 'dd/MM/yyyy' },\n { value: 'datetime', display: 'dd/MM/yyyy HH:mm' }\n ]\"></attribute-select>\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\n </div>\n</details>\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4297
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: DatetimeAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4298
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: DatetimeAttribute, isStandalone: true, selector: "datetime-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n <attribute-select\n [label]=\"'core.component.form-builder.format' | translate\"\n [(model)]=\"component.subtype\"\n [items]=\"[\n { value: 'date', display: 'dd/MM/yyyy' },\n { value: 'datetime', display: 'dd/MM/yyyy HH:mm' }\n ]\"></attribute-select>\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\n </div>\n</details>\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4301
4299
  }
4302
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: DatetimeAttribute, decorators: [{
4300
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: DatetimeAttribute, decorators: [{
4303
4301
  type: Component,
4304
4302
  args: [{ selector: 'datetime-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeInput, AttributeSwitch, AttributeSelect, AttributeExpression, AttributeTextarea, TranslatePipe], template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n <attribute-select\n [label]=\"'core.component.form-builder.format' | translate\"\n [(model)]=\"component.subtype\"\n [items]=\"[\n { value: 'date', display: 'dd/MM/yyyy' },\n { value: 'datetime', display: 'dd/MM/yyyy HH:mm' }\n ]\"></attribute-select>\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\n </div>\n</details>\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n}\n" }]
4305
4303
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
@@ -4378,10 +4376,10 @@ let BuildQueries$1 = class BuildQueries {
4378
4376
  this.modal?.close();
4379
4377
  this.ref.markForCheck();
4380
4378
  };
4381
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: BuildQueries, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
4382
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: BuildQueries, isStandalone: true, selector: "build-queries", inputs: { components: "components", variables: "variables", label: "label", selections: "selections", _valuesKey: ["valuesKey", "_valuesKey"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "@if (!!selection?.queries?.items?.length) {\n <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\n </div>\n </div>\n <sd-modal [title]=\"'core.component.form-builder.set-query-value' | translate\" width=\"400px\">\n <div class=\"c-builder\">\n @for (property of leftProperties; track property.value) {\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\n <div style=\"width: 150px\">\n <div class=\"text-secondary\">{{ property.value }}</div>\n <div class=\"T16M\">{{ property.display }}</div>\n </div>\n <sd-autocomplete\n [label]=\"'core.component.form-builder.value-source-field' | translate\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"model![property.value]\"\n [items]=\"rightProperties\"\n valueField=\"value\"\n displayField=\"display\"\n hideInlineError></sd-autocomplete>\n </div>\n }\n </div>\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\n </ng-container>\n </sd-modal>\n}\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4379
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BuildQueries, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
4380
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: BuildQueries, isStandalone: true, selector: "build-queries", inputs: { components: "components", variables: "variables", label: "label", selections: "selections", _valuesKey: ["valuesKey", "_valuesKey"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "@if (!!selection?.queries?.items?.length) {\n <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\n </div>\n </div>\n <sd-modal [title]=\"'core.component.form-builder.set-query-value' | translate\" width=\"400px\">\n <div class=\"c-builder\">\n @for (property of leftProperties; track property.value) {\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\n <div style=\"width: 150px\">\n <div class=\"text-secondary\">{{ property.value }}</div>\n <div class=\"T16M\">{{ property.display }}</div>\n </div>\n <sd-autocomplete\n [label]=\"'core.component.form-builder.value-source-field' | translate\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"model![property.value]\"\n [items]=\"rightProperties\"\n valueField=\"value\"\n displayField=\"display\"\n hideInlineError></sd-autocomplete>\n </div>\n }\n </div>\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\n </ng-container>\n </sd-modal>\n}\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "clearable", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4383
4381
  };
4384
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: BuildQueries$1, decorators: [{
4382
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BuildQueries$1, decorators: [{
4385
4383
  type: Component,
4386
4384
  args: [{ selector: 'build-queries', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdAutocomplete$1, SdButton, SdModal, TranslatePipe], template: "@if (!!selection?.queries?.items?.length) {\n <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\n </div>\n </div>\n <sd-modal [title]=\"'core.component.form-builder.set-query-value' | translate\" width=\"400px\">\n <div class=\"c-builder\">\n @for (property of leftProperties; track property.value) {\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\n <div style=\"width: 150px\">\n <div class=\"text-secondary\">{{ property.value }}</div>\n <div class=\"T16M\">{{ property.display }}</div>\n </div>\n <sd-autocomplete\n [label]=\"'core.component.form-builder.value-source-field' | translate\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"model![property.value]\"\n [items]=\"rightProperties\"\n valueField=\"value\"\n displayField=\"display\"\n hideInlineError></sd-autocomplete>\n </div>\n }\n </div>\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\n </ng-container>\n </sd-modal>\n}\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"] }]
4387
4385
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { modal: [{
@@ -4493,10 +4491,10 @@ class BuildVariables {
4493
4491
  this.modal?.close();
4494
4492
  this.ref.markForCheck();
4495
4493
  };
4496
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: BuildVariables, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
4497
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: BuildVariables, isStandalone: true, selector: "build-variables", inputs: { components: "components", variables: "variables", label: "label", selections: "selections", _valuesKey: ["valuesKey", "_valuesKey"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "@if (!!selection?.variables?.items?.length) {\n <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\n </div>\n </div>\n <sd-modal [title]=\"'core.component.form-builder.set-on-change-assign' | translate\" width=\"500px\">\n <div class=\"c-builder\">\n <div class=\"d-flex justify-content-end\">\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.add-field' | translate\" color=\"primary\" (click)=\"addField()\"></sd-button>\n </div>\n <!-- C\u1EA5p 1 -->\n @for (item of items; track item.id; let idx = $index) {\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\n <sd-autocomplete\n [label]=\"'core.component.form-builder.target-field' | translate\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"item.key\"\n [items]=\"leftProperties\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-autocomplete>\n <sd-autocomplete\n [label]=\"'core.component.form-builder.target-value' | translate\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"item.value\"\n [items]=\"rightProperties\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-autocomplete>\n </div>\n }\n </div>\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\n </ng-container>\n </sd-modal>\n}\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4494
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BuildVariables, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
4495
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: BuildVariables, isStandalone: true, selector: "build-variables", inputs: { components: "components", variables: "variables", label: "label", selections: "selections", _valuesKey: ["valuesKey", "_valuesKey"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "@if (!!selection?.variables?.items?.length) {\n <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\n </div>\n </div>\n <sd-modal [title]=\"'core.component.form-builder.set-on-change-assign' | translate\" width=\"500px\">\n <div class=\"c-builder\">\n <div class=\"d-flex justify-content-end\">\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.add-field' | translate\" color=\"primary\" (click)=\"addField()\"></sd-button>\n </div>\n <!-- C\u1EA5p 1 -->\n @for (item of items; track item.id; let idx = $index) {\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\n <sd-autocomplete\n [label]=\"'core.component.form-builder.target-field' | translate\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"item.key\"\n [items]=\"leftProperties\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-autocomplete>\n <sd-autocomplete\n [label]=\"'core.component.form-builder.target-value' | translate\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"item.value\"\n [items]=\"rightProperties\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-autocomplete>\n </div>\n }\n </div>\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\n </ng-container>\n </sd-modal>\n}\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "clearable", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4498
4496
  }
4499
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: BuildVariables, decorators: [{
4497
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BuildVariables, decorators: [{
4500
4498
  type: Component,
4501
4499
  args: [{ selector: 'build-variables', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdAutocomplete$1, SdButton, SdModal, TranslatePipe], template: "@if (!!selection?.variables?.items?.length) {\n <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\n </div>\n </div>\n <sd-modal [title]=\"'core.component.form-builder.set-on-change-assign' | translate\" width=\"500px\">\n <div class=\"c-builder\">\n <div class=\"d-flex justify-content-end\">\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.add-field' | translate\" color=\"primary\" (click)=\"addField()\"></sd-button>\n </div>\n <!-- C\u1EA5p 1 -->\n @for (item of items; track item.id; let idx = $index) {\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\n <sd-autocomplete\n [label]=\"'core.component.form-builder.target-field' | translate\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"item.key\"\n [items]=\"leftProperties\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-autocomplete>\n <sd-autocomplete\n [label]=\"'core.component.form-builder.target-value' | translate\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"item.value\"\n [items]=\"rightProperties\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-autocomplete>\n </div>\n }\n </div>\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\n </ng-container>\n </sd-modal>\n}\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"] }]
4502
4500
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { modal: [{
@@ -4591,10 +4589,10 @@ class AttributeSelection {
4591
4589
  this.valuesChange.emit(this.values);
4592
4590
  this.ref.markForCheck();
4593
4591
  };
4594
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeSelection, deps: [{ token: i0.ChangeDetectorRef }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
4595
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: AttributeSelection, isStandalone: true, selector: "attribute-selection", inputs: { components: "components", variables: "variables", component: "component", _valuesKey: ["valuesKey", "_valuesKey"], _values: ["values", "_values"] }, outputs: { valuesKeyChange: "valuesKeyChange", valuesChange: "valuesChange", sdChange: "sdChange" }, ngImport: i0, template: "<sd-section class=\"mt-8\" [title]=\"'core.component.form-builder.data' | translate\" icon=\"format_list_bulleted\">\n @if (selections.length) {\n <div class=\"d-flex align-items-center py-4\">\n <div class=\"T14M\" style=\"flex: 1\">{{ 'core.component.form-builder.data-api' | translate }}</div>\n <sd-autocomplete\n style=\"width: 200px\"\n size=\"sm\"\n [(model)]=\"valuesKey\"\n [items]=\"selections\"\n valueField=\"value\"\n displayField=\"display\"\n (sdChange)=\"onChangeValuesKey($event)\"\n hideInlineError></sd-autocomplete>\n </div>\n <!-- N\u1EBFu l\u00E0 select t\u1EEB API th\u00EC cho ph\u00E9p truy\u1EC1n th\u00EAm Query -->\n\n @if (component.type === 'select' && !!valuesKey) {\n <build-queries\n [label]=\"'core.component.form-builder.query-condition' | translate\"\n [selections]=\"selections\"\n [valuesKey]=\"valuesKey\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.query\"></build-queries>\n <build-variables\n [label]=\"'core.component.form-builder.assign-value' | translate\"\n [selections]=\"selections\"\n [valuesKey]=\"valuesKey\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.setVariables\"></build-variables>\n <!-- <div class=\"d-flex align-items-center py-4\">\n <div class=\"T14M\" style=\"flex: 1\">\u0110i\u1EC1u ki\u1EC7n truy v\u1EA5n</div>\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"component.properties!.query\" hideInlineError></sd-input>\n </div> -->\n }\n }\n @if (!valuesKey) {\n <div class=\"d-flex flex-column\" style=\"gap: 4px\">\n <div class=\"T14M\">{{ 'core.component.form-builder.data-static' | translate }}</div>\n @for (item of values; track item.value; let idx = $index) {\n <div class=\"d-flex align-items-end py-4\" style=\"gap: 4px\">\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"item.value\" (sdChange)=\"onChangeValues()\" hideInlineError></sd-input>\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"item.label\" (sdChange)=\"onChangeValues()\" hideInlineError></sd-input>\n <sd-button prefixIcon=\"delete\" (click)=\"removeItem(idx)\" color=\"error\"></sd-button>\n </div>\n }\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.add-data' | translate\" (click)=\"addItem()\" color=\"primary\"></sd-button>\n </div>\n }\n</sd-section>\n", dependencies: [{ kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: BuildQueries$1, selector: "build-queries", inputs: ["components", "variables", "label", "selections", "valuesKey", "model"], outputs: ["modelChange"] }, { kind: "component", type: BuildVariables, selector: "build-variables", inputs: ["components", "variables", "label", "selections", "valuesKey", "model"], outputs: ["modelChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4592
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeSelection, deps: [{ token: i0.ChangeDetectorRef }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
4593
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: AttributeSelection, isStandalone: true, selector: "attribute-selection", inputs: { components: "components", variables: "variables", component: "component", _valuesKey: ["valuesKey", "_valuesKey"], _values: ["values", "_values"] }, outputs: { valuesKeyChange: "valuesKeyChange", valuesChange: "valuesChange", sdChange: "sdChange" }, ngImport: i0, template: "<sd-section class=\"mt-8\" [title]=\"'core.component.form-builder.data' | translate\" icon=\"format_list_bulleted\">\n @if (selections.length) {\n <div class=\"d-flex align-items-center py-4\">\n <div class=\"T14M\" style=\"flex: 1\">{{ 'core.component.form-builder.data-api' | translate }}</div>\n <sd-autocomplete\n style=\"width: 200px\"\n size=\"sm\"\n [(model)]=\"valuesKey\"\n [items]=\"selections\"\n valueField=\"value\"\n displayField=\"display\"\n (sdChange)=\"onChangeValuesKey($event)\"\n hideInlineError></sd-autocomplete>\n </div>\n <!-- N\u1EBFu l\u00E0 select t\u1EEB API th\u00EC cho ph\u00E9p truy\u1EC1n th\u00EAm Query -->\n\n @if (component.type === 'select' && !!valuesKey) {\n <build-queries\n [label]=\"'core.component.form-builder.query-condition' | translate\"\n [selections]=\"selections\"\n [valuesKey]=\"valuesKey\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.query\"></build-queries>\n <build-variables\n [label]=\"'core.component.form-builder.assign-value' | translate\"\n [selections]=\"selections\"\n [valuesKey]=\"valuesKey\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.setVariables\"></build-variables>\n <!-- <div class=\"d-flex align-items-center py-4\">\n <div class=\"T14M\" style=\"flex: 1\">\u0110i\u1EC1u ki\u1EC7n truy v\u1EA5n</div>\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"component.properties!.query\" hideInlineError></sd-input>\n </div> -->\n }\n }\n @if (!valuesKey) {\n <div class=\"d-flex flex-column\" style=\"gap: 4px\">\n <div class=\"T14M\">{{ 'core.component.form-builder.data-static' | translate }}</div>\n @for (item of values; track item.value; let idx = $index) {\n <div class=\"d-flex align-items-end py-4\" style=\"gap: 4px\">\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"item.value\" (sdChange)=\"onChangeValues()\" hideInlineError></sd-input>\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"item.label\" (sdChange)=\"onChangeValues()\" hideInlineError></sd-input>\n <sd-button prefixIcon=\"delete\" (click)=\"removeItem(idx)\" color=\"error\"></sd-button>\n </div>\n }\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.add-data' | translate\" (click)=\"addItem()\" color=\"primary\"></sd-button>\n </div>\n }\n</sd-section>\n", dependencies: [{ kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "clearable", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: BuildQueries$1, selector: "build-queries", inputs: ["components", "variables", "label", "selections", "valuesKey", "model"], outputs: ["modelChange"] }, { kind: "component", type: BuildVariables, selector: "build-variables", inputs: ["components", "variables", "label", "selections", "valuesKey", "model"], outputs: ["modelChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4596
4594
  }
4597
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeSelection, decorators: [{
4595
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeSelection, decorators: [{
4598
4596
  type: Component,
4599
4597
  args: [{ selector: 'attribute-selection', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdInput$1, SdAutocomplete$1, SdButton, SdSection, BuildQueries$1, BuildVariables, TranslatePipe], template: "<sd-section class=\"mt-8\" [title]=\"'core.component.form-builder.data' | translate\" icon=\"format_list_bulleted\">\n @if (selections.length) {\n <div class=\"d-flex align-items-center py-4\">\n <div class=\"T14M\" style=\"flex: 1\">{{ 'core.component.form-builder.data-api' | translate }}</div>\n <sd-autocomplete\n style=\"width: 200px\"\n size=\"sm\"\n [(model)]=\"valuesKey\"\n [items]=\"selections\"\n valueField=\"value\"\n displayField=\"display\"\n (sdChange)=\"onChangeValuesKey($event)\"\n hideInlineError></sd-autocomplete>\n </div>\n <!-- N\u1EBFu l\u00E0 select t\u1EEB API th\u00EC cho ph\u00E9p truy\u1EC1n th\u00EAm Query -->\n\n @if (component.type === 'select' && !!valuesKey) {\n <build-queries\n [label]=\"'core.component.form-builder.query-condition' | translate\"\n [selections]=\"selections\"\n [valuesKey]=\"valuesKey\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.query\"></build-queries>\n <build-variables\n [label]=\"'core.component.form-builder.assign-value' | translate\"\n [selections]=\"selections\"\n [valuesKey]=\"valuesKey\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.setVariables\"></build-variables>\n <!-- <div class=\"d-flex align-items-center py-4\">\n <div class=\"T14M\" style=\"flex: 1\">\u0110i\u1EC1u ki\u1EC7n truy v\u1EA5n</div>\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"component.properties!.query\" hideInlineError></sd-input>\n </div> -->\n }\n }\n @if (!valuesKey) {\n <div class=\"d-flex flex-column\" style=\"gap: 4px\">\n <div class=\"T14M\">{{ 'core.component.form-builder.data-static' | translate }}</div>\n @for (item of values; track item.value; let idx = $index) {\n <div class=\"d-flex align-items-end py-4\" style=\"gap: 4px\">\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"item.value\" (sdChange)=\"onChangeValues()\" hideInlineError></sd-input>\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"item.label\" (sdChange)=\"onChangeValues()\" hideInlineError></sd-input>\n <sd-button prefixIcon=\"delete\" (click)=\"removeItem(idx)\" color=\"error\"></sd-button>\n </div>\n }\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.add-data' | translate\" (click)=\"addItem()\" color=\"primary\"></sd-button>\n </div>\n }\n</sd-section>\n" }]
4600
4598
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: FormGenericService }], propDecorators: { components: [{
@@ -4672,10 +4670,10 @@ class SelectAttribute {
4672
4670
  this.ref.markForCheck();
4673
4671
  }
4674
4672
  };
4675
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SelectAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4676
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: SelectAttribute, isStandalone: true, selector: "select-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n <attribute-switch [label]=\"'core.component.form-builder.multiple' | translate\" [(model)]=\"component.properties!.multiple\"></attribute-switch>\n @if (component.properties!.viewed) {\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\n }\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <attribute-selection\n [components]=\"components\"\n [component]=\"component\"\n [variables]=\"variables\"\n [(valuesKey)]=\"component.valuesKey\"\n [(values)]=\"component.values\"\n (valuesKeyChange)=\"onChanges()\"\n (valuesChange)=\"onChanges()\"></attribute-selection>\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeSelection, selector: "attribute-selection", inputs: ["components", "variables", "component", "valuesKey", "values"], outputs: ["valuesKeyChange", "valuesChange", "sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4673
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SelectAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4674
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: SelectAttribute, isStandalone: true, selector: "select-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n <attribute-switch [label]=\"'core.component.form-builder.multiple' | translate\" [(model)]=\"component.properties!.multiple\"></attribute-switch>\n @if (component.properties!.viewed) {\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\n }\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <attribute-selection\n [components]=\"components\"\n [component]=\"component\"\n [variables]=\"variables\"\n [(valuesKey)]=\"component.valuesKey\"\n [(values)]=\"component.values\"\n (valuesKeyChange)=\"onChanges()\"\n (valuesChange)=\"onChanges()\"></attribute-selection>\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeSelection, selector: "attribute-selection", inputs: ["components", "variables", "component", "valuesKey", "values"], outputs: ["valuesKeyChange", "valuesChange", "sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4677
4675
  }
4678
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SelectAttribute, decorators: [{
4676
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SelectAttribute, decorators: [{
4679
4677
  type: Component,
4680
4678
  args: [{ selector: 'select-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeSelection, AttributeInput, AttributeSwitch, AttributeExpression, TranslatePipe], template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n <attribute-switch [label]=\"'core.component.form-builder.multiple' | translate\" [(model)]=\"component.properties!.multiple\"></attribute-switch>\n @if (component.properties!.viewed) {\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\n }\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <attribute-selection\n [components]=\"components\"\n [component]=\"component\"\n [variables]=\"variables\"\n [(valuesKey)]=\"component.valuesKey\"\n [(values)]=\"component.values\"\n (valuesKeyChange)=\"onChanges()\"\n (valuesChange)=\"onChanges()\"></attribute-selection>\n}\n" }]
4681
4679
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
@@ -4717,10 +4715,10 @@ class SelectControl {
4717
4715
  ngOnDestroy() {
4718
4716
  this.#subscription.unsubscribe();
4719
4717
  }
4720
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SelectControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4721
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: SelectControl, isStandalone: true, selector: "select-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">Your dropdown selection</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-input c-select\">\n <svg width=\"8\" height=\"8\">\n <path\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n fill=\"currentColor\"\n stroke=\"currentColor\"\n stroke-width=\".5\"\n d=\"M7.75 1.336L4 6.125.258 1.335 0 1.54l4 5.125L8 1.54zm0 0\"></path>\n </svg>\n </div>\n </div>\n}\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}.c-select svg{position:absolute;right:10px;top:10px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4718
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SelectControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4719
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: SelectControl, isStandalone: true, selector: "select-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">Your dropdown selection</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-input c-select\">\n <svg width=\"8\" height=\"8\">\n <path\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n fill=\"currentColor\"\n stroke=\"currentColor\"\n stroke-width=\".5\"\n d=\"M7.75 1.336L4 6.125.258 1.335 0 1.54l4 5.125L8 1.54zm0 0\"></path>\n </svg>\n </div>\n </div>\n}\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}.c-select svg{position:absolute;right:10px;top:10px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4722
4720
  }
4723
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SelectControl, decorators: [{
4721
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SelectControl, decorators: [{
4724
4722
  type: Component,
4725
4723
  args: [{ selector: 'select-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule], template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">Your dropdown selection</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"d-flex align-items-center\">\n <div class=\"c-input c-select\">\n <svg width=\"8\" height=\"8\">\n <path\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n fill=\"currentColor\"\n stroke=\"currentColor\"\n stroke-width=\".5\"\n d=\"M7.75 1.336L4 6.125.258 1.335 0 1.54l4 5.125L8 1.54zm0 0\"></path>\n </svg>\n </div>\n </div>\n}\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}.c-select svg{position:absolute;right:10px;top:10px}\n"] }]
4726
4724
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
@@ -4757,10 +4755,10 @@ class RadioControl {
4757
4755
  ngOnDestroy() {
4758
4756
  this.#subscription.unsubscribe();
4759
4757
  }
4760
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RadioControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4761
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: RadioControl, isStandalone: true, selector: "radio-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">Your radio selection</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"c-radio-item d-flex flex-wrap align-items-center\">\n @if (component.values?.length) {\n <div class=\"d-flex\" [class.flex-column]=\"component.properties?.direction === 'column'\" style=\"gap: 8px\">\n @for (item of component.values; track item.value) {\n <div class=\"d-flex align-items-center my-4\">\n <div class=\"c-rd-ip mr-4\"></div>\n <div class=\"T12M\">{{ item.label }}</div>\n </div>\n }\n </div>\n } @else if (component.valuesKey) {\n <div class=\"T12R text-secondary\">{{ component.valuesKey }}</div>\n }\n </div>\n}\n", styles: [".c-radio-item .c-rd-ip{border:2px solid #828282;width:16px;height:16px;border-radius:11px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4758
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RadioControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4759
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: RadioControl, isStandalone: true, selector: "radio-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">Your radio selection</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"c-radio-item d-flex flex-wrap align-items-center\">\n @if (component.values?.length) {\n <div class=\"d-flex\" [class.flex-column]=\"component.properties?.direction === 'column'\" style=\"gap: 8px\">\n @for (item of component.values; track item.value) {\n <div class=\"d-flex align-items-center my-4\">\n <div class=\"c-rd-ip mr-4\"></div>\n <div class=\"T12M\">{{ item.label }}</div>\n </div>\n }\n </div>\n } @else if (component.valuesKey) {\n <div class=\"T12R text-secondary\">{{ component.valuesKey }}</div>\n }\n </div>\n}\n", styles: [".c-radio-item .c-rd-ip{border:2px solid #828282;width:16px;height:16px;border-radius:11px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4762
4760
  }
4763
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RadioControl, decorators: [{
4761
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RadioControl, decorators: [{
4764
4762
  type: Component,
4765
4763
  args: [{ selector: 'radio-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule], template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">Your radio selection</div>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"c-radio-item d-flex flex-wrap align-items-center\">\n @if (component.values?.length) {\n <div class=\"d-flex\" [class.flex-column]=\"component.properties?.direction === 'column'\" style=\"gap: 8px\">\n @for (item of component.values; track item.value) {\n <div class=\"d-flex align-items-center my-4\">\n <div class=\"c-rd-ip mr-4\"></div>\n <div class=\"T12M\">{{ item.label }}</div>\n </div>\n }\n </div>\n } @else if (component.valuesKey) {\n <div class=\"T12R text-secondary\">{{ component.valuesKey }}</div>\n }\n </div>\n}\n", styles: [".c-radio-item .c-rd-ip{border:2px solid #828282;width:16px;height:16px;border-radius:11px}\n"] }]
4766
4764
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
@@ -4820,10 +4818,10 @@ class RadioAttribute {
4820
4818
  onChanges = () => {
4821
4819
  this.#changes.next();
4822
4820
  };
4823
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RadioAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4824
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: RadioAttribute, isStandalone: true, selector: "radio-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n @if (component.properties!.viewed) {\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\n }\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n <attribute-select\n [form]=\"form\"\n [label]=\"'core.component.form-builder.layout' | translate\"\n [(model)]=\"component.properties!.direction\"\n [items]=\"[\n { value: 'row', display: 'Ngang' },\n { value: 'column', display: ('core.component.form-builder.vertical' | translate) }\n ]\"></attribute-select>\n </div>\n </details>\n @if (!component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n }\n <attribute-selection\n [components]=\"components\"\n [variables]=\"variables\"\n [component]=\"component\"\n [(valuesKey)]=\"component.valuesKey\"\n [(values)]=\"component.values\"\n (valuesKeyChange)=\"onChanges()\"\n (valuesChange)=\"onChanges()\"></attribute-selection>\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeSelection, selector: "attribute-selection", inputs: ["components", "variables", "component", "valuesKey", "values"], outputs: ["valuesKeyChange", "valuesChange", "sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4821
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RadioAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4822
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: RadioAttribute, isStandalone: true, selector: "radio-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n @if (component.properties!.viewed) {\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\n }\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n <attribute-select\n [form]=\"form\"\n [label]=\"'core.component.form-builder.layout' | translate\"\n [(model)]=\"component.properties!.direction\"\n [items]=\"[\n { value: 'row', display: 'Ngang' },\n { value: 'column', display: ('core.component.form-builder.vertical' | translate) }\n ]\"></attribute-select>\n </div>\n </details>\n @if (!component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n }\n <attribute-selection\n [components]=\"components\"\n [variables]=\"variables\"\n [component]=\"component\"\n [(valuesKey)]=\"component.valuesKey\"\n [(values)]=\"component.values\"\n (valuesKeyChange)=\"onChanges()\"\n (valuesChange)=\"onChanges()\"></attribute-selection>\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeSelection, selector: "attribute-selection", inputs: ["components", "variables", "component", "valuesKey", "values"], outputs: ["valuesKeyChange", "valuesChange", "sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4825
4823
  }
4826
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RadioAttribute, decorators: [{
4824
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: RadioAttribute, decorators: [{
4827
4825
  type: Component,
4828
4826
  args: [{ selector: 'radio-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeSelection, AttributeInput, AttributeSwitch, AttributeSelect, AttributeExpression, TranslatePipe], template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n @if (component.properties!.viewed) {\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\n }\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n <attribute-select\n [form]=\"form\"\n [label]=\"'core.component.form-builder.layout' | translate\"\n [(model)]=\"component.properties!.direction\"\n [items]=\"[\n { value: 'row', display: 'Ngang' },\n { value: 'column', display: ('core.component.form-builder.vertical' | translate) }\n ]\"></attribute-select>\n </div>\n </details>\n @if (!component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n }\n <attribute-selection\n [components]=\"components\"\n [variables]=\"variables\"\n [component]=\"component\"\n [(valuesKey)]=\"component.valuesKey\"\n [(values)]=\"component.values\"\n (valuesKeyChange)=\"onChanges()\"\n (valuesChange)=\"onChanges()\"></attribute-selection>\n}\n" }]
4829
4827
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
@@ -4843,10 +4841,10 @@ class CheckboxControl {
4843
4841
  set _component(component) {
4844
4842
  this.component = component;
4845
4843
  }
4846
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: CheckboxControl, deps: [], target: i0.ɵɵFactoryTarget.Component });
4847
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: CheckboxControl, isStandalone: true, selector: "checkbox-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">{{ 'core.component.form-builder.yes-no' | translate }}</div>\n} @else {\n <div class=\"c-checkbox\">\n <div class=\"d-flex align-items-center\">\n <div class=\"c-box mr-4\"></div>\n <div class=\"T14R\">{{ component.label }}</div>\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";.input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);position:relative}.c-checkbox .c-box{border:2px solid #828282;width:16px;height:16px;border-radius:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
4844
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: CheckboxControl, deps: [], target: i0.ɵɵFactoryTarget.Component });
4845
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: CheckboxControl, isStandalone: true, selector: "checkbox-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">{{ 'core.component.form-builder.yes-no' | translate }}</div>\n} @else {\n <div class=\"c-checkbox\">\n <div class=\"d-flex align-items-center\">\n <div class=\"c-box mr-4\"></div>\n <div class=\"T14R\">{{ component.label }}</div>\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";.input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);position:relative}.c-checkbox .c-box{border:2px solid #828282;width:16px;height:16px;border-radius:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
4848
4846
  }
4849
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: CheckboxControl, decorators: [{
4847
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: CheckboxControl, decorators: [{
4850
4848
  type: Component,
4851
4849
  args: [{ selector: 'checkbox-control', imports: [CommonModule, TranslatePipe], template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <div class=\"T14M\">{{ 'core.component.form-builder.yes-no' | translate }}</div>\n} @else {\n <div class=\"c-checkbox\">\n <div class=\"d-flex align-items-center\">\n <div class=\"c-box mr-4\"></div>\n <div class=\"T14R\">{{ component.label }}</div>\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";.input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);position:relative}.c-checkbox .c-box{border:2px solid #828282;width:16px;height:16px;border-radius:2px}\n"] }]
4852
4850
  }], propDecorators: { _component: [{
@@ -4899,10 +4897,10 @@ class CheckboxAttribute {
4899
4897
  this.ref.markForCheck();
4900
4898
  }
4901
4899
  };
4902
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: CheckboxAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4903
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: CheckboxAttribute, isStandalone: true, selector: "checkbox-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n </div>\n</details>\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4900
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: CheckboxAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4901
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: CheckboxAttribute, isStandalone: true, selector: "checkbox-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n </div>\n</details>\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4904
4902
  }
4905
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: CheckboxAttribute, decorators: [{
4903
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: CheckboxAttribute, decorators: [{
4906
4904
  type: Component,
4907
4905
  args: [{ selector: 'checkbox-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeInput, AttributeSwitch, AttributeExpression, TranslatePipe], template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n </div>\n</details>\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n}\n" }]
4908
4906
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
@@ -4972,10 +4970,10 @@ class BuildQueries {
4972
4970
  this.modal?.close();
4973
4971
  this.ref.markForCheck();
4974
4972
  };
4975
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: BuildQueries, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
4976
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: BuildQueries, isStandalone: true, selector: "build-queries", inputs: { label: "label", _queries: ["queries", "_queries"], components: "components", variables: "variables", _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "@if (!!leftProperties?.length) {\n <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\n </div>\n </div>\n <sd-modal [title]=\"'core.component.form-builder.set-query-value' | translate\" width=\"400px\">\n <div class=\"c-builder\">\n @for (property of leftProperties; track property.value) {\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\n <div class=\"T14M\" style=\"width: 150px\">{{ property.display }}</div>\n <sd-autocomplete\n [label]=\"'core.component.form-builder.value-source-field' | translate\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"model![property.value]\"\n [items]=\"rightProperties\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-autocomplete>\n </div>\n }\n </div>\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\n </ng-container>\n </sd-modal>\n}\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4973
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BuildQueries, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
4974
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: BuildQueries, isStandalone: true, selector: "build-queries", inputs: { label: "label", _queries: ["queries", "_queries"], components: "components", variables: "variables", _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "@if (!!leftProperties?.length) {\n <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\n </div>\n </div>\n <sd-modal [title]=\"'core.component.form-builder.set-query-value' | translate\" width=\"400px\">\n <div class=\"c-builder\">\n @for (property of leftProperties; track property.value) {\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\n <div class=\"T14M\" style=\"width: 150px\">{{ property.display }}</div>\n <sd-autocomplete\n [label]=\"'core.component.form-builder.value-source-field' | translate\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"model![property.value]\"\n [items]=\"rightProperties\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-autocomplete>\n </div>\n }\n </div>\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\n </ng-container>\n </sd-modal>\n}\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "clearable", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4977
4975
  }
4978
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: BuildQueries, decorators: [{
4976
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BuildQueries, decorators: [{
4979
4977
  type: Component,
4980
4978
  args: [{ selector: 'build-queries', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdAutocomplete$1, SdButton, SdModal, TranslatePipe], template: "@if (!!leftProperties?.length) {\n <div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\n </div>\n </div>\n <sd-modal [title]=\"'core.component.form-builder.set-query-value' | translate\" width=\"400px\">\n <div class=\"c-builder\">\n @for (property of leftProperties; track property.value) {\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\n <div class=\"T14M\" style=\"width: 150px\">{{ property.display }}</div>\n <sd-autocomplete\n [label]=\"'core.component.form-builder.value-source-field' | translate\"\n [form]=\"form\"\n style=\"flex: 1\"\n [(model)]=\"model![property.value]\"\n [items]=\"rightProperties\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError></sd-autocomplete>\n </div>\n }\n </div>\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\n </ng-container>\n </sd-modal>\n}\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"] }]
4981
4979
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { modal: [{
@@ -5073,10 +5071,10 @@ class HtmlAttribute {
5073
5071
  this.ref.markForCheck();
5074
5072
  }
5075
5073
  };
5076
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HtmlAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: FormGenericService }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
5077
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: HtmlAttribute, isStandalone: true, selector: "html-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, outputs: { attributeChanges: "attributeChanges" }, ngImport: i0, template: "@if (!component.properties!.hidden) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-select\n [label]=\"'core.component.form-builder.template-data' | translate\"\n [(model)]=\"component.template\"\n [items]=\"definitionHtmls\"\n (sdChange)=\"onChangeDefinition($event)\"></attribute-select>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\"></attribute-input>\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.content' | translate\" [(model)]=\"component.content\"></attribute-textarea>\n @if (component.properties?.queries?.length) {\n <build-queries\n [label]=\"'core.component.form-builder.query-condition' | translate\"\n [queries]=\"component.properties?.queries\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.query\"></build-queries>\n }\n </div>\n </details>\n @if (component.properties?.variables?.length) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">format_list_bulleted</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.parameter' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n @for (variable of component.properties?.variables; track variable.key) {\n <attribute-input [form]=\"form\" [label]=\"variable.label\" [(model)]=\"variable.value\"></attribute-input>\n }\n </div>\n </details>\n }\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n </div>\n </details>\n}\n", dependencies: [{ kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: BuildQueries, selector: "build-queries", inputs: ["label", "queries", "components", "variables", "model"], outputs: ["modelChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5074
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: HtmlAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: FormGenericService }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
5075
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: HtmlAttribute, isStandalone: true, selector: "html-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, outputs: { attributeChanges: "attributeChanges" }, ngImport: i0, template: "@if (!component.properties!.hidden) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-select\n [label]=\"'core.component.form-builder.template-data' | translate\"\n [(model)]=\"component.template\"\n [items]=\"definitionHtmls\"\n (sdChange)=\"onChangeDefinition($event)\"></attribute-select>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\"></attribute-input>\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.content' | translate\" [(model)]=\"component.content\"></attribute-textarea>\n @if (component.properties?.queries?.length) {\n <build-queries\n [label]=\"'core.component.form-builder.query-condition' | translate\"\n [queries]=\"component.properties?.queries\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.query\"></build-queries>\n }\n </div>\n </details>\n @if (component.properties?.variables?.length) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">format_list_bulleted</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.parameter' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n @for (variable of component.properties?.variables; track variable.key) {\n <attribute-input [form]=\"form\" [label]=\"variable.label\" [(model)]=\"variable.value\"></attribute-input>\n }\n </div>\n </details>\n }\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n </div>\n </details>\n}\n", dependencies: [{ kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: BuildQueries, selector: "build-queries", inputs: ["label", "queries", "components", "variables", "model"], outputs: ["modelChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5078
5076
  }
5079
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HtmlAttribute, decorators: [{
5077
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: HtmlAttribute, decorators: [{
5080
5078
  type: Component,
5081
5079
  args: [{ selector: 'html-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeInput, AttributeSelect, AttributeExpression, AttributeTextarea, BuildQueries, TranslatePipe], template: "@if (!component.properties!.hidden) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-select\n [label]=\"'core.component.form-builder.template-data' | translate\"\n [(model)]=\"component.template\"\n [items]=\"definitionHtmls\"\n (sdChange)=\"onChangeDefinition($event)\"></attribute-select>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\"></attribute-input>\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.content' | translate\" [(model)]=\"component.content\"></attribute-textarea>\n @if (component.properties?.queries?.length) {\n <build-queries\n [label]=\"'core.component.form-builder.query-condition' | translate\"\n [queries]=\"component.properties?.queries\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.query\"></build-queries>\n }\n </div>\n </details>\n @if (component.properties?.variables?.length) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">format_list_bulleted</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.parameter' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n @for (variable of component.properties?.variables; track variable.key) {\n <attribute-input [form]=\"form\" [label]=\"variable.label\" [(model)]=\"variable.value\"></attribute-input>\n }\n </div>\n </details>\n }\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n </div>\n </details>\n}\n" }]
5082
5080
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: FormGenericService }, { type: BuilderService }], propDecorators: { components: [{
@@ -5134,10 +5132,10 @@ class HtmlControl {
5134
5132
  ngOnDestroy() {
5135
5133
  this.#subscription.unsubscribe();
5136
5134
  }
5137
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HtmlControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
5138
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: HtmlControl, isStandalone: true, selector: "html-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (!content) {\n <div class=\"c-html d-flex align-items-center justify-content-center\">\n <span class=\"material-icons\"> html </span>\n </div>\n} @else {\n <div [innerHTML]=\"hashed | htmlPipe: content: component\"></div>\n}\n", styles: [".c-html{height:70px;border:1px solid var(--md-sys-color-outline-variant);padding:10px;background-color:#f4f4f4}.c-html .material-icons{font-size:48px}\n"], dependencies: [{ kind: "pipe", type: HtmlPipe, name: "htmlPipe" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5135
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: HtmlControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
5136
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: HtmlControl, isStandalone: true, selector: "html-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (!content) {\n <div class=\"c-html d-flex align-items-center justify-content-center\">\n <span class=\"material-icons\"> html </span>\n </div>\n} @else {\n <div [innerHTML]=\"hashed | htmlPipe: content: component\"></div>\n}\n", styles: [".c-html{height:70px;border:1px solid var(--md-sys-color-outline-variant);padding:10px;background-color:#f4f4f4}.c-html .material-icons{font-size:48px}\n"], dependencies: [{ kind: "pipe", type: HtmlPipe, name: "htmlPipe" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5139
5137
  }
5140
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HtmlControl, decorators: [{
5138
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: HtmlControl, decorators: [{
5141
5139
  type: Component,
5142
5140
  args: [{ selector: 'html-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [HtmlPipe], template: "@if (!content) {\n <div class=\"c-html d-flex align-items-center justify-content-center\">\n <span class=\"material-icons\"> html </span>\n </div>\n} @else {\n <div [innerHTML]=\"hashed | htmlPipe: content: component\"></div>\n}\n", styles: [".c-html{height:70px;border:1px solid var(--md-sys-color-outline-variant);padding:10px;background-color:#f4f4f4}.c-html .material-icons{font-size:48px}\n"] }]
5143
5141
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }, { type: FormGenericService }], propDecorators: { _component: [{
@@ -5205,10 +5203,10 @@ class AttributeParameter {
5205
5203
  this.modal?.close();
5206
5204
  this.ref.markForCheck();
5207
5205
  };
5208
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeParameter, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
5209
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: AttributeParameter, isStandalone: true, selector: "attribute-parameter", inputs: { components: "components", label: "label", _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\n </div>\n</div>\n<sd-modal [title]=\"'core.component.form-builder.assign-parameter-value' | translate\" width=\"500px\">\n <div class=\"c-builder\">\n <div class=\"d-flex justify-content-end\">\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.add-field' | translate\" color=\"primary\" (click)=\"addField()\"></sd-button>\n </div>\n <!-- C\u1EA5p 1 -->\n @for (item of items; track item.id; let idx = $index) {\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\n <sd-input [label]=\"'core.component.form-builder.parameter-name' | translate\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"item.key\" required hideInlineError></sd-input>\n <sd-input [label]=\"'core.component.form-builder.parameter-value' | translate\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"item.value\" required hideInlineError></sd-input>\n <div style=\"width: 32px; min-width: 32px\">\n <sd-button\n prefixIcon=\"delete\"\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"remove(idx)\"\n size=\"sm\"\n class=\"p-0\"\n ></sd-button>\n </div>\n </div>\n }\n </div>\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\n </ng-container>\n</sd-modal>\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5206
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeParameter, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
5207
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: AttributeParameter, isStandalone: true, selector: "attribute-parameter", inputs: { components: "components", label: "label", _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\n </div>\n</div>\n<sd-modal [title]=\"'core.component.form-builder.assign-parameter-value' | translate\" width=\"500px\">\n <div class=\"c-builder\">\n <div class=\"d-flex justify-content-end\">\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.add-field' | translate\" color=\"primary\" (click)=\"addField()\"></sd-button>\n </div>\n <!-- C\u1EA5p 1 -->\n @for (item of items; track item.id; let idx = $index) {\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\n <sd-input [label]=\"'core.component.form-builder.parameter-name' | translate\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"item.key\" required hideInlineError></sd-input>\n <sd-input [label]=\"'core.component.form-builder.parameter-value' | translate\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"item.value\" required hideInlineError></sd-input>\n <div style=\"width: 32px; min-width: 32px\">\n <sd-button\n prefixIcon=\"delete\"\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"remove(idx)\"\n size=\"sm\"\n class=\"p-0\"\n ></sd-button>\n </div>\n </div>\n }\n </div>\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\n </ng-container>\n</sd-modal>\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5210
5208
  }
5211
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeParameter, decorators: [{
5209
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeParameter, decorators: [{
5212
5210
  type: Component,
5213
5211
  args: [{ selector: 'attribute-parameter', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdButton, SdModal, SdInput, TranslatePipe], template: "<div class=\"d-flex align-items-center py-4\">\n @if (label) {\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\n }\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\n </div>\n</div>\n<sd-modal [title]=\"'core.component.form-builder.assign-parameter-value' | translate\" width=\"500px\">\n <div class=\"c-builder\">\n <div class=\"d-flex justify-content-end\">\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.add-field' | translate\" color=\"primary\" (click)=\"addField()\"></sd-button>\n </div>\n <!-- C\u1EA5p 1 -->\n @for (item of items; track item.id; let idx = $index) {\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\n <sd-input [label]=\"'core.component.form-builder.parameter-name' | translate\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"item.key\" required hideInlineError></sd-input>\n <sd-input [label]=\"'core.component.form-builder.parameter-value' | translate\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"item.value\" required hideInlineError></sd-input>\n <div style=\"width: 32px; min-width: 32px\">\n <sd-button\n prefixIcon=\"delete\"\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"remove(idx)\"\n size=\"sm\"\n class=\"p-0\"\n ></sd-button>\n </div>\n </div>\n }\n </div>\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\n </ng-container>\n</sd-modal>\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"] }]
5214
5212
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { modal: [{
@@ -5294,10 +5292,10 @@ class UploadAttribute {
5294
5292
  ?.map(val => val?.trim())
5295
5293
  ?.filter(val => !!val) || [];
5296
5294
  };
5297
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: UploadAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
5298
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: UploadAttribute, isStandalone: true, selector: "upload-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n <attribute-select\n [label]=\"'core.component.form-builder.type' | translate\"\n [(model)]=\"component.properties!.type\"\n [items]=\"[\n { value: 'file', display: ('core.component.form-builder.file' | translate) },\n { value: 'image', display: ('core.component.form-builder.image' | translate) }\n ]\"></attribute-select>\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n <attribute-input-number [label]=\"'core.component.form-builder.max-files' | translate\" [(model)]=\"component.properties!.max\"></attribute-input-number>\n <attribute-input-number [label]=\"'core.component.form-builder.size-mb' | translate\" [(model)]=\"component.properties!.maxSize\"></attribute-input-number>\n @if (component.properties!.type === 'file') {\n <attribute-input [label]=\"'core.component.form-builder.format-example' | translate\" [model]=\"extension\" (modelChange)=\"onChangeExtension($event)\"></attribute-input>\n }\n @if (component.properties!.type === 'image') {\n <attribute-select [label]=\"'core.component.form-builder.source-mobile' | translate\" [(model)]=\"component.properties!.source\" [items]=\"sources\"></attribute-select>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">settings</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.parameter' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-parameter [label]=\"'core.component.form-builder.assign-parameter' | translate\" [components]=\"components\" [(model)]=\"component.properties!.args\"></attribute-parameter>\n </div>\n </details>\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInputNumber, selector: "attribute-input-number", inputs: ["label", "disabled", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeParameter, selector: "attribute-parameter", inputs: ["components", "label", "model"], outputs: ["modelChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5295
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: UploadAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
5296
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: UploadAttribute, isStandalone: true, selector: "upload-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n <attribute-select\n [label]=\"'core.component.form-builder.type' | translate\"\n [(model)]=\"component.properties!.type\"\n [items]=\"[\n { value: 'file', display: ('core.component.form-builder.file' | translate) },\n { value: 'image', display: ('core.component.form-builder.image' | translate) }\n ]\"></attribute-select>\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n <attribute-input-number [label]=\"'core.component.form-builder.max-files' | translate\" [(model)]=\"component.properties!.max\"></attribute-input-number>\n <attribute-input-number [label]=\"'core.component.form-builder.size-mb' | translate\" [(model)]=\"component.properties!.maxSize\"></attribute-input-number>\n @if (component.properties!.type === 'file') {\n <attribute-input [label]=\"'core.component.form-builder.format-example' | translate\" [model]=\"extension\" (modelChange)=\"onChangeExtension($event)\"></attribute-input>\n }\n @if (component.properties!.type === 'image') {\n <attribute-select [label]=\"'core.component.form-builder.source-mobile' | translate\" [(model)]=\"component.properties!.source\" [items]=\"sources\"></attribute-select>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">settings</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.parameter' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-parameter [label]=\"'core.component.form-builder.assign-parameter' | translate\" [components]=\"components\" [(model)]=\"component.properties!.args\"></attribute-parameter>\n </div>\n </details>\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInputNumber, selector: "attribute-input-number", inputs: ["label", "disabled", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeParameter, selector: "attribute-parameter", inputs: ["components", "label", "model"], outputs: ["modelChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5299
5297
  }
5300
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: UploadAttribute, decorators: [{
5298
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: UploadAttribute, decorators: [{
5301
5299
  type: Component,
5302
5300
  args: [{ selector: 'upload-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeInput, AttributeInputNumber, AttributeSwitch, AttributeSelect, AttributeExpression, AttributeParameter, TranslatePipe], template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n <attribute-select\n [label]=\"'core.component.form-builder.type' | translate\"\n [(model)]=\"component.properties!.type\"\n [items]=\"[\n { value: 'file', display: ('core.component.form-builder.file' | translate) },\n { value: 'image', display: ('core.component.form-builder.image' | translate) }\n ]\"></attribute-select>\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n <attribute-input-number [label]=\"'core.component.form-builder.max-files' | translate\" [(model)]=\"component.properties!.max\"></attribute-input-number>\n <attribute-input-number [label]=\"'core.component.form-builder.size-mb' | translate\" [(model)]=\"component.properties!.maxSize\"></attribute-input-number>\n @if (component.properties!.type === 'file') {\n <attribute-input [label]=\"'core.component.form-builder.format-example' | translate\" [model]=\"extension\" (modelChange)=\"onChangeExtension($event)\"></attribute-input>\n }\n @if (component.properties!.type === 'image') {\n <attribute-select [label]=\"'core.component.form-builder.source-mobile' | translate\" [(model)]=\"component.properties!.source\" [items]=\"sources\"></attribute-select>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">settings</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.parameter' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-parameter [label]=\"'core.component.form-builder.assign-parameter' | translate\" [components]=\"components\" [(model)]=\"component.properties!.args\"></attribute-parameter>\n </div>\n </details>\n}\n" }]
5303
5301
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
@@ -5338,10 +5336,10 @@ class UploadControl {
5338
5336
  ngOnDestroy() {
5339
5337
  this.#subscription.unsubscribe();
5340
5338
  }
5341
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: UploadControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
5342
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: UploadControl, isStandalone: true, selector: "upload-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <svg\n width=\"64\"\n height=\"64\"\n viewBox=\"0 0 1280 1280\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n stroke-linejoin=\"round\"\n stroke-miterlimit=\"2\"\n alt=\"This is an image placeholder\">\n <path fill=\"#e5e9ed\" d=\"M0 0h1280v1280H0z\"></path>\n <path d=\"M910 410H370v470h540V410zm-57.333 57.333v355.334H427.333V467.333h425.334z\" fill=\"#cad3db\"></path>\n <path d=\"M810 770H480v-60l100-170 130 170 100-65v125z\" fill=\"#cad3db\"></path>\n <circle cx=\"750\" cy=\"550\" r=\"50\" fill=\"#cad3db\" transform=\"translate(10 10)\"></circle>\n </svg>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"c-upload-file d-flex align-items-center justify-content-between\">\n <svg\n width=\"64\"\n height=\"64\"\n viewBox=\"0 0 1280 1280\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n stroke-linejoin=\"round\"\n stroke-miterlimit=\"2\"\n alt=\"This is an image placeholder\">\n <path fill=\"#e5e9ed\" d=\"M0 0h1280v1280H0z\"></path>\n <path d=\"M910 410H370v470h540V410zm-57.333 57.333v355.334H427.333V467.333h425.334z\" fill=\"#cad3db\"></path>\n <path d=\"M810 770H480v-60l100-170 130 170 100-65v125z\" fill=\"#cad3db\"></path>\n <circle cx=\"750\" cy=\"550\" r=\"50\" fill=\"#cad3db\" transform=\"translate(10 10)\"></circle>\n </svg>\n </div>\n}\n", styles: [".c-upload-file{border:1px solid var(--md-sys-color-outline-variant);padding:5px;color:#afafaf}.c-upload-file .material-icons{font-size:20px!important}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5339
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: UploadControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
5340
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: UploadControl, isStandalone: true, selector: "upload-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <svg\n width=\"64\"\n height=\"64\"\n viewBox=\"0 0 1280 1280\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n stroke-linejoin=\"round\"\n stroke-miterlimit=\"2\"\n alt=\"This is an image placeholder\">\n <path fill=\"#e5e9ed\" d=\"M0 0h1280v1280H0z\"></path>\n <path d=\"M910 410H370v470h540V410zm-57.333 57.333v355.334H427.333V467.333h425.334z\" fill=\"#cad3db\"></path>\n <path d=\"M810 770H480v-60l100-170 130 170 100-65v125z\" fill=\"#cad3db\"></path>\n <circle cx=\"750\" cy=\"550\" r=\"50\" fill=\"#cad3db\" transform=\"translate(10 10)\"></circle>\n </svg>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"c-upload-file d-flex align-items-center justify-content-between\">\n <svg\n width=\"64\"\n height=\"64\"\n viewBox=\"0 0 1280 1280\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n stroke-linejoin=\"round\"\n stroke-miterlimit=\"2\"\n alt=\"This is an image placeholder\">\n <path fill=\"#e5e9ed\" d=\"M0 0h1280v1280H0z\"></path>\n <path d=\"M910 410H370v470h540V410zm-57.333 57.333v355.334H427.333V467.333h425.334z\" fill=\"#cad3db\"></path>\n <path d=\"M810 770H480v-60l100-170 130 170 100-65v125z\" fill=\"#cad3db\"></path>\n <circle cx=\"750\" cy=\"550\" r=\"50\" fill=\"#cad3db\" transform=\"translate(10 10)\"></circle>\n </svg>\n </div>\n}\n", styles: [".c-upload-file{border:1px solid var(--md-sys-color-outline-variant);padding:5px;color:#afafaf}.c-upload-file .material-icons{font-size:20px!important}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5343
5341
  }
5344
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: UploadControl, decorators: [{
5342
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: UploadControl, decorators: [{
5345
5343
  type: Component,
5346
5344
  args: [{ selector: 'upload-control', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (component.properties?.viewed) {\n <div class=\"d-block T12R text-secondary\">\n {{ component.label }}\n </div>\n <svg\n width=\"64\"\n height=\"64\"\n viewBox=\"0 0 1280 1280\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n stroke-linejoin=\"round\"\n stroke-miterlimit=\"2\"\n alt=\"This is an image placeholder\">\n <path fill=\"#e5e9ed\" d=\"M0 0h1280v1280H0z\"></path>\n <path d=\"M910 410H370v470h540V410zm-57.333 57.333v355.334H427.333V467.333h425.334z\" fill=\"#cad3db\"></path>\n <path d=\"M810 770H480v-60l100-170 130 170 100-65v125z\" fill=\"#cad3db\"></path>\n <circle cx=\"750\" cy=\"550\" r=\"50\" fill=\"#cad3db\" transform=\"translate(10 10)\"></circle>\n </svg>\n} @else {\n <div class=\"d-block mb-0 T14M\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span class=\"text-error mb-2\">*</span>\n }\n </div>\n <div class=\"c-upload-file d-flex align-items-center justify-content-between\">\n <svg\n width=\"64\"\n height=\"64\"\n viewBox=\"0 0 1280 1280\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n stroke-linejoin=\"round\"\n stroke-miterlimit=\"2\"\n alt=\"This is an image placeholder\">\n <path fill=\"#e5e9ed\" d=\"M0 0h1280v1280H0z\"></path>\n <path d=\"M910 410H370v470h540V410zm-57.333 57.333v355.334H427.333V467.333h425.334z\" fill=\"#cad3db\"></path>\n <path d=\"M810 770H480v-60l100-170 130 170 100-65v125z\" fill=\"#cad3db\"></path>\n <circle cx=\"750\" cy=\"550\" r=\"50\" fill=\"#cad3db\" transform=\"translate(10 10)\"></circle>\n </svg>\n </div>\n}\n", styles: [".c-upload-file{border:1px solid var(--md-sys-color-outline-variant);padding:5px;color:#afafaf}.c-upload-file .material-icons{font-size:20px!important}\n"] }]
5347
5345
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
@@ -5447,10 +5445,10 @@ class AttributeTable {
5447
5445
  }
5448
5446
  this.modal?.close();
5449
5447
  };
5450
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeTable, deps: [{ token: SD_FORM_GENERIC_CONFIGURATION, optional: true }], target: i0.ɵɵFactoryTarget.Component });
5451
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: AttributeTable, isStandalone: true, selector: "attribute-table", inputs: { components: "components", variables: "variables", _columnsKey: ["columnsKey", "_columnsKey"], _columns: ["columns", "_columns"] }, outputs: { columnsKeyChange: "columnsKeyChange", columnsChange: "columnsChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">view_column</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.column-list' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n @if (tables.length) {\n <sd-autocomplete\n class=\"py-8\"\n [label]=\"'core.component.form-builder.column-data' | translate\"\n [(model)]=\"columnsKey\"\n [items]=\"tables\"\n valueField=\"value\"\n displayField=\"display\"\n (sdChange)=\"onChangeColumnsKey($event)\"\n hideInlineError></sd-autocomplete>\n }\n @if (!columnsKey) {\n <div class=\"fb-columns-list\">\n @for (item of columns; track item.key; let idx = $index) {\n <div class=\"fb-column-row\" [class.is-active]=\"idx === selectedIdx\">\n <span class=\"fb-column-row__type-icon\"><span class=\"msi\">{{ columnTypeSymbol(item.type) }}</span></span>\n <div class=\"fb-column-row__meta\">\n <div class=\"fb-column-row__label\">\n {{ item.label }}\n @if (item.validate?.required) {\n <span class=\"fb-column-row__req\">*</span>\n }\n </div>\n <div class=\"fb-column-row__sub mono\">{{ item.key }} \u00B7 {{ item.type }}</div>\n </div>\n <button type=\"button\" class=\"fb-icon-btn\" [attr.aria-label]=\"'core.component.form-builder.column-config' | translate\" (click)=\"editColumn(idx)\">\n <span class=\"msi\">edit</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn danger\" [attr.aria-label]=\"'core.component.form-builder.delete' | translate\" (click)=\"removeColumn(idx)\">\n <span class=\"msi\">delete</span>\n </button>\n </div>\n }\n <a class=\"fb-add-link\" (click)=\"addColumn()\">\n <span class=\"msi\">add</span>\n {{ 'core.component.form-builder.add-column' | translate }}\n </a>\n </div>\n }\n </div>\n</details>\n\n<sd-modal [title]=\"'core.component.form-builder.column-config' | translate\" width=\"600px\">\n @if (column) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"column.key\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.column-name' | translate\" [(model)]=\"column.label\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.width' | translate\" [(model)]=\"column.width\"></attribute-input>\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"column.validate!.required\"></attribute-switch>\n <attribute-select [form]=\"form\" [label]=\"'core.component.form-builder.data-type' | translate\" [(model)]=\"column.type\" [items]=\"types\"></attribute-select>\n </div>\n </details>\n @if (column.type === 'boolean') {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.show-when-true' | translate\" [(model)]=\"column.displayOnTrue\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.show-when-false' | translate\" [(model)]=\"column.displayOnFalse\"></attribute-input>\n </div>\n </details>\n } @else if (column.type === 'values') {\n <attribute-selection\n [components]=\"components\"\n [variables]=\"variables\"\n [component]=\"column\"\n [(valuesKey)]=\"column.valuesKey\"\n [(values)]=\"column.values\"></attribute-selection>\n } @else if (column.type === 'file' || column.type === 'image') {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">settings</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.parameter' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-parameter [label]=\"'core.component.form-builder.assign-parameter' | translate\" [components]=\"components\" [(model)]=\"column!.args\"></attribute-parameter>\n </div>\n </details>\n }\n }\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"onConfirm()\" color=\"primary\"></sd-button>\n </ng-container>\n</sd-modal>\n", dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: AttributeSelection, selector: "attribute-selection", inputs: ["components", "variables", "component", "valuesKey", "values"], outputs: ["valuesKeyChange", "valuesChange", "sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeParameter, selector: "attribute-parameter", inputs: ["components", "label", "model"], outputs: ["modelChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
5448
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeTable, deps: [{ token: SD_FORM_GENERIC_CONFIGURATION, optional: true }], target: i0.ɵɵFactoryTarget.Component });
5449
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: AttributeTable, isStandalone: true, selector: "attribute-table", inputs: { components: "components", variables: "variables", _columnsKey: ["columnsKey", "_columnsKey"], _columns: ["columns", "_columns"] }, outputs: { columnsKeyChange: "columnsKeyChange", columnsChange: "columnsChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">view_column</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.column-list' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n @if (tables.length) {\n <sd-autocomplete\n class=\"py-8\"\n [label]=\"'core.component.form-builder.column-data' | translate\"\n [(model)]=\"columnsKey\"\n [items]=\"tables\"\n valueField=\"value\"\n displayField=\"display\"\n (sdChange)=\"onChangeColumnsKey($event)\"\n hideInlineError></sd-autocomplete>\n }\n @if (!columnsKey) {\n <div class=\"fb-columns-list\">\n @for (item of columns; track item.key; let idx = $index) {\n <div class=\"fb-column-row\" [class.is-active]=\"idx === selectedIdx\">\n <span class=\"fb-column-row__type-icon\"><span class=\"msi\">{{ columnTypeSymbol(item.type) }}</span></span>\n <div class=\"fb-column-row__meta\">\n <div class=\"fb-column-row__label\">\n {{ item.label }}\n @if (item.validate?.required) {\n <span class=\"fb-column-row__req\">*</span>\n }\n </div>\n <div class=\"fb-column-row__sub mono\">{{ item.key }} \u00B7 {{ item.type }}</div>\n </div>\n <button type=\"button\" class=\"fb-icon-btn\" [attr.aria-label]=\"'core.component.form-builder.column-config' | translate\" (click)=\"editColumn(idx)\">\n <span class=\"msi\">edit</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn danger\" [attr.aria-label]=\"'core.component.form-builder.delete' | translate\" (click)=\"removeColumn(idx)\">\n <span class=\"msi\">delete</span>\n </button>\n </div>\n }\n <a class=\"fb-add-link\" (click)=\"addColumn()\">\n <span class=\"msi\">add</span>\n {{ 'core.component.form-builder.add-column' | translate }}\n </a>\n </div>\n }\n </div>\n</details>\n\n<sd-modal [title]=\"'core.component.form-builder.column-config' | translate\" width=\"600px\">\n @if (column) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"column.key\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.column-name' | translate\" [(model)]=\"column.label\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.width' | translate\" [(model)]=\"column.width\"></attribute-input>\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"column.validate!.required\"></attribute-switch>\n <attribute-select [form]=\"form\" [label]=\"'core.component.form-builder.data-type' | translate\" [(model)]=\"column.type\" [items]=\"types\"></attribute-select>\n </div>\n </details>\n @if (column.type === 'boolean') {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.show-when-true' | translate\" [(model)]=\"column.displayOnTrue\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.show-when-false' | translate\" [(model)]=\"column.displayOnFalse\"></attribute-input>\n </div>\n </details>\n } @else if (column.type === 'values') {\n <attribute-selection\n [components]=\"components\"\n [variables]=\"variables\"\n [component]=\"column\"\n [(valuesKey)]=\"column.valuesKey\"\n [(values)]=\"column.values\"></attribute-selection>\n } @else if (column.type === 'file' || column.type === 'image') {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">settings</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.parameter' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-parameter [label]=\"'core.component.form-builder.assign-parameter' | translate\" [components]=\"components\" [(model)]=\"column!.args\"></attribute-parameter>\n </div>\n </details>\n }\n }\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"onConfirm()\" color=\"primary\"></sd-button>\n </ng-container>\n</sd-modal>\n", dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "clearable", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: AttributeSelection, selector: "attribute-selection", inputs: ["components", "variables", "component", "valuesKey", "values"], outputs: ["valuesKeyChange", "valuesChange", "sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeParameter, selector: "attribute-parameter", inputs: ["components", "label", "model"], outputs: ["modelChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
5452
5450
  }
5453
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: AttributeTable, decorators: [{
5451
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AttributeTable, decorators: [{
5454
5452
  type: Component,
5455
5453
  args: [{ selector: 'attribute-table', imports: [
5456
5454
  MatIconModule,
@@ -5543,10 +5541,10 @@ class TableAttribute {
5543
5541
  onChanges = () => {
5544
5542
  this.#changes.next();
5545
5543
  };
5546
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TableAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
5547
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: TableAttribute, isStandalone: true, selector: "table-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <attribute-table\n [components]=\"components\"\n [variables]=\"variables\"\n [(columnsKey)]=\"component.columnsKey\"\n [(columns)]=\"component.columns\"\n (columnsKeyChange)=\"onChanges()\"\n (columnsChange)=\"onChanges()\"></attribute-table>\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeTable, selector: "attribute-table", inputs: ["components", "variables", "columnsKey", "columns"], outputs: ["columnsKeyChange", "columnsChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5544
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: TableAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
5545
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: TableAttribute, isStandalone: true, selector: "table-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <attribute-table\n [components]=\"components\"\n [variables]=\"variables\"\n [(columnsKey)]=\"component.columnsKey\"\n [(columns)]=\"component.columns\"\n (columnsKeyChange)=\"onChanges()\"\n (columnsChange)=\"onChanges()\"></attribute-table>\n}\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeTable, selector: "attribute-table", inputs: ["components", "variables", "columnsKey", "columns"], outputs: ["columnsKeyChange", "columnsChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5548
5546
  }
5549
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TableAttribute, decorators: [{
5547
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: TableAttribute, decorators: [{
5550
5548
  type: Component,
5551
5549
  args: [{ selector: 'table-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeInput, AttributeSwitch, AttributeTable, AttributeExpression, TranslatePipe], template: "<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\n </div>\n</details>\n\n@if (!component.properties!.hidden && !component.properties!.viewed) {\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\n <attribute-expression\n [label]=\"'core.component.form-builder.visible-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\n <attribute-expression\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\n @if (!component.disabled) {\n <attribute-expression\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">verified</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\n @if (!component.validate!.required) {\n <attribute-expression\n [label]=\"'core.component.form-builder.required-when' | translate\"\n [components]=\"components\"\n [variables]=\"variables\"\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\n }\n </div>\n </details>\n <attribute-table\n [components]=\"components\"\n [variables]=\"variables\"\n [(columnsKey)]=\"component.columnsKey\"\n [(columns)]=\"component.columns\"\n (columnsKeyChange)=\"onChanges()\"\n (columnsChange)=\"onChanges()\"></attribute-table>\n}\n" }]
5552
5550
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
@@ -5623,10 +5621,10 @@ class TableControl {
5623
5621
  return '—';
5624
5622
  return rowIndex === 1 ? 'Sample value' : '—';
5625
5623
  };
5626
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TableControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
5627
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: TableControl, isStandalone: true, selector: "table-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "<div class=\"fb-table-control\" [class.is-viewed]=\"component.properties?.viewed\">\n <div class=\"fb-table-control__label\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span>*</span>\n }\n </div>\n\n @if (component.columns?.length) {\n <div class=\"fb-table-control__frame\">\n <div class=\"fb-table-control__header\">\n @for (column of component.columns; track column.key) {\n <div class=\"fb-table-control__cell\" [style.width]=\"column.width\">\n <span class=\"fb-table-control__icon msi\">{{ columnIcon(column.type) }}</span>\n <span>{{ column.label }}</span>\n @if (column.validate?.required) {\n <span class=\"fb-table-control__required\">*</span>\n }\n </div>\n }\n </div>\n\n <div class=\"fb-table-control__body\">\n @for (row of sampleRows(); track row) {\n <div class=\"fb-table-control__row\">\n @for (column of component.columns; track column.key) {\n <div class=\"fb-table-control__cell\" [style.width]=\"column.width\">\n {{ cellPreview(column, row) }}\n </div>\n }\n </div>\n }\n </div>\n </div>\n\n <button type=\"button\" class=\"fb-table-control__add\">\n <span>+</span>\n Add row\n </button>\n }\n</div>\n", styles: [":host{display:block;width:100%;max-width:100%;min-width:0}.fb-table-control{display:flex;flex-direction:column;gap:8px;width:100%;max-width:100%;min-width:0;overflow:hidden;color:var(--sd-black500, #212121)}.fb-table-control__label{font-size:14px;line-height:20px;font-weight:600;color:var(--sd-black400, #757575)}.fb-table-control__label span{color:var(--sd-error, #F82C13)}.fb-table-control__frame{width:100%;max-width:100%;min-width:0;overflow-x:auto;overflow-y:hidden;border:1px solid var(--sd-black200, #E6E6E6);border-radius:10px;background:#fff;overscroll-behavior-x:contain}.fb-table-control__header,.fb-table-control__row{display:flex;width:max-content;min-width:max-content}.fb-table-control__header{min-height:44px;background:color-mix(in srgb,var(--sd-black100, #F2F2F2) 70%,#fff);border-bottom:1px solid var(--sd-black200, #E6E6E6)}.fb-table-control__row{min-height:42px;border-bottom:1px solid var(--sd-black200, #E6E6E6)}.fb-table-control__row:last-child{border-bottom:0}.fb-table-control__cell{width:136px;flex:0 0 auto;min-width:96px;display:inline-flex;align-items:center;gap:7px;padding:10px 14px;color:var(--sd-black400, #757575);font-size:13px;line-height:18px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;border-right:0}.fb-table-control__cell:last-child{border-right:0}.fb-table-control__header .fb-table-control__cell{color:var(--sd-black400, #757575);font-weight:700}.fb-table-control__icon{width:16px;height:16px;flex:0 0 16px;display:inline-flex;align-items:center;justify-content:center;color:var(--sd-black400, #757575);font-size:16px;line-height:1;font-variation-settings:\"FILL\" 0,\"wght\" 300,\"GRAD\" 0,\"opsz\" 20}.fb-table-control__required{color:var(--sd-error, #F82C13)}.fb-table-control__add{align-self:flex-start;height:28px;border:0;background:transparent;color:var(--sd-primary, #2A66F4);display:inline-flex;align-items:center;gap:8px;padding:0 6px;font-size:14px;font-weight:600;cursor:default}.fb-table-control__add span{font-size:18px;line-height:1}.fb-table-control.is-viewed .fb-table-control__header{background:var(--sd-black100, #F2F2F2)}.fb-table-control.is-viewed .fb-table-control__add{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5624
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: TableControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
5625
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: TableControl, isStandalone: true, selector: "table-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "<div class=\"fb-table-control\" [class.is-viewed]=\"component.properties?.viewed\">\n <div class=\"fb-table-control__label\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span>*</span>\n }\n </div>\n\n @if (component.columns?.length) {\n <div class=\"fb-table-control__frame\">\n <div class=\"fb-table-control__header\">\n @for (column of component.columns; track column.key) {\n <div class=\"fb-table-control__cell\" [style.width]=\"column.width\">\n <span class=\"fb-table-control__icon msi\">{{ columnIcon(column.type) }}</span>\n <span>{{ column.label }}</span>\n @if (column.validate?.required) {\n <span class=\"fb-table-control__required\">*</span>\n }\n </div>\n }\n </div>\n\n <div class=\"fb-table-control__body\">\n @for (row of sampleRows(); track row) {\n <div class=\"fb-table-control__row\">\n @for (column of component.columns; track column.key) {\n <div class=\"fb-table-control__cell\" [style.width]=\"column.width\">\n {{ cellPreview(column, row) }}\n </div>\n }\n </div>\n }\n </div>\n </div>\n\n <button type=\"button\" class=\"fb-table-control__add\">\n <span>+</span>\n Add row\n </button>\n }\n</div>\n", styles: [":host{display:block;width:100%;max-width:100%;min-width:0}.fb-table-control{display:flex;flex-direction:column;gap:8px;width:100%;max-width:100%;min-width:0;overflow:hidden;color:var(--sd-black500, #212121)}.fb-table-control__label{font-size:14px;line-height:20px;font-weight:600;color:var(--sd-black400, #757575)}.fb-table-control__label span{color:var(--sd-error, #F82C13)}.fb-table-control__frame{width:100%;max-width:100%;min-width:0;overflow-x:auto;overflow-y:hidden;border:1px solid var(--sd-black200, #E6E6E6);border-radius:10px;background:#fff;overscroll-behavior-x:contain}.fb-table-control__header,.fb-table-control__row{display:flex;width:max-content;min-width:max-content}.fb-table-control__header{min-height:44px;background:color-mix(in srgb,var(--sd-black100, #F2F2F2) 70%,#fff);border-bottom:1px solid var(--sd-black200, #E6E6E6)}.fb-table-control__row{min-height:42px;border-bottom:1px solid var(--sd-black200, #E6E6E6)}.fb-table-control__row:last-child{border-bottom:0}.fb-table-control__cell{width:136px;flex:0 0 auto;min-width:96px;display:inline-flex;align-items:center;gap:7px;padding:10px 14px;color:var(--sd-black400, #757575);font-size:13px;line-height:18px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;border-right:0}.fb-table-control__cell:last-child{border-right:0}.fb-table-control__header .fb-table-control__cell{color:var(--sd-black400, #757575);font-weight:700}.fb-table-control__icon{width:16px;height:16px;flex:0 0 16px;display:inline-flex;align-items:center;justify-content:center;color:var(--sd-black400, #757575);font-size:16px;line-height:1;font-variation-settings:\"FILL\" 0,\"wght\" 300,\"GRAD\" 0,\"opsz\" 20}.fb-table-control__required{color:var(--sd-error, #F82C13)}.fb-table-control__add{align-self:flex-start;height:28px;border:0;background:transparent;color:var(--sd-primary, #2A66F4);display:inline-flex;align-items:center;gap:8px;padding:0 6px;font-size:14px;font-weight:600;cursor:default}.fb-table-control__add span{font-size:18px;line-height:1}.fb-table-control.is-viewed .fb-table-control__header{background:var(--sd-black100, #F2F2F2)}.fb-table-control.is-viewed .fb-table-control__add{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5628
5626
  }
5629
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: TableControl, decorators: [{
5627
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: TableControl, decorators: [{
5630
5628
  type: Component,
5631
5629
  args: [{ selector: 'table-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule], template: "<div class=\"fb-table-control\" [class.is-viewed]=\"component.properties?.viewed\">\n <div class=\"fb-table-control__label\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span>*</span>\n }\n </div>\n\n @if (component.columns?.length) {\n <div class=\"fb-table-control__frame\">\n <div class=\"fb-table-control__header\">\n @for (column of component.columns; track column.key) {\n <div class=\"fb-table-control__cell\" [style.width]=\"column.width\">\n <span class=\"fb-table-control__icon msi\">{{ columnIcon(column.type) }}</span>\n <span>{{ column.label }}</span>\n @if (column.validate?.required) {\n <span class=\"fb-table-control__required\">*</span>\n }\n </div>\n }\n </div>\n\n <div class=\"fb-table-control__body\">\n @for (row of sampleRows(); track row) {\n <div class=\"fb-table-control__row\">\n @for (column of component.columns; track column.key) {\n <div class=\"fb-table-control__cell\" [style.width]=\"column.width\">\n {{ cellPreview(column, row) }}\n </div>\n }\n </div>\n }\n </div>\n </div>\n\n <button type=\"button\" class=\"fb-table-control__add\">\n <span>+</span>\n Add row\n </button>\n }\n</div>\n", styles: [":host{display:block;width:100%;max-width:100%;min-width:0}.fb-table-control{display:flex;flex-direction:column;gap:8px;width:100%;max-width:100%;min-width:0;overflow:hidden;color:var(--sd-black500, #212121)}.fb-table-control__label{font-size:14px;line-height:20px;font-weight:600;color:var(--sd-black400, #757575)}.fb-table-control__label span{color:var(--sd-error, #F82C13)}.fb-table-control__frame{width:100%;max-width:100%;min-width:0;overflow-x:auto;overflow-y:hidden;border:1px solid var(--sd-black200, #E6E6E6);border-radius:10px;background:#fff;overscroll-behavior-x:contain}.fb-table-control__header,.fb-table-control__row{display:flex;width:max-content;min-width:max-content}.fb-table-control__header{min-height:44px;background:color-mix(in srgb,var(--sd-black100, #F2F2F2) 70%,#fff);border-bottom:1px solid var(--sd-black200, #E6E6E6)}.fb-table-control__row{min-height:42px;border-bottom:1px solid var(--sd-black200, #E6E6E6)}.fb-table-control__row:last-child{border-bottom:0}.fb-table-control__cell{width:136px;flex:0 0 auto;min-width:96px;display:inline-flex;align-items:center;gap:7px;padding:10px 14px;color:var(--sd-black400, #757575);font-size:13px;line-height:18px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;border-right:0}.fb-table-control__cell:last-child{border-right:0}.fb-table-control__header .fb-table-control__cell{color:var(--sd-black400, #757575);font-weight:700}.fb-table-control__icon{width:16px;height:16px;flex:0 0 16px;display:inline-flex;align-items:center;justify-content:center;color:var(--sd-black400, #757575);font-size:16px;line-height:1;font-variation-settings:\"FILL\" 0,\"wght\" 300,\"GRAD\" 0,\"opsz\" 20}.fb-table-control__required{color:var(--sd-error, #F82C13)}.fb-table-control__add{align-self:flex-start;height:28px;border:0;background:transparent;color:var(--sd-primary, #2A66F4);display:inline-flex;align-items:center;gap:8px;padding:0 6px;font-size:14px;font-weight:600;cursor:default}.fb-table-control__add span{font-size:18px;line-height:1}.fb-table-control.is-viewed .fb-table-control__header{background:var(--sd-black100, #F2F2F2)}.fb-table-control.is-viewed .fb-table-control__add{display:none}\n"] }]
5632
5630
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
@@ -5677,10 +5675,10 @@ class GroupAttribute {
5677
5675
  symbolForChild = (c) => {
5678
5676
  return this.componentIcons[c.type]?.symbol ?? 'help';
5679
5677
  };
5680
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: GroupAttribute, deps: [], target: i0.ɵɵFactoryTarget.Component });
5681
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: GroupAttribute, isStandalone: true, selector: "group-attribute", inputs: { group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@let g = group();\n\n<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-input [form]=\"form\" [(model)]=\"g.label\" [label]=\"'core.component.form-builder.label' | translate\"></attribute-input>\n\n <div class=\"fb-field\">\n <div class=\"fb-field__label\">{{ 'core.component.form-builder.group-icon' | translate }}</div>\n <div class=\"fb-icon-picker\">\n @for (icon of iconPresets; track icon) {\n <button type=\"button\" class=\"fb-icon-picker__btn\"\n [class.is-active]=\"g.properties.icon === icon\"\n (click)=\"pickIcon(icon)\">\n <span class=\"msi\">{{ icon }}</span>\n </button>\n }\n </div>\n </div>\n\n <div class=\"fb-field\">\n <div class=\"fb-field__label\">{{ 'core.component.form-builder.group-accent-color' | translate }}</div>\n <div class=\"fb-color-swatches\">\n @for (color of colorPresets; track color) {\n <span class=\"fb-color-swatch\"\n [class]=\"color\"\n [class.is-active]=\"g.properties.color === color\"\n (click)=\"pickColor(color)\"\n [attr.aria-label]=\"color\"></span>\n }\n </div>\n </div>\n </div>\n</details>\n\n<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">account_tree</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.group-children' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n @if (!g.components?.length) {\n <div class=\"fb-children-empty\">{{ 'core.component.form-builder.group-no-children' | translate }}</div>\n } @else {\n <div class=\"fb-children-list\">\n @for (child of g.components; track child.id) {\n <div class=\"fb-child-row\">\n <span class=\"fb-child-row__icon\"><span class=\"msi\">{{ symbolForChild(child) }}</span></span>\n <span class=\"fb-child-row__label\">{{ child.label }}</span>\n <span class=\"fb-child-row__key\">{{ child.key }}</span>\n </div>\n }\n </div>\n }\n </div>\n</details>\n\n<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-expression\n [components]=\"[]\"\n [variables]=\"[]\"\n [(model)]=\"g.properties.visibleWhenExpression\"\n [label]=\"'core.component.form-builder.visible-when' | translate\">\n </attribute-expression>\n <attribute-expression\n [components]=\"[]\"\n [variables]=\"[]\"\n [(model)]=\"g.properties.hiddenWhenExpression\"\n [label]=\"'core.component.form-builder.hidden-when' | translate\">\n </attribute-expression>\n </div>\n</details>\n", styles: [":host{display:block}.fb-children-empty{font-size:12px;color:var(--md-sys-color-on-surface-variant);font-style:italic;padding:8px 0}\n"], dependencies: [{ kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5678
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: GroupAttribute, deps: [], target: i0.ɵɵFactoryTarget.Component });
5679
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: GroupAttribute, isStandalone: true, selector: "group-attribute", inputs: { group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@let g = group();\n\n<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-input [form]=\"form\" [(model)]=\"g.label\" [label]=\"'core.component.form-builder.label' | translate\"></attribute-input>\n\n <div class=\"fb-field\">\n <div class=\"fb-field__label\">{{ 'core.component.form-builder.group-icon' | translate }}</div>\n <div class=\"fb-icon-picker\">\n @for (icon of iconPresets; track icon) {\n <button type=\"button\" class=\"fb-icon-picker__btn\"\n [class.is-active]=\"g.properties.icon === icon\"\n (click)=\"pickIcon(icon)\">\n <span class=\"msi\">{{ icon }}</span>\n </button>\n }\n </div>\n </div>\n\n <div class=\"fb-field\">\n <div class=\"fb-field__label\">{{ 'core.component.form-builder.group-accent-color' | translate }}</div>\n <div class=\"fb-color-swatches\">\n @for (color of colorPresets; track color) {\n <span class=\"fb-color-swatch\"\n [class]=\"color\"\n [class.is-active]=\"g.properties.color === color\"\n (click)=\"pickColor(color)\"\n [attr.aria-label]=\"color\"></span>\n }\n </div>\n </div>\n </div>\n</details>\n\n<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">account_tree</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.group-children' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n @if (!g.components?.length) {\n <div class=\"fb-children-empty\">{{ 'core.component.form-builder.group-no-children' | translate }}</div>\n } @else {\n <div class=\"fb-children-list\">\n @for (child of g.components; track child.id) {\n <div class=\"fb-child-row\">\n <span class=\"fb-child-row__icon\"><span class=\"msi\">{{ symbolForChild(child) }}</span></span>\n <span class=\"fb-child-row__label\">{{ child.label }}</span>\n <span class=\"fb-child-row__key\">{{ child.key }}</span>\n </div>\n }\n </div>\n }\n </div>\n</details>\n\n<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-expression\n [components]=\"[]\"\n [variables]=\"[]\"\n [(model)]=\"g.properties.visibleWhenExpression\"\n [label]=\"'core.component.form-builder.visible-when' | translate\">\n </attribute-expression>\n <attribute-expression\n [components]=\"[]\"\n [variables]=\"[]\"\n [(model)]=\"g.properties.hiddenWhenExpression\"\n [label]=\"'core.component.form-builder.hidden-when' | translate\">\n </attribute-expression>\n </div>\n</details>\n", styles: [":host{display:block}.fb-children-empty{font-size:12px;color:var(--md-sys-color-on-surface-variant);font-style:italic;padding:8px 0}\n"], dependencies: [{ kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5682
5680
  }
5683
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: GroupAttribute, decorators: [{
5681
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: GroupAttribute, decorators: [{
5684
5682
  type: Component,
5685
5683
  args: [{ selector: 'group-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeInput, AttributeExpression, TranslatePipe], template: "@let g = group();\n\n<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">info</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-input [form]=\"form\" [(model)]=\"g.label\" [label]=\"'core.component.form-builder.label' | translate\"></attribute-input>\n\n <div class=\"fb-field\">\n <div class=\"fb-field__label\">{{ 'core.component.form-builder.group-icon' | translate }}</div>\n <div class=\"fb-icon-picker\">\n @for (icon of iconPresets; track icon) {\n <button type=\"button\" class=\"fb-icon-picker__btn\"\n [class.is-active]=\"g.properties.icon === icon\"\n (click)=\"pickIcon(icon)\">\n <span class=\"msi\">{{ icon }}</span>\n </button>\n }\n </div>\n </div>\n\n <div class=\"fb-field\">\n <div class=\"fb-field__label\">{{ 'core.component.form-builder.group-accent-color' | translate }}</div>\n <div class=\"fb-color-swatches\">\n @for (color of colorPresets; track color) {\n <span class=\"fb-color-swatch\"\n [class]=\"color\"\n [class.is-active]=\"g.properties.color === color\"\n (click)=\"pickColor(color)\"\n [attr.aria-label]=\"color\"></span>\n }\n </div>\n </div>\n </div>\n</details>\n\n<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">account_tree</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.group-children' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n @if (!g.components?.length) {\n <div class=\"fb-children-empty\">{{ 'core.component.form-builder.group-no-children' | translate }}</div>\n } @else {\n <div class=\"fb-children-list\">\n @for (child of g.components; track child.id) {\n <div class=\"fb-child-row\">\n <span class=\"fb-child-row__icon\"><span class=\"msi\">{{ symbolForChild(child) }}</span></span>\n <span class=\"fb-child-row__label\">{{ child.label }}</span>\n <span class=\"fb-child-row__key\">{{ child.key }}</span>\n </div>\n }\n </div>\n }\n </div>\n</details>\n\n<details class=\"fb-section\" open>\n <summary class=\"fb-section__head\">\n <span class=\"msi\">visibility</span>\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\n <span class=\"msi chev\">chevron_right</span>\n </summary>\n <div class=\"fb-section__body\">\n <attribute-expression\n [components]=\"[]\"\n [variables]=\"[]\"\n [(model)]=\"g.properties.visibleWhenExpression\"\n [label]=\"'core.component.form-builder.visible-when' | translate\">\n </attribute-expression>\n <attribute-expression\n [components]=\"[]\"\n [variables]=\"[]\"\n [(model)]=\"g.properties.hiddenWhenExpression\"\n [label]=\"'core.component.form-builder.hidden-when' | translate\">\n </attribute-expression>\n </div>\n</details>\n", styles: [":host{display:block}.fb-children-empty{font-size:12px;color:var(--md-sys-color-on-surface-variant);font-style:italic;padding:8px 0}\n"] }]
5686
5684
  }], ctorParameters: () => [], propDecorators: { group: [{ type: i0.Input, args: [{ isSignal: true, alias: "group", required: true }] }] } });
@@ -5767,10 +5765,10 @@ class ConfigureValidationComponent {
5767
5765
  this.accept.emit(this.validations);
5768
5766
  this.modal?.close();
5769
5767
  };
5770
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ConfigureValidationComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: SD_FORM_GENERIC_CONFIGURATION, optional: true }], target: i0.ɵɵFactoryTarget.Component });
5771
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ConfigureValidationComponent, isStandalone: true, selector: "configure-validation", outputs: { accept: "accept" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<sd-modal [title]=\"'core.component.form-builder.config-validation-error-warning' | translate\" view=\"dialog\" width=\"800px\" #popupConfigureVariables>\n @for (validation of validations; track $index; let idx = $index) {\n <div class=\"mat-elevation-z2 position-relative p-8 mb-16\" style=\"border-radius: 8px;\">\n <div class=\"row mx-0\">\n <sd-select\n class=\"col-3\"\n [label]=\"'core.component.form-builder.message-type' | translate\"\n [(model)]=\"validation.alert\"\n [items]=\"alerts\"\n valueField=\"value\"\n displayField=\"display\"\n required></sd-select>\n @if (validation.type === 'expression') {\n <sd-input class=\"col-9\" [form]=\"form\" [label]=\"'core.component.form-builder.message-display' | translate\" [(model)]=\"validation.message\" required></sd-input>\n <expression-builder class=\"col-12\" [label]=\"'core.component.form-builder.condition-expression' | translate\" [(model)]=\"validation.expression\" [attributes]=\"attributes\"></expression-builder>\n } @else if (validation.type === 'function') {\n <sd-select\n class=\"col-9\"\n [form]=\"form\"\n [(model)]=\"validation.code\"\n [items]=\"functions\"\n valueField=\"value\"\n displayField=\"display\"\n required></sd-select>\n }\n <mat-icon class=\"c-close-icon\" (click)=\"removaValidation(idx)\">delete</mat-icon>\n <!-- <sd-button\n \n prefixIcon=\"delete\"\n (click)=\"removaValidation(idx)\"\n color=\"error\"\n type=\"link\"></sd-button> -->\n </div>\n </div>\n }\n <sd-button [title]=\"'core.component.form-builder.add-validation' | translate\" [matMenuTriggerFor]=\"menu\" prefixIcon=\"add\" color=\"primary\" type=\"link\"></sd-button>\n <mat-menu #menu=\"matMenu\">\n <button (click)=\"addValidation('expression')\" mat-menu-item type=\"button\">\n <!-- <mat-icon fontIcon=\"warning\"></mat-icon> -->\n <span>{{ 'core.component.form-builder.expression' | translate }}</span>\n </button>\n <button (click)=\"addValidation('function')\" mat-menu-item type=\"button\">\n <!-- <mat-icon fontIcon=\"error\"></mat-icon> -->\n <span>{{ 'core.component.form-builder.available-methods' | translate }}</span>\n </button>\n </mat-menu>\n <ng-container sdFooter>\n <sd-button type=\"fill\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"updateValidations()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\n </ng-container>\n</sd-modal>\n", styles: [".text-primary{color:var(--sd-primary)!important}.bg-primary{background:var(--sd-primary)!important}.border-primary{border-color:var(--sd-primary)!important}.text-primary-light{color:var(--sd-primary-light)!important}.bg-primary-light{background:var(--sd-primary-light)!important}.border-primary-light{border-color:var(--sd-primary-light)!important}.text-primary-dark{color:var(--sd-primary-dark)!important}.bg-primary-dark{background:var(--sd-primary-dark)!important}.border-primary-dark{border-color:var(--sd-primary-dark)!important}.text-info{color:var(--sd-info)!important}.bg-info{background:var(--sd-info)!important}.border-info{border-color:var(--sd-info)!important}.text-info-light{color:var(--sd-info-light)!important}.bg-info-light{background:var(--sd-info-light)!important}.border-info-light{border-color:var(--sd-info-light)!important}.text-info-dark{color:var(--sd-info-dark)!important}.bg-info-dark{background:var(--sd-info-dark)!important}.border-info-dark{border-color:var(--sd-info-dark)!important}.text-success{color:var(--sd-success)!important}.bg-success{background:var(--sd-success)!important}.border-success{border-color:var(--sd-success)!important}.text-success-light{color:var(--sd-success-light)!important}.bg-success-light{background:var(--sd-success-light)!important}.border-success-light{border-color:var(--sd-success-light)!important}.text-success-dark{color:var(--sd-success-dark)!important}.bg-success-dark{background:var(--sd-success-dark)!important}.border-success-dark{border-color:var(--sd-success-dark)!important}.text-warning{color:var(--sd-warning)!important}.bg-warning{background:var(--sd-warning)!important}.border-warning{border-color:var(--sd-warning)!important}.text-warning-light{color:var(--sd-warning-light)!important}.bg-warning-light{background:var(--sd-warning-light)!important}.border-warning-light{border-color:var(--sd-warning-light)!important}.text-warning-dark{color:var(--sd-warning-dark)!important}.bg-warning-dark{background:var(--sd-warning-dark)!important}.border-warning-dark{border-color:var(--sd-warning-dark)!important}.text-error{color:var(--sd-error)!important}.bg-error{background:var(--sd-error)!important}.border-error{border-color:var(--sd-error)!important}.text-error-light{color:var(--sd-error-light)!important}.bg-error-light{background:var(--sd-error-light)!important}.border-error-light{border-color:var(--sd-error-light)!important}.text-error-dark{color:var(--sd-error-dark)!important}.bg-error-dark{background:var(--sd-error-dark)!important}.border-error-dark{border-color:var(--sd-error-dark)!important}.text-secondary{color:var(--sd-secondary)!important}.bg-secondary{background:var(--sd-secondary)!important}.border-secondary{border-color:var(--sd-secondary)!important}.text-secondary-light{color:var(--sd-secondary-light)!important}.bg-secondary-light{background:var(--sd-secondary-light)!important}.border-secondary-light{border-color:var(--sd-secondary-light)!important}.text-secondary-dark{color:var(--sd-secondary-dark)!important}.bg-secondary-dark{background:var(--sd-secondary-dark)!important}.border-secondary-dark{border-color:var(--sd-secondary-dark)!important}.text-light{color:var(--sd-light)!important}.bg-light{background:var(--sd-light)!important}.border-light{border-color:var(--sd-light)!important}.text-dark{color:var(--sd-dark)!important}.bg-dark{background:var(--sd-dark)!important}.border-dark{border-color:var(--sd-dark)!important}.text-black500{color:var(--sd-black500)!important}.bg-black500{background:var(--sd-black500)!important}.border-black500{border-color:var(--sd-black500)!important}.text-black400{color:var(--sd-black400)!important}.bg-black400{background:var(--sd-black400)!important}.border-black400{border-color:var(--sd-black400)!important}.text-black300{color:var(--sd-black300)!important}.bg-black300{background:var(--sd-black300)!important}.border-black300{border-color:var(--sd-black300)!important}.text-black200{color:var(--sd-black200)!important}.bg-black200{background:var(--sd-black200)!important}.border-black200{border-color:var(--sd-black200)!important}.text-black100{color:var(--sd-black100)!important}.bg-black100{background:var(--sd-black100)!important}.border-black100{border-color:var(--sd-black100)!important}.text-white{color:#fff!important}.bg-white{background:#fff!important}.border-white{border-color:#fff!important}.text-black{color:#000!important}.bg-black{background:#000!important}.border-black{border-color:#000!important}.c-close-icon{margin-left:auto;font-size:16px;width:16px;height:16px;cursor:pointer;border-radius:50%;color:var(--sd-error);top:4px;right:4px;position:absolute}.c-close-icon:hover{background-color:var(--sd-black200)}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$4.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i1$4.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i1$4.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "bare", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: ExpressionBuilderComponent, selector: "expression-builder", inputs: ["label", "attributes", "model"], outputs: ["modelChange", "sdChange", "edit"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5768
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ConfigureValidationComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: SD_FORM_GENERIC_CONFIGURATION, optional: true }], target: i0.ɵɵFactoryTarget.Component });
5769
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: ConfigureValidationComponent, isStandalone: true, selector: "configure-validation", outputs: { accept: "accept" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<sd-modal [title]=\"'core.component.form-builder.config-validation-error-warning' | translate\" view=\"dialog\" width=\"800px\" #popupConfigureVariables>\n @for (validation of validations; track $index; let idx = $index) {\n <div class=\"mat-elevation-z2 position-relative p-8 mb-16\" style=\"border-radius: 8px;\">\n <div class=\"row mx-0\">\n <sd-select\n class=\"col-3\"\n [label]=\"'core.component.form-builder.message-type' | translate\"\n [(model)]=\"validation.alert\"\n [items]=\"alerts\"\n valueField=\"value\"\n displayField=\"display\"\n required></sd-select>\n @if (validation.type === 'expression') {\n <sd-input class=\"col-9\" [form]=\"form\" [label]=\"'core.component.form-builder.message-display' | translate\" [(model)]=\"validation.message\" required></sd-input>\n <expression-builder class=\"col-12\" [label]=\"'core.component.form-builder.condition-expression' | translate\" [(model)]=\"validation.expression\" [attributes]=\"attributes\"></expression-builder>\n } @else if (validation.type === 'function') {\n <sd-select\n class=\"col-9\"\n [form]=\"form\"\n [(model)]=\"validation.code\"\n [items]=\"functions\"\n valueField=\"value\"\n displayField=\"display\"\n required></sd-select>\n }\n <mat-icon class=\"c-close-icon\" (click)=\"removaValidation(idx)\">delete</mat-icon>\n <!-- <sd-button\n \n prefixIcon=\"delete\"\n (click)=\"removaValidation(idx)\"\n color=\"error\"\n type=\"link\"></sd-button> -->\n </div>\n </div>\n }\n <sd-button [title]=\"'core.component.form-builder.add-validation' | translate\" [matMenuTriggerFor]=\"menu\" prefixIcon=\"add\" color=\"primary\" type=\"link\"></sd-button>\n <mat-menu #menu=\"matMenu\">\n <button (click)=\"addValidation('expression')\" mat-menu-item type=\"button\">\n <!-- <mat-icon fontIcon=\"warning\"></mat-icon> -->\n <span>{{ 'core.component.form-builder.expression' | translate }}</span>\n </button>\n <button (click)=\"addValidation('function')\" mat-menu-item type=\"button\">\n <!-- <mat-icon fontIcon=\"error\"></mat-icon> -->\n <span>{{ 'core.component.form-builder.available-methods' | translate }}</span>\n </button>\n </mat-menu>\n <ng-container sdFooter>\n <sd-button type=\"fill\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"updateValidations()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\n </ng-container>\n</sd-modal>\n", styles: [".text-primary{color:var(--sd-primary)!important}.bg-primary{background:var(--sd-primary)!important}.border-primary{border-color:var(--sd-primary)!important}.text-primary-light{color:var(--sd-primary-light)!important}.bg-primary-light{background:var(--sd-primary-light)!important}.border-primary-light{border-color:var(--sd-primary-light)!important}.text-primary-dark{color:var(--sd-primary-dark)!important}.bg-primary-dark{background:var(--sd-primary-dark)!important}.border-primary-dark{border-color:var(--sd-primary-dark)!important}.text-info{color:var(--sd-info)!important}.bg-info{background:var(--sd-info)!important}.border-info{border-color:var(--sd-info)!important}.text-info-light{color:var(--sd-info-light)!important}.bg-info-light{background:var(--sd-info-light)!important}.border-info-light{border-color:var(--sd-info-light)!important}.text-info-dark{color:var(--sd-info-dark)!important}.bg-info-dark{background:var(--sd-info-dark)!important}.border-info-dark{border-color:var(--sd-info-dark)!important}.text-success{color:var(--sd-success)!important}.bg-success{background:var(--sd-success)!important}.border-success{border-color:var(--sd-success)!important}.text-success-light{color:var(--sd-success-light)!important}.bg-success-light{background:var(--sd-success-light)!important}.border-success-light{border-color:var(--sd-success-light)!important}.text-success-dark{color:var(--sd-success-dark)!important}.bg-success-dark{background:var(--sd-success-dark)!important}.border-success-dark{border-color:var(--sd-success-dark)!important}.text-warning{color:var(--sd-warning)!important}.bg-warning{background:var(--sd-warning)!important}.border-warning{border-color:var(--sd-warning)!important}.text-warning-light{color:var(--sd-warning-light)!important}.bg-warning-light{background:var(--sd-warning-light)!important}.border-warning-light{border-color:var(--sd-warning-light)!important}.text-warning-dark{color:var(--sd-warning-dark)!important}.bg-warning-dark{background:var(--sd-warning-dark)!important}.border-warning-dark{border-color:var(--sd-warning-dark)!important}.text-error{color:var(--sd-error)!important}.bg-error{background:var(--sd-error)!important}.border-error{border-color:var(--sd-error)!important}.text-error-light{color:var(--sd-error-light)!important}.bg-error-light{background:var(--sd-error-light)!important}.border-error-light{border-color:var(--sd-error-light)!important}.text-error-dark{color:var(--sd-error-dark)!important}.bg-error-dark{background:var(--sd-error-dark)!important}.border-error-dark{border-color:var(--sd-error-dark)!important}.text-secondary{color:var(--sd-secondary)!important}.bg-secondary{background:var(--sd-secondary)!important}.border-secondary{border-color:var(--sd-secondary)!important}.text-secondary-light{color:var(--sd-secondary-light)!important}.bg-secondary-light{background:var(--sd-secondary-light)!important}.border-secondary-light{border-color:var(--sd-secondary-light)!important}.text-secondary-dark{color:var(--sd-secondary-dark)!important}.bg-secondary-dark{background:var(--sd-secondary-dark)!important}.border-secondary-dark{border-color:var(--sd-secondary-dark)!important}.text-light{color:var(--sd-light)!important}.bg-light{background:var(--sd-light)!important}.border-light{border-color:var(--sd-light)!important}.text-dark{color:var(--sd-dark)!important}.bg-dark{background:var(--sd-dark)!important}.border-dark{border-color:var(--sd-dark)!important}.text-black500{color:var(--sd-black500)!important}.bg-black500{background:var(--sd-black500)!important}.border-black500{border-color:var(--sd-black500)!important}.text-black400{color:var(--sd-black400)!important}.bg-black400{background:var(--sd-black400)!important}.border-black400{border-color:var(--sd-black400)!important}.text-black300{color:var(--sd-black300)!important}.bg-black300{background:var(--sd-black300)!important}.border-black300{border-color:var(--sd-black300)!important}.text-black200{color:var(--sd-black200)!important}.bg-black200{background:var(--sd-black200)!important}.border-black200{border-color:var(--sd-black200)!important}.text-black100{color:var(--sd-black100)!important}.bg-black100{background:var(--sd-black100)!important}.border-black100{border-color:var(--sd-black100)!important}.text-white{color:#fff!important}.bg-white{background:#fff!important}.border-white{border-color:#fff!important}.text-black{color:#000!important}.bg-black{background:#000!important}.border-black{border-color:#000!important}.c-close-icon{margin-left:auto;font-size:16px;width:16px;height:16px;cursor:pointer;border-radius:50%;color:var(--sd-error);top:4px;right:4px;position:absolute}.c-close-icon:hover{background-color:var(--sd-black200)}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$4.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i1$4.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i1$4.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "clearable", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: ExpressionBuilderComponent, selector: "expression-builder", inputs: ["label", "attributes", "model"], outputs: ["modelChange", "sdChange", "edit"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5772
5770
  }
5773
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ConfigureValidationComponent, decorators: [{
5771
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ConfigureValidationComponent, decorators: [{
5774
5772
  type: Component,
5775
5773
  args: [{ selector: 'configure-validation', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatMenuModule, SdModal, SdButton, SdInput, SdSelect, ExpressionBuilderComponent, MatIconModule, TranslatePipe], template: "<sd-modal [title]=\"'core.component.form-builder.config-validation-error-warning' | translate\" view=\"dialog\" width=\"800px\" #popupConfigureVariables>\n @for (validation of validations; track $index; let idx = $index) {\n <div class=\"mat-elevation-z2 position-relative p-8 mb-16\" style=\"border-radius: 8px;\">\n <div class=\"row mx-0\">\n <sd-select\n class=\"col-3\"\n [label]=\"'core.component.form-builder.message-type' | translate\"\n [(model)]=\"validation.alert\"\n [items]=\"alerts\"\n valueField=\"value\"\n displayField=\"display\"\n required></sd-select>\n @if (validation.type === 'expression') {\n <sd-input class=\"col-9\" [form]=\"form\" [label]=\"'core.component.form-builder.message-display' | translate\" [(model)]=\"validation.message\" required></sd-input>\n <expression-builder class=\"col-12\" [label]=\"'core.component.form-builder.condition-expression' | translate\" [(model)]=\"validation.expression\" [attributes]=\"attributes\"></expression-builder>\n } @else if (validation.type === 'function') {\n <sd-select\n class=\"col-9\"\n [form]=\"form\"\n [(model)]=\"validation.code\"\n [items]=\"functions\"\n valueField=\"value\"\n displayField=\"display\"\n required></sd-select>\n }\n <mat-icon class=\"c-close-icon\" (click)=\"removaValidation(idx)\">delete</mat-icon>\n <!-- <sd-button\n \n prefixIcon=\"delete\"\n (click)=\"removaValidation(idx)\"\n color=\"error\"\n type=\"link\"></sd-button> -->\n </div>\n </div>\n }\n <sd-button [title]=\"'core.component.form-builder.add-validation' | translate\" [matMenuTriggerFor]=\"menu\" prefixIcon=\"add\" color=\"primary\" type=\"link\"></sd-button>\n <mat-menu #menu=\"matMenu\">\n <button (click)=\"addValidation('expression')\" mat-menu-item type=\"button\">\n <!-- <mat-icon fontIcon=\"warning\"></mat-icon> -->\n <span>{{ 'core.component.form-builder.expression' | translate }}</span>\n </button>\n <button (click)=\"addValidation('function')\" mat-menu-item type=\"button\">\n <!-- <mat-icon fontIcon=\"error\"></mat-icon> -->\n <span>{{ 'core.component.form-builder.available-methods' | translate }}</span>\n </button>\n </mat-menu>\n <ng-container sdFooter>\n <sd-button type=\"fill\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"updateValidations()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\n </ng-container>\n</sd-modal>\n", styles: [".text-primary{color:var(--sd-primary)!important}.bg-primary{background:var(--sd-primary)!important}.border-primary{border-color:var(--sd-primary)!important}.text-primary-light{color:var(--sd-primary-light)!important}.bg-primary-light{background:var(--sd-primary-light)!important}.border-primary-light{border-color:var(--sd-primary-light)!important}.text-primary-dark{color:var(--sd-primary-dark)!important}.bg-primary-dark{background:var(--sd-primary-dark)!important}.border-primary-dark{border-color:var(--sd-primary-dark)!important}.text-info{color:var(--sd-info)!important}.bg-info{background:var(--sd-info)!important}.border-info{border-color:var(--sd-info)!important}.text-info-light{color:var(--sd-info-light)!important}.bg-info-light{background:var(--sd-info-light)!important}.border-info-light{border-color:var(--sd-info-light)!important}.text-info-dark{color:var(--sd-info-dark)!important}.bg-info-dark{background:var(--sd-info-dark)!important}.border-info-dark{border-color:var(--sd-info-dark)!important}.text-success{color:var(--sd-success)!important}.bg-success{background:var(--sd-success)!important}.border-success{border-color:var(--sd-success)!important}.text-success-light{color:var(--sd-success-light)!important}.bg-success-light{background:var(--sd-success-light)!important}.border-success-light{border-color:var(--sd-success-light)!important}.text-success-dark{color:var(--sd-success-dark)!important}.bg-success-dark{background:var(--sd-success-dark)!important}.border-success-dark{border-color:var(--sd-success-dark)!important}.text-warning{color:var(--sd-warning)!important}.bg-warning{background:var(--sd-warning)!important}.border-warning{border-color:var(--sd-warning)!important}.text-warning-light{color:var(--sd-warning-light)!important}.bg-warning-light{background:var(--sd-warning-light)!important}.border-warning-light{border-color:var(--sd-warning-light)!important}.text-warning-dark{color:var(--sd-warning-dark)!important}.bg-warning-dark{background:var(--sd-warning-dark)!important}.border-warning-dark{border-color:var(--sd-warning-dark)!important}.text-error{color:var(--sd-error)!important}.bg-error{background:var(--sd-error)!important}.border-error{border-color:var(--sd-error)!important}.text-error-light{color:var(--sd-error-light)!important}.bg-error-light{background:var(--sd-error-light)!important}.border-error-light{border-color:var(--sd-error-light)!important}.text-error-dark{color:var(--sd-error-dark)!important}.bg-error-dark{background:var(--sd-error-dark)!important}.border-error-dark{border-color:var(--sd-error-dark)!important}.text-secondary{color:var(--sd-secondary)!important}.bg-secondary{background:var(--sd-secondary)!important}.border-secondary{border-color:var(--sd-secondary)!important}.text-secondary-light{color:var(--sd-secondary-light)!important}.bg-secondary-light{background:var(--sd-secondary-light)!important}.border-secondary-light{border-color:var(--sd-secondary-light)!important}.text-secondary-dark{color:var(--sd-secondary-dark)!important}.bg-secondary-dark{background:var(--sd-secondary-dark)!important}.border-secondary-dark{border-color:var(--sd-secondary-dark)!important}.text-light{color:var(--sd-light)!important}.bg-light{background:var(--sd-light)!important}.border-light{border-color:var(--sd-light)!important}.text-dark{color:var(--sd-dark)!important}.bg-dark{background:var(--sd-dark)!important}.border-dark{border-color:var(--sd-dark)!important}.text-black500{color:var(--sd-black500)!important}.bg-black500{background:var(--sd-black500)!important}.border-black500{border-color:var(--sd-black500)!important}.text-black400{color:var(--sd-black400)!important}.bg-black400{background:var(--sd-black400)!important}.border-black400{border-color:var(--sd-black400)!important}.text-black300{color:var(--sd-black300)!important}.bg-black300{background:var(--sd-black300)!important}.border-black300{border-color:var(--sd-black300)!important}.text-black200{color:var(--sd-black200)!important}.bg-black200{background:var(--sd-black200)!important}.border-black200{border-color:var(--sd-black200)!important}.text-black100{color:var(--sd-black100)!important}.bg-black100{background:var(--sd-black100)!important}.border-black100{border-color:var(--sd-black100)!important}.text-white{color:#fff!important}.bg-white{background:#fff!important}.border-white{border-color:#fff!important}.text-black{color:#000!important}.bg-black{background:#000!important}.border-black{border-color:#000!important}.c-close-icon{margin-left:auto;font-size:16px;width:16px;height:16px;cursor:pointer;border-radius:50%;color:var(--sd-error);top:4px;right:4px;position:absolute}.c-close-icon:hover{background-color:var(--sd-black200)}\n"] }]
5776
5774
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
@@ -5788,7 +5786,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
5788
5786
  /* eslint-disable @angular-eslint/no-input-rename */
5789
5787
  /* eslint-disable @typescript-eslint/no-explicit-any */
5790
5788
  /* eslint-disable @typescript-eslint/no-unused-vars */
5791
- class SdFormBuilder extends SdBaseSecureComponent {
5789
+ class SdFormBuilder {
5792
5790
  // ── viewChild signals (Angular 17+) ────────────────────────────────────
5793
5791
  popupViewJSON = viewChild('popupViewJSON', ...(ngDevMode ? [{ debugName: "popupViewJSON" }] : /* istanbul ignore next */ []));
5794
5792
  popupConfigureVariables = viewChild('popupConfigureVariables', ...(ngDevMode ? [{ debugName: "popupConfigureVariables" }] : /* istanbul ignore next */ []));
@@ -5811,7 +5809,10 @@ class SdFormBuilder extends SdBaseSecureComponent {
5811
5809
  paletteSearch = signal('', ...(ngDevMode ? [{ debugName: "paletteSearch" }] : /* istanbul ignore next */ []));
5812
5810
  paletteGroups = computed(() => {
5813
5811
  const term = this.paletteSearch().trim().toLowerCase();
5814
- const match = (c) => !term || c.name.toLowerCase().includes(term) || c.type.toLowerCase().includes(term);
5812
+ // why: trong chế độ Detail group, ẩn item 'group' khỏi palette — không cho group lồng group.
5813
+ const inGroup = !!this.editingGroupId();
5814
+ const match = (c) => (!inGroup || c.type !== 'group') &&
5815
+ (!term || c.name.toLowerCase().includes(term) || c.type.toLowerCase().includes(term));
5815
5816
  const buckets = { basic: [], choice: [], advanced: [], layout: [] };
5816
5817
  for (const c of this.formBuilderComponents) {
5817
5818
  if (match(c))
@@ -5835,6 +5836,23 @@ class SdFormBuilder extends SdBaseSecureComponent {
5835
5836
  clonedVariables = [];
5836
5837
  selectedComponent = signal(undefined, ...(ngDevMode ? [{ debugName: "selectedComponent" }] : /* istanbul ignore next */ []));
5837
5838
  isPreview = signal(false, ...(ngDevMode ? [{ debugName: "isPreview" }] : /* istanbul ignore next */ []));
5839
+ // ── group drill-in (Detail) ─────────────────────────────────────────────
5840
+ // why: bỏ hẳn drag/drop trong group. Thay vào đó "Detail" 1 group → mở canvas
5841
+ // riêng chỉ thiết kế children của group đó (cùng tooling: palette/reorder/resize/
5842
+ // attribute), KHÔNG cho group lồng group. OK = giữ, Cancel = revert. Depth tối đa
5843
+ // 1 (group không chứa group) nên chỉ cần 1 con trỏ editingGroupId, không cần stack.
5844
+ editingGroupId = signal(undefined, ...(ngDevMode ? [{ debugName: "editingGroupId" }] : /* istanbul ignore next */ []));
5845
+ /** Group đang được Detail (tìm ở TOP-LEVEL theo id), undefined = đang ở canvas chính. */
5846
+ editingGroup = computed(() => {
5847
+ const id = this.editingGroupId();
5848
+ if (!id)
5849
+ return undefined;
5850
+ return this.components.find(c => c.id === id && c.type === 'group');
5851
+ }, ...(ngDevMode ? [{ debugName: "editingGroup" }] : /* istanbul ignore next */ []));
5852
+ /** Snapshot (deep clone JSON) của group.components khi vào Detail — phục vụ Cancel. */
5853
+ #groupSnapshot;
5854
+ /** Mảng components đang được canvas thao tác: children của group khi Detail, ngược lại là top-level. */
5855
+ #scope = () => this.editingGroup()?.components ?? this.components;
5838
5856
  /** Signal toàn cục: TRUE khi BẤT KỲ cdkDrag nào đang active (palette, canvas, group, resize).
5839
5857
  * Trigger class `.fb-shell--dragging` để ẩn hover/actions/resize toàn diện, không phụ thuộc :has(). */
5840
5858
  isAnyDragging = signal(false, ...(ngDevMode ? [{ debugName: "isAnyDragging" }] : /* istanbul ignore next */ []));
@@ -5874,7 +5892,6 @@ class SdFormBuilder extends SdBaseSecureComponent {
5874
5892
  #validationsChanges = new Subject();
5875
5893
  #subscription = new Subscription();
5876
5894
  constructor() {
5877
- super();
5878
5895
  // Khi input `formGeneric` ref thay đổi: clone components/variables/validations
5879
5896
  // sang local arrays và bắn subject tương ứng cho stream debounced (syncRows).
5880
5897
  // untracked() bao bọc các mutation để không tạo cycle (effect chỉ tracks formGeneric()).
@@ -5906,6 +5923,9 @@ class SdFormBuilder extends SdBaseSecureComponent {
5906
5923
  this.#subscription.unsubscribe();
5907
5924
  }
5908
5925
  addComponent = (item, index) => {
5926
+ // why: không cho thêm group khi đang Detail trong 1 group (tránh group lồng group).
5927
+ if (item.type === 'group' && this.editingGroupId())
5928
+ return;
5909
5929
  const id = GenerateId();
5910
5930
  let newComponent;
5911
5931
  if (item.type === 'group') {
@@ -5948,14 +5968,15 @@ class SdFormBuilder extends SdBaseSecureComponent {
5948
5968
  properties: {},
5949
5969
  };
5950
5970
  }
5971
+ const scope = this.#scope();
5951
5972
  if (index !== undefined) {
5952
- this.components.splice(index, 0, newComponent);
5973
+ scope.splice(index, 0, newComponent);
5953
5974
  }
5954
5975
  else {
5955
- this.components.push(newComponent);
5976
+ scope.push(newComponent);
5956
5977
  }
5957
5978
  this.#recountTabIndex();
5958
- const created = this.components?.find(component => component.id === id);
5979
+ const created = scope.find(component => component.id === id);
5959
5980
  this.selectedComponent.set(created);
5960
5981
  this.selectComponent(created);
5961
5982
  this.#ref.markForCheck();
@@ -5996,43 +6017,42 @@ class SdFormBuilder extends SdBaseSecureComponent {
5996
6017
  setMode = (preview) => {
5997
6018
  this.isPreview.set(preview);
5998
6019
  };
5999
- /** Nested drop handler when dragging a palette item or canvas item INTO a group body. */
6000
- dropInGroup = (event, group) => {
6001
- if (event.previousContainer === event.container) {
6002
- moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
6003
- return;
6004
- }
6005
- const dropped = event.previousContainer.data[event.previousIndex];
6006
- if (dropped && 'symbol' in dropped) {
6007
- // Palette → group: tạo component mới rồi push vào group.components.
6008
- const item = dropped;
6009
- if (item.type === 'group') {
6010
- this.#notifyService.warning('Group lồng group chưa được hỗ trợ.');
6011
- return;
6012
- }
6013
- const newComponent = this.#createComponentFromPalette(item);
6014
- group.components.splice(event.currentIndex, 0, newComponent);
6015
- this.selectedComponent.set(newComponent);
6016
- this.#ref.markForCheck();
6017
- }
6018
- else {
6019
- // Canvas group: chuyển instance hiện có.
6020
- const component = dropped;
6021
- if (component.type === 'group') {
6022
- this.#notifyService.warning('Group lồng group chưa được hỗ trợ.');
6023
- return;
6024
- }
6025
- transferArrayItem(event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex);
6026
- this.#syncRowsToComponents();
6020
+ // ── Group drill-in (Detail) navigation ──────────────────────────────────
6021
+ /** Mở canvas thiết kế riêng cho 1 group (chỉ children của nó). Snapshot để Cancel revert. */
6022
+ enterGroupEdit = (group) => {
6023
+ this.#groupSnapshot = JSON.stringify(group.components ?? []);
6024
+ this.editingGroupId.set(group.id);
6025
+ this.selectedComponent.set(undefined);
6026
+ this.#recountTabIndex();
6027
+ this.#ref.markForCheck();
6028
+ };
6029
+ /** OK: giữ thay đổi children, quay về canvas chính. */
6030
+ confirmGroupEdit = () => {
6031
+ this.#groupSnapshot = undefined;
6032
+ this.editingGroupId.set(undefined);
6033
+ this.selectedComponent.set(undefined);
6034
+ this.#syncComponentsToRows();
6035
+ this.#ref.markForCheck();
6036
+ };
6037
+ /** Cancel: revert children về snapshot lúc vào Detail, rồi quay về canvas chính. */
6038
+ cancelGroupEdit = () => {
6039
+ const g = this.editingGroup();
6040
+ if (g && this.#groupSnapshot !== undefined) {
6041
+ g.components = JSON.parse(this.#groupSnapshot);
6027
6042
  }
6043
+ this.#groupSnapshot = undefined;
6044
+ this.editingGroupId.set(undefined);
6045
+ this.selectedComponent.set(undefined);
6046
+ this.#syncComponentsToRows();
6047
+ this.#ref.markForCheck();
6028
6048
  };
6029
- /** Quick-add break sau row chỉ định.
6030
- * Tính component index cuối cùng của row đó trong this.components, splice break vào sau.
6031
- * Không qua palette — chỉ là utility action bám theo row trên canvas.
6049
+ /** Quick-add break sau row chỉ định (theo scope hiện tại — top-level hoặc group).
6050
+ * Tính component index cuối cùng của row đó trong scope, splice break vào sau.
6032
6051
  */
6033
6052
  insertBreakAfter = (row) => {
6053
+ const scope = this.#scope();
6034
6054
  const lastItemId = row.items[row.items.length - 1]?.id;
6035
- const insertAfter = lastItemId ? this.components.findIndex(c => c.id === lastItemId) : this.components.length - 1;
6055
+ const insertAfter = lastItemId ? scope.findIndex(c => c.id === lastItemId) : scope.length - 1;
6036
6056
  const newBreak = {
6037
6057
  id: GenerateId(),
6038
6058
  key: GenerateKey(),
@@ -6043,19 +6063,21 @@ class SdFormBuilder extends SdBaseSecureComponent {
6043
6063
  disabled: false,
6044
6064
  properties: {},
6045
6065
  };
6046
- this.components.splice(insertAfter + 1, 0, newBreak);
6066
+ scope.splice(insertAfter + 1, 0, newBreak);
6047
6067
  this.#recountTabIndex();
6048
6068
  this.#ref.markForCheck();
6049
6069
  };
6050
- /** Remove a child component from a group's nested list. */
6051
- removeFromGroup = (group, id) => {
6052
- group.components = group.components.filter(c => c.id !== id);
6070
+ /** Xoá component theo scope hiện tại (top-level hoặc children của group đang Detail). */
6071
+ removeComponent = (id) => {
6072
+ const g = this.editingGroup();
6073
+ if (g) {
6074
+ g.components = g.components.filter((t) => t.id !== id);
6075
+ }
6076
+ else {
6077
+ this.components = this.components.filter((t) => t.id !== id);
6078
+ }
6053
6079
  if (this.selectedComponent()?.id === id)
6054
6080
  this.selectedComponent.set(undefined);
6055
- this.#ref.markForCheck();
6056
- };
6057
- removeComponent = (id) => {
6058
- this.components = this.components.filter((t) => t.id !== id);
6059
6081
  this.#recountTabIndex();
6060
6082
  };
6061
6083
  selectComponent = (item) => {
@@ -6074,10 +6096,6 @@ class SdFormBuilder extends SdBaseSecureComponent {
6074
6096
  }
6075
6097
  };
6076
6098
  drop = (event) => {
6077
- if (this.#dropIntoGroupAtPointer(event)) {
6078
- this.#recountTabIndex();
6079
- return;
6080
- }
6081
6099
  if (event.previousContainer === event.container) {
6082
6100
  moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
6083
6101
  this.#syncRowsToComponents();
@@ -6085,7 +6103,7 @@ class SdFormBuilder extends SdBaseSecureComponent {
6085
6103
  if (!event.isPointerOverContainer) {
6086
6104
  const dragItemId = event.item.element.nativeElement.id;
6087
6105
  if (dragItemId) {
6088
- const dragItem = this.components.find((t) => t.id === dragItemId);
6106
+ const dragItem = this.#scope().find((t) => t.id === dragItemId);
6089
6107
  this.xuLyKeoCheo(dragItem);
6090
6108
  }
6091
6109
  }
@@ -6154,8 +6172,9 @@ class SdFormBuilder extends SdBaseSecureComponent {
6154
6172
  return false;
6155
6173
  };
6156
6174
  #recountTabIndex = () => {
6157
- // Tránh dùng map vì nó sẽ sinh ra reference mới
6158
- this.components.forEach((item, index) => {
6175
+ // Tránh dùng map vì nó sẽ sinh ra reference mới. Chạy theo scope hiện tại (top-level hoặc group).
6176
+ const scope = this.#scope();
6177
+ scope.forEach((item, index) => {
6159
6178
  if (item.layout) {
6160
6179
  item.layout.row = `${index + 1}`;
6161
6180
  item.layout.columns = item.layout?.columns || '12';
@@ -6169,15 +6188,15 @@ class SdFormBuilder extends SdBaseSecureComponent {
6169
6188
  });
6170
6189
  const sel = this.selectedComponent();
6171
6190
  if (sel && sel?.layout?.row) {
6172
- sel.layout.row = this.components.find(t => t.id === sel.id)?.layout?.row;
6191
+ sel.layout.row = scope.find(t => t.id === sel.id)?.layout?.row;
6173
6192
  }
6174
6193
  this.#syncComponentsToRows();
6175
6194
  };
6176
- // Hàm xử lý chuyển đổi components -> dragDropRows
6195
+ // Hàm xử lý chuyển đổi components (scope hiện tại) -> dragDropRows
6177
6196
  // Dựa vào columns của component để quyết định dragDropRows có bao nhiêu items trên row, đảm bảo columns tổng số items <= 12
6178
6197
  #syncComponentsToRows = () => {
6179
6198
  this.dragDropRows = [];
6180
- for (const component of this.components) {
6199
+ for (const component of this.#scope()) {
6181
6200
  // lấy dòng cuối cùng của dragDropList
6182
6201
  let lastRow = { rowIndex: this.dragDropRows.length, items: [] };
6183
6202
  if (this.dragDropRows.length) {
@@ -6198,99 +6217,18 @@ class SdFormBuilder extends SdBaseSecureComponent {
6198
6217
  }
6199
6218
  }
6200
6219
  };
6201
- // Hàm xử lý chuyển đổi dragDropRows -> components
6220
+ // Hàm xử lý chuyển đổi dragDropRows -> components (ghi về scope hiện tại)
6202
6221
  // Vì khi kéo thả sẽ thay đổi vị trí, do đó cần sắp xếp lại components
6203
6222
  #syncRowsToComponents = () => {
6204
6223
  // rải data ma trận droplist => schema.components
6205
- this.components = this.dragDropRows?.map(e => e.items)?.reduce((current, next) => [...current, ...next], []) || [];
6206
- };
6207
- #createComponentFromPalette = (item) => {
6208
- const id = GenerateId();
6209
- if (item.type === 'group') {
6210
- return {
6211
- id,
6212
- type: 'group',
6213
- label: 'Group',
6214
- layout: { columns: '12' },
6215
- components: [],
6216
- properties: {
6217
- icon: item.symbol || 'category',
6218
- color: 'primary',
6219
- },
6220
- };
6221
- }
6222
- if (item.type === 'break') {
6223
- return {
6224
- id,
6225
- key: GenerateKey(),
6226
- type: 'break',
6227
- label: 'Break',
6228
- layout: { columns: '12' },
6229
- validate: {},
6230
- disabled: false,
6231
- properties: {},
6232
- };
6233
- }
6234
- return {
6235
- id,
6236
- key: GenerateKey(),
6237
- type: item.type,
6238
- label: item.type,
6239
- layout: { columns: '12' },
6240
- validate: { required: false },
6241
- disabled: false,
6242
- properties: {},
6243
- };
6244
- };
6245
- #dropIntoGroupAtPointer = (event) => {
6246
- const dropPoint = event.dropPoint || this.lastDragPointer;
6247
- if (!dropPoint)
6248
- return false;
6249
- const bodyEl = document.elementFromPoint(dropPoint.x, dropPoint.y)?.closest('.fb-group__body');
6250
- const groupEl = bodyEl?.closest('.fb-group');
6251
- const group = groupEl?.id ? this.#findGroupById(groupEl.id) : undefined;
6252
- if (!group || event.container.data === group.components)
6253
- return false;
6254
- const dropped = event.previousContainer.data[event.previousIndex];
6255
- if (!dropped)
6256
- return false;
6257
- if ('symbol' in dropped) {
6258
- const paletteItem = dropped;
6259
- if (paletteItem.type === 'group') {
6260
- this.#notifyService.warning('Group lồng group chưa được hỗ trợ.');
6261
- return true;
6262
- }
6263
- const created = this.#createComponentFromPalette(paletteItem);
6264
- group.components.push(created);
6265
- this.selectedComponent.set(created);
6224
+ const flat = this.dragDropRows?.map(e => e.items)?.reduce((current, next) => [...current, ...next], []) || [];
6225
+ const g = this.editingGroup();
6226
+ if (g) {
6227
+ g.components = flat;
6266
6228
  }
6267
6229
  else {
6268
- if (!('type' in dropped))
6269
- return false;
6270
- const component = dropped;
6271
- if (component.type === 'group') {
6272
- this.#notifyService.warning('Group lồng group chưa được hỗ trợ.');
6273
- return true;
6274
- }
6275
- transferArrayItem(event.previousContainer.data, group.components, event.previousIndex, group.components.length);
6276
- this.#syncRowsToComponents();
6277
- this.selectedComponent.set(component);
6230
+ this.components = flat;
6278
6231
  }
6279
- this.#ref.markForCheck();
6280
- return true;
6281
- };
6282
- #findGroupById = (id, items = this.components) => {
6283
- for (const item of items) {
6284
- if (item.type === 'group') {
6285
- const group = item;
6286
- if (group.id === id)
6287
- return group;
6288
- const nested = this.#findGroupById(id, group.components || []);
6289
- if (nested)
6290
- return nested;
6291
- }
6292
- }
6293
- return undefined;
6294
6232
  };
6295
6233
  changeSizeControl = async (event, item, items, currentIndex) => {
6296
6234
  // const totalColumnInRow = items.map(k => k.layout.columns).reduce((acc, curr) => acc + parseInt(curr, 0), 0);
@@ -6325,35 +6263,6 @@ class SdFormBuilder extends SdBaseSecureComponent {
6325
6263
  dragEndChangeSizeControl = (event) => {
6326
6264
  this.#recountTabIndex();
6327
6265
  };
6328
- /** Resize a child item INSIDE a group.
6329
- * Math: lấy bounding của chính item, tính (mouse.x - item.left) / colWidth = newCols.
6330
- * Cách này đúng cho cả flex-wrap (item ở wrap row 2+) vì dùng item-relative,
6331
- * không phải sum-of-all-preceding-cols (sai khi item wrap xuống row mới).
6332
- */
6333
- changeSizeChildInGroup = (event, child, group) => {
6334
- const groupEl = document.getElementById(group.id);
6335
- const bodyEl = groupEl?.querySelector('.fb-group__body');
6336
- const childEl = document.getElementById(child.id);
6337
- if (!bodyEl || !childEl)
6338
- return;
6339
- const bodyRect = bodyEl.getBoundingClientRect();
6340
- const childRect = childEl.getBoundingClientRect();
6341
- // Width của 1 col trong group body (loại trừ padding nếu có).
6342
- const bodyStyle = getComputedStyle(bodyEl);
6343
- const padL = parseFloat(bodyStyle.paddingLeft) || 0;
6344
- const padR = parseFloat(bodyStyle.paddingRight) || 0;
6345
- const colWidth = (bodyRect.width - padL - padR) / 12;
6346
- if (colWidth <= 0)
6347
- return;
6348
- // Mới: new right edge = mouse.x; new width = mouse.x - child.left
6349
- const newWidth = event.pointerPosition.x - childRect.left;
6350
- let newCols = Math.round(newWidth / colWidth);
6351
- if (newCols < 2)
6352
- newCols = 2;
6353
- if (newCols > 12)
6354
- newCols = 12;
6355
- child.layout.columns = `${newCols}`;
6356
- };
6357
6266
  onChangeViewed = (component) => {
6358
6267
  component.properties.viewed = !component.properties.viewed;
6359
6268
  // Emit khi có sự thay đổi để control và attribute lắng nghe và render lại
@@ -6364,14 +6273,15 @@ class SdFormBuilder extends SdBaseSecureComponent {
6364
6273
  // Emit khi có sự thay đổi để control và attribute lắng nghe và render lại
6365
6274
  this.#builderService.componentEmitters.next(component);
6366
6275
  };
6367
- // Duplicate component nhưng sẽ clear id và key để tránh trùng lặp
6276
+ // Duplicate component nhưng sẽ clear id và key để tránh trùng lặp (theo scope hiện tại)
6368
6277
  onDuplicate = (component) => {
6369
6278
  const clonedComponent = JSON.parse(JSON.stringify(component));
6370
6279
  clonedComponent.id = GenerateId();
6371
6280
  clonedComponent.key = GenerateKey();
6372
- this.components.push(clonedComponent);
6281
+ const scope = this.#scope();
6282
+ scope.push(clonedComponent);
6373
6283
  this.#recountTabIndex();
6374
- const created = this.components?.find(t => t.id === clonedComponent.id);
6284
+ const created = scope.find(t => t.id === clonedComponent.id);
6375
6285
  this.selectedComponent.set(created);
6376
6286
  this.selectComponent(created);
6377
6287
  this.#ref.markForCheck();
@@ -6470,12 +6380,12 @@ class SdFormBuilder extends SdBaseSecureComponent {
6470
6380
  this.#notifyService.success('Submit success');
6471
6381
  }
6472
6382
  };
6473
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdFormBuilder, deps: [], target: i0.ɵɵFactoryTarget.Component });
6474
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: SdFormBuilder, isStandalone: true, selector: "sd-form-builder", inputs: { formGeneric: { classPropertyName: "formGeneric", publicName: "formGeneric", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "popupViewJSON", first: true, predicate: ["popupViewJSON"], descendants: true, isSignal: true }, { propertyName: "popupConfigureVariables", first: true, predicate: ["popupConfigureVariables"], descendants: true, isSignal: true }, { propertyName: "configureValidation", first: true, predicate: ConfigureValidationComponent, descendants: true, isSignal: true }, { propertyName: "formRender", first: true, predicate: SdFormRender, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- cdkDropListGroup: auto-connect t\u1EA5t c\u1EA3 cdkDropList trong palette, canvas rows, group bodies.\n [class.fb-shell--dragging]: JS-driven flag \u0111\u1EC3 \u1EA9n hover/actions/resize to\u00E0n di\u1EC7n\n trong l\u00FAc drag (CSS :has() kh\u00F4ng b\u1EAFt 100% tr\u01B0\u1EDDng h\u1EE3p v\u1EDBi CDK preview clone). -->\n<div class=\"fb-shell\" cdkDropListGroup [class.fb-shell--dragging]=\"isAnyDragging()\">\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 LEFT PALETTE \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <aside class=\"fb-palette\">\n <div class=\"fb-panel-header\">\n <div class=\"fb-panel-header__title\">{{ 'core.component.form-builder.components' | translate }}</div>\n </div>\n\n <!-- Search pill -->\n <div class=\"fb-palette__search\">\n <span class=\"msi\" aria-hidden=\"true\">search</span>\n <input\n type=\"text\"\n [placeholder]=\"'core.component.form-builder.search-components' | translate\"\n [value]=\"paletteSearch()\"\n (input)=\"paletteSearch.set($any($event.target).value)\" />\n <span class=\"kbd\">\u2318K</span>\n </div>\n\n <div class=\"fb-palette__scroll\">\n @for (group of paletteGroups(); track group.key) {\n <div class=\"fb-palette__group-label\">{{ group.label }}</div>\n <div\n class=\"fb-palette__list\"\n cdkDropList\n [cdkDropListData]=\"group.items\"\n [cdkDropListEnterPredicate]=\"noReturnPredicate\">\n @for (formBuilderComponent of group.items; track formBuilderComponent.type) {\n <div\n cdkDrag\n class=\"fb-palette-item\"\n [matTooltip]=\"formBuilderComponent.name\"\n matTooltipPosition=\"right\"\n (click)=\"addComponent(formBuilderComponent)\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"onAnyDragEnded()\"\n aria-hidden=\"true\">\n <span class=\"fb-palette-item__icon\"><span class=\"msi\">{{ formBuilderComponent.symbol }}</span></span>\n <span class=\"fb-palette-item__name\">{{ formBuilderComponent.name }}</span>\n <span class=\"fb-palette-item__drag\"><span class=\"msi\">drag_indicator</span></span>\n <!-- Generic drag preview: ch\u1EC9 icon (puck), label \u1EA9n -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n </div>\n }\n </div>\n }\n </div>\n </aside>\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 CENTER CANVAS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <section class=\"fb-canvas\">\n <header class=\"fb-canvas__header\">\n <div class=\"fb-canvas__title\">\n <span>{{ 'core.component.form-builder.layout' | translate }}</span>\n </div>\n <div class=\"fb-canvas__actions\">\n <!-- Toolbar cluster: view JSON / variables / validation -->\n <button\n type=\"button\"\n class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.view-json' | translate\"\n (click)=\"viewJSON()\">\n <span class=\"msi\">data_object</span>\n </button>\n <button\n type=\"button\"\n class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.config-variable' | translate\"\n (click)=\"configureVariables()\">\n <span class=\"msi\">data_array</span>\n </button>\n <button\n type=\"button\"\n class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.config-validation-warning-error' | translate\"\n (click)=\"openConfigureValidation()\">\n <span class=\"msi\">rule</span>\n </button>\n\n <span class=\"fb-divider\"></span>\n\n <!-- M3 segmented Design/Preview toggle -->\n <div class=\"fb-mode-toggle\" role=\"tablist\">\n <button\n type=\"button\"\n role=\"tab\"\n [class.is-active]=\"!isPreview()\"\n (click)=\"setMode(false)\">\n <span class=\"msi\">edit</span>\n <span>{{ 'core.component.form-builder.design' | translate }}</span>\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n [class.is-active]=\"isPreview()\"\n (click)=\"setMode(true)\">\n <span class=\"msi\">visibility</span>\n <span>{{ 'core.component.form-builder.preview' | translate }}</span>\n </button>\n </div>\n </div>\n </header>\n\n <div\n class=\"fb-canvas__body\"\n [class.is-preview]=\"isPreview()\"\n id=\"frmComponent\">\n @if (isPreview()) {\n <!-- \u2500\u2500 Preview mode \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"fb-preview-card\">\n <div class=\"fb-preview-card__chip\">\n <span class=\"msi\">visibility</span>\n {{ 'core.component.form-builder.preview-runtime' | translate }}\n </div>\n <sd-form-render [configuration]=\"{ components: this.components, validations: this.validations }\"></sd-form-render>\n <div class=\"fb-preview-card__footer\">\n <sd-button type=\"outline\" [title]=\"'core.component.form-builder.cancel' | translate\" (click)=\"setMode(false)\"></sd-button>\n <sd-button type=\"fill\" color=\"primary\" [title]=\"'core.component.form-builder.submit' | translate\" (click)=\"onValidate()\"></sd-button>\n </div>\n </div>\n } @else {\n <!-- \u2500\u2500 Design mode \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (!dragDropRows.length) {\n <div class=\"fb-empty\">\n <div class=\"fb-empty__art\"><span class=\"msi\">dashboard_customize</span></div>\n <div class=\"fb-empty__title\">{{ 'core.component.form-builder.empty-title' | translate }}</div>\n <div class=\"fb-empty__hint\">\n {{ 'core.component.form-builder.empty-hint' | translate }}\n <span class=\"fb-empty__kbd\"><span class=\"msi\">keyboard</span>\u2318 K</span>\n </div>\n </div>\n }\n\n <div\n cdkDropList\n cdkDropListOrientation=\"vertical\"\n [cdkDropListData]=\"dragDropRows\"\n (cdkDropListDropped)=\"drop($event)\"\n (click)=\"clickFormContentEmpty()\"\n aria-hidden=\"true\">\n @for (row of dragDropRows; track row.rowIndex) {\n <div\n cdkDrag\n class=\"fb-row\"\n (mouseover)=\"onMouseover($event, row)\"\n (focus)=\"onFocus($event)\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"onAnyDragEnded()\"\n [class.is-drag-target]=\"targetItem === row\"\n [id]=\"'row_' + row.rowIndex\"\n aria-hidden=\"true\">\n <div class=\"fb-row__drag\" [matTooltip]=\"'core.component.form-builder.drag-vertically' | translate\" cdkDragHandle>\n <span class=\"msi\">drag_indicator</span>\n </div>\n <!-- Generic puck preview -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <!-- Quick-add break button \u2014 show on row hover, insert break after this row -->\n <button\n type=\"button\"\n class=\"fb-row-break-btn\"\n [matTooltip]=\"'core.component.form-builder.break' | translate\"\n matTooltipPosition=\"right\"\n (click)=\"insertBreakAfter(row); $event.stopPropagation()\">\n <span class=\"msi\">horizontal_rule</span>\n </button>\n\n <div\n class=\"fb-row__items\"\n style=\"display: flex; flex: 1; gap: var(--gap-2);\"\n cdkDropList\n cdkDropListOrientation=\"horizontal\"\n [cdkDropListData]=\"row.items\"\n (cdkDropListDropped)=\"drop($event)\">\n\n @for (item of row.items; track item.id; let i = $index) {\n <!-- Group component renders as outlined card with colored header bar -->\n @if (item.type === 'group') {\n @let g = $any(item);\n @let cv = groupColorVars(g.properties?.color);\n <div\n cdkDrag\n [id]=\"item.id\"\n class=\"fb-group column-{{ item.layout?.columns || 12 }}\"\n [class.fb-item]=\"false\"\n [class.is-selected]=\"item.id === selectedComponent()?.id\"\n [class.is-hidden]=\"item.properties?.hidden\"\n [style.flex]=\"'0 0 calc(' + (+(item.layout?.columns || 12)) + '/12 * 100% - var(--gap-2))'\"\n [style.maxWidth]=\"'calc(' + (+(item.layout?.columns || 12)) + '/12 * 100% - var(--gap-2))'\"\n (click)=\"selectComponent(item); $event.stopPropagation()\"\n (cdkDragStarted)=\"dragStartComponentItem($event); onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"dragEndComponentItem($event); onAnyDragEnded()\"\n aria-hidden=\"true\">\n <!-- Generic puck preview -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <!-- cdkDragHandle: ch\u1EC9 cho ph\u00E9p k\u00E9o group qua header \u2014 body free cho click v\u00E0o child. -->\n <div class=\"fb-group__header\" cdkDragHandle [style.background]=\"cv.bg\" [style.color]=\"cv.fg\">\n <span class=\"fb-group__icon\"><span class=\"msi\">{{ g.properties?.icon || 'category' }}</span></span>\n <span class=\"fb-group__label\">{{ item.label }}</span>\n @if (hasConditional(item)) {\n <span class=\"fb-group__conditional-chip\">\n <span class=\"msi\" style=\"font-size: 12px;\">bolt</span>\n {{ 'core.component.form-builder.conditional' | translate }}\n </span>\n }\n <span class=\"fb-group__count\">{{ g.components?.length || 0 }} fields</span>\n </div>\n <!-- Floating action toolbar -->\n <div class=\"fb-actions\">\n <button type=\"button\" class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.duplicate' | translate\"\n (click)=\"onDuplicate(item); $event.stopPropagation()\">\n <span class=\"msi\">content_copy</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"item.properties?.hidden\"\n [class.on]=\"item.properties?.hidden\"\n [matTooltip]=\"item.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\n (click)=\"onChangeHidden(item); $event.stopPropagation()\">\n <span class=\"msi\">{{ item.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn danger\"\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"removeComponent(item.id); $event.stopPropagation()\">\n <span class=\"msi\">delete</span>\n </button>\n </div>\n\n <div\n class=\"fb-group__body\"\n cdkDropList\n cdkDropListOrientation=\"horizontal\"\n [cdkDropListData]=\"g.components\"\n (cdkDropListDropped)=\"dropInGroup($event, g)\">\n @if (!g.components?.length) {\n <div class=\"fb-group__empty\">\n <span class=\"msi\" style=\"font-size: 16px; margin-right: 6px;\">south</span>\n {{ 'core.component.form-builder.group-drop-here' | translate }}\n </div>\n }\n @for (child of g.components; track child.id; let ci = $index) {\n <div\n cdkDrag\n [id]=\"child.id\"\n class=\"fb-item is-child column-{{ child.layout?.columns || 12 }}\"\n [class.is-selected]=\"child.id === selectedComponent()?.id\"\n [class.is-hidden]=\"child.properties?.hidden\"\n [class.is-readonly]=\"child.properties?.viewed\"\n (click)=\"selectComponent(child); $event.stopPropagation()\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"onAnyDragEnded()\">\n <!-- Generic puck preview -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <ng-container\n *ngTemplateOutlet=\"controlTemplate; context: { $implicit: child }\">\n </ng-container>\n <!-- Resize handle cho group child \u2014 chia 12-col ngay trong group body.\n Wrapping cdkDropList c\u00F3 enterPredicate=false \u0111\u1EC3 KH\u00D4NG nh\u1EADn drop\n (ch\u1EC9 d\u00F9ng l\u00E0m context cho cdkDrag), tr\u00E1nh xung \u0111\u1ED9t v\u1EDBi group__body drop list. -->\n <div cdkDropList cdkDropListOrientation=\"horizontal\" [cdkDropListEnterPredicate]=\"noReturnPredicate\">\n <div\n cdkDrag\n cdkDragLockAxis=\"x\"\n class=\"fb-resize\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"changeSizeChildInGroup($event, child, g)\"\n (cdkDragEnded)=\"dragEndChangeSizeControl($event); onAnyDragEnded()\"\n [matTooltip]=\"'core.component.form-builder.flex' | translate\"\n aria-label=\"resize\"></div>\n </div>\n <!-- Inline status chips for nested children -->\n @if (child.properties?.hidden) {\n <span class=\"fb-status-chip hidden\">\n <span class=\"msi\">visibility_off</span>\n {{ 'core.component.form-builder.hidden' | translate }}\n </span>\n } @else if (child.properties?.viewed) {\n <span class=\"fb-status-chip readonly\">\n <span class=\"msi\">edit_off</span>\n {{ 'core.component.form-builder.read-only' | translate }}\n </span>\n } @else if (hasConditional(child)) {\n <span class=\"fb-status-chip conditional\">\n <span class=\"msi\">bolt</span>\n {{ 'core.component.form-builder.conditional' | translate }}\n </span>\n }\n <div class=\"fb-actions\">\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"child.properties?.viewed\"\n [class.on]=\"child.properties?.viewed\"\n [matTooltip]=\"child.properties?.viewed ? ('core.component.form-builder.unset-readonly' | translate) : ('core.component.form-builder.set-readonly' | translate)\"\n (click)=\"onChangeViewed(child); $event.stopPropagation()\">\n <span class=\"msi\">edit_off</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.duplicate' | translate\"\n (click)=\"onDuplicate(child); $event.stopPropagation()\">\n <span class=\"msi\">content_copy</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"child.properties?.hidden\"\n [class.on]=\"child.properties?.hidden\"\n [matTooltip]=\"child.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\n (click)=\"onChangeHidden(child); $event.stopPropagation()\">\n <span class=\"msi\">{{ child.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn danger\"\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"removeFromGroup(g, child.id); $event.stopPropagation()\">\n <span class=\"msi\">delete</span>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n } @else if (item.type === 'break') {\n <!-- Break: row separator c\u1ED1 \u0111\u1ECBnh. Render 12-col line, kh\u00F4ng c\u00F3 resize/edit attribute. -->\n <div\n cdkDrag\n [id]=\"item.id\"\n class=\"fb-item is-break column-12\"\n [class.is-selected]=\"item.id === selectedComponent()?.id\"\n [class.is-hidden]=\"item.properties?.hidden\"\n (click)=\"selectComponent(item); $event.stopPropagation()\"\n (cdkDragStarted)=\"dragStartComponentItem($event); onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"dragEndComponentItem($event); onAnyDragEnded()\"\n aria-hidden=\"true\">\n <!-- Generic puck preview -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <div class=\"fb-break-line\">\n <span class=\"msi\">horizontal_rule</span>\n <span class=\"fb-break-label\">{{ 'core.component.form-builder.break' | translate }}</span>\n </div>\n <div class=\"fb-actions\">\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"item.properties?.hidden\"\n [class.on]=\"item.properties?.hidden\"\n [matTooltip]=\"item.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\n (click)=\"onChangeHidden(item); $event.stopPropagation()\">\n <span class=\"msi\">{{ item.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn danger\"\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"removeComponent(item.id); $event.stopPropagation()\">\n <span class=\"msi\">delete</span>\n </button>\n </div>\n </div>\n } @else {\n <!-- Regular form component -->\n <div\n cdkDrag\n [id]=\"item.id\"\n class=\"fb-item column-{{ item.layout?.columns || 12 }}\"\n [class.is-selected]=\"item.id === selectedComponent()?.id\"\n [class.is-hidden]=\"item.properties?.hidden\"\n [class.is-readonly]=\"item.properties?.viewed\"\n (click)=\"selectComponent(item); $event.stopPropagation()\"\n (cdkDragStarted)=\"dragStartComponentItem($event); onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"dragEndComponentItem($event); onAnyDragEnded()\"\n aria-hidden=\"true\">\n <!-- Generic puck preview -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n\n <!-- Status chip (mutually exclusive priority: hidden > readonly > conditional) -->\n @if (item.properties?.hidden) {\n <span class=\"fb-status-chip hidden\">\n <span class=\"msi\">visibility_off</span>\n {{ 'core.component.form-builder.hidden' | translate }}\n </span>\n } @else if (item.properties?.viewed) {\n <span class=\"fb-status-chip readonly\">\n <span class=\"msi\">edit_off</span>\n {{ 'core.component.form-builder.read-only' | translate }}\n </span>\n } @else if (hasConditional(item)) {\n <span class=\"fb-status-chip conditional\">\n <span class=\"msi\">bolt</span>\n {{ 'core.component.form-builder.conditional' | translate }}\n </span>\n }\n\n <!-- Floating action toolbar pill -->\n <div class=\"fb-actions\">\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"item.properties?.viewed\"\n [class.on]=\"item.properties?.viewed\"\n [matTooltip]=\"item.properties?.viewed ? ('core.component.form-builder.unset-readonly' | translate) : ('core.component.form-builder.set-readonly' | translate)\"\n (click)=\"onChangeViewed(item); $event.stopPropagation()\">\n <span class=\"msi\">edit_off</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.duplicate' | translate\"\n (click)=\"onDuplicate(item); $event.stopPropagation()\">\n <span class=\"msi\">content_copy</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"item.properties?.hidden\"\n [class.on]=\"item.properties?.hidden\"\n [matTooltip]=\"item.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\n (click)=\"onChangeHidden(item); $event.stopPropagation()\">\n <span class=\"msi\">{{ item.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn danger\"\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"removeComponent(item.id); $event.stopPropagation()\">\n <span class=\"msi\">delete</span>\n </button>\n </div>\n\n <ng-container\n *ngTemplateOutlet=\"controlTemplate; context: { $implicit: item }\">\n </ng-container>\n\n <!-- Resize handle (pill) \u2014 cdkDragLockAxis=\"x\" \u0111\u1EC3 ch\u1EC9 k\u00E9o ngang.\n Wrapping cdkDropList c\u00F3 enterPredicate=false, kh\u00F4ng nh\u1EADn drop. -->\n <div cdkDropList cdkDropListOrientation=\"horizontal\" [cdkDropListEnterPredicate]=\"noReturnPredicate\">\n <div\n cdkDrag\n cdkDragLockAxis=\"x\"\n class=\"fb-resize\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"changeSizeControl($event, item, row.items, i)\"\n (cdkDragEnded)=\"dragEndChangeSizeControl($event); onAnyDragEnded()\"\n [matTooltip]=\"'core.component.form-builder.flex' | translate\"\n aria-label=\"resize\"></div>\n </div>\n </div>\n }\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n </section>\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 RIGHT ATTRIBUTES \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <aside class=\"fb-attrs\">\n <div class=\"fb-panel-header\">\n <div class=\"fb-panel-header__title\">{{ 'core.component.form-builder.attribute' | translate }}</div>\n </div>\n\n @let sel = selectedComponent();\n @if (sel) {\n <!-- Selection header: type icon + name + key/type -->\n <div class=\"fb-attrs__selection\">\n <span class=\"fb-attrs__sel-icon\"><span class=\"msi\">{{ symbolFor(sel) }}</span></span>\n <div class=\"fb-attrs__sel-meta\">\n <div class=\"fb-attrs__sel-name\">{{ $any(sel).label || ('core.component.form-builder.untitled' | translate) }}</div>\n <div class=\"fb-attrs__sel-key\">\n @if ($any(sel).key) {\n {{ $any(sel).key }} \u00B7 {{ typeLabelFor(sel) }}\n } @else {\n {{ typeLabelFor(sel) }}\n }\n </div>\n </div>\n </div>\n\n <div class=\"fb-attrs__body\" aria-hidden=\"true\">\n @if (sel.type === 'textfield') {\n <textfield-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></textfield-attribute>\n } @else if (sel.type === 'textarea') {\n <textarea-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></textarea-attribute>\n } @else if (sel.type === 'chip-string') {\n <chip-string-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></chip-string-attribute>\n } @else if (sel.type === 'chip-calendar') {\n <chip-calendar-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></chip-calendar-attribute>\n } @else if (sel.type === 'number') {\n <number-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></number-attribute>\n } @else if (sel.type === 'datetime') {\n <datetime-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></datetime-attribute>\n } @else if (sel.type === 'select') {\n <select-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></select-attribute>\n } @else if (sel.type === 'radio') {\n <radio-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></radio-attribute>\n } @else if (sel.type === 'checkbox') {\n <checkbox-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></checkbox-attribute>\n } @else if (sel.type === 'html') {\n <html-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></html-attribute>\n } @else if (sel.type === 'upload') {\n <upload-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></upload-attribute>\n } @else if (sel.type === 'table') {\n <table-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></table-attribute>\n } @else if (sel.type === 'group') {\n <group-attribute [group]=\"$any(sel)\"></group-attribute>\n }\n </div>\n } @else {\n <div class=\"fb-attrs__placeholder\">\n <span class=\"msi\">ads_click</span>\n <div class=\"title\">{{ 'core.component.form-builder.no-selection-title' | translate }}</div>\n <div class=\"hint\">{{ 'core.component.form-builder.no-selection-hint' | translate }}</div>\n </div>\n }\n </aside>\n</div>\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Reusable control template \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n<ng-template #controlTemplate let-item>\n @if (item.type === 'textfield') {\n <textfield-control [component]=\"item\"></textfield-control>\n } @else if (item.type === 'textarea') {\n <textarea-control [component]=\"item\"></textarea-control>\n } @else if (item.type === 'chip-string') {\n <chip-string-control [component]=\"item\"></chip-string-control>\n } @else if (item.type === 'chip-calendar') {\n <chip-calendar-control [component]=\"item\"></chip-calendar-control>\n } @else if (item.type === 'number') {\n <number-control [component]=\"item\"></number-control>\n } @else if (item.type === 'datetime') {\n <datetime-control [component]=\"item\"></datetime-control>\n } @else if (item.type === 'select') {\n <select-control [component]=\"item\"></select-control>\n } @else if (item.type === 'radio') {\n <radio-control [component]=\"item\"></radio-control>\n } @else if (item.type === 'checkbox') {\n <checkbox-control [component]=\"item\"></checkbox-control>\n } @else if (item.type === 'html') {\n <html-control [component]=\"item\"></html-control>\n } @else if (item.type === 'upload') {\n <upload-control [component]=\"item\"></upload-control>\n } @else if (item.type === 'table') {\n <table-control [component]=\"item\"></table-control>\n }\n</ng-template>\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 JSON / variables modals \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n<sd-modal title=\"JSON\" view=\"dialog\" width=\"80%\" #popupViewJSON>\n <sd-textarea [(model)]=\"jsonString\"></sd-textarea>\n <ng-container sdFooter>\n <sd-button type=\"fill\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"updateJSON()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\n </ng-container>\n</sd-modal>\n<sd-modal [title]=\"'core.component.form-builder.config-variable' | translate\" view=\"dialog\" width=\"800px\" #popupConfigureVariables>\n @for (variable of clonedVariables; track variable.id) {\n <div class=\"d-flex align-items-center\" style=\"gap: 8px\">\n <sd-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"variable.key\" required></sd-input>\n <sd-input [form]=\"form\" [label]=\"'core.component.form-builder.display-label' | translate\" [(model)]=\"variable.label\" required></sd-input>\n <sd-button prefixIcon=\"delete\" (click)=\"removeVariables(variable.id)\" color=\"error\"></sd-button>\n </div>\n }\n <a href=\"javascript:;\" (click)=\"addVariables()\">{{ 'core.component.form-builder.add-variable' | translate }}</a>\n <ng-container sdFooter>\n <sd-button type=\"fill\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"updateVariables()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\n </ng-container>\n</sd-modal>\n<configure-validation (accept)=\"onUpdateValidations($event)\"></configure-validation>\n", styles: [":host{--md-sys-color-primary: var(--sd-primary, #2A66F4);--md-sys-color-on-primary: #ffffff;--md-sys-color-primary-container: var(--sd-primary-light, #EAF1FF);--md-sys-color-on-primary-container: var(--sd-primary, #2A66F4);--md-sys-color-info: var(--sd-info, #2962FF);--md-sys-color-info-container: var(--sd-info-light, #E7E9FF);--md-sys-color-secondary: #625b71;--md-sys-color-secondary-container: #e8def8;--md-sys-color-on-secondary-container: #1d192b;--md-sys-color-surface: #fbfafc;--md-sys-color-surface-container-lowest: #ffffff;--md-sys-color-surface-container-low: #f6f4f8;--md-sys-color-surface-container: #f1eef3;--md-sys-color-surface-container-high: #ebe8ee;--md-sys-color-surface-container-highest: #e6e2ea;--md-sys-color-on-surface: #1c1b1f;--md-sys-color-on-surface-variant: #49454e;--md-sys-color-outline: #79747e;--md-sys-color-outline-variant: #d6d2da;--md-sys-color-error: #b3261e;--md-sys-color-error-container: #f9dedc;--md-sys-color-warning: #8a5400;--md-sys-color-warning-container: #ffddb1;--md-sys-color-success: #1f6f43;--md-sys-color-success-container: #b7f0cb;--h-row: 28px;--h-field: 32px;--h-palette: 36px;--h-header: 36px;--h-section: 28px;--h-action-btn: 24px;--gap-1: 4px;--gap-2: 8px;--gap-3: 12px;--gap-4: 16px;--gap-5: 24px;--r-xs: 4px;--r-sm: 8px;--r-md: 12px;--r-lg: 16px;--r-xl: 28px;--r-pill: 999px;--elev-1: 0 1px 2px 0 rgba(0, 0, 0, .06);--elev-2: 0 2px 6px 0 rgba(0, 0, 0, .08), 0 1px 2px 0 rgba(0, 0, 0, .04);--elev-3: 0 6px 14px 0 rgba(0, 0, 0, .1), 0 2px 4px 0 rgba(0, 0, 0, .06);display:block;width:100%;height:100%;font-family:Roboto,system-ui,sans-serif;font-size:13px;color:var(--md-sys-color-on-surface);background:var(--md-sys-color-surface)}:host ::ng-deep .msi{font-family:Material Symbols Rounded;font-weight:400;font-style:normal;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;font-feature-settings:\"liga\";-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"wght\" 300,\"opsz\" 24,\"GRAD\" 0,\"FILL\" 0}:host ::ng-deep .msi.filled{font-variation-settings:\"wght\" 300,\"opsz\" 24,\"GRAD\" 0,\"FILL\" 1}:host ::ng-deep .mono{font-family:Roboto Mono,ui-monospace,monospace}:host ::ng-deep .fb-icon-btn{width:28px;height:28px;border-radius:var(--r-sm);border:none;background:transparent;color:var(--md-sys-color-on-surface-variant);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background .12s ease,color .12s ease}:host ::ng-deep .fb-icon-btn:hover{background:color-mix(in srgb,var(--md-sys-color-on-surface) 8%,transparent);color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-icon-btn.is-active{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container)}:host ::ng-deep .fb-icon-btn.danger:hover{color:var(--md-sys-color-error);background:var(--md-sys-color-error-container)}:host ::ng-deep .fb-icon-btn.warning.on{color:var(--md-sys-color-warning);background:var(--md-sys-color-warning-container)}:host ::ng-deep .fb-icon-btn .msi{font-size:18px}:host ::ng-deep .fb-field{display:flex;flex-direction:column;gap:4px}:host ::ng-deep .fb-field__label{font-size:11px;font-weight:500;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-field__input{height:var(--h-row);padding:0 10px;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px;display:flex;align-items:center;justify-content:space-between;color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-field__input.placeholder{color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-field__input:focus-within,:host ::ng-deep .fb-field__input.focused{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent)}:host ::ng-deep .fb-field__input .msi{font-size:16px;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-field-row{display:flex;align-items:center;gap:var(--gap-2);justify-content:space-between}:host ::ng-deep .fb-switch{display:inline-flex;width:34px;height:18px;border-radius:999px;background:var(--md-sys-color-surface-container-highest);border:1.5px solid var(--md-sys-color-outline);padding:1px;align-items:center;cursor:pointer;position:relative;flex-shrink:0}:host ::ng-deep .fb-switch .fb-switch__thumb{width:12px;height:12px;border-radius:50%;background:var(--md-sys-color-outline)}:host ::ng-deep .fb-switch.on{background:var(--md-sys-color-primary);border-color:var(--md-sys-color-primary);justify-content:flex-end}:host ::ng-deep .fb-switch.on .fb-switch__thumb{background:var(--md-sys-color-on-primary);width:14px;height:14px}:host ::ng-deep .fb-expr{display:flex;align-items:center;gap:6px;height:var(--h-row);padding:0 6px 0 0;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-expr__badge{height:100%;display:inline-flex;align-items:center;justify-content:center;padding:0 6px;background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);font-family:Roboto Mono,monospace;font-size:10px;font-weight:500;border-radius:var(--r-xs) 0 0 var(--r-xs)}:host ::ng-deep .fb-expr__code{font-family:Roboto Mono,monospace;flex:1;font-size:11px;color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-expr__code .var{color:var(--md-sys-color-primary);font-weight:500}:host ::ng-deep .fb-expr__code .op{color:var(--md-sys-color-error)}:host ::ng-deep .fb-expr__code .lit{color:var(--md-sys-color-success)}:host ::ng-deep .fb-expr .empty{color:var(--md-sys-color-on-surface-variant);font-style:italic;padding-left:6px;flex:1}:host ::ng-deep details.fb-section{border-bottom:1px solid var(--md-sys-color-outline-variant);margin:0;padding:0;background:transparent}:host ::ng-deep details.fb-section>summary{list-style:none}:host ::ng-deep details.fb-section>summary::-webkit-details-marker{display:none}:host ::ng-deep .fb-section__head{height:var(--h-section);padding:0 var(--gap-4);display:flex;align-items:center;gap:var(--gap-2);cursor:pointer;font-size:12px;font-weight:500;color:var(--md-sys-color-on-surface);-webkit-user-select:none;user-select:none}:host ::ng-deep .fb-section__head .msi{font-size:16px;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-section__head .fb-section__title{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep .fb-section__head .chev{margin-left:auto;transition:transform .16s ease}:host ::ng-deep details.fb-section[open] .fb-section__head .chev{transform:rotate(90deg)}:host ::ng-deep .fb-section__body{padding:4px var(--gap-4) var(--gap-3);display:flex;flex-direction:column;gap:var(--gap-2)}:host ::ng-deep .fb-columns-list{display:flex;flex-direction:column;gap:var(--gap-1);padding-top:var(--gap-1)}:host ::ng-deep .fb-column-row{display:flex;align-items:center;gap:var(--gap-2);height:40px;padding:6px 10px;border-radius:var(--r-sm);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px;cursor:pointer;transition:background .12s ease,border-color .12s ease,box-shadow .12s ease}:host ::ng-deep .fb-column-row:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 4%,transparent);border-color:color-mix(in srgb,var(--md-sys-color-primary) 30%,transparent)}:host ::ng-deep .fb-column-row.is-active{border-color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 30%,transparent)}:host ::ng-deep .fb-column-row .fb-column-row__type-icon{width:28px;height:28px;border-radius:var(--r-sm);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}:host ::ng-deep .fb-column-row .fb-column-row__type-icon .msi{font-size:16px}:host ::ng-deep .fb-column-row .fb-column-row__meta{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}:host ::ng-deep .fb-column-row .fb-column-row__meta .fb-column-row__label{font-size:13px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-column-row .fb-column-row__meta .fb-column-row__req{color:var(--md-sys-color-error);margin-left:2px;font-weight:600}:host ::ng-deep .fb-column-row .fb-column-row__meta .fb-column-row__sub{font-size:11px;color:var(--md-sys-color-on-surface-variant);font-family:Roboto Mono,ui-monospace,monospace;letter-spacing:.02em}:host ::ng-deep .cdk-drag-preview.fb-drag-preview,:host ::ng-deep .fb-drag-preview{width:36px;height:36px;min-width:36px;min-height:36px;max-width:36px;max-height:36px;box-sizing:border-box;border-radius:50%;background:var(--md-sys-color-primary, #6750a4);display:inline-flex;align-items:center;justify-content:center;box-shadow:0 10px 24px #00000042,0 3px 8px #00000024;border:3px solid var(--md-sys-color-on-primary, #ffffff);cursor:grabbing;pointer-events:none;-webkit-user-select:none;user-select:none;opacity:.96;overflow:hidden;z-index:10000}:host ::ng-deep .cdk-drag-preview.fb-drag-preview:after,:host ::ng-deep .fb-drag-preview:after{content:\"\";width:8px;height:8px;border-radius:50%;background:var(--md-sys-color-on-primary, #ffffff);opacity:.9}@keyframes fb-drop-pulse{0%,to{box-shadow:0 0 0 3px color-mix(in srgb,var(--md-sys-color-info) 16%,transparent)}50%{box-shadow:0 0 0 5px color-mix(in srgb,var(--md-sys-color-info) 24%,transparent)}}:host ::ng-deep .cdk-drag-placeholder{background:transparent!important;border:none!important;border-radius:999px!important;padding:0!important;transform:none!important;transition:none!important;pointer-events:none;overflow:hidden;animation:none!important;opacity:0!important}:host ::ng-deep .cdk-drag-placeholder>*{visibility:hidden!important;pointer-events:none!important}:host ::ng-deep .fb-palette__list>.cdk-drag-placeholder{display:none!important}:host ::ng-deep .fb-row__items>.cdk-drag-placeholder,:host ::ng-deep .fb-group__body>.cdk-drag-placeholder{width:0!important;min-width:0!important;max-width:0!important;height:auto!important;min-height:0!important;align-self:stretch;flex:0 0 0!important;margin:0!important}:host ::ng-deep [cdkDropListOrientation=vertical]>.cdk-drag-placeholder{width:auto!important;height:0!important;min-height:0!important;max-height:0!important;flex:0 0 0!important;margin:0!important;align-self:stretch}:host ::ng-deep .cdk-drop-list-receiving{background:color-mix(in srgb,var(--md-sys-color-primary) 3%,transparent);transition:background .16s ease}:host ::ng-deep .fb-group__body.cdk-drop-list-receiving,:host ::ng-deep .fb-group__body.cdk-drop-list-dragging{background:color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent)!important;outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 78%,transparent);outline-offset:-6px;border-radius:var(--r-sm)}:host ::ng-deep .fb-resize.cdk-drag-preview{display:none!important}:host ::ng-deep .fb-shell--dragging .fb-item:hover,:host ::ng-deep .fb-shell--dragging .fb-group:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-item:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group:hover{border-color:transparent!important;background:transparent!important}:host ::ng-deep .fb-shell--dragging .fb-row:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row:hover{outline-color:transparent!important;background:transparent!important}:host ::ng-deep .fb-shell--dragging .fb-row:hover .fb-row__drag,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row:hover .fb-row__drag{opacity:0!important}:host ::ng-deep .fb-shell--dragging .fb-row.is-drag-target,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row.is-drag-target{outline-color:color-mix(in srgb,var(--md-sys-color-info) 44%,transparent)!important;background:color-mix(in srgb,var(--md-sys-color-info) 4%,transparent)!important}:host ::ng-deep .fb-shell--dragging .fb-row__drag,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row__drag{opacity:0!important}:host ::ng-deep .fb-shell--dragging .fb-actions,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-actions{opacity:0!important;pointer-events:none!important;transform:translateY(-2px)!important}:host ::ng-deep .fb-shell--dragging .fb-resize,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-resize{opacity:0!important;pointer-events:none!important}:host ::ng-deep .fb-shell--dragging .fb-row-break-btn,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row-break-btn{opacity:0!important;pointer-events:none!important}:host ::ng-deep .fb-shell--dragging .fb-palette-item:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-palette-item:hover{background:transparent!important}:host ::ng-deep .fb-shell--dragging .fb-palette-item:hover .fb-palette-item__drag,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-palette-item:hover .fb-palette-item__drag{opacity:0!important}:host ::ng-deep .fb-shell--dragging .fb-group__body,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__body{min-height:80px!important;background:color-mix(in srgb,var(--md-sys-color-primary) 5%,transparent)!important;outline:2px dashed color-mix(in srgb,var(--md-sys-color-primary) 50%,transparent)!important;outline-offset:-6px;border-radius:var(--r-sm);transition:background .16s ease,outline .16s ease,min-height .16s ease}:host ::ng-deep .fb-shell--dragging .fb-group__empty,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__empty{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 55%,transparent);background:color-mix(in srgb,var(--md-sys-color-primary) 7%,transparent);color:var(--md-sys-color-primary)}:host ::ng-deep .fb-shell--dragging .fb-group__body.cdk-drop-list-receiving,:host ::ng-deep .fb-shell--dragging .fb-group__body.cdk-drop-list-dragging,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__body.cdk-drop-list-receiving,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__body.cdk-drop-list-dragging{background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)!important;outline:2px solid var(--md-sys-color-primary)!important}:host ::ng-deep .cdk-drag-animating{transition:transform .22s cubic-bezier(.2,0,0,1)!important}:host ::ng-deep .cdk-drag-dragging{transition:none!important}:host ::ng-deep .fb-item:not(.cdk-drag-dragging){transition:flex .12s cubic-bezier(.2,0,0,1),max-width .12s cubic-bezier(.2,0,0,1),border-color .12s,background .12s}.fb-shell{width:100%;height:100%;display:flex;background:var(--md-sys-color-surface);overflow:hidden;min-height:0}.fb-panel-header{height:var(--h-header);display:flex;align-items:center;justify-content:space-between;padding:0 var(--gap-3);border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);flex-shrink:0}.fb-panel-header__title{font-size:11px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant)}.fb-panel-header__actions{display:flex;align-items:center;gap:2px}.fb-palette{width:220px;flex-shrink:0;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-right:1px solid var(--md-sys-color-outline-variant)}.fb-palette__scroll{flex:1;overflow-y:auto;padding-bottom:var(--gap-3)}.fb-palette__search{margin:var(--gap-3);height:32px;display:flex;align-items:center;gap:var(--gap-2);padding:0 var(--gap-3);border-radius:var(--r-pill);background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant);font-size:13px;flex-shrink:0}.fb-palette__search .msi{font-size:18px}.fb-palette__search input{flex:1;border:none;outline:none;background:transparent;color:var(--md-sys-color-on-surface);font-size:13px;font-family:inherit}.fb-palette__search input::placeholder{color:var(--md-sys-color-on-surface-variant)}.fb-palette__search .kbd{font-family:Roboto Mono,monospace;font-size:10px;padding:1px 6px;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant)}.fb-palette__group-label{font-size:11px;font-weight:500;letter-spacing:.04em;color:var(--md-sys-color-on-surface-variant);padding:var(--gap-3) var(--gap-4) var(--gap-1);text-transform:uppercase}.fb-palette__list{display:flex;flex-direction:column;padding:0 var(--gap-2)}.fb-palette-item{height:var(--h-palette);display:flex;align-items:center;gap:var(--gap-3);padding:0 var(--gap-3);border-radius:var(--r-sm);cursor:grab;color:var(--md-sys-color-on-surface);position:relative;-webkit-user-select:none;user-select:none}.fb-palette-item:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent)}.fb-palette-item .fb-palette-item__icon{width:24px;height:24px;border-radius:var(--r-xs);display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);flex-shrink:0}.fb-palette-item .fb-palette-item__icon .msi{font-size:16px}.fb-palette-item .fb-palette-item__name{font-size:13px;font-weight:400}.fb-palette-item .fb-palette-item__drag{margin-left:auto;color:var(--md-sys-color-outline);opacity:0;transition:opacity .12s ease}.fb-palette-item .fb-palette-item__drag .msi{font-size:16px}.fb-palette-item:hover .fb-palette-item__drag{opacity:1}.fb-canvas{flex:1 1 0;min-width:0;display:flex;flex-direction:column;background:var(--md-sys-color-surface);overflow:hidden}.fb-canvas__header{height:var(--h-header);display:flex;align-items:center;justify-content:space-between;padding:0 var(--gap-4);border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);gap:var(--gap-3);flex-shrink:0}.fb-canvas__title{display:flex;align-items:center;gap:var(--gap-2);font-size:11px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant)}.fb-canvas__title .breadcrumb-sep{color:var(--md-sys-color-outline)}.fb-canvas__actions{display:flex;align-items:center;gap:var(--gap-2)}.fb-divider{width:1px;height:18px;background:var(--md-sys-color-outline-variant)}.fb-canvas__body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;padding:var(--gap-4);position:relative;background:var(--md-sys-color-surface);min-width:0}.fb-canvas__body.is-preview{background:var(--md-sys-color-surface-container-low);padding:32px}.fb-mode-toggle{display:inline-flex;height:28px;border:1px solid var(--md-sys-color-outline);border-radius:var(--r-pill);overflow:hidden;flex-shrink:0}.fb-mode-toggle button{border:0;background:transparent;padding:0 var(--gap-3);font-size:12px;font-weight:500;display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-surface-variant);cursor:pointer}.fb-mode-toggle button .msi{font-size:16px}.fb-mode-toggle button.is-active{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.fb-row{position:relative;display:flex;gap:var(--gap-2);padding:6px var(--gap-2);border-radius:var(--r-sm);margin-bottom:6px;min-width:0;transition:outline .12s ease,background .12s ease;outline:1px dashed transparent;outline-offset:-1px}.fb-row:hover{outline-color:var(--md-sys-color-outline-variant);background:color-mix(in srgb,var(--md-sys-color-primary) 3%,transparent)}.fb-row:hover .fb-row__drag{opacity:1}.fb-row.is-drag-target{outline-color:color-mix(in srgb,var(--md-sys-color-info) 44%,transparent);background:color-mix(in srgb,var(--md-sys-color-info) 4%,transparent)}.fb-row.is-drag-target:after{content:\"\";position:absolute;left:10px;right:10px;bottom:-3px;height:4px;border-radius:999px;background:var(--md-sys-color-info);box-shadow:0 0 0 4px color-mix(in srgb,var(--md-sys-color-info) 18%,transparent);pointer-events:none;animation:fb-drop-pulse .9s ease-in-out infinite;z-index:3}.fb-row__drag{position:absolute;left:-22px;top:50%;transform:translateY(-50%);width:18px;height:22px;border-radius:var(--r-xs);display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-high);opacity:0;cursor:grab;z-index:2}.fb-row__drag .msi{font-size:14px}.fb-row-break-btn{position:absolute;right:-28px;top:50%;transform:translateY(-50%);width:22px;height:22px;border-radius:var(--r-pill);display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-high);border:1px solid var(--md-sys-color-outline-variant);cursor:pointer;opacity:0;z-index:2;transition:opacity .12s ease,background .12s ease,color .12s ease}.fb-row-break-btn .msi{font-size:14px}.fb-row-break-btn:hover{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);border-color:transparent}.fb-row:hover .fb-row-break-btn{opacity:1}.fb-item{position:relative;border:1.5px dashed transparent;border-radius:var(--r-md);padding:var(--gap-2) var(--gap-3);min-height:56px;min-width:0;transition:border-color .12s ease,background .12s ease;background:transparent;cursor:grab;display:flex;flex-direction:column;gap:6px}.fb-item:hover{border-color:color-mix(in srgb,var(--md-sys-color-primary) 60%,transparent)}.fb-item.is-selected{border:1.5px solid var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 4%,transparent)}.fb-item.is-hidden{opacity:.45}.fb-item.is-readonly:after{content:\"\";position:absolute;inset:0;border-radius:var(--r-md);background:repeating-linear-gradient(135deg,transparent 0 6px,color-mix(in srgb,var(--md-sys-color-on-surface) 4%,transparent) 6px 7px);pointer-events:none}.fb-item.column-2{flex:0 0 calc(16.6666666667% - var(--gap-2));max-width:calc(16.6666666667% - var(--gap-2))}.fb-item.column-3{flex:0 0 calc(25% - var(--gap-2));max-width:calc(25% - var(--gap-2))}.fb-item.column-4{flex:0 0 calc(33.3333333333% - var(--gap-2));max-width:calc(33.3333333333% - var(--gap-2))}.fb-item.column-5{flex:0 0 calc(41.6666666667% - var(--gap-2));max-width:calc(41.6666666667% - var(--gap-2))}.fb-item.column-6{flex:0 0 calc(50% - var(--gap-2));max-width:calc(50% - var(--gap-2))}.fb-item.column-7{flex:0 0 calc(58.3333333333% - var(--gap-2));max-width:calc(58.3333333333% - var(--gap-2))}.fb-item.column-8{flex:0 0 calc(66.6666666667% - var(--gap-2));max-width:calc(66.6666666667% - var(--gap-2))}.fb-item.column-9{flex:0 0 calc(75% - var(--gap-2));max-width:calc(75% - var(--gap-2))}.fb-item.column-10{flex:0 0 calc(83.3333333333% - var(--gap-2));max-width:calc(83.3333333333% - var(--gap-2))}.fb-item.column-11{flex:0 0 calc(91.6666666667% - var(--gap-2));max-width:calc(91.6666666667% - var(--gap-2))}.fb-item.column-12{flex:1 1 100%;max-width:100%}.fb-actions{position:absolute;top:-14px;right:8px;display:flex;align-items:center;gap:2px;padding:2px;border-radius:var(--r-pill);background:var(--md-sys-color-surface-container-lowest);box-shadow:var(--elev-2);border:1px solid var(--md-sys-color-outline-variant);z-index:4;opacity:0;transform:translateY(-2px);pointer-events:none;transition:opacity .12s ease,transform .12s ease}.fb-actions .fb-icon-btn{width:24px;height:24px}.fb-actions .fb-icon-btn .msi{font-size:16px}.fb-item:hover .fb-actions,.fb-item.is-selected .fb-actions{opacity:1;transform:translateY(0);pointer-events:auto}table-control{display:block;width:100%;max-width:100%;min-width:0}.fb-group>.fb-actions{top:6px;right:8px}.fb-group:hover>.fb-actions,.fb-group.is-selected>.fb-actions{opacity:1;transform:translateY(0);pointer-events:auto}.fb-status-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;height:18px;border-radius:var(--r-pill);font-size:10px;font-weight:500;letter-spacing:.02em;position:absolute;top:-9px;left:12px;z-index:3;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface-variant)}.fb-status-chip .msi{font-size:12px}.fb-status-chip.readonly{color:var(--md-sys-color-warning);background:var(--md-sys-color-warning-container);border-color:transparent}.fb-status-chip.hidden{color:var(--md-sys-color-on-surface-variant)}.fb-status-chip.conditional{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);border-color:transparent}.fb-resize{position:absolute;top:8px;bottom:8px;right:-5px;width:6px;border-radius:999px;background:var(--md-sys-color-primary);display:flex;align-items:center;justify-content:center;cursor:col-resize;opacity:0;transition:opacity .12s ease;z-index:3}.fb-resize:before{content:\"\";width:2px;height:18px;background:var(--md-sys-color-on-primary);border-radius:999px}.fb-item:hover .fb-resize{opacity:1}.fb-item.is-break{min-height:28px;padding:8px var(--gap-3);justify-content:center}.fb-break-line{display:flex;align-items:center;gap:var(--gap-2);color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:500;letter-spacing:.06em;text-transform:uppercase}.fb-break-line:before,.fb-break-line:after{content:\"\";flex:1;height:1px;background:var(--md-sys-color-outline-variant)}.fb-break-line .msi{display:none}.fb-break-line .fb-break-label{color:var(--md-sys-color-on-surface-variant)}.fb-drop-hint{height:36px;border-radius:var(--r-sm);border:1.5px dashed var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 6%,transparent);color:var(--md-sys-color-primary);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:500;gap:6px;margin:4px 0}.fb-drop-hint .msi{font-size:16px}.fb-group{background:var(--md-sys-color-surface-container-lowest);border-radius:var(--r-lg);border:1.5px dashed transparent;transition:border-color .12s ease,background .12s ease;position:relative;display:flex;flex-direction:column;overflow:visible;cursor:default}.fb-group:hover{border-color:color-mix(in srgb,var(--md-sys-color-primary) 60%,transparent)}.fb-group.is-selected{border:1.5px solid var(--md-sys-color-primary)}.fb-group.is-hidden{opacity:.55}.fb-group__header{display:flex;align-items:center;gap:var(--gap-2);padding:8px 12px;border-top-left-radius:12px;border-top-right-radius:12px;cursor:grab}.fb-group__header:active{cursor:grabbing}.fb-group__header .fb-group__icon .msi{font-size:18px}.fb-group__header .fb-group__label{font-size:13px;font-weight:500}.fb-group__header .fb-group__count{margin-left:auto;font-size:10px;opacity:.75}.fb-group__conditional-chip{display:inline-flex;align-items:center;gap:4px;font-family:Roboto Mono,monospace;font-size:10px;padding:2px 8px;border-radius:var(--r-pill);background:color-mix(in srgb,currentColor 12%,transparent)}.fb-group__body{padding:12px;display:flex;flex-wrap:wrap;gap:var(--gap-2);min-height:60px;position:relative}.fb-group__empty{display:flex;align-items:center;justify-content:center;height:56px;border-radius:var(--r-sm);border:1.5px dashed var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant);font-size:12px;font-style:italic}.fb-empty{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--gap-3);color:var(--md-sys-color-on-surface-variant);text-align:center;padding:24px;pointer-events:none}.fb-empty__art{width:96px;height:96px;border-radius:var(--r-xl);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center}.fb-empty__art .msi{font-size:44px}.fb-empty__title{font-size:16px;font-weight:500;color:var(--md-sys-color-on-surface)}.fb-empty__hint{font-size:13px;max-width:320px;line-height:1.5}.fb-empty__kbd{display:inline-flex;align-items:center;gap:6px;font-family:Roboto Mono,monospace;font-size:11px;padding:4px 8px;border-radius:var(--r-xs);border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface-variant)}.fb-empty__kbd .msi{font-size:12px}.fb-attrs{width:320px;flex-shrink:0;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-left:1px solid var(--md-sys-color-outline-variant)}.fb-attrs__selection{padding:var(--gap-3) var(--gap-4);display:flex;align-items:center;gap:var(--gap-2);border-bottom:1px solid var(--md-sys-color-outline-variant)}.fb-attrs__sel-icon{width:28px;height:28px;border-radius:var(--r-sm);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.fb-attrs__sel-icon .msi{font-size:18px}.fb-attrs__sel-meta{display:flex;flex-direction:column;min-width:0}.fb-attrs__sel-name{font-size:13px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-attrs__sel-key{font-family:Roboto Mono,monospace;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.fb-attrs__body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;min-width:0}.fb-attrs__placeholder{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--gap-2);padding:32px;color:var(--md-sys-color-on-surface-variant);text-align:center}.fb-attrs__placeholder .msi{font-size:32px;color:var(--md-sys-color-outline)}.fb-attrs__placeholder .title{font-size:13px;font-weight:500;color:var(--md-sys-color-on-surface)}.fb-attrs__placeholder .hint{font-size:12px;max-width:220px;line-height:1.5}.fb-preview-card{max-width:760px;margin:0 auto;background:var(--md-sys-color-surface-container-lowest);border-radius:var(--r-lg);padding:32px;box-shadow:var(--elev-1)}.fb-preview-card__chip{display:inline-flex;align-items:center;gap:6px;padding:2px 10px;height:22px;border-radius:var(--r-pill);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);font-size:10px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;margin-bottom:var(--gap-3)}.fb-preview-card__title{font-size:20px;font-weight:500;margin:0 0 var(--gap-4);color:var(--md-sys-color-on-surface)}.fb-preview-card__footer{display:flex;justify-content:flex-end;gap:var(--gap-2);margin-top:var(--gap-4);padding-top:var(--gap-4);border-top:1px solid var(--md-sys-color-outline-variant)}.fb-icon-picker{display:grid;grid-template-columns:repeat(6,1fr);gap:4px;margin-top:4px}.fb-icon-picker .fb-icon-picker__btn{height:28px;border-radius:var(--r-xs);border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface-variant);display:inline-flex;align-items:center;justify-content:center;cursor:pointer}.fb-icon-picker .fb-icon-picker__btn .msi{font-size:16px}.fb-icon-picker .fb-icon-picker__btn.is-active{border-color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary)}.fb-icon-picker .fb-icon-picker__btn:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent)}.fb-color-swatches{display:flex;gap:var(--gap-2);margin-top:4px}.fb-color-swatches .fb-color-swatch{width:24px;height:24px;border-radius:50%;cursor:pointer;border:2px solid transparent}.fb-color-swatches .fb-color-swatch.is-active{border-color:var(--md-sys-color-on-surface)}.fb-color-swatches .fb-color-swatch.primary{background:var(--md-sys-color-primary)}.fb-color-swatches .fb-color-swatch.secondary{background:var(--md-sys-color-secondary)}.fb-color-swatches .fb-color-swatch.success{background:var(--md-sys-color-success)}.fb-color-swatches .fb-color-swatch.warning{background:var(--md-sys-color-warning)}.fb-color-swatches .fb-color-swatch.error{background:var(--md-sys-color-error)}.fb-children-list{display:flex;flex-direction:column;gap:4px}.fb-child-row{display:flex;align-items:center;gap:var(--gap-2);height:30px;padding:0 8px;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px}.fb-child-row .fb-child-row__icon{width:22px;height:22px;border-radius:var(--r-xs);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.fb-child-row .fb-child-row__icon .msi{font-size:14px}.fb-child-row .fb-child-row__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fb-child-row .fb-child-row__key{font-family:Roboto Mono,monospace;font-size:10px;color:var(--md-sys-color-on-surface-variant)}.fb-child-row:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 4%,transparent)}.fb-add-link{display:inline-flex;align-items:center;gap:4px;font-size:12px;color:var(--md-sys-color-primary);cursor:pointer;padding:4px 0;text-decoration:none}.fb-add-link .msi{font-size:14px}.fb-add-link:hover{text-decoration:underline}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i3.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: i3.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i3.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: i3.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: i3.CdkDragPreview, selector: "ng-template[cdkDragPreview]", inputs: ["data", "matchSize"] }, { kind: "component", type:
6383
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SdFormBuilder, deps: [], target: i0.ɵɵFactoryTarget.Component });
6384
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: SdFormBuilder, isStandalone: true, selector: "sd-form-builder", inputs: { formGeneric: { classPropertyName: "formGeneric", publicName: "formGeneric", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "popupViewJSON", first: true, predicate: ["popupViewJSON"], descendants: true, isSignal: true }, { propertyName: "popupConfigureVariables", first: true, predicate: ["popupConfigureVariables"], descendants: true, isSignal: true }, { propertyName: "configureValidation", first: true, predicate: ConfigureValidationComponent, descendants: true, isSignal: true }, { propertyName: "formRender", first: true, predicate: SdFormRender, descendants: true, isSignal: true }], ngImport: i0, template: "<!-- cdkDropListGroup: auto-connect t\u1EA5t c\u1EA3 cdkDropList trong palette, canvas rows, group bodies.\n [class.fb-shell--dragging]: JS-driven flag \u0111\u1EC3 \u1EA9n hover/actions/resize to\u00E0n di\u1EC7n\n trong l\u00FAc drag (CSS :has() kh\u00F4ng b\u1EAFt 100% tr\u01B0\u1EDDng h\u1EE3p v\u1EDBi CDK preview clone). -->\n<div class=\"fb-shell\" cdkDropListGroup [class.fb-shell--dragging]=\"isAnyDragging()\">\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 LEFT PALETTE \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <aside class=\"fb-palette\">\n <div class=\"fb-panel-header\">\n <div class=\"fb-panel-header__title\">{{ 'core.component.form-builder.components' | translate }}</div>\n </div>\n\n <!-- Search pill -->\n <div class=\"fb-palette__search\">\n <span class=\"msi\" aria-hidden=\"true\">search</span>\n <input\n type=\"text\"\n [placeholder]=\"'core.component.form-builder.search-components' | translate\"\n [value]=\"paletteSearch()\"\n (input)=\"paletteSearch.set($any($event.target).value)\" />\n <span class=\"kbd\">\u2318K</span>\n </div>\n\n <div class=\"fb-palette__scroll\">\n @for (group of paletteGroups(); track group.key) {\n <div class=\"fb-palette__group-label\">{{ group.label }}</div>\n <div\n class=\"fb-palette__list\"\n cdkDropList\n [cdkDropListData]=\"group.items\"\n [cdkDropListEnterPredicate]=\"noReturnPredicate\">\n @for (formBuilderComponent of group.items; track formBuilderComponent.type) {\n <div\n cdkDrag\n class=\"fb-palette-item\"\n [matTooltip]=\"formBuilderComponent.name\"\n matTooltipPosition=\"right\"\n (click)=\"addComponent(formBuilderComponent)\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"onAnyDragEnded()\"\n aria-hidden=\"true\">\n <span class=\"fb-palette-item__icon\"><span class=\"msi\">{{ formBuilderComponent.symbol }}</span></span>\n <span class=\"fb-palette-item__name\">{{ formBuilderComponent.name }}</span>\n <span class=\"fb-palette-item__drag\"><span class=\"msi\">drag_indicator</span></span>\n <!-- Generic drag preview: ch\u1EC9 icon (puck), label \u1EA9n -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n </div>\n }\n </div>\n }\n </div>\n </aside>\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 CENTER CANVAS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <section class=\"fb-canvas\">\n @let _editing = editingGroup();\n @if (_editing) {\n <!-- \u2500\u2500 Drill-in header: \u0111ang thi\u1EBFt k\u1EBF children c\u1EE7a 1 group \u2500\u2500 -->\n <header class=\"fb-canvas__header fb-canvas__header--group\">\n <div class=\"fb-canvas__title fb-groupedit__crumb\">\n <button type=\"button\" class=\"fb-icon-btn\" [matTooltip]=\"'core.component.form-builder.back-to-design' | translate\" (click)=\"cancelGroupEdit()\">\n <span class=\"msi\">chevron_left</span>\n </button>\n <span class=\"fb-groupedit__icon\"><span class=\"msi\">{{ _editing.properties?.icon || 'category' }}</span></span>\n <span>{{ _editing.label || ('core.component.form-builder.edit-group' | translate) }}</span>\n <span class=\"fb-groupedit__hint\">{{ 'core.component.form-builder.edit-group' | translate }}</span>\n </div>\n <div class=\"fb-canvas__actions\">\n <sd-button type=\"outline\" [title]=\"'core.component.form-builder.cancel' | translate\" (click)=\"cancelGroupEdit()\"></sd-button>\n <sd-button type=\"fill\" color=\"primary\" prefixIcon=\"check\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"confirmGroupEdit()\"></sd-button>\n </div>\n </header>\n } @else {\n <header class=\"fb-canvas__header\">\n <div class=\"fb-canvas__title\">\n <span>{{ 'core.component.form-builder.layout' | translate }}</span>\n </div>\n <div class=\"fb-canvas__actions\">\n <!-- Toolbar cluster: view JSON / variables / validation -->\n <button\n type=\"button\"\n class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.view-json' | translate\"\n (click)=\"viewJSON()\">\n <span class=\"msi\">data_object</span>\n </button>\n <button\n type=\"button\"\n class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.config-variable' | translate\"\n (click)=\"configureVariables()\">\n <span class=\"msi\">data_array</span>\n </button>\n <button\n type=\"button\"\n class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.config-validation-warning-error' | translate\"\n (click)=\"openConfigureValidation()\">\n <span class=\"msi\">rule</span>\n </button>\n\n <span class=\"fb-divider\"></span>\n\n <!-- M3 segmented Design/Preview toggle -->\n <div class=\"fb-mode-toggle\" role=\"tablist\">\n <button\n type=\"button\"\n role=\"tab\"\n [class.is-active]=\"!isPreview()\"\n (click)=\"setMode(false)\">\n <span class=\"msi\">edit</span>\n <span>{{ 'core.component.form-builder.design' | translate }}</span>\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n [class.is-active]=\"isPreview()\"\n (click)=\"setMode(true)\">\n <span class=\"msi\">visibility</span>\n <span>{{ 'core.component.form-builder.preview' | translate }}</span>\n </button>\n </div>\n </div>\n </header>\n }\n\n <div\n class=\"fb-canvas__body\"\n [class.is-preview]=\"isPreview()\"\n id=\"frmComponent\">\n @if (isPreview()) {\n <!-- \u2500\u2500 Preview mode \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"fb-preview-card\">\n <div class=\"fb-preview-card__chip\">\n <span class=\"msi\">visibility</span>\n {{ 'core.component.form-builder.preview-runtime' | translate }}\n </div>\n <sd-form-render [configuration]=\"{ components: this.components, validations: this.validations }\"></sd-form-render>\n <div class=\"fb-preview-card__footer\">\n <sd-button type=\"outline\" [title]=\"'core.component.form-builder.cancel' | translate\" (click)=\"setMode(false)\"></sd-button>\n <sd-button type=\"fill\" color=\"primary\" [title]=\"'core.component.form-builder.submit' | translate\" (click)=\"onValidate()\"></sd-button>\n </div>\n </div>\n } @else {\n <!-- \u2500\u2500 Design mode \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (!dragDropRows.length) {\n <div class=\"fb-empty\">\n <div class=\"fb-empty__art\"><span class=\"msi\">dashboard_customize</span></div>\n <div class=\"fb-empty__title\">{{ 'core.component.form-builder.empty-title' | translate }}</div>\n <div class=\"fb-empty__hint\">\n {{ 'core.component.form-builder.empty-hint' | translate }}\n <span class=\"fb-empty__kbd\"><span class=\"msi\">keyboard</span>\u2318 K</span>\n </div>\n </div>\n }\n\n <div\n cdkDropList\n cdkDropListOrientation=\"vertical\"\n [cdkDropListData]=\"dragDropRows\"\n (cdkDropListDropped)=\"drop($event)\"\n (click)=\"clickFormContentEmpty()\"\n aria-hidden=\"true\">\n @for (row of dragDropRows; track row.rowIndex) {\n <div\n cdkDrag\n class=\"fb-row\"\n (mouseover)=\"onMouseover($event, row)\"\n (focus)=\"onFocus($event)\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"onAnyDragEnded()\"\n [class.is-drag-target]=\"targetItem === row\"\n [id]=\"'row_' + row.rowIndex\"\n aria-hidden=\"true\">\n <div class=\"fb-row__drag\" [matTooltip]=\"'core.component.form-builder.drag-vertically' | translate\" cdkDragHandle>\n <span class=\"msi\">drag_indicator</span>\n </div>\n <!-- Generic puck preview -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <!-- Quick-add break button \u2014 show on row hover, insert break after this row -->\n <button\n type=\"button\"\n class=\"fb-row-break-btn\"\n [matTooltip]=\"'core.component.form-builder.break' | translate\"\n matTooltipPosition=\"right\"\n (click)=\"insertBreakAfter(row); $event.stopPropagation()\">\n <span class=\"msi\">horizontal_rule</span>\n </button>\n\n <div\n class=\"fb-row__items\"\n style=\"display: flex; flex: 1; gap: var(--gap-2);\"\n cdkDropList\n cdkDropListOrientation=\"horizontal\"\n [cdkDropListData]=\"row.items\"\n (cdkDropListDropped)=\"drop($event)\">\n\n @for (item of row.items; track item.id; let i = $index) {\n <!-- Group component renders as outlined card with colored header bar -->\n @if (item.type === 'group') {\n @let g = $any(item);\n @let cv = groupColorVars(g.properties?.color);\n <div\n cdkDrag\n [id]=\"item.id\"\n class=\"fb-group column-{{ item.layout?.columns || 12 }}\"\n [class.fb-item]=\"false\"\n [class.is-selected]=\"item.id === selectedComponent()?.id\"\n [class.is-hidden]=\"item.properties?.hidden\"\n [style.flex]=\"'0 0 calc(' + (+(item.layout?.columns || 12)) + '/12 * 100% - var(--gap-2))'\"\n [style.maxWidth]=\"'calc(' + (+(item.layout?.columns || 12)) + '/12 * 100% - var(--gap-2))'\"\n (click)=\"selectComponent(item); $event.stopPropagation()\"\n (cdkDragStarted)=\"dragStartComponentItem($event); onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"dragEndComponentItem($event); onAnyDragEnded()\"\n aria-hidden=\"true\">\n <!-- Generic puck preview -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <!-- cdkDragHandle: ch\u1EC9 cho ph\u00E9p k\u00E9o group qua header \u2014 body free cho click v\u00E0o child. -->\n <div class=\"fb-group__header\" cdkDragHandle [style.background]=\"cv.bg\" [style.color]=\"cv.fg\">\n <span class=\"fb-group__icon\"><span class=\"msi\">{{ g.properties?.icon || 'category' }}</span></span>\n <span class=\"fb-group__label\">{{ item.label }}</span>\n @if (hasConditional(item)) {\n <span class=\"fb-group__conditional-chip\">\n <span class=\"msi\" style=\"font-size: 12px;\">bolt</span>\n {{ 'core.component.form-builder.conditional' | translate }}\n </span>\n }\n <span class=\"fb-group__count\">{{ g.components?.length || 0 }} fields</span>\n </div>\n <!-- Floating action toolbar -->\n <div class=\"fb-actions\">\n <!-- why: Detail = m\u1EDF canvas thi\u1EBFt k\u1EBF ri\u00EAng cho group (thay cho drag/drop trong group). -->\n <button type=\"button\" class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.edit-group' | translate\"\n (click)=\"enterGroupEdit(g); $event.stopPropagation()\">\n <span class=\"msi\">open_in_full</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.duplicate' | translate\"\n (click)=\"onDuplicate(item); $event.stopPropagation()\">\n <span class=\"msi\">content_copy</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"item.properties?.hidden\"\n [class.on]=\"item.properties?.hidden\"\n [matTooltip]=\"item.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\n (click)=\"onChangeHidden(item); $event.stopPropagation()\">\n <span class=\"msi\">{{ item.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn danger\"\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"removeComponent(item.id); $event.stopPropagation()\">\n <span class=\"msi\">delete</span>\n </button>\n </div>\n\n <!-- Static preview: children render read-only (kh\u00F4ng drag/resize/select).\n S\u1EEDa n\u1ED9i dung group qua n\u00FAt Detail (enterGroupEdit). -->\n <div class=\"fb-group__body fb-group__body--static\" (click)=\"enterGroupEdit(g); $event.stopPropagation()\">\n @if (!g.components?.length) {\n <div class=\"fb-group__empty\">\n <span class=\"msi\" style=\"font-size: 16px; margin-right: 6px;\">open_in_full</span>\n {{ 'core.component.form-builder.group-empty-hint' | translate }}\n </div>\n }\n @for (child of g.components; track child.id) {\n <div\n class=\"fb-item is-child fb-item--static column-{{ child.layout?.columns || 12 }}\"\n [class.is-hidden]=\"child.properties?.hidden\">\n <ng-container\n *ngTemplateOutlet=\"controlTemplate; context: { $implicit: child }\">\n </ng-container>\n </div>\n }\n </div>\n </div>\n } @else if (item.type === 'break') {\n <!-- Break: row separator c\u1ED1 \u0111\u1ECBnh. Render 12-col line, kh\u00F4ng c\u00F3 resize/edit attribute. -->\n <div\n cdkDrag\n [id]=\"item.id\"\n class=\"fb-item is-break column-12\"\n [class.is-selected]=\"item.id === selectedComponent()?.id\"\n [class.is-hidden]=\"item.properties?.hidden\"\n (click)=\"selectComponent(item); $event.stopPropagation()\"\n (cdkDragStarted)=\"dragStartComponentItem($event); onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"dragEndComponentItem($event); onAnyDragEnded()\"\n aria-hidden=\"true\">\n <!-- Generic puck preview -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <div class=\"fb-break-line\">\n <span class=\"msi\">horizontal_rule</span>\n <span class=\"fb-break-label\">{{ 'core.component.form-builder.break' | translate }}</span>\n </div>\n <div class=\"fb-actions\">\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"item.properties?.hidden\"\n [class.on]=\"item.properties?.hidden\"\n [matTooltip]=\"item.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\n (click)=\"onChangeHidden(item); $event.stopPropagation()\">\n <span class=\"msi\">{{ item.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn danger\"\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"removeComponent(item.id); $event.stopPropagation()\">\n <span class=\"msi\">delete</span>\n </button>\n </div>\n </div>\n } @else {\n <!-- Regular form component -->\n <div\n cdkDrag\n [id]=\"item.id\"\n class=\"fb-item column-{{ item.layout?.columns || 12 }}\"\n [class.is-selected]=\"item.id === selectedComponent()?.id\"\n [class.is-hidden]=\"item.properties?.hidden\"\n [class.is-readonly]=\"item.properties?.viewed\"\n (click)=\"selectComponent(item); $event.stopPropagation()\"\n (cdkDragStarted)=\"dragStartComponentItem($event); onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"dragEndComponentItem($event); onAnyDragEnded()\"\n aria-hidden=\"true\">\n <!-- Generic puck preview -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n\n <!-- Status chip (mutually exclusive priority: hidden > readonly > conditional) -->\n @if (item.properties?.hidden) {\n <span class=\"fb-status-chip hidden\">\n <span class=\"msi\">visibility_off</span>\n {{ 'core.component.form-builder.hidden' | translate }}\n </span>\n } @else if (item.properties?.viewed) {\n <span class=\"fb-status-chip readonly\">\n <span class=\"msi\">edit_off</span>\n {{ 'core.component.form-builder.read-only' | translate }}\n </span>\n } @else if (hasConditional(item)) {\n <span class=\"fb-status-chip conditional\">\n <span class=\"msi\">bolt</span>\n {{ 'core.component.form-builder.conditional' | translate }}\n </span>\n }\n\n <!-- Floating action toolbar pill -->\n <div class=\"fb-actions\">\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"item.properties?.viewed\"\n [class.on]=\"item.properties?.viewed\"\n [matTooltip]=\"item.properties?.viewed ? ('core.component.form-builder.unset-readonly' | translate) : ('core.component.form-builder.set-readonly' | translate)\"\n (click)=\"onChangeViewed(item); $event.stopPropagation()\">\n <span class=\"msi\">edit_off</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.duplicate' | translate\"\n (click)=\"onDuplicate(item); $event.stopPropagation()\">\n <span class=\"msi\">content_copy</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"item.properties?.hidden\"\n [class.on]=\"item.properties?.hidden\"\n [matTooltip]=\"item.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\n (click)=\"onChangeHidden(item); $event.stopPropagation()\">\n <span class=\"msi\">{{ item.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn danger\"\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"removeComponent(item.id); $event.stopPropagation()\">\n <span class=\"msi\">delete</span>\n </button>\n </div>\n\n <ng-container\n *ngTemplateOutlet=\"controlTemplate; context: { $implicit: item }\">\n </ng-container>\n\n <!-- Resize handle (pill) \u2014 cdkDragLockAxis=\"x\" \u0111\u1EC3 ch\u1EC9 k\u00E9o ngang.\n Wrapping cdkDropList c\u00F3 enterPredicate=false, kh\u00F4ng nh\u1EADn drop. -->\n <div cdkDropList cdkDropListOrientation=\"horizontal\" [cdkDropListEnterPredicate]=\"noReturnPredicate\">\n <div\n cdkDrag\n cdkDragLockAxis=\"x\"\n class=\"fb-resize\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"changeSizeControl($event, item, row.items, i)\"\n (cdkDragEnded)=\"dragEndChangeSizeControl($event); onAnyDragEnded()\"\n [matTooltip]=\"'core.component.form-builder.flex' | translate\"\n aria-label=\"resize\"></div>\n </div>\n </div>\n }\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n </section>\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 RIGHT ATTRIBUTES \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <aside class=\"fb-attrs\">\n <div class=\"fb-panel-header\">\n <div class=\"fb-panel-header__title\">{{ 'core.component.form-builder.attribute' | translate }}</div>\n </div>\n\n @let sel = selectedComponent();\n @if (sel) {\n <!-- Selection header: type icon + name + key/type -->\n <div class=\"fb-attrs__selection\">\n <span class=\"fb-attrs__sel-icon\"><span class=\"msi\">{{ symbolFor(sel) }}</span></span>\n <div class=\"fb-attrs__sel-meta\">\n <div class=\"fb-attrs__sel-name\">{{ $any(sel).label || ('core.component.form-builder.untitled' | translate) }}</div>\n <div class=\"fb-attrs__sel-key\">\n @if ($any(sel).key) {\n {{ $any(sel).key }} \u00B7 {{ typeLabelFor(sel) }}\n } @else {\n {{ typeLabelFor(sel) }}\n }\n </div>\n </div>\n </div>\n\n <div class=\"fb-attrs__body\" aria-hidden=\"true\">\n @if (sel.type === 'textfield') {\n <textfield-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></textfield-attribute>\n } @else if (sel.type === 'textarea') {\n <textarea-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></textarea-attribute>\n } @else if (sel.type === 'chip-string') {\n <chip-string-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></chip-string-attribute>\n } @else if (sel.type === 'chip-calendar') {\n <chip-calendar-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></chip-calendar-attribute>\n } @else if (sel.type === 'number') {\n <number-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></number-attribute>\n } @else if (sel.type === 'datetime') {\n <datetime-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></datetime-attribute>\n } @else if (sel.type === 'select') {\n <select-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></select-attribute>\n } @else if (sel.type === 'radio') {\n <radio-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></radio-attribute>\n } @else if (sel.type === 'checkbox') {\n <checkbox-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></checkbox-attribute>\n } @else if (sel.type === 'html') {\n <html-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></html-attribute>\n } @else if (sel.type === 'upload') {\n <upload-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></upload-attribute>\n } @else if (sel.type === 'table') {\n <table-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></table-attribute>\n } @else if (sel.type === 'group') {\n <group-attribute [group]=\"$any(sel)\"></group-attribute>\n }\n </div>\n } @else {\n <div class=\"fb-attrs__placeholder\">\n <span class=\"msi\">ads_click</span>\n <div class=\"title\">{{ 'core.component.form-builder.no-selection-title' | translate }}</div>\n <div class=\"hint\">{{ 'core.component.form-builder.no-selection-hint' | translate }}</div>\n </div>\n }\n </aside>\n</div>\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Reusable control template \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n<ng-template #controlTemplate let-item>\n @if (item.type === 'textfield') {\n <textfield-control [component]=\"item\"></textfield-control>\n } @else if (item.type === 'textarea') {\n <textarea-control [component]=\"item\"></textarea-control>\n } @else if (item.type === 'chip-string') {\n <chip-string-control [component]=\"item\"></chip-string-control>\n } @else if (item.type === 'chip-calendar') {\n <chip-calendar-control [component]=\"item\"></chip-calendar-control>\n } @else if (item.type === 'number') {\n <number-control [component]=\"item\"></number-control>\n } @else if (item.type === 'datetime') {\n <datetime-control [component]=\"item\"></datetime-control>\n } @else if (item.type === 'select') {\n <select-control [component]=\"item\"></select-control>\n } @else if (item.type === 'radio') {\n <radio-control [component]=\"item\"></radio-control>\n } @else if (item.type === 'checkbox') {\n <checkbox-control [component]=\"item\"></checkbox-control>\n } @else if (item.type === 'html') {\n <html-control [component]=\"item\"></html-control>\n } @else if (item.type === 'upload') {\n <upload-control [component]=\"item\"></upload-control>\n } @else if (item.type === 'table') {\n <table-control [component]=\"item\"></table-control>\n }\n</ng-template>\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 JSON / variables modals \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n<sd-modal title=\"JSON\" view=\"dialog\" width=\"80%\" #popupViewJSON>\n <sd-textarea [(model)]=\"jsonString\"></sd-textarea>\n <ng-container sdFooter>\n <sd-button type=\"fill\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"updateJSON()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\n </ng-container>\n</sd-modal>\n<sd-modal [title]=\"'core.component.form-builder.config-variable' | translate\" view=\"dialog\" width=\"800px\" #popupConfigureVariables>\n @for (variable of clonedVariables; track variable.id) {\n <div class=\"d-flex align-items-center\" style=\"gap: 8px\">\n <sd-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"variable.key\" required></sd-input>\n <sd-input [form]=\"form\" [label]=\"'core.component.form-builder.display-label' | translate\" [(model)]=\"variable.label\" required></sd-input>\n <sd-button prefixIcon=\"delete\" (click)=\"removeVariables(variable.id)\" color=\"error\"></sd-button>\n </div>\n }\n <a href=\"javascript:;\" (click)=\"addVariables()\">{{ 'core.component.form-builder.add-variable' | translate }}</a>\n <ng-container sdFooter>\n <sd-button type=\"fill\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"updateVariables()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\n </ng-container>\n</sd-modal>\n<configure-validation (accept)=\"onUpdateValidations($event)\"></configure-validation>\n", styles: ["@charset \"UTF-8\";:host{--md-sys-color-primary: var(--sd-primary, #2A66F4);--md-sys-color-on-primary: #ffffff;--md-sys-color-primary-container: var(--sd-primary-light, #EAF1FF);--md-sys-color-on-primary-container: var(--sd-primary, #2A66F4);--md-sys-color-info: var(--sd-info, #2962FF);--md-sys-color-info-container: var(--sd-info-light, #E7E9FF);--md-sys-color-secondary: #625b71;--md-sys-color-secondary-container: #e8def8;--md-sys-color-on-secondary-container: #1d192b;--md-sys-color-surface: #fbfafc;--md-sys-color-surface-container-lowest: #ffffff;--md-sys-color-surface-container-low: #f6f4f8;--md-sys-color-surface-container: #f1eef3;--md-sys-color-surface-container-high: #ebe8ee;--md-sys-color-surface-container-highest: #e6e2ea;--md-sys-color-on-surface: #1c1b1f;--md-sys-color-on-surface-variant: #49454e;--md-sys-color-outline: #79747e;--md-sys-color-outline-variant: #d6d2da;--md-sys-color-error: #b3261e;--md-sys-color-error-container: #f9dedc;--md-sys-color-warning: #8a5400;--md-sys-color-warning-container: #ffddb1;--md-sys-color-success: #1f6f43;--md-sys-color-success-container: #b7f0cb;--h-row: 28px;--h-field: 32px;--h-palette: 36px;--h-header: 36px;--h-section: 28px;--h-action-btn: 24px;--gap-1: 4px;--gap-2: 8px;--gap-3: 12px;--gap-4: 16px;--gap-5: 24px;--r-xs: 4px;--r-sm: 8px;--r-md: 12px;--r-lg: 16px;--r-xl: 28px;--r-pill: 999px;--elev-1: 0 1px 2px 0 rgba(0, 0, 0, .06);--elev-2: 0 2px 6px 0 rgba(0, 0, 0, .08), 0 1px 2px 0 rgba(0, 0, 0, .04);--elev-3: 0 6px 14px 0 rgba(0, 0, 0, .1), 0 2px 4px 0 rgba(0, 0, 0, .06);display:block;width:100%;height:100%;font-family:Roboto,system-ui,sans-serif;font-size:13px;color:var(--md-sys-color-on-surface);background:var(--md-sys-color-surface)}:host ::ng-deep .msi{font-family:Material Symbols Rounded;font-weight:400;font-style:normal;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;font-feature-settings:\"liga\";-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"wght\" 300,\"opsz\" 24,\"GRAD\" 0,\"FILL\" 0}:host ::ng-deep .msi.filled{font-variation-settings:\"wght\" 300,\"opsz\" 24,\"GRAD\" 0,\"FILL\" 1}:host ::ng-deep .mono{font-family:Roboto Mono,ui-monospace,monospace}:host ::ng-deep .fb-icon-btn{width:28px;height:28px;border-radius:var(--r-sm);border:none;background:transparent;color:var(--md-sys-color-on-surface-variant);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background .12s ease,color .12s ease}:host ::ng-deep .fb-icon-btn:hover{background:color-mix(in srgb,var(--md-sys-color-on-surface) 8%,transparent);color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-icon-btn.is-active{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container)}:host ::ng-deep .fb-icon-btn.danger:hover{color:var(--md-sys-color-error);background:var(--md-sys-color-error-container)}:host ::ng-deep .fb-icon-btn.warning.on{color:var(--md-sys-color-warning);background:var(--md-sys-color-warning-container)}:host ::ng-deep .fb-icon-btn .msi{font-size:18px}:host ::ng-deep .fb-field{display:flex;flex-direction:column;gap:4px}:host ::ng-deep .fb-field__label{font-size:11px;font-weight:500;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-field__input{height:var(--h-row);padding:0 10px;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px;display:flex;align-items:center;justify-content:space-between;color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-field__input.placeholder{color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-field__input:focus-within,:host ::ng-deep .fb-field__input.focused{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent)}:host ::ng-deep .fb-field__input .msi{font-size:16px;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-field-row{display:flex;align-items:center;gap:var(--gap-2);justify-content:space-between}:host ::ng-deep .fb-switch{display:inline-flex;width:34px;height:18px;border-radius:999px;background:var(--md-sys-color-surface-container-highest);border:1.5px solid var(--md-sys-color-outline);padding:1px;align-items:center;cursor:pointer;position:relative;flex-shrink:0}:host ::ng-deep .fb-switch .fb-switch__thumb{width:12px;height:12px;border-radius:50%;background:var(--md-sys-color-outline)}:host ::ng-deep .fb-switch.on{background:var(--md-sys-color-primary);border-color:var(--md-sys-color-primary);justify-content:flex-end}:host ::ng-deep .fb-switch.on .fb-switch__thumb{background:var(--md-sys-color-on-primary);width:14px;height:14px}:host ::ng-deep .fb-expr{display:flex;align-items:center;gap:6px;height:var(--h-row);padding:0 6px 0 0;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-expr__badge{height:100%;display:inline-flex;align-items:center;justify-content:center;padding:0 6px;background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);font-family:Roboto Mono,monospace;font-size:10px;font-weight:500;border-radius:var(--r-xs) 0 0 var(--r-xs)}:host ::ng-deep .fb-expr__code{font-family:Roboto Mono,monospace;flex:1;font-size:11px;color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-expr__code .var{color:var(--md-sys-color-primary);font-weight:500}:host ::ng-deep .fb-expr__code .op{color:var(--md-sys-color-error)}:host ::ng-deep .fb-expr__code .lit{color:var(--md-sys-color-success)}:host ::ng-deep .fb-expr .empty{color:var(--md-sys-color-on-surface-variant);font-style:italic;padding-left:6px;flex:1}:host ::ng-deep details.fb-section{border-bottom:1px solid var(--md-sys-color-outline-variant);margin:0;padding:0;background:transparent}:host ::ng-deep details.fb-section>summary{list-style:none}:host ::ng-deep details.fb-section>summary::-webkit-details-marker{display:none}:host ::ng-deep .fb-section__head{height:var(--h-section);padding:0 var(--gap-4);display:flex;align-items:center;gap:var(--gap-2);cursor:pointer;font-size:12px;font-weight:500;color:var(--md-sys-color-on-surface);-webkit-user-select:none;user-select:none}:host ::ng-deep .fb-section__head .msi{font-size:16px;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-section__head .fb-section__title{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep .fb-section__head .chev{margin-left:auto;transition:transform .16s ease}:host ::ng-deep details.fb-section[open] .fb-section__head .chev{transform:rotate(90deg)}:host ::ng-deep .fb-section__body{padding:4px var(--gap-4) var(--gap-3);display:flex;flex-direction:column;gap:var(--gap-2)}:host ::ng-deep .fb-columns-list{display:flex;flex-direction:column;gap:var(--gap-1);padding-top:var(--gap-1)}:host ::ng-deep .fb-column-row{display:flex;align-items:center;gap:var(--gap-2);height:40px;padding:6px 10px;border-radius:var(--r-sm);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px;cursor:pointer;transition:background .12s ease,border-color .12s ease,box-shadow .12s ease}:host ::ng-deep .fb-column-row:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 4%,transparent);border-color:color-mix(in srgb,var(--md-sys-color-primary) 30%,transparent)}:host ::ng-deep .fb-column-row.is-active{border-color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 30%,transparent)}:host ::ng-deep .fb-column-row .fb-column-row__type-icon{width:28px;height:28px;border-radius:var(--r-sm);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}:host ::ng-deep .fb-column-row .fb-column-row__type-icon .msi{font-size:16px}:host ::ng-deep .fb-column-row .fb-column-row__meta{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}:host ::ng-deep .fb-column-row .fb-column-row__meta .fb-column-row__label{font-size:13px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-column-row .fb-column-row__meta .fb-column-row__req{color:var(--md-sys-color-error);margin-left:2px;font-weight:600}:host ::ng-deep .fb-column-row .fb-column-row__meta .fb-column-row__sub{font-size:11px;color:var(--md-sys-color-on-surface-variant);font-family:Roboto Mono,ui-monospace,monospace;letter-spacing:.02em}:host ::ng-deep .cdk-drag-preview.fb-drag-preview,:host ::ng-deep .fb-drag-preview{width:36px;height:36px;min-width:36px;min-height:36px;max-width:36px;max-height:36px;box-sizing:border-box;border-radius:50%;background:var(--md-sys-color-primary, #6750a4);display:inline-flex;align-items:center;justify-content:center;box-shadow:0 10px 24px #00000042,0 3px 8px #00000024;border:3px solid var(--md-sys-color-on-primary, #ffffff);cursor:grabbing;pointer-events:none;-webkit-user-select:none;user-select:none;opacity:.96;overflow:hidden;z-index:10000}:host ::ng-deep .cdk-drag-preview.fb-drag-preview:after,:host ::ng-deep .fb-drag-preview:after{content:\"\";width:8px;height:8px;border-radius:50%;background:var(--md-sys-color-on-primary, #ffffff);opacity:.9}@keyframes fb-drop-pulse{0%,to{box-shadow:0 0 0 3px color-mix(in srgb,var(--md-sys-color-info) 16%,transparent)}50%{box-shadow:0 0 0 5px color-mix(in srgb,var(--md-sys-color-info) 24%,transparent)}}:host ::ng-deep .cdk-drag-placeholder{background:transparent!important;border:none!important;border-radius:999px!important;padding:0!important;transform:none!important;transition:none!important;pointer-events:none;overflow:hidden;animation:none!important;opacity:0!important}:host ::ng-deep .cdk-drag-placeholder>*{visibility:hidden!important;pointer-events:none!important}:host ::ng-deep .fb-palette__list>.cdk-drag-placeholder{display:none!important}:host ::ng-deep .fb-row__items>.cdk-drag-placeholder,:host ::ng-deep .fb-group__body>.cdk-drag-placeholder{width:0!important;min-width:0!important;max-width:0!important;height:auto!important;min-height:0!important;align-self:stretch;flex:0 0 0!important;margin:0!important}:host ::ng-deep [cdkDropListOrientation=vertical]>.cdk-drag-placeholder{width:auto!important;height:0!important;min-height:0!important;max-height:0!important;flex:0 0 0!important;margin:0!important;align-self:stretch}:host ::ng-deep .cdk-drop-list-receiving{background:color-mix(in srgb,var(--md-sys-color-primary) 3%,transparent);transition:background .16s ease}:host ::ng-deep .fb-group__body.cdk-drop-list-receiving,:host ::ng-deep .fb-group__body.cdk-drop-list-dragging{background:color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent)!important;outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 78%,transparent);outline-offset:-6px;border-radius:var(--r-sm)}:host ::ng-deep .fb-resize.cdk-drag-preview{display:none!important}:host ::ng-deep .fb-shell--dragging .fb-item:hover,:host ::ng-deep .fb-shell--dragging .fb-group:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-item:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group:hover{border-color:transparent!important;background:transparent!important}:host ::ng-deep .fb-shell--dragging .fb-row:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row:hover{outline-color:transparent!important;background:transparent!important}:host ::ng-deep .fb-shell--dragging .fb-row:hover .fb-row__drag,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row:hover .fb-row__drag{opacity:0!important}:host ::ng-deep .fb-shell--dragging .fb-row.is-drag-target,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row.is-drag-target{outline-color:color-mix(in srgb,var(--md-sys-color-info) 44%,transparent)!important;background:color-mix(in srgb,var(--md-sys-color-info) 4%,transparent)!important}:host ::ng-deep .fb-shell--dragging .fb-row__drag,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row__drag{opacity:0!important}:host ::ng-deep .fb-shell--dragging .fb-actions,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-actions{opacity:0!important;pointer-events:none!important;transform:translateY(-2px)!important}:host ::ng-deep .fb-shell--dragging .fb-resize,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-resize{opacity:0!important;pointer-events:none!important}:host ::ng-deep .fb-shell--dragging .fb-row-break-btn,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row-break-btn{opacity:0!important;pointer-events:none!important}:host ::ng-deep .fb-shell--dragging .fb-palette-item:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-palette-item:hover{background:transparent!important}:host ::ng-deep .fb-shell--dragging .fb-palette-item:hover .fb-palette-item__drag,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-palette-item:hover .fb-palette-item__drag{opacity:0!important}:host ::ng-deep .fb-shell--dragging .fb-group__body,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__body{min-height:80px!important;background:color-mix(in srgb,var(--md-sys-color-primary) 5%,transparent)!important;outline:2px dashed color-mix(in srgb,var(--md-sys-color-primary) 50%,transparent)!important;outline-offset:-6px;border-radius:var(--r-sm);transition:background .16s ease,outline .16s ease,min-height .16s ease}:host ::ng-deep .fb-shell--dragging .fb-group__empty,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__empty{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 55%,transparent);background:color-mix(in srgb,var(--md-sys-color-primary) 7%,transparent);color:var(--md-sys-color-primary)}:host ::ng-deep .fb-shell--dragging .fb-group__body.cdk-drop-list-receiving,:host ::ng-deep .fb-shell--dragging .fb-group__body.cdk-drop-list-dragging,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__body.cdk-drop-list-receiving,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__body.cdk-drop-list-dragging{background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)!important;outline:2px solid var(--md-sys-color-primary)!important}:host ::ng-deep .cdk-drag-animating{transition:transform .22s cubic-bezier(.2,0,0,1)!important}:host ::ng-deep .cdk-drag-dragging{transition:none!important}:host ::ng-deep .fb-item:not(.cdk-drag-dragging){transition:flex .12s cubic-bezier(.2,0,0,1),max-width .12s cubic-bezier(.2,0,0,1),border-color .12s,background .12s}.fb-shell{width:100%;height:100%;display:flex;background:var(--md-sys-color-surface);overflow:hidden;min-height:0}.fb-panel-header{height:var(--h-header);display:flex;align-items:center;justify-content:space-between;padding:0 var(--gap-3);border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);flex-shrink:0}.fb-panel-header__title{font-size:11px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant)}.fb-panel-header__actions{display:flex;align-items:center;gap:2px}.fb-palette{width:220px;flex-shrink:0;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-right:1px solid var(--md-sys-color-outline-variant)}.fb-palette__scroll{flex:1;overflow-y:auto;padding-bottom:var(--gap-3)}.fb-palette__search{margin:var(--gap-3);height:32px;display:flex;align-items:center;gap:var(--gap-2);padding:0 var(--gap-3);border-radius:var(--r-pill);background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant);font-size:13px;flex-shrink:0}.fb-palette__search .msi{font-size:18px}.fb-palette__search input{flex:1;border:none;outline:none;background:transparent;color:var(--md-sys-color-on-surface);font-size:13px;font-family:inherit}.fb-palette__search input::placeholder{color:var(--md-sys-color-on-surface-variant)}.fb-palette__search .kbd{font-family:Roboto Mono,monospace;font-size:10px;padding:1px 6px;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant)}.fb-palette__group-label{font-size:11px;font-weight:500;letter-spacing:.04em;color:var(--md-sys-color-on-surface-variant);padding:var(--gap-3) var(--gap-4) var(--gap-1);text-transform:uppercase}.fb-palette__list{display:flex;flex-direction:column;padding:0 var(--gap-2)}.fb-palette-item{height:var(--h-palette);display:flex;align-items:center;gap:var(--gap-3);padding:0 var(--gap-3);border-radius:var(--r-sm);cursor:grab;color:var(--md-sys-color-on-surface);position:relative;-webkit-user-select:none;user-select:none}.fb-palette-item:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent)}.fb-palette-item .fb-palette-item__icon{width:24px;height:24px;border-radius:var(--r-xs);display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);flex-shrink:0}.fb-palette-item .fb-palette-item__icon .msi{font-size:16px}.fb-palette-item .fb-palette-item__name{font-size:13px;font-weight:400}.fb-palette-item .fb-palette-item__drag{margin-left:auto;color:var(--md-sys-color-outline);opacity:0;transition:opacity .12s ease}.fb-palette-item .fb-palette-item__drag .msi{font-size:16px}.fb-palette-item:hover .fb-palette-item__drag{opacity:1}.fb-canvas{flex:1 1 0;min-width:0;display:flex;flex-direction:column;background:var(--md-sys-color-surface);overflow:hidden}.fb-canvas__header{height:var(--h-header);display:flex;align-items:center;justify-content:space-between;padding:0 var(--gap-4);border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);gap:var(--gap-3);flex-shrink:0}.fb-canvas__title{display:flex;align-items:center;gap:var(--gap-2);font-size:11px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant)}.fb-canvas__title .breadcrumb-sep{color:var(--md-sys-color-outline)}.fb-canvas__actions{display:flex;align-items:center;gap:var(--gap-2)}.fb-divider{width:1px;height:18px;background:var(--md-sys-color-outline-variant)}.fb-canvas__body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;padding:var(--gap-4);position:relative;background:var(--md-sys-color-surface);min-width:0}.fb-canvas__body.is-preview{background:var(--md-sys-color-surface-container-low);padding:32px}.fb-mode-toggle{display:inline-flex;height:28px;border:1px solid var(--md-sys-color-outline);border-radius:var(--r-pill);overflow:hidden;flex-shrink:0}.fb-mode-toggle button{border:0;background:transparent;padding:0 var(--gap-3);font-size:12px;font-weight:500;display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-surface-variant);cursor:pointer}.fb-mode-toggle button .msi{font-size:16px}.fb-mode-toggle button.is-active{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.fb-row{position:relative;display:flex;gap:var(--gap-2);padding:6px var(--gap-2);border-radius:var(--r-sm);margin-bottom:6px;min-width:0;transition:outline .12s ease,background .12s ease;outline:1px dashed transparent;outline-offset:-1px}.fb-row:hover{outline-color:var(--md-sys-color-outline-variant);background:color-mix(in srgb,var(--md-sys-color-primary) 3%,transparent)}.fb-row:hover .fb-row__drag{opacity:1}.fb-row.is-drag-target{outline-color:color-mix(in srgb,var(--md-sys-color-info) 44%,transparent);background:color-mix(in srgb,var(--md-sys-color-info) 4%,transparent)}.fb-row.is-drag-target:after{content:\"\";position:absolute;left:10px;right:10px;bottom:-3px;height:4px;border-radius:999px;background:var(--md-sys-color-info);box-shadow:0 0 0 4px color-mix(in srgb,var(--md-sys-color-info) 18%,transparent);pointer-events:none;animation:fb-drop-pulse .9s ease-in-out infinite;z-index:3}.fb-row__drag{position:absolute;left:-22px;top:50%;transform:translateY(-50%);width:18px;height:22px;border-radius:var(--r-xs);display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-high);opacity:0;cursor:grab;z-index:2}.fb-row__drag .msi{font-size:14px}.fb-row-break-btn{position:absolute;right:-28px;top:50%;transform:translateY(-50%);width:22px;height:22px;border-radius:var(--r-pill);display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-high);border:1px solid var(--md-sys-color-outline-variant);cursor:pointer;opacity:0;z-index:2;transition:opacity .12s ease,background .12s ease,color .12s ease}.fb-row-break-btn .msi{font-size:14px}.fb-row-break-btn:hover{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);border-color:transparent}.fb-row:hover .fb-row-break-btn{opacity:1}.fb-item{position:relative;border:1.5px dashed transparent;border-radius:var(--r-md);padding:var(--gap-2) var(--gap-3);min-height:56px;min-width:0;transition:border-color .12s ease,background .12s ease;background:transparent;cursor:grab;display:flex;flex-direction:column;gap:6px}.fb-item:hover{border-color:color-mix(in srgb,var(--md-sys-color-primary) 60%,transparent)}.fb-item.is-selected{border:1.5px solid var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 4%,transparent)}.fb-item.is-hidden{opacity:.45}.fb-item.is-readonly:after{content:\"\";position:absolute;inset:0;border-radius:var(--r-md);background:repeating-linear-gradient(135deg,transparent 0 6px,color-mix(in srgb,var(--md-sys-color-on-surface) 4%,transparent) 6px 7px);pointer-events:none}.fb-item.column-2{flex:0 0 calc(16.6666666667% - var(--gap-2));max-width:calc(16.6666666667% - var(--gap-2))}.fb-item.column-3{flex:0 0 calc(25% - var(--gap-2));max-width:calc(25% - var(--gap-2))}.fb-item.column-4{flex:0 0 calc(33.3333333333% - var(--gap-2));max-width:calc(33.3333333333% - var(--gap-2))}.fb-item.column-5{flex:0 0 calc(41.6666666667% - var(--gap-2));max-width:calc(41.6666666667% - var(--gap-2))}.fb-item.column-6{flex:0 0 calc(50% - var(--gap-2));max-width:calc(50% - var(--gap-2))}.fb-item.column-7{flex:0 0 calc(58.3333333333% - var(--gap-2));max-width:calc(58.3333333333% - var(--gap-2))}.fb-item.column-8{flex:0 0 calc(66.6666666667% - var(--gap-2));max-width:calc(66.6666666667% - var(--gap-2))}.fb-item.column-9{flex:0 0 calc(75% - var(--gap-2));max-width:calc(75% - var(--gap-2))}.fb-item.column-10{flex:0 0 calc(83.3333333333% - var(--gap-2));max-width:calc(83.3333333333% - var(--gap-2))}.fb-item.column-11{flex:0 0 calc(91.6666666667% - var(--gap-2));max-width:calc(91.6666666667% - var(--gap-2))}.fb-item.column-12{flex:1 1 100%;max-width:100%}.fb-actions{position:absolute;top:-14px;right:8px;display:flex;align-items:center;gap:2px;padding:2px;border-radius:var(--r-pill);background:var(--md-sys-color-surface-container-lowest);box-shadow:var(--elev-2);border:1px solid var(--md-sys-color-outline-variant);z-index:4;opacity:0;transform:translateY(-2px);pointer-events:none;transition:opacity .12s ease,transform .12s ease}.fb-actions .fb-icon-btn{width:24px;height:24px}.fb-actions .fb-icon-btn .msi{font-size:16px}.fb-item:hover .fb-actions,.fb-item.is-selected .fb-actions{opacity:1;transform:translateY(0);pointer-events:auto}table-control{display:block;width:100%;max-width:100%;min-width:0}.fb-group>.fb-actions{top:6px;right:8px}.fb-group:hover>.fb-actions,.fb-group.is-selected>.fb-actions{opacity:1;transform:translateY(0);pointer-events:auto}.fb-status-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;height:18px;border-radius:var(--r-pill);font-size:10px;font-weight:500;letter-spacing:.02em;position:absolute;top:-9px;left:12px;z-index:3;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface-variant)}.fb-status-chip .msi{font-size:12px}.fb-status-chip.readonly{color:var(--md-sys-color-warning);background:var(--md-sys-color-warning-container);border-color:transparent}.fb-status-chip.hidden{color:var(--md-sys-color-on-surface-variant)}.fb-status-chip.conditional{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);border-color:transparent}.fb-resize{position:absolute;top:8px;bottom:8px;right:-5px;width:6px;border-radius:999px;background:var(--md-sys-color-primary);display:flex;align-items:center;justify-content:center;cursor:col-resize;opacity:0;transition:opacity .12s ease;z-index:3}.fb-resize:before{content:\"\";width:2px;height:18px;background:var(--md-sys-color-on-primary);border-radius:999px}.fb-item:hover .fb-resize{opacity:1}.fb-item.is-break{min-height:28px;padding:8px var(--gap-3);justify-content:center}.fb-break-line{display:flex;align-items:center;gap:var(--gap-2);color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:500;letter-spacing:.06em;text-transform:uppercase}.fb-break-line:before,.fb-break-line:after{content:\"\";flex:1;height:1px;background:var(--md-sys-color-outline-variant)}.fb-break-line .msi{display:none}.fb-break-line .fb-break-label{color:var(--md-sys-color-on-surface-variant)}.fb-drop-hint{height:36px;border-radius:var(--r-sm);border:1.5px dashed var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 6%,transparent);color:var(--md-sys-color-primary);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:500;gap:6px;margin:4px 0}.fb-drop-hint .msi{font-size:16px}.fb-group{background:var(--md-sys-color-surface-container-lowest);border-radius:var(--r-lg);border:1.5px dashed transparent;transition:border-color .12s ease,background .12s ease;position:relative;display:flex;flex-direction:column;overflow:visible;cursor:default}.fb-group:hover{border-color:color-mix(in srgb,var(--md-sys-color-primary) 60%,transparent)}.fb-group.is-selected{border:1.5px solid var(--md-sys-color-primary)}.fb-group.is-hidden{opacity:.55}.fb-group__header{display:flex;align-items:center;gap:var(--gap-2);padding:8px 12px;border-top-left-radius:12px;border-top-right-radius:12px;cursor:grab}.fb-group__header:active{cursor:grabbing}.fb-group__header .fb-group__icon .msi{font-size:18px}.fb-group__header .fb-group__label{font-size:13px;font-weight:500}.fb-group__header .fb-group__count{margin-left:auto;font-size:10px;opacity:.75}.fb-group__conditional-chip{display:inline-flex;align-items:center;gap:4px;font-family:Roboto Mono,monospace;font-size:10px;padding:2px 8px;border-radius:var(--r-pill);background:color-mix(in srgb,currentColor 12%,transparent)}.fb-group__body{padding:12px;display:flex;flex-wrap:wrap;gap:var(--gap-2);min-height:60px;position:relative}.fb-group__empty{display:flex;align-items:center;justify-content:center;height:56px;border-radius:var(--r-sm);border:1.5px dashed var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant);font-size:12px;font-style:italic}.fb-empty{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--gap-3);color:var(--md-sys-color-on-surface-variant);text-align:center;padding:24px;pointer-events:none}.fb-empty__art{width:96px;height:96px;border-radius:var(--r-xl);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center}.fb-empty__art .msi{font-size:44px}.fb-empty__title{font-size:16px;font-weight:500;color:var(--md-sys-color-on-surface)}.fb-empty__hint{font-size:13px;max-width:320px;line-height:1.5}.fb-empty__kbd{display:inline-flex;align-items:center;gap:6px;font-family:Roboto Mono,monospace;font-size:11px;padding:4px 8px;border-radius:var(--r-xs);border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface-variant)}.fb-empty__kbd .msi{font-size:12px}.fb-attrs{width:320px;flex-shrink:0;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-left:1px solid var(--md-sys-color-outline-variant)}.fb-attrs__selection{padding:var(--gap-3) var(--gap-4);display:flex;align-items:center;gap:var(--gap-2);border-bottom:1px solid var(--md-sys-color-outline-variant)}.fb-attrs__sel-icon{width:28px;height:28px;border-radius:var(--r-sm);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.fb-attrs__sel-icon .msi{font-size:18px}.fb-attrs__sel-meta{display:flex;flex-direction:column;min-width:0}.fb-attrs__sel-name{font-size:13px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-attrs__sel-key{font-family:Roboto Mono,monospace;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.fb-attrs__body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;min-width:0}.fb-attrs__placeholder{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--gap-2);padding:32px;color:var(--md-sys-color-on-surface-variant);text-align:center}.fb-attrs__placeholder .msi{font-size:32px;color:var(--md-sys-color-outline)}.fb-attrs__placeholder .title{font-size:13px;font-weight:500;color:var(--md-sys-color-on-surface)}.fb-attrs__placeholder .hint{font-size:12px;max-width:220px;line-height:1.5}.fb-preview-card{max-width:760px;margin:0 auto;background:var(--md-sys-color-surface-container-lowest);border-radius:var(--r-lg);padding:32px;box-shadow:var(--elev-1)}.fb-preview-card__chip{display:inline-flex;align-items:center;gap:6px;padding:2px 10px;height:22px;border-radius:var(--r-pill);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);font-size:10px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;margin-bottom:var(--gap-3)}.fb-preview-card__title{font-size:20px;font-weight:500;margin:0 0 var(--gap-4);color:var(--md-sys-color-on-surface)}.fb-preview-card__footer{display:flex;justify-content:flex-end;gap:var(--gap-2);margin-top:var(--gap-4);padding-top:var(--gap-4);border-top:1px solid var(--md-sys-color-outline-variant)}.fb-icon-picker{display:grid;grid-template-columns:repeat(6,1fr);gap:4px;margin-top:4px}.fb-icon-picker .fb-icon-picker__btn{height:28px;border-radius:var(--r-xs);border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface-variant);display:inline-flex;align-items:center;justify-content:center;cursor:pointer}.fb-icon-picker .fb-icon-picker__btn .msi{font-size:16px}.fb-icon-picker .fb-icon-picker__btn.is-active{border-color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary)}.fb-icon-picker .fb-icon-picker__btn:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent)}.fb-color-swatches{display:flex;gap:var(--gap-2);margin-top:4px}.fb-color-swatches .fb-color-swatch{width:24px;height:24px;border-radius:50%;cursor:pointer;border:2px solid transparent}.fb-color-swatches .fb-color-swatch.is-active{border-color:var(--md-sys-color-on-surface)}.fb-color-swatches .fb-color-swatch.primary{background:var(--md-sys-color-primary)}.fb-color-swatches .fb-color-swatch.secondary{background:var(--md-sys-color-secondary)}.fb-color-swatches .fb-color-swatch.success{background:var(--md-sys-color-success)}.fb-color-swatches .fb-color-swatch.warning{background:var(--md-sys-color-warning)}.fb-color-swatches .fb-color-swatch.error{background:var(--md-sys-color-error)}.fb-children-list{display:flex;flex-direction:column;gap:4px}.fb-child-row{display:flex;align-items:center;gap:var(--gap-2);height:30px;padding:0 8px;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px}.fb-child-row .fb-child-row__icon{width:22px;height:22px;border-radius:var(--r-xs);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.fb-child-row .fb-child-row__icon .msi{font-size:14px}.fb-child-row .fb-child-row__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fb-child-row .fb-child-row__key{font-family:Roboto Mono,monospace;font-size:10px;color:var(--md-sys-color-on-surface-variant)}.fb-child-row:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 4%,transparent)}.fb-add-link{display:inline-flex;align-items:center;gap:4px;font-size:12px;color:var(--md-sys-color-primary);cursor:pointer;padding:4px 0;text-decoration:none}.fb-add-link .msi{font-size:14px}.fb-add-link:hover{text-decoration:underline}.fb-group__body--static{display:flex;flex-wrap:wrap;gap:var(--gap-2, 8px);cursor:pointer;min-height:48px}.fb-group__body--static .fb-item--static{pointer-events:none;position:relative}.fb-group__body--static .fb-item--static .fb-resize,.fb-group__body--static .fb-item--static .fb-actions,.fb-group__body--static .fb-item--static .fb-status-chip{display:none!important}.fb-canvas__header--group .fb-groupedit__crumb{display:flex;align-items:center;gap:6px;font-weight:600}.fb-canvas__header--group .fb-groupedit__icon .msi{font-size:18px;color:var(--md-sys-color-primary)}.fb-canvas__header--group .fb-groupedit__hint{font-weight:400;font-size:12px;color:var(--md-sys-color-on-surface-variant, #6b6b6b);padding:1px 8px;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i3.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: i3.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i3.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: i3.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: i3.CdkDragPreview, selector: "ng-template[cdkDragPreview]", inputs: ["data", "matchSize"] }, { kind: "component", type:
6475
6385
  // Controls
6476
6386
  TextFieldControl, selector: "textfield-control", inputs: ["component"] }, { kind: "component", type: TextfieldAttribute, selector: "textfield-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: TextareaControl, selector: "textarea-control", inputs: ["component"] }, { kind: "component", type: TextareaAttribute, selector: "textarea-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: ChipStringControl, selector: "chip-string-control", inputs: ["component"] }, { kind: "component", type: ChipStringAttribute, selector: "chip-string-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: ChipCalendarControl, selector: "chip-calendar-control", inputs: ["component"] }, { kind: "component", type: ChipCalendarAttribute, selector: "chip-calendar-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: NumberControl, selector: "number-control", inputs: ["component"] }, { kind: "component", type: NumberAttribute, selector: "number-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: SelectControl, selector: "select-control", inputs: ["component"] }, { kind: "component", type: SelectAttribute, selector: "select-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: DatetimeControl, selector: "datetime-control", inputs: ["component"] }, { kind: "component", type: DatetimeAttribute, selector: "datetime-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: RadioControl, selector: "radio-control", inputs: ["component"] }, { kind: "component", type: RadioAttribute, selector: "radio-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: CheckboxControl, selector: "checkbox-control", inputs: ["component"] }, { kind: "component", type: CheckboxAttribute, selector: "checkbox-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: HtmlControl, selector: "html-control", inputs: ["component"] }, { kind: "component", type: HtmlAttribute, selector: "html-attribute", inputs: ["components", "variables", "component"], outputs: ["attributeChanges"] }, { kind: "component", type: UploadControl, selector: "upload-control", inputs: ["component"] }, { kind: "component", type: UploadAttribute, selector: "upload-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: TableControl, selector: "table-control", inputs: ["component"] }, { kind: "component", type: TableAttribute, selector: "table-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: GroupAttribute, selector: "group-attribute", inputs: ["group"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdTextarea, selector: "sd-textarea", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "rows", "hideInlineError", "required", "disabled", "viewed", "autoHeight", "maxlength", "pattern", "validator", "inlineError", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdFormRender, selector: "sd-form-render", inputs: ["form", "configuration", "defaultEntity", "entity", "properties", "viewed"] }, { kind: "component", type: ConfigureValidationComponent, selector: "configure-validation", outputs: ["accept"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
6477
6387
  }
6478
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdFormBuilder, decorators: [{
6388
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SdFormBuilder, decorators: [{
6479
6389
  type: Component,
6480
6390
  args: [{ selector: 'sd-form-builder', imports: [
6481
6391
  CommonModule,
@@ -6514,14 +6424,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
6514
6424
  SdButton,
6515
6425
  SdFormRender,
6516
6426
  ConfigureValidationComponent, TranslatePipe
6517
- ], template: "<!-- cdkDropListGroup: auto-connect t\u1EA5t c\u1EA3 cdkDropList trong palette, canvas rows, group bodies.\n [class.fb-shell--dragging]: JS-driven flag \u0111\u1EC3 \u1EA9n hover/actions/resize to\u00E0n di\u1EC7n\n trong l\u00FAc drag (CSS :has() kh\u00F4ng b\u1EAFt 100% tr\u01B0\u1EDDng h\u1EE3p v\u1EDBi CDK preview clone). -->\n<div class=\"fb-shell\" cdkDropListGroup [class.fb-shell--dragging]=\"isAnyDragging()\">\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 LEFT PALETTE \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <aside class=\"fb-palette\">\n <div class=\"fb-panel-header\">\n <div class=\"fb-panel-header__title\">{{ 'core.component.form-builder.components' | translate }}</div>\n </div>\n\n <!-- Search pill -->\n <div class=\"fb-palette__search\">\n <span class=\"msi\" aria-hidden=\"true\">search</span>\n <input\n type=\"text\"\n [placeholder]=\"'core.component.form-builder.search-components' | translate\"\n [value]=\"paletteSearch()\"\n (input)=\"paletteSearch.set($any($event.target).value)\" />\n <span class=\"kbd\">\u2318K</span>\n </div>\n\n <div class=\"fb-palette__scroll\">\n @for (group of paletteGroups(); track group.key) {\n <div class=\"fb-palette__group-label\">{{ group.label }}</div>\n <div\n class=\"fb-palette__list\"\n cdkDropList\n [cdkDropListData]=\"group.items\"\n [cdkDropListEnterPredicate]=\"noReturnPredicate\">\n @for (formBuilderComponent of group.items; track formBuilderComponent.type) {\n <div\n cdkDrag\n class=\"fb-palette-item\"\n [matTooltip]=\"formBuilderComponent.name\"\n matTooltipPosition=\"right\"\n (click)=\"addComponent(formBuilderComponent)\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"onAnyDragEnded()\"\n aria-hidden=\"true\">\n <span class=\"fb-palette-item__icon\"><span class=\"msi\">{{ formBuilderComponent.symbol }}</span></span>\n <span class=\"fb-palette-item__name\">{{ formBuilderComponent.name }}</span>\n <span class=\"fb-palette-item__drag\"><span class=\"msi\">drag_indicator</span></span>\n <!-- Generic drag preview: ch\u1EC9 icon (puck), label \u1EA9n -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n </div>\n }\n </div>\n }\n </div>\n </aside>\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 CENTER CANVAS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <section class=\"fb-canvas\">\n <header class=\"fb-canvas__header\">\n <div class=\"fb-canvas__title\">\n <span>{{ 'core.component.form-builder.layout' | translate }}</span>\n </div>\n <div class=\"fb-canvas__actions\">\n <!-- Toolbar cluster: view JSON / variables / validation -->\n <button\n type=\"button\"\n class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.view-json' | translate\"\n (click)=\"viewJSON()\">\n <span class=\"msi\">data_object</span>\n </button>\n <button\n type=\"button\"\n class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.config-variable' | translate\"\n (click)=\"configureVariables()\">\n <span class=\"msi\">data_array</span>\n </button>\n <button\n type=\"button\"\n class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.config-validation-warning-error' | translate\"\n (click)=\"openConfigureValidation()\">\n <span class=\"msi\">rule</span>\n </button>\n\n <span class=\"fb-divider\"></span>\n\n <!-- M3 segmented Design/Preview toggle -->\n <div class=\"fb-mode-toggle\" role=\"tablist\">\n <button\n type=\"button\"\n role=\"tab\"\n [class.is-active]=\"!isPreview()\"\n (click)=\"setMode(false)\">\n <span class=\"msi\">edit</span>\n <span>{{ 'core.component.form-builder.design' | translate }}</span>\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n [class.is-active]=\"isPreview()\"\n (click)=\"setMode(true)\">\n <span class=\"msi\">visibility</span>\n <span>{{ 'core.component.form-builder.preview' | translate }}</span>\n </button>\n </div>\n </div>\n </header>\n\n <div\n class=\"fb-canvas__body\"\n [class.is-preview]=\"isPreview()\"\n id=\"frmComponent\">\n @if (isPreview()) {\n <!-- \u2500\u2500 Preview mode \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"fb-preview-card\">\n <div class=\"fb-preview-card__chip\">\n <span class=\"msi\">visibility</span>\n {{ 'core.component.form-builder.preview-runtime' | translate }}\n </div>\n <sd-form-render [configuration]=\"{ components: this.components, validations: this.validations }\"></sd-form-render>\n <div class=\"fb-preview-card__footer\">\n <sd-button type=\"outline\" [title]=\"'core.component.form-builder.cancel' | translate\" (click)=\"setMode(false)\"></sd-button>\n <sd-button type=\"fill\" color=\"primary\" [title]=\"'core.component.form-builder.submit' | translate\" (click)=\"onValidate()\"></sd-button>\n </div>\n </div>\n } @else {\n <!-- \u2500\u2500 Design mode \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (!dragDropRows.length) {\n <div class=\"fb-empty\">\n <div class=\"fb-empty__art\"><span class=\"msi\">dashboard_customize</span></div>\n <div class=\"fb-empty__title\">{{ 'core.component.form-builder.empty-title' | translate }}</div>\n <div class=\"fb-empty__hint\">\n {{ 'core.component.form-builder.empty-hint' | translate }}\n <span class=\"fb-empty__kbd\"><span class=\"msi\">keyboard</span>\u2318 K</span>\n </div>\n </div>\n }\n\n <div\n cdkDropList\n cdkDropListOrientation=\"vertical\"\n [cdkDropListData]=\"dragDropRows\"\n (cdkDropListDropped)=\"drop($event)\"\n (click)=\"clickFormContentEmpty()\"\n aria-hidden=\"true\">\n @for (row of dragDropRows; track row.rowIndex) {\n <div\n cdkDrag\n class=\"fb-row\"\n (mouseover)=\"onMouseover($event, row)\"\n (focus)=\"onFocus($event)\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"onAnyDragEnded()\"\n [class.is-drag-target]=\"targetItem === row\"\n [id]=\"'row_' + row.rowIndex\"\n aria-hidden=\"true\">\n <div class=\"fb-row__drag\" [matTooltip]=\"'core.component.form-builder.drag-vertically' | translate\" cdkDragHandle>\n <span class=\"msi\">drag_indicator</span>\n </div>\n <!-- Generic puck preview -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <!-- Quick-add break button \u2014 show on row hover, insert break after this row -->\n <button\n type=\"button\"\n class=\"fb-row-break-btn\"\n [matTooltip]=\"'core.component.form-builder.break' | translate\"\n matTooltipPosition=\"right\"\n (click)=\"insertBreakAfter(row); $event.stopPropagation()\">\n <span class=\"msi\">horizontal_rule</span>\n </button>\n\n <div\n class=\"fb-row__items\"\n style=\"display: flex; flex: 1; gap: var(--gap-2);\"\n cdkDropList\n cdkDropListOrientation=\"horizontal\"\n [cdkDropListData]=\"row.items\"\n (cdkDropListDropped)=\"drop($event)\">\n\n @for (item of row.items; track item.id; let i = $index) {\n <!-- Group component renders as outlined card with colored header bar -->\n @if (item.type === 'group') {\n @let g = $any(item);\n @let cv = groupColorVars(g.properties?.color);\n <div\n cdkDrag\n [id]=\"item.id\"\n class=\"fb-group column-{{ item.layout?.columns || 12 }}\"\n [class.fb-item]=\"false\"\n [class.is-selected]=\"item.id === selectedComponent()?.id\"\n [class.is-hidden]=\"item.properties?.hidden\"\n [style.flex]=\"'0 0 calc(' + (+(item.layout?.columns || 12)) + '/12 * 100% - var(--gap-2))'\"\n [style.maxWidth]=\"'calc(' + (+(item.layout?.columns || 12)) + '/12 * 100% - var(--gap-2))'\"\n (click)=\"selectComponent(item); $event.stopPropagation()\"\n (cdkDragStarted)=\"dragStartComponentItem($event); onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"dragEndComponentItem($event); onAnyDragEnded()\"\n aria-hidden=\"true\">\n <!-- Generic puck preview -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <!-- cdkDragHandle: ch\u1EC9 cho ph\u00E9p k\u00E9o group qua header \u2014 body free cho click v\u00E0o child. -->\n <div class=\"fb-group__header\" cdkDragHandle [style.background]=\"cv.bg\" [style.color]=\"cv.fg\">\n <span class=\"fb-group__icon\"><span class=\"msi\">{{ g.properties?.icon || 'category' }}</span></span>\n <span class=\"fb-group__label\">{{ item.label }}</span>\n @if (hasConditional(item)) {\n <span class=\"fb-group__conditional-chip\">\n <span class=\"msi\" style=\"font-size: 12px;\">bolt</span>\n {{ 'core.component.form-builder.conditional' | translate }}\n </span>\n }\n <span class=\"fb-group__count\">{{ g.components?.length || 0 }} fields</span>\n </div>\n <!-- Floating action toolbar -->\n <div class=\"fb-actions\">\n <button type=\"button\" class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.duplicate' | translate\"\n (click)=\"onDuplicate(item); $event.stopPropagation()\">\n <span class=\"msi\">content_copy</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"item.properties?.hidden\"\n [class.on]=\"item.properties?.hidden\"\n [matTooltip]=\"item.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\n (click)=\"onChangeHidden(item); $event.stopPropagation()\">\n <span class=\"msi\">{{ item.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn danger\"\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"removeComponent(item.id); $event.stopPropagation()\">\n <span class=\"msi\">delete</span>\n </button>\n </div>\n\n <div\n class=\"fb-group__body\"\n cdkDropList\n cdkDropListOrientation=\"horizontal\"\n [cdkDropListData]=\"g.components\"\n (cdkDropListDropped)=\"dropInGroup($event, g)\">\n @if (!g.components?.length) {\n <div class=\"fb-group__empty\">\n <span class=\"msi\" style=\"font-size: 16px; margin-right: 6px;\">south</span>\n {{ 'core.component.form-builder.group-drop-here' | translate }}\n </div>\n }\n @for (child of g.components; track child.id; let ci = $index) {\n <div\n cdkDrag\n [id]=\"child.id\"\n class=\"fb-item is-child column-{{ child.layout?.columns || 12 }}\"\n [class.is-selected]=\"child.id === selectedComponent()?.id\"\n [class.is-hidden]=\"child.properties?.hidden\"\n [class.is-readonly]=\"child.properties?.viewed\"\n (click)=\"selectComponent(child); $event.stopPropagation()\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"onAnyDragEnded()\">\n <!-- Generic puck preview -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <ng-container\n *ngTemplateOutlet=\"controlTemplate; context: { $implicit: child }\">\n </ng-container>\n <!-- Resize handle cho group child \u2014 chia 12-col ngay trong group body.\n Wrapping cdkDropList c\u00F3 enterPredicate=false \u0111\u1EC3 KH\u00D4NG nh\u1EADn drop\n (ch\u1EC9 d\u00F9ng l\u00E0m context cho cdkDrag), tr\u00E1nh xung \u0111\u1ED9t v\u1EDBi group__body drop list. -->\n <div cdkDropList cdkDropListOrientation=\"horizontal\" [cdkDropListEnterPredicate]=\"noReturnPredicate\">\n <div\n cdkDrag\n cdkDragLockAxis=\"x\"\n class=\"fb-resize\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"changeSizeChildInGroup($event, child, g)\"\n (cdkDragEnded)=\"dragEndChangeSizeControl($event); onAnyDragEnded()\"\n [matTooltip]=\"'core.component.form-builder.flex' | translate\"\n aria-label=\"resize\"></div>\n </div>\n <!-- Inline status chips for nested children -->\n @if (child.properties?.hidden) {\n <span class=\"fb-status-chip hidden\">\n <span class=\"msi\">visibility_off</span>\n {{ 'core.component.form-builder.hidden' | translate }}\n </span>\n } @else if (child.properties?.viewed) {\n <span class=\"fb-status-chip readonly\">\n <span class=\"msi\">edit_off</span>\n {{ 'core.component.form-builder.read-only' | translate }}\n </span>\n } @else if (hasConditional(child)) {\n <span class=\"fb-status-chip conditional\">\n <span class=\"msi\">bolt</span>\n {{ 'core.component.form-builder.conditional' | translate }}\n </span>\n }\n <div class=\"fb-actions\">\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"child.properties?.viewed\"\n [class.on]=\"child.properties?.viewed\"\n [matTooltip]=\"child.properties?.viewed ? ('core.component.form-builder.unset-readonly' | translate) : ('core.component.form-builder.set-readonly' | translate)\"\n (click)=\"onChangeViewed(child); $event.stopPropagation()\">\n <span class=\"msi\">edit_off</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.duplicate' | translate\"\n (click)=\"onDuplicate(child); $event.stopPropagation()\">\n <span class=\"msi\">content_copy</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"child.properties?.hidden\"\n [class.on]=\"child.properties?.hidden\"\n [matTooltip]=\"child.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\n (click)=\"onChangeHidden(child); $event.stopPropagation()\">\n <span class=\"msi\">{{ child.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn danger\"\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"removeFromGroup(g, child.id); $event.stopPropagation()\">\n <span class=\"msi\">delete</span>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n } @else if (item.type === 'break') {\n <!-- Break: row separator c\u1ED1 \u0111\u1ECBnh. Render 12-col line, kh\u00F4ng c\u00F3 resize/edit attribute. -->\n <div\n cdkDrag\n [id]=\"item.id\"\n class=\"fb-item is-break column-12\"\n [class.is-selected]=\"item.id === selectedComponent()?.id\"\n [class.is-hidden]=\"item.properties?.hidden\"\n (click)=\"selectComponent(item); $event.stopPropagation()\"\n (cdkDragStarted)=\"dragStartComponentItem($event); onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"dragEndComponentItem($event); onAnyDragEnded()\"\n aria-hidden=\"true\">\n <!-- Generic puck preview -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <div class=\"fb-break-line\">\n <span class=\"msi\">horizontal_rule</span>\n <span class=\"fb-break-label\">{{ 'core.component.form-builder.break' | translate }}</span>\n </div>\n <div class=\"fb-actions\">\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"item.properties?.hidden\"\n [class.on]=\"item.properties?.hidden\"\n [matTooltip]=\"item.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\n (click)=\"onChangeHidden(item); $event.stopPropagation()\">\n <span class=\"msi\">{{ item.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn danger\"\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"removeComponent(item.id); $event.stopPropagation()\">\n <span class=\"msi\">delete</span>\n </button>\n </div>\n </div>\n } @else {\n <!-- Regular form component -->\n <div\n cdkDrag\n [id]=\"item.id\"\n class=\"fb-item column-{{ item.layout?.columns || 12 }}\"\n [class.is-selected]=\"item.id === selectedComponent()?.id\"\n [class.is-hidden]=\"item.properties?.hidden\"\n [class.is-readonly]=\"item.properties?.viewed\"\n (click)=\"selectComponent(item); $event.stopPropagation()\"\n (cdkDragStarted)=\"dragStartComponentItem($event); onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"dragEndComponentItem($event); onAnyDragEnded()\"\n aria-hidden=\"true\">\n <!-- Generic puck preview -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n\n <!-- Status chip (mutually exclusive priority: hidden > readonly > conditional) -->\n @if (item.properties?.hidden) {\n <span class=\"fb-status-chip hidden\">\n <span class=\"msi\">visibility_off</span>\n {{ 'core.component.form-builder.hidden' | translate }}\n </span>\n } @else if (item.properties?.viewed) {\n <span class=\"fb-status-chip readonly\">\n <span class=\"msi\">edit_off</span>\n {{ 'core.component.form-builder.read-only' | translate }}\n </span>\n } @else if (hasConditional(item)) {\n <span class=\"fb-status-chip conditional\">\n <span class=\"msi\">bolt</span>\n {{ 'core.component.form-builder.conditional' | translate }}\n </span>\n }\n\n <!-- Floating action toolbar pill -->\n <div class=\"fb-actions\">\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"item.properties?.viewed\"\n [class.on]=\"item.properties?.viewed\"\n [matTooltip]=\"item.properties?.viewed ? ('core.component.form-builder.unset-readonly' | translate) : ('core.component.form-builder.set-readonly' | translate)\"\n (click)=\"onChangeViewed(item); $event.stopPropagation()\">\n <span class=\"msi\">edit_off</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.duplicate' | translate\"\n (click)=\"onDuplicate(item); $event.stopPropagation()\">\n <span class=\"msi\">content_copy</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"item.properties?.hidden\"\n [class.on]=\"item.properties?.hidden\"\n [matTooltip]=\"item.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\n (click)=\"onChangeHidden(item); $event.stopPropagation()\">\n <span class=\"msi\">{{ item.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn danger\"\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"removeComponent(item.id); $event.stopPropagation()\">\n <span class=\"msi\">delete</span>\n </button>\n </div>\n\n <ng-container\n *ngTemplateOutlet=\"controlTemplate; context: { $implicit: item }\">\n </ng-container>\n\n <!-- Resize handle (pill) \u2014 cdkDragLockAxis=\"x\" \u0111\u1EC3 ch\u1EC9 k\u00E9o ngang.\n Wrapping cdkDropList c\u00F3 enterPredicate=false, kh\u00F4ng nh\u1EADn drop. -->\n <div cdkDropList cdkDropListOrientation=\"horizontal\" [cdkDropListEnterPredicate]=\"noReturnPredicate\">\n <div\n cdkDrag\n cdkDragLockAxis=\"x\"\n class=\"fb-resize\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"changeSizeControl($event, item, row.items, i)\"\n (cdkDragEnded)=\"dragEndChangeSizeControl($event); onAnyDragEnded()\"\n [matTooltip]=\"'core.component.form-builder.flex' | translate\"\n aria-label=\"resize\"></div>\n </div>\n </div>\n }\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n </section>\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 RIGHT ATTRIBUTES \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <aside class=\"fb-attrs\">\n <div class=\"fb-panel-header\">\n <div class=\"fb-panel-header__title\">{{ 'core.component.form-builder.attribute' | translate }}</div>\n </div>\n\n @let sel = selectedComponent();\n @if (sel) {\n <!-- Selection header: type icon + name + key/type -->\n <div class=\"fb-attrs__selection\">\n <span class=\"fb-attrs__sel-icon\"><span class=\"msi\">{{ symbolFor(sel) }}</span></span>\n <div class=\"fb-attrs__sel-meta\">\n <div class=\"fb-attrs__sel-name\">{{ $any(sel).label || ('core.component.form-builder.untitled' | translate) }}</div>\n <div class=\"fb-attrs__sel-key\">\n @if ($any(sel).key) {\n {{ $any(sel).key }} \u00B7 {{ typeLabelFor(sel) }}\n } @else {\n {{ typeLabelFor(sel) }}\n }\n </div>\n </div>\n </div>\n\n <div class=\"fb-attrs__body\" aria-hidden=\"true\">\n @if (sel.type === 'textfield') {\n <textfield-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></textfield-attribute>\n } @else if (sel.type === 'textarea') {\n <textarea-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></textarea-attribute>\n } @else if (sel.type === 'chip-string') {\n <chip-string-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></chip-string-attribute>\n } @else if (sel.type === 'chip-calendar') {\n <chip-calendar-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></chip-calendar-attribute>\n } @else if (sel.type === 'number') {\n <number-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></number-attribute>\n } @else if (sel.type === 'datetime') {\n <datetime-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></datetime-attribute>\n } @else if (sel.type === 'select') {\n <select-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></select-attribute>\n } @else if (sel.type === 'radio') {\n <radio-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></radio-attribute>\n } @else if (sel.type === 'checkbox') {\n <checkbox-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></checkbox-attribute>\n } @else if (sel.type === 'html') {\n <html-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></html-attribute>\n } @else if (sel.type === 'upload') {\n <upload-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></upload-attribute>\n } @else if (sel.type === 'table') {\n <table-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></table-attribute>\n } @else if (sel.type === 'group') {\n <group-attribute [group]=\"$any(sel)\"></group-attribute>\n }\n </div>\n } @else {\n <div class=\"fb-attrs__placeholder\">\n <span class=\"msi\">ads_click</span>\n <div class=\"title\">{{ 'core.component.form-builder.no-selection-title' | translate }}</div>\n <div class=\"hint\">{{ 'core.component.form-builder.no-selection-hint' | translate }}</div>\n </div>\n }\n </aside>\n</div>\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Reusable control template \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n<ng-template #controlTemplate let-item>\n @if (item.type === 'textfield') {\n <textfield-control [component]=\"item\"></textfield-control>\n } @else if (item.type === 'textarea') {\n <textarea-control [component]=\"item\"></textarea-control>\n } @else if (item.type === 'chip-string') {\n <chip-string-control [component]=\"item\"></chip-string-control>\n } @else if (item.type === 'chip-calendar') {\n <chip-calendar-control [component]=\"item\"></chip-calendar-control>\n } @else if (item.type === 'number') {\n <number-control [component]=\"item\"></number-control>\n } @else if (item.type === 'datetime') {\n <datetime-control [component]=\"item\"></datetime-control>\n } @else if (item.type === 'select') {\n <select-control [component]=\"item\"></select-control>\n } @else if (item.type === 'radio') {\n <radio-control [component]=\"item\"></radio-control>\n } @else if (item.type === 'checkbox') {\n <checkbox-control [component]=\"item\"></checkbox-control>\n } @else if (item.type === 'html') {\n <html-control [component]=\"item\"></html-control>\n } @else if (item.type === 'upload') {\n <upload-control [component]=\"item\"></upload-control>\n } @else if (item.type === 'table') {\n <table-control [component]=\"item\"></table-control>\n }\n</ng-template>\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 JSON / variables modals \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n<sd-modal title=\"JSON\" view=\"dialog\" width=\"80%\" #popupViewJSON>\n <sd-textarea [(model)]=\"jsonString\"></sd-textarea>\n <ng-container sdFooter>\n <sd-button type=\"fill\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"updateJSON()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\n </ng-container>\n</sd-modal>\n<sd-modal [title]=\"'core.component.form-builder.config-variable' | translate\" view=\"dialog\" width=\"800px\" #popupConfigureVariables>\n @for (variable of clonedVariables; track variable.id) {\n <div class=\"d-flex align-items-center\" style=\"gap: 8px\">\n <sd-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"variable.key\" required></sd-input>\n <sd-input [form]=\"form\" [label]=\"'core.component.form-builder.display-label' | translate\" [(model)]=\"variable.label\" required></sd-input>\n <sd-button prefixIcon=\"delete\" (click)=\"removeVariables(variable.id)\" color=\"error\"></sd-button>\n </div>\n }\n <a href=\"javascript:;\" (click)=\"addVariables()\">{{ 'core.component.form-builder.add-variable' | translate }}</a>\n <ng-container sdFooter>\n <sd-button type=\"fill\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"updateVariables()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\n </ng-container>\n</sd-modal>\n<configure-validation (accept)=\"onUpdateValidations($event)\"></configure-validation>\n", styles: [":host{--md-sys-color-primary: var(--sd-primary, #2A66F4);--md-sys-color-on-primary: #ffffff;--md-sys-color-primary-container: var(--sd-primary-light, #EAF1FF);--md-sys-color-on-primary-container: var(--sd-primary, #2A66F4);--md-sys-color-info: var(--sd-info, #2962FF);--md-sys-color-info-container: var(--sd-info-light, #E7E9FF);--md-sys-color-secondary: #625b71;--md-sys-color-secondary-container: #e8def8;--md-sys-color-on-secondary-container: #1d192b;--md-sys-color-surface: #fbfafc;--md-sys-color-surface-container-lowest: #ffffff;--md-sys-color-surface-container-low: #f6f4f8;--md-sys-color-surface-container: #f1eef3;--md-sys-color-surface-container-high: #ebe8ee;--md-sys-color-surface-container-highest: #e6e2ea;--md-sys-color-on-surface: #1c1b1f;--md-sys-color-on-surface-variant: #49454e;--md-sys-color-outline: #79747e;--md-sys-color-outline-variant: #d6d2da;--md-sys-color-error: #b3261e;--md-sys-color-error-container: #f9dedc;--md-sys-color-warning: #8a5400;--md-sys-color-warning-container: #ffddb1;--md-sys-color-success: #1f6f43;--md-sys-color-success-container: #b7f0cb;--h-row: 28px;--h-field: 32px;--h-palette: 36px;--h-header: 36px;--h-section: 28px;--h-action-btn: 24px;--gap-1: 4px;--gap-2: 8px;--gap-3: 12px;--gap-4: 16px;--gap-5: 24px;--r-xs: 4px;--r-sm: 8px;--r-md: 12px;--r-lg: 16px;--r-xl: 28px;--r-pill: 999px;--elev-1: 0 1px 2px 0 rgba(0, 0, 0, .06);--elev-2: 0 2px 6px 0 rgba(0, 0, 0, .08), 0 1px 2px 0 rgba(0, 0, 0, .04);--elev-3: 0 6px 14px 0 rgba(0, 0, 0, .1), 0 2px 4px 0 rgba(0, 0, 0, .06);display:block;width:100%;height:100%;font-family:Roboto,system-ui,sans-serif;font-size:13px;color:var(--md-sys-color-on-surface);background:var(--md-sys-color-surface)}:host ::ng-deep .msi{font-family:Material Symbols Rounded;font-weight:400;font-style:normal;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;font-feature-settings:\"liga\";-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"wght\" 300,\"opsz\" 24,\"GRAD\" 0,\"FILL\" 0}:host ::ng-deep .msi.filled{font-variation-settings:\"wght\" 300,\"opsz\" 24,\"GRAD\" 0,\"FILL\" 1}:host ::ng-deep .mono{font-family:Roboto Mono,ui-monospace,monospace}:host ::ng-deep .fb-icon-btn{width:28px;height:28px;border-radius:var(--r-sm);border:none;background:transparent;color:var(--md-sys-color-on-surface-variant);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background .12s ease,color .12s ease}:host ::ng-deep .fb-icon-btn:hover{background:color-mix(in srgb,var(--md-sys-color-on-surface) 8%,transparent);color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-icon-btn.is-active{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container)}:host ::ng-deep .fb-icon-btn.danger:hover{color:var(--md-sys-color-error);background:var(--md-sys-color-error-container)}:host ::ng-deep .fb-icon-btn.warning.on{color:var(--md-sys-color-warning);background:var(--md-sys-color-warning-container)}:host ::ng-deep .fb-icon-btn .msi{font-size:18px}:host ::ng-deep .fb-field{display:flex;flex-direction:column;gap:4px}:host ::ng-deep .fb-field__label{font-size:11px;font-weight:500;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-field__input{height:var(--h-row);padding:0 10px;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px;display:flex;align-items:center;justify-content:space-between;color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-field__input.placeholder{color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-field__input:focus-within,:host ::ng-deep .fb-field__input.focused{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent)}:host ::ng-deep .fb-field__input .msi{font-size:16px;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-field-row{display:flex;align-items:center;gap:var(--gap-2);justify-content:space-between}:host ::ng-deep .fb-switch{display:inline-flex;width:34px;height:18px;border-radius:999px;background:var(--md-sys-color-surface-container-highest);border:1.5px solid var(--md-sys-color-outline);padding:1px;align-items:center;cursor:pointer;position:relative;flex-shrink:0}:host ::ng-deep .fb-switch .fb-switch__thumb{width:12px;height:12px;border-radius:50%;background:var(--md-sys-color-outline)}:host ::ng-deep .fb-switch.on{background:var(--md-sys-color-primary);border-color:var(--md-sys-color-primary);justify-content:flex-end}:host ::ng-deep .fb-switch.on .fb-switch__thumb{background:var(--md-sys-color-on-primary);width:14px;height:14px}:host ::ng-deep .fb-expr{display:flex;align-items:center;gap:6px;height:var(--h-row);padding:0 6px 0 0;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-expr__badge{height:100%;display:inline-flex;align-items:center;justify-content:center;padding:0 6px;background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);font-family:Roboto Mono,monospace;font-size:10px;font-weight:500;border-radius:var(--r-xs) 0 0 var(--r-xs)}:host ::ng-deep .fb-expr__code{font-family:Roboto Mono,monospace;flex:1;font-size:11px;color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-expr__code .var{color:var(--md-sys-color-primary);font-weight:500}:host ::ng-deep .fb-expr__code .op{color:var(--md-sys-color-error)}:host ::ng-deep .fb-expr__code .lit{color:var(--md-sys-color-success)}:host ::ng-deep .fb-expr .empty{color:var(--md-sys-color-on-surface-variant);font-style:italic;padding-left:6px;flex:1}:host ::ng-deep details.fb-section{border-bottom:1px solid var(--md-sys-color-outline-variant);margin:0;padding:0;background:transparent}:host ::ng-deep details.fb-section>summary{list-style:none}:host ::ng-deep details.fb-section>summary::-webkit-details-marker{display:none}:host ::ng-deep .fb-section__head{height:var(--h-section);padding:0 var(--gap-4);display:flex;align-items:center;gap:var(--gap-2);cursor:pointer;font-size:12px;font-weight:500;color:var(--md-sys-color-on-surface);-webkit-user-select:none;user-select:none}:host ::ng-deep .fb-section__head .msi{font-size:16px;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-section__head .fb-section__title{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep .fb-section__head .chev{margin-left:auto;transition:transform .16s ease}:host ::ng-deep details.fb-section[open] .fb-section__head .chev{transform:rotate(90deg)}:host ::ng-deep .fb-section__body{padding:4px var(--gap-4) var(--gap-3);display:flex;flex-direction:column;gap:var(--gap-2)}:host ::ng-deep .fb-columns-list{display:flex;flex-direction:column;gap:var(--gap-1);padding-top:var(--gap-1)}:host ::ng-deep .fb-column-row{display:flex;align-items:center;gap:var(--gap-2);height:40px;padding:6px 10px;border-radius:var(--r-sm);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px;cursor:pointer;transition:background .12s ease,border-color .12s ease,box-shadow .12s ease}:host ::ng-deep .fb-column-row:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 4%,transparent);border-color:color-mix(in srgb,var(--md-sys-color-primary) 30%,transparent)}:host ::ng-deep .fb-column-row.is-active{border-color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 30%,transparent)}:host ::ng-deep .fb-column-row .fb-column-row__type-icon{width:28px;height:28px;border-radius:var(--r-sm);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}:host ::ng-deep .fb-column-row .fb-column-row__type-icon .msi{font-size:16px}:host ::ng-deep .fb-column-row .fb-column-row__meta{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}:host ::ng-deep .fb-column-row .fb-column-row__meta .fb-column-row__label{font-size:13px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-column-row .fb-column-row__meta .fb-column-row__req{color:var(--md-sys-color-error);margin-left:2px;font-weight:600}:host ::ng-deep .fb-column-row .fb-column-row__meta .fb-column-row__sub{font-size:11px;color:var(--md-sys-color-on-surface-variant);font-family:Roboto Mono,ui-monospace,monospace;letter-spacing:.02em}:host ::ng-deep .cdk-drag-preview.fb-drag-preview,:host ::ng-deep .fb-drag-preview{width:36px;height:36px;min-width:36px;min-height:36px;max-width:36px;max-height:36px;box-sizing:border-box;border-radius:50%;background:var(--md-sys-color-primary, #6750a4);display:inline-flex;align-items:center;justify-content:center;box-shadow:0 10px 24px #00000042,0 3px 8px #00000024;border:3px solid var(--md-sys-color-on-primary, #ffffff);cursor:grabbing;pointer-events:none;-webkit-user-select:none;user-select:none;opacity:.96;overflow:hidden;z-index:10000}:host ::ng-deep .cdk-drag-preview.fb-drag-preview:after,:host ::ng-deep .fb-drag-preview:after{content:\"\";width:8px;height:8px;border-radius:50%;background:var(--md-sys-color-on-primary, #ffffff);opacity:.9}@keyframes fb-drop-pulse{0%,to{box-shadow:0 0 0 3px color-mix(in srgb,var(--md-sys-color-info) 16%,transparent)}50%{box-shadow:0 0 0 5px color-mix(in srgb,var(--md-sys-color-info) 24%,transparent)}}:host ::ng-deep .cdk-drag-placeholder{background:transparent!important;border:none!important;border-radius:999px!important;padding:0!important;transform:none!important;transition:none!important;pointer-events:none;overflow:hidden;animation:none!important;opacity:0!important}:host ::ng-deep .cdk-drag-placeholder>*{visibility:hidden!important;pointer-events:none!important}:host ::ng-deep .fb-palette__list>.cdk-drag-placeholder{display:none!important}:host ::ng-deep .fb-row__items>.cdk-drag-placeholder,:host ::ng-deep .fb-group__body>.cdk-drag-placeholder{width:0!important;min-width:0!important;max-width:0!important;height:auto!important;min-height:0!important;align-self:stretch;flex:0 0 0!important;margin:0!important}:host ::ng-deep [cdkDropListOrientation=vertical]>.cdk-drag-placeholder{width:auto!important;height:0!important;min-height:0!important;max-height:0!important;flex:0 0 0!important;margin:0!important;align-self:stretch}:host ::ng-deep .cdk-drop-list-receiving{background:color-mix(in srgb,var(--md-sys-color-primary) 3%,transparent);transition:background .16s ease}:host ::ng-deep .fb-group__body.cdk-drop-list-receiving,:host ::ng-deep .fb-group__body.cdk-drop-list-dragging{background:color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent)!important;outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 78%,transparent);outline-offset:-6px;border-radius:var(--r-sm)}:host ::ng-deep .fb-resize.cdk-drag-preview{display:none!important}:host ::ng-deep .fb-shell--dragging .fb-item:hover,:host ::ng-deep .fb-shell--dragging .fb-group:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-item:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group:hover{border-color:transparent!important;background:transparent!important}:host ::ng-deep .fb-shell--dragging .fb-row:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row:hover{outline-color:transparent!important;background:transparent!important}:host ::ng-deep .fb-shell--dragging .fb-row:hover .fb-row__drag,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row:hover .fb-row__drag{opacity:0!important}:host ::ng-deep .fb-shell--dragging .fb-row.is-drag-target,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row.is-drag-target{outline-color:color-mix(in srgb,var(--md-sys-color-info) 44%,transparent)!important;background:color-mix(in srgb,var(--md-sys-color-info) 4%,transparent)!important}:host ::ng-deep .fb-shell--dragging .fb-row__drag,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row__drag{opacity:0!important}:host ::ng-deep .fb-shell--dragging .fb-actions,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-actions{opacity:0!important;pointer-events:none!important;transform:translateY(-2px)!important}:host ::ng-deep .fb-shell--dragging .fb-resize,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-resize{opacity:0!important;pointer-events:none!important}:host ::ng-deep .fb-shell--dragging .fb-row-break-btn,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row-break-btn{opacity:0!important;pointer-events:none!important}:host ::ng-deep .fb-shell--dragging .fb-palette-item:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-palette-item:hover{background:transparent!important}:host ::ng-deep .fb-shell--dragging .fb-palette-item:hover .fb-palette-item__drag,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-palette-item:hover .fb-palette-item__drag{opacity:0!important}:host ::ng-deep .fb-shell--dragging .fb-group__body,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__body{min-height:80px!important;background:color-mix(in srgb,var(--md-sys-color-primary) 5%,transparent)!important;outline:2px dashed color-mix(in srgb,var(--md-sys-color-primary) 50%,transparent)!important;outline-offset:-6px;border-radius:var(--r-sm);transition:background .16s ease,outline .16s ease,min-height .16s ease}:host ::ng-deep .fb-shell--dragging .fb-group__empty,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__empty{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 55%,transparent);background:color-mix(in srgb,var(--md-sys-color-primary) 7%,transparent);color:var(--md-sys-color-primary)}:host ::ng-deep .fb-shell--dragging .fb-group__body.cdk-drop-list-receiving,:host ::ng-deep .fb-shell--dragging .fb-group__body.cdk-drop-list-dragging,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__body.cdk-drop-list-receiving,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__body.cdk-drop-list-dragging{background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)!important;outline:2px solid var(--md-sys-color-primary)!important}:host ::ng-deep .cdk-drag-animating{transition:transform .22s cubic-bezier(.2,0,0,1)!important}:host ::ng-deep .cdk-drag-dragging{transition:none!important}:host ::ng-deep .fb-item:not(.cdk-drag-dragging){transition:flex .12s cubic-bezier(.2,0,0,1),max-width .12s cubic-bezier(.2,0,0,1),border-color .12s,background .12s}.fb-shell{width:100%;height:100%;display:flex;background:var(--md-sys-color-surface);overflow:hidden;min-height:0}.fb-panel-header{height:var(--h-header);display:flex;align-items:center;justify-content:space-between;padding:0 var(--gap-3);border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);flex-shrink:0}.fb-panel-header__title{font-size:11px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant)}.fb-panel-header__actions{display:flex;align-items:center;gap:2px}.fb-palette{width:220px;flex-shrink:0;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-right:1px solid var(--md-sys-color-outline-variant)}.fb-palette__scroll{flex:1;overflow-y:auto;padding-bottom:var(--gap-3)}.fb-palette__search{margin:var(--gap-3);height:32px;display:flex;align-items:center;gap:var(--gap-2);padding:0 var(--gap-3);border-radius:var(--r-pill);background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant);font-size:13px;flex-shrink:0}.fb-palette__search .msi{font-size:18px}.fb-palette__search input{flex:1;border:none;outline:none;background:transparent;color:var(--md-sys-color-on-surface);font-size:13px;font-family:inherit}.fb-palette__search input::placeholder{color:var(--md-sys-color-on-surface-variant)}.fb-palette__search .kbd{font-family:Roboto Mono,monospace;font-size:10px;padding:1px 6px;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant)}.fb-palette__group-label{font-size:11px;font-weight:500;letter-spacing:.04em;color:var(--md-sys-color-on-surface-variant);padding:var(--gap-3) var(--gap-4) var(--gap-1);text-transform:uppercase}.fb-palette__list{display:flex;flex-direction:column;padding:0 var(--gap-2)}.fb-palette-item{height:var(--h-palette);display:flex;align-items:center;gap:var(--gap-3);padding:0 var(--gap-3);border-radius:var(--r-sm);cursor:grab;color:var(--md-sys-color-on-surface);position:relative;-webkit-user-select:none;user-select:none}.fb-palette-item:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent)}.fb-palette-item .fb-palette-item__icon{width:24px;height:24px;border-radius:var(--r-xs);display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);flex-shrink:0}.fb-palette-item .fb-palette-item__icon .msi{font-size:16px}.fb-palette-item .fb-palette-item__name{font-size:13px;font-weight:400}.fb-palette-item .fb-palette-item__drag{margin-left:auto;color:var(--md-sys-color-outline);opacity:0;transition:opacity .12s ease}.fb-palette-item .fb-palette-item__drag .msi{font-size:16px}.fb-palette-item:hover .fb-palette-item__drag{opacity:1}.fb-canvas{flex:1 1 0;min-width:0;display:flex;flex-direction:column;background:var(--md-sys-color-surface);overflow:hidden}.fb-canvas__header{height:var(--h-header);display:flex;align-items:center;justify-content:space-between;padding:0 var(--gap-4);border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);gap:var(--gap-3);flex-shrink:0}.fb-canvas__title{display:flex;align-items:center;gap:var(--gap-2);font-size:11px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant)}.fb-canvas__title .breadcrumb-sep{color:var(--md-sys-color-outline)}.fb-canvas__actions{display:flex;align-items:center;gap:var(--gap-2)}.fb-divider{width:1px;height:18px;background:var(--md-sys-color-outline-variant)}.fb-canvas__body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;padding:var(--gap-4);position:relative;background:var(--md-sys-color-surface);min-width:0}.fb-canvas__body.is-preview{background:var(--md-sys-color-surface-container-low);padding:32px}.fb-mode-toggle{display:inline-flex;height:28px;border:1px solid var(--md-sys-color-outline);border-radius:var(--r-pill);overflow:hidden;flex-shrink:0}.fb-mode-toggle button{border:0;background:transparent;padding:0 var(--gap-3);font-size:12px;font-weight:500;display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-surface-variant);cursor:pointer}.fb-mode-toggle button .msi{font-size:16px}.fb-mode-toggle button.is-active{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.fb-row{position:relative;display:flex;gap:var(--gap-2);padding:6px var(--gap-2);border-radius:var(--r-sm);margin-bottom:6px;min-width:0;transition:outline .12s ease,background .12s ease;outline:1px dashed transparent;outline-offset:-1px}.fb-row:hover{outline-color:var(--md-sys-color-outline-variant);background:color-mix(in srgb,var(--md-sys-color-primary) 3%,transparent)}.fb-row:hover .fb-row__drag{opacity:1}.fb-row.is-drag-target{outline-color:color-mix(in srgb,var(--md-sys-color-info) 44%,transparent);background:color-mix(in srgb,var(--md-sys-color-info) 4%,transparent)}.fb-row.is-drag-target:after{content:\"\";position:absolute;left:10px;right:10px;bottom:-3px;height:4px;border-radius:999px;background:var(--md-sys-color-info);box-shadow:0 0 0 4px color-mix(in srgb,var(--md-sys-color-info) 18%,transparent);pointer-events:none;animation:fb-drop-pulse .9s ease-in-out infinite;z-index:3}.fb-row__drag{position:absolute;left:-22px;top:50%;transform:translateY(-50%);width:18px;height:22px;border-radius:var(--r-xs);display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-high);opacity:0;cursor:grab;z-index:2}.fb-row__drag .msi{font-size:14px}.fb-row-break-btn{position:absolute;right:-28px;top:50%;transform:translateY(-50%);width:22px;height:22px;border-radius:var(--r-pill);display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-high);border:1px solid var(--md-sys-color-outline-variant);cursor:pointer;opacity:0;z-index:2;transition:opacity .12s ease,background .12s ease,color .12s ease}.fb-row-break-btn .msi{font-size:14px}.fb-row-break-btn:hover{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);border-color:transparent}.fb-row:hover .fb-row-break-btn{opacity:1}.fb-item{position:relative;border:1.5px dashed transparent;border-radius:var(--r-md);padding:var(--gap-2) var(--gap-3);min-height:56px;min-width:0;transition:border-color .12s ease,background .12s ease;background:transparent;cursor:grab;display:flex;flex-direction:column;gap:6px}.fb-item:hover{border-color:color-mix(in srgb,var(--md-sys-color-primary) 60%,transparent)}.fb-item.is-selected{border:1.5px solid var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 4%,transparent)}.fb-item.is-hidden{opacity:.45}.fb-item.is-readonly:after{content:\"\";position:absolute;inset:0;border-radius:var(--r-md);background:repeating-linear-gradient(135deg,transparent 0 6px,color-mix(in srgb,var(--md-sys-color-on-surface) 4%,transparent) 6px 7px);pointer-events:none}.fb-item.column-2{flex:0 0 calc(16.6666666667% - var(--gap-2));max-width:calc(16.6666666667% - var(--gap-2))}.fb-item.column-3{flex:0 0 calc(25% - var(--gap-2));max-width:calc(25% - var(--gap-2))}.fb-item.column-4{flex:0 0 calc(33.3333333333% - var(--gap-2));max-width:calc(33.3333333333% - var(--gap-2))}.fb-item.column-5{flex:0 0 calc(41.6666666667% - var(--gap-2));max-width:calc(41.6666666667% - var(--gap-2))}.fb-item.column-6{flex:0 0 calc(50% - var(--gap-2));max-width:calc(50% - var(--gap-2))}.fb-item.column-7{flex:0 0 calc(58.3333333333% - var(--gap-2));max-width:calc(58.3333333333% - var(--gap-2))}.fb-item.column-8{flex:0 0 calc(66.6666666667% - var(--gap-2));max-width:calc(66.6666666667% - var(--gap-2))}.fb-item.column-9{flex:0 0 calc(75% - var(--gap-2));max-width:calc(75% - var(--gap-2))}.fb-item.column-10{flex:0 0 calc(83.3333333333% - var(--gap-2));max-width:calc(83.3333333333% - var(--gap-2))}.fb-item.column-11{flex:0 0 calc(91.6666666667% - var(--gap-2));max-width:calc(91.6666666667% - var(--gap-2))}.fb-item.column-12{flex:1 1 100%;max-width:100%}.fb-actions{position:absolute;top:-14px;right:8px;display:flex;align-items:center;gap:2px;padding:2px;border-radius:var(--r-pill);background:var(--md-sys-color-surface-container-lowest);box-shadow:var(--elev-2);border:1px solid var(--md-sys-color-outline-variant);z-index:4;opacity:0;transform:translateY(-2px);pointer-events:none;transition:opacity .12s ease,transform .12s ease}.fb-actions .fb-icon-btn{width:24px;height:24px}.fb-actions .fb-icon-btn .msi{font-size:16px}.fb-item:hover .fb-actions,.fb-item.is-selected .fb-actions{opacity:1;transform:translateY(0);pointer-events:auto}table-control{display:block;width:100%;max-width:100%;min-width:0}.fb-group>.fb-actions{top:6px;right:8px}.fb-group:hover>.fb-actions,.fb-group.is-selected>.fb-actions{opacity:1;transform:translateY(0);pointer-events:auto}.fb-status-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;height:18px;border-radius:var(--r-pill);font-size:10px;font-weight:500;letter-spacing:.02em;position:absolute;top:-9px;left:12px;z-index:3;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface-variant)}.fb-status-chip .msi{font-size:12px}.fb-status-chip.readonly{color:var(--md-sys-color-warning);background:var(--md-sys-color-warning-container);border-color:transparent}.fb-status-chip.hidden{color:var(--md-sys-color-on-surface-variant)}.fb-status-chip.conditional{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);border-color:transparent}.fb-resize{position:absolute;top:8px;bottom:8px;right:-5px;width:6px;border-radius:999px;background:var(--md-sys-color-primary);display:flex;align-items:center;justify-content:center;cursor:col-resize;opacity:0;transition:opacity .12s ease;z-index:3}.fb-resize:before{content:\"\";width:2px;height:18px;background:var(--md-sys-color-on-primary);border-radius:999px}.fb-item:hover .fb-resize{opacity:1}.fb-item.is-break{min-height:28px;padding:8px var(--gap-3);justify-content:center}.fb-break-line{display:flex;align-items:center;gap:var(--gap-2);color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:500;letter-spacing:.06em;text-transform:uppercase}.fb-break-line:before,.fb-break-line:after{content:\"\";flex:1;height:1px;background:var(--md-sys-color-outline-variant)}.fb-break-line .msi{display:none}.fb-break-line .fb-break-label{color:var(--md-sys-color-on-surface-variant)}.fb-drop-hint{height:36px;border-radius:var(--r-sm);border:1.5px dashed var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 6%,transparent);color:var(--md-sys-color-primary);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:500;gap:6px;margin:4px 0}.fb-drop-hint .msi{font-size:16px}.fb-group{background:var(--md-sys-color-surface-container-lowest);border-radius:var(--r-lg);border:1.5px dashed transparent;transition:border-color .12s ease,background .12s ease;position:relative;display:flex;flex-direction:column;overflow:visible;cursor:default}.fb-group:hover{border-color:color-mix(in srgb,var(--md-sys-color-primary) 60%,transparent)}.fb-group.is-selected{border:1.5px solid var(--md-sys-color-primary)}.fb-group.is-hidden{opacity:.55}.fb-group__header{display:flex;align-items:center;gap:var(--gap-2);padding:8px 12px;border-top-left-radius:12px;border-top-right-radius:12px;cursor:grab}.fb-group__header:active{cursor:grabbing}.fb-group__header .fb-group__icon .msi{font-size:18px}.fb-group__header .fb-group__label{font-size:13px;font-weight:500}.fb-group__header .fb-group__count{margin-left:auto;font-size:10px;opacity:.75}.fb-group__conditional-chip{display:inline-flex;align-items:center;gap:4px;font-family:Roboto Mono,monospace;font-size:10px;padding:2px 8px;border-radius:var(--r-pill);background:color-mix(in srgb,currentColor 12%,transparent)}.fb-group__body{padding:12px;display:flex;flex-wrap:wrap;gap:var(--gap-2);min-height:60px;position:relative}.fb-group__empty{display:flex;align-items:center;justify-content:center;height:56px;border-radius:var(--r-sm);border:1.5px dashed var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant);font-size:12px;font-style:italic}.fb-empty{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--gap-3);color:var(--md-sys-color-on-surface-variant);text-align:center;padding:24px;pointer-events:none}.fb-empty__art{width:96px;height:96px;border-radius:var(--r-xl);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center}.fb-empty__art .msi{font-size:44px}.fb-empty__title{font-size:16px;font-weight:500;color:var(--md-sys-color-on-surface)}.fb-empty__hint{font-size:13px;max-width:320px;line-height:1.5}.fb-empty__kbd{display:inline-flex;align-items:center;gap:6px;font-family:Roboto Mono,monospace;font-size:11px;padding:4px 8px;border-radius:var(--r-xs);border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface-variant)}.fb-empty__kbd .msi{font-size:12px}.fb-attrs{width:320px;flex-shrink:0;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-left:1px solid var(--md-sys-color-outline-variant)}.fb-attrs__selection{padding:var(--gap-3) var(--gap-4);display:flex;align-items:center;gap:var(--gap-2);border-bottom:1px solid var(--md-sys-color-outline-variant)}.fb-attrs__sel-icon{width:28px;height:28px;border-radius:var(--r-sm);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.fb-attrs__sel-icon .msi{font-size:18px}.fb-attrs__sel-meta{display:flex;flex-direction:column;min-width:0}.fb-attrs__sel-name{font-size:13px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-attrs__sel-key{font-family:Roboto Mono,monospace;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.fb-attrs__body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;min-width:0}.fb-attrs__placeholder{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--gap-2);padding:32px;color:var(--md-sys-color-on-surface-variant);text-align:center}.fb-attrs__placeholder .msi{font-size:32px;color:var(--md-sys-color-outline)}.fb-attrs__placeholder .title{font-size:13px;font-weight:500;color:var(--md-sys-color-on-surface)}.fb-attrs__placeholder .hint{font-size:12px;max-width:220px;line-height:1.5}.fb-preview-card{max-width:760px;margin:0 auto;background:var(--md-sys-color-surface-container-lowest);border-radius:var(--r-lg);padding:32px;box-shadow:var(--elev-1)}.fb-preview-card__chip{display:inline-flex;align-items:center;gap:6px;padding:2px 10px;height:22px;border-radius:var(--r-pill);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);font-size:10px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;margin-bottom:var(--gap-3)}.fb-preview-card__title{font-size:20px;font-weight:500;margin:0 0 var(--gap-4);color:var(--md-sys-color-on-surface)}.fb-preview-card__footer{display:flex;justify-content:flex-end;gap:var(--gap-2);margin-top:var(--gap-4);padding-top:var(--gap-4);border-top:1px solid var(--md-sys-color-outline-variant)}.fb-icon-picker{display:grid;grid-template-columns:repeat(6,1fr);gap:4px;margin-top:4px}.fb-icon-picker .fb-icon-picker__btn{height:28px;border-radius:var(--r-xs);border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface-variant);display:inline-flex;align-items:center;justify-content:center;cursor:pointer}.fb-icon-picker .fb-icon-picker__btn .msi{font-size:16px}.fb-icon-picker .fb-icon-picker__btn.is-active{border-color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary)}.fb-icon-picker .fb-icon-picker__btn:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent)}.fb-color-swatches{display:flex;gap:var(--gap-2);margin-top:4px}.fb-color-swatches .fb-color-swatch{width:24px;height:24px;border-radius:50%;cursor:pointer;border:2px solid transparent}.fb-color-swatches .fb-color-swatch.is-active{border-color:var(--md-sys-color-on-surface)}.fb-color-swatches .fb-color-swatch.primary{background:var(--md-sys-color-primary)}.fb-color-swatches .fb-color-swatch.secondary{background:var(--md-sys-color-secondary)}.fb-color-swatches .fb-color-swatch.success{background:var(--md-sys-color-success)}.fb-color-swatches .fb-color-swatch.warning{background:var(--md-sys-color-warning)}.fb-color-swatches .fb-color-swatch.error{background:var(--md-sys-color-error)}.fb-children-list{display:flex;flex-direction:column;gap:4px}.fb-child-row{display:flex;align-items:center;gap:var(--gap-2);height:30px;padding:0 8px;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px}.fb-child-row .fb-child-row__icon{width:22px;height:22px;border-radius:var(--r-xs);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.fb-child-row .fb-child-row__icon .msi{font-size:14px}.fb-child-row .fb-child-row__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fb-child-row .fb-child-row__key{font-family:Roboto Mono,monospace;font-size:10px;color:var(--md-sys-color-on-surface-variant)}.fb-child-row:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 4%,transparent)}.fb-add-link{display:inline-flex;align-items:center;gap:4px;font-size:12px;color:var(--md-sys-color-primary);cursor:pointer;padding:4px 0;text-decoration:none}.fb-add-link .msi{font-size:14px}.fb-add-link:hover{text-decoration:underline}\n"] }]
6427
+ ], template: "<!-- cdkDropListGroup: auto-connect t\u1EA5t c\u1EA3 cdkDropList trong palette, canvas rows, group bodies.\n [class.fb-shell--dragging]: JS-driven flag \u0111\u1EC3 \u1EA9n hover/actions/resize to\u00E0n di\u1EC7n\n trong l\u00FAc drag (CSS :has() kh\u00F4ng b\u1EAFt 100% tr\u01B0\u1EDDng h\u1EE3p v\u1EDBi CDK preview clone). -->\n<div class=\"fb-shell\" cdkDropListGroup [class.fb-shell--dragging]=\"isAnyDragging()\">\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 LEFT PALETTE \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <aside class=\"fb-palette\">\n <div class=\"fb-panel-header\">\n <div class=\"fb-panel-header__title\">{{ 'core.component.form-builder.components' | translate }}</div>\n </div>\n\n <!-- Search pill -->\n <div class=\"fb-palette__search\">\n <span class=\"msi\" aria-hidden=\"true\">search</span>\n <input\n type=\"text\"\n [placeholder]=\"'core.component.form-builder.search-components' | translate\"\n [value]=\"paletteSearch()\"\n (input)=\"paletteSearch.set($any($event.target).value)\" />\n <span class=\"kbd\">\u2318K</span>\n </div>\n\n <div class=\"fb-palette__scroll\">\n @for (group of paletteGroups(); track group.key) {\n <div class=\"fb-palette__group-label\">{{ group.label }}</div>\n <div\n class=\"fb-palette__list\"\n cdkDropList\n [cdkDropListData]=\"group.items\"\n [cdkDropListEnterPredicate]=\"noReturnPredicate\">\n @for (formBuilderComponent of group.items; track formBuilderComponent.type) {\n <div\n cdkDrag\n class=\"fb-palette-item\"\n [matTooltip]=\"formBuilderComponent.name\"\n matTooltipPosition=\"right\"\n (click)=\"addComponent(formBuilderComponent)\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"onAnyDragEnded()\"\n aria-hidden=\"true\">\n <span class=\"fb-palette-item__icon\"><span class=\"msi\">{{ formBuilderComponent.symbol }}</span></span>\n <span class=\"fb-palette-item__name\">{{ formBuilderComponent.name }}</span>\n <span class=\"fb-palette-item__drag\"><span class=\"msi\">drag_indicator</span></span>\n <!-- Generic drag preview: ch\u1EC9 icon (puck), label \u1EA9n -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n </div>\n }\n </div>\n }\n </div>\n </aside>\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 CENTER CANVAS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <section class=\"fb-canvas\">\n @let _editing = editingGroup();\n @if (_editing) {\n <!-- \u2500\u2500 Drill-in header: \u0111ang thi\u1EBFt k\u1EBF children c\u1EE7a 1 group \u2500\u2500 -->\n <header class=\"fb-canvas__header fb-canvas__header--group\">\n <div class=\"fb-canvas__title fb-groupedit__crumb\">\n <button type=\"button\" class=\"fb-icon-btn\" [matTooltip]=\"'core.component.form-builder.back-to-design' | translate\" (click)=\"cancelGroupEdit()\">\n <span class=\"msi\">chevron_left</span>\n </button>\n <span class=\"fb-groupedit__icon\"><span class=\"msi\">{{ _editing.properties?.icon || 'category' }}</span></span>\n <span>{{ _editing.label || ('core.component.form-builder.edit-group' | translate) }}</span>\n <span class=\"fb-groupedit__hint\">{{ 'core.component.form-builder.edit-group' | translate }}</span>\n </div>\n <div class=\"fb-canvas__actions\">\n <sd-button type=\"outline\" [title]=\"'core.component.form-builder.cancel' | translate\" (click)=\"cancelGroupEdit()\"></sd-button>\n <sd-button type=\"fill\" color=\"primary\" prefixIcon=\"check\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"confirmGroupEdit()\"></sd-button>\n </div>\n </header>\n } @else {\n <header class=\"fb-canvas__header\">\n <div class=\"fb-canvas__title\">\n <span>{{ 'core.component.form-builder.layout' | translate }}</span>\n </div>\n <div class=\"fb-canvas__actions\">\n <!-- Toolbar cluster: view JSON / variables / validation -->\n <button\n type=\"button\"\n class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.view-json' | translate\"\n (click)=\"viewJSON()\">\n <span class=\"msi\">data_object</span>\n </button>\n <button\n type=\"button\"\n class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.config-variable' | translate\"\n (click)=\"configureVariables()\">\n <span class=\"msi\">data_array</span>\n </button>\n <button\n type=\"button\"\n class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.config-validation-warning-error' | translate\"\n (click)=\"openConfigureValidation()\">\n <span class=\"msi\">rule</span>\n </button>\n\n <span class=\"fb-divider\"></span>\n\n <!-- M3 segmented Design/Preview toggle -->\n <div class=\"fb-mode-toggle\" role=\"tablist\">\n <button\n type=\"button\"\n role=\"tab\"\n [class.is-active]=\"!isPreview()\"\n (click)=\"setMode(false)\">\n <span class=\"msi\">edit</span>\n <span>{{ 'core.component.form-builder.design' | translate }}</span>\n </button>\n <button\n type=\"button\"\n role=\"tab\"\n [class.is-active]=\"isPreview()\"\n (click)=\"setMode(true)\">\n <span class=\"msi\">visibility</span>\n <span>{{ 'core.component.form-builder.preview' | translate }}</span>\n </button>\n </div>\n </div>\n </header>\n }\n\n <div\n class=\"fb-canvas__body\"\n [class.is-preview]=\"isPreview()\"\n id=\"frmComponent\">\n @if (isPreview()) {\n <!-- \u2500\u2500 Preview mode \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"fb-preview-card\">\n <div class=\"fb-preview-card__chip\">\n <span class=\"msi\">visibility</span>\n {{ 'core.component.form-builder.preview-runtime' | translate }}\n </div>\n <sd-form-render [configuration]=\"{ components: this.components, validations: this.validations }\"></sd-form-render>\n <div class=\"fb-preview-card__footer\">\n <sd-button type=\"outline\" [title]=\"'core.component.form-builder.cancel' | translate\" (click)=\"setMode(false)\"></sd-button>\n <sd-button type=\"fill\" color=\"primary\" [title]=\"'core.component.form-builder.submit' | translate\" (click)=\"onValidate()\"></sd-button>\n </div>\n </div>\n } @else {\n <!-- \u2500\u2500 Design mode \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (!dragDropRows.length) {\n <div class=\"fb-empty\">\n <div class=\"fb-empty__art\"><span class=\"msi\">dashboard_customize</span></div>\n <div class=\"fb-empty__title\">{{ 'core.component.form-builder.empty-title' | translate }}</div>\n <div class=\"fb-empty__hint\">\n {{ 'core.component.form-builder.empty-hint' | translate }}\n <span class=\"fb-empty__kbd\"><span class=\"msi\">keyboard</span>\u2318 K</span>\n </div>\n </div>\n }\n\n <div\n cdkDropList\n cdkDropListOrientation=\"vertical\"\n [cdkDropListData]=\"dragDropRows\"\n (cdkDropListDropped)=\"drop($event)\"\n (click)=\"clickFormContentEmpty()\"\n aria-hidden=\"true\">\n @for (row of dragDropRows; track row.rowIndex) {\n <div\n cdkDrag\n class=\"fb-row\"\n (mouseover)=\"onMouseover($event, row)\"\n (focus)=\"onFocus($event)\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"onAnyDragEnded()\"\n [class.is-drag-target]=\"targetItem === row\"\n [id]=\"'row_' + row.rowIndex\"\n aria-hidden=\"true\">\n <div class=\"fb-row__drag\" [matTooltip]=\"'core.component.form-builder.drag-vertically' | translate\" cdkDragHandle>\n <span class=\"msi\">drag_indicator</span>\n </div>\n <!-- Generic puck preview -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <!-- Quick-add break button \u2014 show on row hover, insert break after this row -->\n <button\n type=\"button\"\n class=\"fb-row-break-btn\"\n [matTooltip]=\"'core.component.form-builder.break' | translate\"\n matTooltipPosition=\"right\"\n (click)=\"insertBreakAfter(row); $event.stopPropagation()\">\n <span class=\"msi\">horizontal_rule</span>\n </button>\n\n <div\n class=\"fb-row__items\"\n style=\"display: flex; flex: 1; gap: var(--gap-2);\"\n cdkDropList\n cdkDropListOrientation=\"horizontal\"\n [cdkDropListData]=\"row.items\"\n (cdkDropListDropped)=\"drop($event)\">\n\n @for (item of row.items; track item.id; let i = $index) {\n <!-- Group component renders as outlined card with colored header bar -->\n @if (item.type === 'group') {\n @let g = $any(item);\n @let cv = groupColorVars(g.properties?.color);\n <div\n cdkDrag\n [id]=\"item.id\"\n class=\"fb-group column-{{ item.layout?.columns || 12 }}\"\n [class.fb-item]=\"false\"\n [class.is-selected]=\"item.id === selectedComponent()?.id\"\n [class.is-hidden]=\"item.properties?.hidden\"\n [style.flex]=\"'0 0 calc(' + (+(item.layout?.columns || 12)) + '/12 * 100% - var(--gap-2))'\"\n [style.maxWidth]=\"'calc(' + (+(item.layout?.columns || 12)) + '/12 * 100% - var(--gap-2))'\"\n (click)=\"selectComponent(item); $event.stopPropagation()\"\n (cdkDragStarted)=\"dragStartComponentItem($event); onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"dragEndComponentItem($event); onAnyDragEnded()\"\n aria-hidden=\"true\">\n <!-- Generic puck preview -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <!-- cdkDragHandle: ch\u1EC9 cho ph\u00E9p k\u00E9o group qua header \u2014 body free cho click v\u00E0o child. -->\n <div class=\"fb-group__header\" cdkDragHandle [style.background]=\"cv.bg\" [style.color]=\"cv.fg\">\n <span class=\"fb-group__icon\"><span class=\"msi\">{{ g.properties?.icon || 'category' }}</span></span>\n <span class=\"fb-group__label\">{{ item.label }}</span>\n @if (hasConditional(item)) {\n <span class=\"fb-group__conditional-chip\">\n <span class=\"msi\" style=\"font-size: 12px;\">bolt</span>\n {{ 'core.component.form-builder.conditional' | translate }}\n </span>\n }\n <span class=\"fb-group__count\">{{ g.components?.length || 0 }} fields</span>\n </div>\n <!-- Floating action toolbar -->\n <div class=\"fb-actions\">\n <!-- why: Detail = m\u1EDF canvas thi\u1EBFt k\u1EBF ri\u00EAng cho group (thay cho drag/drop trong group). -->\n <button type=\"button\" class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.edit-group' | translate\"\n (click)=\"enterGroupEdit(g); $event.stopPropagation()\">\n <span class=\"msi\">open_in_full</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.duplicate' | translate\"\n (click)=\"onDuplicate(item); $event.stopPropagation()\">\n <span class=\"msi\">content_copy</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"item.properties?.hidden\"\n [class.on]=\"item.properties?.hidden\"\n [matTooltip]=\"item.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\n (click)=\"onChangeHidden(item); $event.stopPropagation()\">\n <span class=\"msi\">{{ item.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn danger\"\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"removeComponent(item.id); $event.stopPropagation()\">\n <span class=\"msi\">delete</span>\n </button>\n </div>\n\n <!-- Static preview: children render read-only (kh\u00F4ng drag/resize/select).\n S\u1EEDa n\u1ED9i dung group qua n\u00FAt Detail (enterGroupEdit). -->\n <div class=\"fb-group__body fb-group__body--static\" (click)=\"enterGroupEdit(g); $event.stopPropagation()\">\n @if (!g.components?.length) {\n <div class=\"fb-group__empty\">\n <span class=\"msi\" style=\"font-size: 16px; margin-right: 6px;\">open_in_full</span>\n {{ 'core.component.form-builder.group-empty-hint' | translate }}\n </div>\n }\n @for (child of g.components; track child.id) {\n <div\n class=\"fb-item is-child fb-item--static column-{{ child.layout?.columns || 12 }}\"\n [class.is-hidden]=\"child.properties?.hidden\">\n <ng-container\n *ngTemplateOutlet=\"controlTemplate; context: { $implicit: child }\">\n </ng-container>\n </div>\n }\n </div>\n </div>\n } @else if (item.type === 'break') {\n <!-- Break: row separator c\u1ED1 \u0111\u1ECBnh. Render 12-col line, kh\u00F4ng c\u00F3 resize/edit attribute. -->\n <div\n cdkDrag\n [id]=\"item.id\"\n class=\"fb-item is-break column-12\"\n [class.is-selected]=\"item.id === selectedComponent()?.id\"\n [class.is-hidden]=\"item.properties?.hidden\"\n (click)=\"selectComponent(item); $event.stopPropagation()\"\n (cdkDragStarted)=\"dragStartComponentItem($event); onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"dragEndComponentItem($event); onAnyDragEnded()\"\n aria-hidden=\"true\">\n <!-- Generic puck preview -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <div class=\"fb-break-line\">\n <span class=\"msi\">horizontal_rule</span>\n <span class=\"fb-break-label\">{{ 'core.component.form-builder.break' | translate }}</span>\n </div>\n <div class=\"fb-actions\">\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"item.properties?.hidden\"\n [class.on]=\"item.properties?.hidden\"\n [matTooltip]=\"item.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\n (click)=\"onChangeHidden(item); $event.stopPropagation()\">\n <span class=\"msi\">{{ item.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn danger\"\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"removeComponent(item.id); $event.stopPropagation()\">\n <span class=\"msi\">delete</span>\n </button>\n </div>\n </div>\n } @else {\n <!-- Regular form component -->\n <div\n cdkDrag\n [id]=\"item.id\"\n class=\"fb-item column-{{ item.layout?.columns || 12 }}\"\n [class.is-selected]=\"item.id === selectedComponent()?.id\"\n [class.is-hidden]=\"item.properties?.hidden\"\n [class.is-readonly]=\"item.properties?.viewed\"\n (click)=\"selectComponent(item); $event.stopPropagation()\"\n (cdkDragStarted)=\"dragStartComponentItem($event); onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"dragEndComponentItem($event); onAnyDragEnded()\"\n aria-hidden=\"true\">\n <!-- Generic puck preview -->\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n\n <!-- Status chip (mutually exclusive priority: hidden > readonly > conditional) -->\n @if (item.properties?.hidden) {\n <span class=\"fb-status-chip hidden\">\n <span class=\"msi\">visibility_off</span>\n {{ 'core.component.form-builder.hidden' | translate }}\n </span>\n } @else if (item.properties?.viewed) {\n <span class=\"fb-status-chip readonly\">\n <span class=\"msi\">edit_off</span>\n {{ 'core.component.form-builder.read-only' | translate }}\n </span>\n } @else if (hasConditional(item)) {\n <span class=\"fb-status-chip conditional\">\n <span class=\"msi\">bolt</span>\n {{ 'core.component.form-builder.conditional' | translate }}\n </span>\n }\n\n <!-- Floating action toolbar pill -->\n <div class=\"fb-actions\">\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"item.properties?.viewed\"\n [class.on]=\"item.properties?.viewed\"\n [matTooltip]=\"item.properties?.viewed ? ('core.component.form-builder.unset-readonly' | translate) : ('core.component.form-builder.set-readonly' | translate)\"\n (click)=\"onChangeViewed(item); $event.stopPropagation()\">\n <span class=\"msi\">edit_off</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn\"\n [matTooltip]=\"'core.component.form-builder.duplicate' | translate\"\n (click)=\"onDuplicate(item); $event.stopPropagation()\">\n <span class=\"msi\">content_copy</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn\"\n [class.warning]=\"item.properties?.hidden\"\n [class.on]=\"item.properties?.hidden\"\n [matTooltip]=\"item.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\n (click)=\"onChangeHidden(item); $event.stopPropagation()\">\n <span class=\"msi\">{{ item.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\n </button>\n <button type=\"button\" class=\"fb-icon-btn danger\"\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"removeComponent(item.id); $event.stopPropagation()\">\n <span class=\"msi\">delete</span>\n </button>\n </div>\n\n <ng-container\n *ngTemplateOutlet=\"controlTemplate; context: { $implicit: item }\">\n </ng-container>\n\n <!-- Resize handle (pill) \u2014 cdkDragLockAxis=\"x\" \u0111\u1EC3 ch\u1EC9 k\u00E9o ngang.\n Wrapping cdkDropList c\u00F3 enterPredicate=false, kh\u00F4ng nh\u1EADn drop. -->\n <div cdkDropList cdkDropListOrientation=\"horizontal\" [cdkDropListEnterPredicate]=\"noReturnPredicate\">\n <div\n cdkDrag\n cdkDragLockAxis=\"x\"\n class=\"fb-resize\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"changeSizeControl($event, item, row.items, i)\"\n (cdkDragEnded)=\"dragEndChangeSizeControl($event); onAnyDragEnded()\"\n [matTooltip]=\"'core.component.form-builder.flex' | translate\"\n aria-label=\"resize\"></div>\n </div>\n </div>\n }\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n </section>\n\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 RIGHT ATTRIBUTES \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <aside class=\"fb-attrs\">\n <div class=\"fb-panel-header\">\n <div class=\"fb-panel-header__title\">{{ 'core.component.form-builder.attribute' | translate }}</div>\n </div>\n\n @let sel = selectedComponent();\n @if (sel) {\n <!-- Selection header: type icon + name + key/type -->\n <div class=\"fb-attrs__selection\">\n <span class=\"fb-attrs__sel-icon\"><span class=\"msi\">{{ symbolFor(sel) }}</span></span>\n <div class=\"fb-attrs__sel-meta\">\n <div class=\"fb-attrs__sel-name\">{{ $any(sel).label || ('core.component.form-builder.untitled' | translate) }}</div>\n <div class=\"fb-attrs__sel-key\">\n @if ($any(sel).key) {\n {{ $any(sel).key }} \u00B7 {{ typeLabelFor(sel) }}\n } @else {\n {{ typeLabelFor(sel) }}\n }\n </div>\n </div>\n </div>\n\n <div class=\"fb-attrs__body\" aria-hidden=\"true\">\n @if (sel.type === 'textfield') {\n <textfield-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></textfield-attribute>\n } @else if (sel.type === 'textarea') {\n <textarea-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></textarea-attribute>\n } @else if (sel.type === 'chip-string') {\n <chip-string-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></chip-string-attribute>\n } @else if (sel.type === 'chip-calendar') {\n <chip-calendar-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></chip-calendar-attribute>\n } @else if (sel.type === 'number') {\n <number-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></number-attribute>\n } @else if (sel.type === 'datetime') {\n <datetime-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></datetime-attribute>\n } @else if (sel.type === 'select') {\n <select-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></select-attribute>\n } @else if (sel.type === 'radio') {\n <radio-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></radio-attribute>\n } @else if (sel.type === 'checkbox') {\n <checkbox-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></checkbox-attribute>\n } @else if (sel.type === 'html') {\n <html-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></html-attribute>\n } @else if (sel.type === 'upload') {\n <upload-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></upload-attribute>\n } @else if (sel.type === 'table') {\n <table-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></table-attribute>\n } @else if (sel.type === 'group') {\n <group-attribute [group]=\"$any(sel)\"></group-attribute>\n }\n </div>\n } @else {\n <div class=\"fb-attrs__placeholder\">\n <span class=\"msi\">ads_click</span>\n <div class=\"title\">{{ 'core.component.form-builder.no-selection-title' | translate }}</div>\n <div class=\"hint\">{{ 'core.component.form-builder.no-selection-hint' | translate }}</div>\n </div>\n }\n </aside>\n</div>\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Reusable control template \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n<ng-template #controlTemplate let-item>\n @if (item.type === 'textfield') {\n <textfield-control [component]=\"item\"></textfield-control>\n } @else if (item.type === 'textarea') {\n <textarea-control [component]=\"item\"></textarea-control>\n } @else if (item.type === 'chip-string') {\n <chip-string-control [component]=\"item\"></chip-string-control>\n } @else if (item.type === 'chip-calendar') {\n <chip-calendar-control [component]=\"item\"></chip-calendar-control>\n } @else if (item.type === 'number') {\n <number-control [component]=\"item\"></number-control>\n } @else if (item.type === 'datetime') {\n <datetime-control [component]=\"item\"></datetime-control>\n } @else if (item.type === 'select') {\n <select-control [component]=\"item\"></select-control>\n } @else if (item.type === 'radio') {\n <radio-control [component]=\"item\"></radio-control>\n } @else if (item.type === 'checkbox') {\n <checkbox-control [component]=\"item\"></checkbox-control>\n } @else if (item.type === 'html') {\n <html-control [component]=\"item\"></html-control>\n } @else if (item.type === 'upload') {\n <upload-control [component]=\"item\"></upload-control>\n } @else if (item.type === 'table') {\n <table-control [component]=\"item\"></table-control>\n }\n</ng-template>\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 JSON / variables modals \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n<sd-modal title=\"JSON\" view=\"dialog\" width=\"80%\" #popupViewJSON>\n <sd-textarea [(model)]=\"jsonString\"></sd-textarea>\n <ng-container sdFooter>\n <sd-button type=\"fill\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"updateJSON()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\n </ng-container>\n</sd-modal>\n<sd-modal [title]=\"'core.component.form-builder.config-variable' | translate\" view=\"dialog\" width=\"800px\" #popupConfigureVariables>\n @for (variable of clonedVariables; track variable.id) {\n <div class=\"d-flex align-items-center\" style=\"gap: 8px\">\n <sd-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"variable.key\" required></sd-input>\n <sd-input [form]=\"form\" [label]=\"'core.component.form-builder.display-label' | translate\" [(model)]=\"variable.label\" required></sd-input>\n <sd-button prefixIcon=\"delete\" (click)=\"removeVariables(variable.id)\" color=\"error\"></sd-button>\n </div>\n }\n <a href=\"javascript:;\" (click)=\"addVariables()\">{{ 'core.component.form-builder.add-variable' | translate }}</a>\n <ng-container sdFooter>\n <sd-button type=\"fill\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"updateVariables()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\n </ng-container>\n</sd-modal>\n<configure-validation (accept)=\"onUpdateValidations($event)\"></configure-validation>\n", styles: ["@charset \"UTF-8\";:host{--md-sys-color-primary: var(--sd-primary, #2A66F4);--md-sys-color-on-primary: #ffffff;--md-sys-color-primary-container: var(--sd-primary-light, #EAF1FF);--md-sys-color-on-primary-container: var(--sd-primary, #2A66F4);--md-sys-color-info: var(--sd-info, #2962FF);--md-sys-color-info-container: var(--sd-info-light, #E7E9FF);--md-sys-color-secondary: #625b71;--md-sys-color-secondary-container: #e8def8;--md-sys-color-on-secondary-container: #1d192b;--md-sys-color-surface: #fbfafc;--md-sys-color-surface-container-lowest: #ffffff;--md-sys-color-surface-container-low: #f6f4f8;--md-sys-color-surface-container: #f1eef3;--md-sys-color-surface-container-high: #ebe8ee;--md-sys-color-surface-container-highest: #e6e2ea;--md-sys-color-on-surface: #1c1b1f;--md-sys-color-on-surface-variant: #49454e;--md-sys-color-outline: #79747e;--md-sys-color-outline-variant: #d6d2da;--md-sys-color-error: #b3261e;--md-sys-color-error-container: #f9dedc;--md-sys-color-warning: #8a5400;--md-sys-color-warning-container: #ffddb1;--md-sys-color-success: #1f6f43;--md-sys-color-success-container: #b7f0cb;--h-row: 28px;--h-field: 32px;--h-palette: 36px;--h-header: 36px;--h-section: 28px;--h-action-btn: 24px;--gap-1: 4px;--gap-2: 8px;--gap-3: 12px;--gap-4: 16px;--gap-5: 24px;--r-xs: 4px;--r-sm: 8px;--r-md: 12px;--r-lg: 16px;--r-xl: 28px;--r-pill: 999px;--elev-1: 0 1px 2px 0 rgba(0, 0, 0, .06);--elev-2: 0 2px 6px 0 rgba(0, 0, 0, .08), 0 1px 2px 0 rgba(0, 0, 0, .04);--elev-3: 0 6px 14px 0 rgba(0, 0, 0, .1), 0 2px 4px 0 rgba(0, 0, 0, .06);display:block;width:100%;height:100%;font-family:Roboto,system-ui,sans-serif;font-size:13px;color:var(--md-sys-color-on-surface);background:var(--md-sys-color-surface)}:host ::ng-deep .msi{font-family:Material Symbols Rounded;font-weight:400;font-style:normal;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;font-feature-settings:\"liga\";-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"wght\" 300,\"opsz\" 24,\"GRAD\" 0,\"FILL\" 0}:host ::ng-deep .msi.filled{font-variation-settings:\"wght\" 300,\"opsz\" 24,\"GRAD\" 0,\"FILL\" 1}:host ::ng-deep .mono{font-family:Roboto Mono,ui-monospace,monospace}:host ::ng-deep .fb-icon-btn{width:28px;height:28px;border-radius:var(--r-sm);border:none;background:transparent;color:var(--md-sys-color-on-surface-variant);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background .12s ease,color .12s ease}:host ::ng-deep .fb-icon-btn:hover{background:color-mix(in srgb,var(--md-sys-color-on-surface) 8%,transparent);color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-icon-btn.is-active{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container)}:host ::ng-deep .fb-icon-btn.danger:hover{color:var(--md-sys-color-error);background:var(--md-sys-color-error-container)}:host ::ng-deep .fb-icon-btn.warning.on{color:var(--md-sys-color-warning);background:var(--md-sys-color-warning-container)}:host ::ng-deep .fb-icon-btn .msi{font-size:18px}:host ::ng-deep .fb-field{display:flex;flex-direction:column;gap:4px}:host ::ng-deep .fb-field__label{font-size:11px;font-weight:500;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-field__input{height:var(--h-row);padding:0 10px;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px;display:flex;align-items:center;justify-content:space-between;color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-field__input.placeholder{color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-field__input:focus-within,:host ::ng-deep .fb-field__input.focused{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent)}:host ::ng-deep .fb-field__input .msi{font-size:16px;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-field-row{display:flex;align-items:center;gap:var(--gap-2);justify-content:space-between}:host ::ng-deep .fb-switch{display:inline-flex;width:34px;height:18px;border-radius:999px;background:var(--md-sys-color-surface-container-highest);border:1.5px solid var(--md-sys-color-outline);padding:1px;align-items:center;cursor:pointer;position:relative;flex-shrink:0}:host ::ng-deep .fb-switch .fb-switch__thumb{width:12px;height:12px;border-radius:50%;background:var(--md-sys-color-outline)}:host ::ng-deep .fb-switch.on{background:var(--md-sys-color-primary);border-color:var(--md-sys-color-primary);justify-content:flex-end}:host ::ng-deep .fb-switch.on .fb-switch__thumb{background:var(--md-sys-color-on-primary);width:14px;height:14px}:host ::ng-deep .fb-expr{display:flex;align-items:center;gap:6px;height:var(--h-row);padding:0 6px 0 0;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-expr__badge{height:100%;display:inline-flex;align-items:center;justify-content:center;padding:0 6px;background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);font-family:Roboto Mono,monospace;font-size:10px;font-weight:500;border-radius:var(--r-xs) 0 0 var(--r-xs)}:host ::ng-deep .fb-expr__code{font-family:Roboto Mono,monospace;flex:1;font-size:11px;color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-expr__code .var{color:var(--md-sys-color-primary);font-weight:500}:host ::ng-deep .fb-expr__code .op{color:var(--md-sys-color-error)}:host ::ng-deep .fb-expr__code .lit{color:var(--md-sys-color-success)}:host ::ng-deep .fb-expr .empty{color:var(--md-sys-color-on-surface-variant);font-style:italic;padding-left:6px;flex:1}:host ::ng-deep details.fb-section{border-bottom:1px solid var(--md-sys-color-outline-variant);margin:0;padding:0;background:transparent}:host ::ng-deep details.fb-section>summary{list-style:none}:host ::ng-deep details.fb-section>summary::-webkit-details-marker{display:none}:host ::ng-deep .fb-section__head{height:var(--h-section);padding:0 var(--gap-4);display:flex;align-items:center;gap:var(--gap-2);cursor:pointer;font-size:12px;font-weight:500;color:var(--md-sys-color-on-surface);-webkit-user-select:none;user-select:none}:host ::ng-deep .fb-section__head .msi{font-size:16px;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-section__head .fb-section__title{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep .fb-section__head .chev{margin-left:auto;transition:transform .16s ease}:host ::ng-deep details.fb-section[open] .fb-section__head .chev{transform:rotate(90deg)}:host ::ng-deep .fb-section__body{padding:4px var(--gap-4) var(--gap-3);display:flex;flex-direction:column;gap:var(--gap-2)}:host ::ng-deep .fb-columns-list{display:flex;flex-direction:column;gap:var(--gap-1);padding-top:var(--gap-1)}:host ::ng-deep .fb-column-row{display:flex;align-items:center;gap:var(--gap-2);height:40px;padding:6px 10px;border-radius:var(--r-sm);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px;cursor:pointer;transition:background .12s ease,border-color .12s ease,box-shadow .12s ease}:host ::ng-deep .fb-column-row:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 4%,transparent);border-color:color-mix(in srgb,var(--md-sys-color-primary) 30%,transparent)}:host ::ng-deep .fb-column-row.is-active{border-color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 30%,transparent)}:host ::ng-deep .fb-column-row .fb-column-row__type-icon{width:28px;height:28px;border-radius:var(--r-sm);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}:host ::ng-deep .fb-column-row .fb-column-row__type-icon .msi{font-size:16px}:host ::ng-deep .fb-column-row .fb-column-row__meta{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}:host ::ng-deep .fb-column-row .fb-column-row__meta .fb-column-row__label{font-size:13px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-column-row .fb-column-row__meta .fb-column-row__req{color:var(--md-sys-color-error);margin-left:2px;font-weight:600}:host ::ng-deep .fb-column-row .fb-column-row__meta .fb-column-row__sub{font-size:11px;color:var(--md-sys-color-on-surface-variant);font-family:Roboto Mono,ui-monospace,monospace;letter-spacing:.02em}:host ::ng-deep .cdk-drag-preview.fb-drag-preview,:host ::ng-deep .fb-drag-preview{width:36px;height:36px;min-width:36px;min-height:36px;max-width:36px;max-height:36px;box-sizing:border-box;border-radius:50%;background:var(--md-sys-color-primary, #6750a4);display:inline-flex;align-items:center;justify-content:center;box-shadow:0 10px 24px #00000042,0 3px 8px #00000024;border:3px solid var(--md-sys-color-on-primary, #ffffff);cursor:grabbing;pointer-events:none;-webkit-user-select:none;user-select:none;opacity:.96;overflow:hidden;z-index:10000}:host ::ng-deep .cdk-drag-preview.fb-drag-preview:after,:host ::ng-deep .fb-drag-preview:after{content:\"\";width:8px;height:8px;border-radius:50%;background:var(--md-sys-color-on-primary, #ffffff);opacity:.9}@keyframes fb-drop-pulse{0%,to{box-shadow:0 0 0 3px color-mix(in srgb,var(--md-sys-color-info) 16%,transparent)}50%{box-shadow:0 0 0 5px color-mix(in srgb,var(--md-sys-color-info) 24%,transparent)}}:host ::ng-deep .cdk-drag-placeholder{background:transparent!important;border:none!important;border-radius:999px!important;padding:0!important;transform:none!important;transition:none!important;pointer-events:none;overflow:hidden;animation:none!important;opacity:0!important}:host ::ng-deep .cdk-drag-placeholder>*{visibility:hidden!important;pointer-events:none!important}:host ::ng-deep .fb-palette__list>.cdk-drag-placeholder{display:none!important}:host ::ng-deep .fb-row__items>.cdk-drag-placeholder,:host ::ng-deep .fb-group__body>.cdk-drag-placeholder{width:0!important;min-width:0!important;max-width:0!important;height:auto!important;min-height:0!important;align-self:stretch;flex:0 0 0!important;margin:0!important}:host ::ng-deep [cdkDropListOrientation=vertical]>.cdk-drag-placeholder{width:auto!important;height:0!important;min-height:0!important;max-height:0!important;flex:0 0 0!important;margin:0!important;align-self:stretch}:host ::ng-deep .cdk-drop-list-receiving{background:color-mix(in srgb,var(--md-sys-color-primary) 3%,transparent);transition:background .16s ease}:host ::ng-deep .fb-group__body.cdk-drop-list-receiving,:host ::ng-deep .fb-group__body.cdk-drop-list-dragging{background:color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent)!important;outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 78%,transparent);outline-offset:-6px;border-radius:var(--r-sm)}:host ::ng-deep .fb-resize.cdk-drag-preview{display:none!important}:host ::ng-deep .fb-shell--dragging .fb-item:hover,:host ::ng-deep .fb-shell--dragging .fb-group:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-item:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group:hover{border-color:transparent!important;background:transparent!important}:host ::ng-deep .fb-shell--dragging .fb-row:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row:hover{outline-color:transparent!important;background:transparent!important}:host ::ng-deep .fb-shell--dragging .fb-row:hover .fb-row__drag,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row:hover .fb-row__drag{opacity:0!important}:host ::ng-deep .fb-shell--dragging .fb-row.is-drag-target,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row.is-drag-target{outline-color:color-mix(in srgb,var(--md-sys-color-info) 44%,transparent)!important;background:color-mix(in srgb,var(--md-sys-color-info) 4%,transparent)!important}:host ::ng-deep .fb-shell--dragging .fb-row__drag,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row__drag{opacity:0!important}:host ::ng-deep .fb-shell--dragging .fb-actions,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-actions{opacity:0!important;pointer-events:none!important;transform:translateY(-2px)!important}:host ::ng-deep .fb-shell--dragging .fb-resize,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-resize{opacity:0!important;pointer-events:none!important}:host ::ng-deep .fb-shell--dragging .fb-row-break-btn,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row-break-btn{opacity:0!important;pointer-events:none!important}:host ::ng-deep .fb-shell--dragging .fb-palette-item:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-palette-item:hover{background:transparent!important}:host ::ng-deep .fb-shell--dragging .fb-palette-item:hover .fb-palette-item__drag,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-palette-item:hover .fb-palette-item__drag{opacity:0!important}:host ::ng-deep .fb-shell--dragging .fb-group__body,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__body{min-height:80px!important;background:color-mix(in srgb,var(--md-sys-color-primary) 5%,transparent)!important;outline:2px dashed color-mix(in srgb,var(--md-sys-color-primary) 50%,transparent)!important;outline-offset:-6px;border-radius:var(--r-sm);transition:background .16s ease,outline .16s ease,min-height .16s ease}:host ::ng-deep .fb-shell--dragging .fb-group__empty,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__empty{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 55%,transparent);background:color-mix(in srgb,var(--md-sys-color-primary) 7%,transparent);color:var(--md-sys-color-primary)}:host ::ng-deep .fb-shell--dragging .fb-group__body.cdk-drop-list-receiving,:host ::ng-deep .fb-shell--dragging .fb-group__body.cdk-drop-list-dragging,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__body.cdk-drop-list-receiving,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__body.cdk-drop-list-dragging{background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)!important;outline:2px solid var(--md-sys-color-primary)!important}:host ::ng-deep .cdk-drag-animating{transition:transform .22s cubic-bezier(.2,0,0,1)!important}:host ::ng-deep .cdk-drag-dragging{transition:none!important}:host ::ng-deep .fb-item:not(.cdk-drag-dragging){transition:flex .12s cubic-bezier(.2,0,0,1),max-width .12s cubic-bezier(.2,0,0,1),border-color .12s,background .12s}.fb-shell{width:100%;height:100%;display:flex;background:var(--md-sys-color-surface);overflow:hidden;min-height:0}.fb-panel-header{height:var(--h-header);display:flex;align-items:center;justify-content:space-between;padding:0 var(--gap-3);border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);flex-shrink:0}.fb-panel-header__title{font-size:11px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant)}.fb-panel-header__actions{display:flex;align-items:center;gap:2px}.fb-palette{width:220px;flex-shrink:0;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-right:1px solid var(--md-sys-color-outline-variant)}.fb-palette__scroll{flex:1;overflow-y:auto;padding-bottom:var(--gap-3)}.fb-palette__search{margin:var(--gap-3);height:32px;display:flex;align-items:center;gap:var(--gap-2);padding:0 var(--gap-3);border-radius:var(--r-pill);background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant);font-size:13px;flex-shrink:0}.fb-palette__search .msi{font-size:18px}.fb-palette__search input{flex:1;border:none;outline:none;background:transparent;color:var(--md-sys-color-on-surface);font-size:13px;font-family:inherit}.fb-palette__search input::placeholder{color:var(--md-sys-color-on-surface-variant)}.fb-palette__search .kbd{font-family:Roboto Mono,monospace;font-size:10px;padding:1px 6px;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant)}.fb-palette__group-label{font-size:11px;font-weight:500;letter-spacing:.04em;color:var(--md-sys-color-on-surface-variant);padding:var(--gap-3) var(--gap-4) var(--gap-1);text-transform:uppercase}.fb-palette__list{display:flex;flex-direction:column;padding:0 var(--gap-2)}.fb-palette-item{height:var(--h-palette);display:flex;align-items:center;gap:var(--gap-3);padding:0 var(--gap-3);border-radius:var(--r-sm);cursor:grab;color:var(--md-sys-color-on-surface);position:relative;-webkit-user-select:none;user-select:none}.fb-palette-item:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent)}.fb-palette-item .fb-palette-item__icon{width:24px;height:24px;border-radius:var(--r-xs);display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);flex-shrink:0}.fb-palette-item .fb-palette-item__icon .msi{font-size:16px}.fb-palette-item .fb-palette-item__name{font-size:13px;font-weight:400}.fb-palette-item .fb-palette-item__drag{margin-left:auto;color:var(--md-sys-color-outline);opacity:0;transition:opacity .12s ease}.fb-palette-item .fb-palette-item__drag .msi{font-size:16px}.fb-palette-item:hover .fb-palette-item__drag{opacity:1}.fb-canvas{flex:1 1 0;min-width:0;display:flex;flex-direction:column;background:var(--md-sys-color-surface);overflow:hidden}.fb-canvas__header{height:var(--h-header);display:flex;align-items:center;justify-content:space-between;padding:0 var(--gap-4);border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);gap:var(--gap-3);flex-shrink:0}.fb-canvas__title{display:flex;align-items:center;gap:var(--gap-2);font-size:11px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant)}.fb-canvas__title .breadcrumb-sep{color:var(--md-sys-color-outline)}.fb-canvas__actions{display:flex;align-items:center;gap:var(--gap-2)}.fb-divider{width:1px;height:18px;background:var(--md-sys-color-outline-variant)}.fb-canvas__body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;padding:var(--gap-4);position:relative;background:var(--md-sys-color-surface);min-width:0}.fb-canvas__body.is-preview{background:var(--md-sys-color-surface-container-low);padding:32px}.fb-mode-toggle{display:inline-flex;height:28px;border:1px solid var(--md-sys-color-outline);border-radius:var(--r-pill);overflow:hidden;flex-shrink:0}.fb-mode-toggle button{border:0;background:transparent;padding:0 var(--gap-3);font-size:12px;font-weight:500;display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-surface-variant);cursor:pointer}.fb-mode-toggle button .msi{font-size:16px}.fb-mode-toggle button.is-active{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.fb-row{position:relative;display:flex;gap:var(--gap-2);padding:6px var(--gap-2);border-radius:var(--r-sm);margin-bottom:6px;min-width:0;transition:outline .12s ease,background .12s ease;outline:1px dashed transparent;outline-offset:-1px}.fb-row:hover{outline-color:var(--md-sys-color-outline-variant);background:color-mix(in srgb,var(--md-sys-color-primary) 3%,transparent)}.fb-row:hover .fb-row__drag{opacity:1}.fb-row.is-drag-target{outline-color:color-mix(in srgb,var(--md-sys-color-info) 44%,transparent);background:color-mix(in srgb,var(--md-sys-color-info) 4%,transparent)}.fb-row.is-drag-target:after{content:\"\";position:absolute;left:10px;right:10px;bottom:-3px;height:4px;border-radius:999px;background:var(--md-sys-color-info);box-shadow:0 0 0 4px color-mix(in srgb,var(--md-sys-color-info) 18%,transparent);pointer-events:none;animation:fb-drop-pulse .9s ease-in-out infinite;z-index:3}.fb-row__drag{position:absolute;left:-22px;top:50%;transform:translateY(-50%);width:18px;height:22px;border-radius:var(--r-xs);display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-high);opacity:0;cursor:grab;z-index:2}.fb-row__drag .msi{font-size:14px}.fb-row-break-btn{position:absolute;right:-28px;top:50%;transform:translateY(-50%);width:22px;height:22px;border-radius:var(--r-pill);display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-high);border:1px solid var(--md-sys-color-outline-variant);cursor:pointer;opacity:0;z-index:2;transition:opacity .12s ease,background .12s ease,color .12s ease}.fb-row-break-btn .msi{font-size:14px}.fb-row-break-btn:hover{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);border-color:transparent}.fb-row:hover .fb-row-break-btn{opacity:1}.fb-item{position:relative;border:1.5px dashed transparent;border-radius:var(--r-md);padding:var(--gap-2) var(--gap-3);min-height:56px;min-width:0;transition:border-color .12s ease,background .12s ease;background:transparent;cursor:grab;display:flex;flex-direction:column;gap:6px}.fb-item:hover{border-color:color-mix(in srgb,var(--md-sys-color-primary) 60%,transparent)}.fb-item.is-selected{border:1.5px solid var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 4%,transparent)}.fb-item.is-hidden{opacity:.45}.fb-item.is-readonly:after{content:\"\";position:absolute;inset:0;border-radius:var(--r-md);background:repeating-linear-gradient(135deg,transparent 0 6px,color-mix(in srgb,var(--md-sys-color-on-surface) 4%,transparent) 6px 7px);pointer-events:none}.fb-item.column-2{flex:0 0 calc(16.6666666667% - var(--gap-2));max-width:calc(16.6666666667% - var(--gap-2))}.fb-item.column-3{flex:0 0 calc(25% - var(--gap-2));max-width:calc(25% - var(--gap-2))}.fb-item.column-4{flex:0 0 calc(33.3333333333% - var(--gap-2));max-width:calc(33.3333333333% - var(--gap-2))}.fb-item.column-5{flex:0 0 calc(41.6666666667% - var(--gap-2));max-width:calc(41.6666666667% - var(--gap-2))}.fb-item.column-6{flex:0 0 calc(50% - var(--gap-2));max-width:calc(50% - var(--gap-2))}.fb-item.column-7{flex:0 0 calc(58.3333333333% - var(--gap-2));max-width:calc(58.3333333333% - var(--gap-2))}.fb-item.column-8{flex:0 0 calc(66.6666666667% - var(--gap-2));max-width:calc(66.6666666667% - var(--gap-2))}.fb-item.column-9{flex:0 0 calc(75% - var(--gap-2));max-width:calc(75% - var(--gap-2))}.fb-item.column-10{flex:0 0 calc(83.3333333333% - var(--gap-2));max-width:calc(83.3333333333% - var(--gap-2))}.fb-item.column-11{flex:0 0 calc(91.6666666667% - var(--gap-2));max-width:calc(91.6666666667% - var(--gap-2))}.fb-item.column-12{flex:1 1 100%;max-width:100%}.fb-actions{position:absolute;top:-14px;right:8px;display:flex;align-items:center;gap:2px;padding:2px;border-radius:var(--r-pill);background:var(--md-sys-color-surface-container-lowest);box-shadow:var(--elev-2);border:1px solid var(--md-sys-color-outline-variant);z-index:4;opacity:0;transform:translateY(-2px);pointer-events:none;transition:opacity .12s ease,transform .12s ease}.fb-actions .fb-icon-btn{width:24px;height:24px}.fb-actions .fb-icon-btn .msi{font-size:16px}.fb-item:hover .fb-actions,.fb-item.is-selected .fb-actions{opacity:1;transform:translateY(0);pointer-events:auto}table-control{display:block;width:100%;max-width:100%;min-width:0}.fb-group>.fb-actions{top:6px;right:8px}.fb-group:hover>.fb-actions,.fb-group.is-selected>.fb-actions{opacity:1;transform:translateY(0);pointer-events:auto}.fb-status-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;height:18px;border-radius:var(--r-pill);font-size:10px;font-weight:500;letter-spacing:.02em;position:absolute;top:-9px;left:12px;z-index:3;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface-variant)}.fb-status-chip .msi{font-size:12px}.fb-status-chip.readonly{color:var(--md-sys-color-warning);background:var(--md-sys-color-warning-container);border-color:transparent}.fb-status-chip.hidden{color:var(--md-sys-color-on-surface-variant)}.fb-status-chip.conditional{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);border-color:transparent}.fb-resize{position:absolute;top:8px;bottom:8px;right:-5px;width:6px;border-radius:999px;background:var(--md-sys-color-primary);display:flex;align-items:center;justify-content:center;cursor:col-resize;opacity:0;transition:opacity .12s ease;z-index:3}.fb-resize:before{content:\"\";width:2px;height:18px;background:var(--md-sys-color-on-primary);border-radius:999px}.fb-item:hover .fb-resize{opacity:1}.fb-item.is-break{min-height:28px;padding:8px var(--gap-3);justify-content:center}.fb-break-line{display:flex;align-items:center;gap:var(--gap-2);color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:500;letter-spacing:.06em;text-transform:uppercase}.fb-break-line:before,.fb-break-line:after{content:\"\";flex:1;height:1px;background:var(--md-sys-color-outline-variant)}.fb-break-line .msi{display:none}.fb-break-line .fb-break-label{color:var(--md-sys-color-on-surface-variant)}.fb-drop-hint{height:36px;border-radius:var(--r-sm);border:1.5px dashed var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 6%,transparent);color:var(--md-sys-color-primary);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:500;gap:6px;margin:4px 0}.fb-drop-hint .msi{font-size:16px}.fb-group{background:var(--md-sys-color-surface-container-lowest);border-radius:var(--r-lg);border:1.5px dashed transparent;transition:border-color .12s ease,background .12s ease;position:relative;display:flex;flex-direction:column;overflow:visible;cursor:default}.fb-group:hover{border-color:color-mix(in srgb,var(--md-sys-color-primary) 60%,transparent)}.fb-group.is-selected{border:1.5px solid var(--md-sys-color-primary)}.fb-group.is-hidden{opacity:.55}.fb-group__header{display:flex;align-items:center;gap:var(--gap-2);padding:8px 12px;border-top-left-radius:12px;border-top-right-radius:12px;cursor:grab}.fb-group__header:active{cursor:grabbing}.fb-group__header .fb-group__icon .msi{font-size:18px}.fb-group__header .fb-group__label{font-size:13px;font-weight:500}.fb-group__header .fb-group__count{margin-left:auto;font-size:10px;opacity:.75}.fb-group__conditional-chip{display:inline-flex;align-items:center;gap:4px;font-family:Roboto Mono,monospace;font-size:10px;padding:2px 8px;border-radius:var(--r-pill);background:color-mix(in srgb,currentColor 12%,transparent)}.fb-group__body{padding:12px;display:flex;flex-wrap:wrap;gap:var(--gap-2);min-height:60px;position:relative}.fb-group__empty{display:flex;align-items:center;justify-content:center;height:56px;border-radius:var(--r-sm);border:1.5px dashed var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant);font-size:12px;font-style:italic}.fb-empty{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--gap-3);color:var(--md-sys-color-on-surface-variant);text-align:center;padding:24px;pointer-events:none}.fb-empty__art{width:96px;height:96px;border-radius:var(--r-xl);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center}.fb-empty__art .msi{font-size:44px}.fb-empty__title{font-size:16px;font-weight:500;color:var(--md-sys-color-on-surface)}.fb-empty__hint{font-size:13px;max-width:320px;line-height:1.5}.fb-empty__kbd{display:inline-flex;align-items:center;gap:6px;font-family:Roboto Mono,monospace;font-size:11px;padding:4px 8px;border-radius:var(--r-xs);border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface-variant)}.fb-empty__kbd .msi{font-size:12px}.fb-attrs{width:320px;flex-shrink:0;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-left:1px solid var(--md-sys-color-outline-variant)}.fb-attrs__selection{padding:var(--gap-3) var(--gap-4);display:flex;align-items:center;gap:var(--gap-2);border-bottom:1px solid var(--md-sys-color-outline-variant)}.fb-attrs__sel-icon{width:28px;height:28px;border-radius:var(--r-sm);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.fb-attrs__sel-icon .msi{font-size:18px}.fb-attrs__sel-meta{display:flex;flex-direction:column;min-width:0}.fb-attrs__sel-name{font-size:13px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-attrs__sel-key{font-family:Roboto Mono,monospace;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.fb-attrs__body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;min-width:0}.fb-attrs__placeholder{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--gap-2);padding:32px;color:var(--md-sys-color-on-surface-variant);text-align:center}.fb-attrs__placeholder .msi{font-size:32px;color:var(--md-sys-color-outline)}.fb-attrs__placeholder .title{font-size:13px;font-weight:500;color:var(--md-sys-color-on-surface)}.fb-attrs__placeholder .hint{font-size:12px;max-width:220px;line-height:1.5}.fb-preview-card{max-width:760px;margin:0 auto;background:var(--md-sys-color-surface-container-lowest);border-radius:var(--r-lg);padding:32px;box-shadow:var(--elev-1)}.fb-preview-card__chip{display:inline-flex;align-items:center;gap:6px;padding:2px 10px;height:22px;border-radius:var(--r-pill);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);font-size:10px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;margin-bottom:var(--gap-3)}.fb-preview-card__title{font-size:20px;font-weight:500;margin:0 0 var(--gap-4);color:var(--md-sys-color-on-surface)}.fb-preview-card__footer{display:flex;justify-content:flex-end;gap:var(--gap-2);margin-top:var(--gap-4);padding-top:var(--gap-4);border-top:1px solid var(--md-sys-color-outline-variant)}.fb-icon-picker{display:grid;grid-template-columns:repeat(6,1fr);gap:4px;margin-top:4px}.fb-icon-picker .fb-icon-picker__btn{height:28px;border-radius:var(--r-xs);border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface-variant);display:inline-flex;align-items:center;justify-content:center;cursor:pointer}.fb-icon-picker .fb-icon-picker__btn .msi{font-size:16px}.fb-icon-picker .fb-icon-picker__btn.is-active{border-color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary)}.fb-icon-picker .fb-icon-picker__btn:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent)}.fb-color-swatches{display:flex;gap:var(--gap-2);margin-top:4px}.fb-color-swatches .fb-color-swatch{width:24px;height:24px;border-radius:50%;cursor:pointer;border:2px solid transparent}.fb-color-swatches .fb-color-swatch.is-active{border-color:var(--md-sys-color-on-surface)}.fb-color-swatches .fb-color-swatch.primary{background:var(--md-sys-color-primary)}.fb-color-swatches .fb-color-swatch.secondary{background:var(--md-sys-color-secondary)}.fb-color-swatches .fb-color-swatch.success{background:var(--md-sys-color-success)}.fb-color-swatches .fb-color-swatch.warning{background:var(--md-sys-color-warning)}.fb-color-swatches .fb-color-swatch.error{background:var(--md-sys-color-error)}.fb-children-list{display:flex;flex-direction:column;gap:4px}.fb-child-row{display:flex;align-items:center;gap:var(--gap-2);height:30px;padding:0 8px;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px}.fb-child-row .fb-child-row__icon{width:22px;height:22px;border-radius:var(--r-xs);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.fb-child-row .fb-child-row__icon .msi{font-size:14px}.fb-child-row .fb-child-row__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fb-child-row .fb-child-row__key{font-family:Roboto Mono,monospace;font-size:10px;color:var(--md-sys-color-on-surface-variant)}.fb-child-row:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 4%,transparent)}.fb-add-link{display:inline-flex;align-items:center;gap:4px;font-size:12px;color:var(--md-sys-color-primary);cursor:pointer;padding:4px 0;text-decoration:none}.fb-add-link .msi{font-size:14px}.fb-add-link:hover{text-decoration:underline}.fb-group__body--static{display:flex;flex-wrap:wrap;gap:var(--gap-2, 8px);cursor:pointer;min-height:48px}.fb-group__body--static .fb-item--static{pointer-events:none;position:relative}.fb-group__body--static .fb-item--static .fb-resize,.fb-group__body--static .fb-item--static .fb-actions,.fb-group__body--static .fb-item--static .fb-status-chip{display:none!important}.fb-canvas__header--group .fb-groupedit__crumb{display:flex;align-items:center;gap:6px;font-weight:600}.fb-canvas__header--group .fb-groupedit__icon .msi{font-size:18px;color:var(--md-sys-color-primary)}.fb-canvas__header--group .fb-groupedit__hint{font-weight:400;font-size:12px;color:var(--md-sys-color-on-surface-variant, #6b6b6b);padding:1px 8px;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent)}\n"] }]
6518
6428
  }], ctorParameters: () => [], propDecorators: { popupViewJSON: [{ type: i0.ViewChild, args: ['popupViewJSON', { isSignal: true }] }], popupConfigureVariables: [{ type: i0.ViewChild, args: ['popupConfigureVariables', { isSignal: true }] }], configureValidation: [{ type: i0.ViewChild, args: [i0.forwardRef(() => ConfigureValidationComponent), { isSignal: true }] }], formRender: [{ type: i0.ViewChild, args: [i0.forwardRef(() => SdFormRender), { isSignal: true }] }], formGeneric: [{ type: i0.Input, args: [{ isSignal: true, alias: "formGeneric", required: false }] }] } });
6519
6429
 
6520
6430
  /* eslint-disable @angular-eslint/no-input-rename */
6521
6431
  /* eslint-disable @typescript-eslint/no-explicit-any */
6522
6432
  // Template là các mẫu do Portal định nghĩa sẵn (key, label ....) để người dùng chọn nhanh
6523
6433
  // Khi thực hiện sao chép 1 template chúng ta sẽ CLONE để tránh ảnh hưởng template gốc
6524
- class SdFeelExpression extends SdBaseSecureComponent {
6434
+ class SdFeelExpression {
6525
6435
  ref;
6526
6436
  expressionFeelPipe;
6527
6437
  formGenericService;
@@ -6555,7 +6465,6 @@ class SdFeelExpression extends SdBaseSecureComponent {
6555
6465
  modelChange = new EventEmitter();
6556
6466
  sdChange = new EventEmitter();
6557
6467
  constructor(ref, expressionFeelPipe, formGenericService) {
6558
- super();
6559
6468
  this.ref = ref;
6560
6469
  this.expressionFeelPipe = expressionFeelPipe;
6561
6470
  this.formGenericService = formGenericService;
@@ -6681,10 +6590,10 @@ class SdFeelExpression extends SdBaseSecureComponent {
6681
6590
  }
6682
6591
  return attributes;
6683
6592
  };
6684
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdFeelExpression, deps: [{ token: i0.ChangeDetectorRef }, { token: ExpressionFeelPipe }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
6685
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: SdFeelExpression, isStandalone: true, selector: "sd-feel-expression", inputs: { components: "components", _expression: ["expression", "_expression"], _model: ["model", "_model"] }, outputs: { expressionChange: "expressionChange", modelChange: "modelChange", sdChange: "sdChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], usesInheritance: true, ngImport: i0, template: "<a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{model || '--'}}</a>\n@if (expression) {\n<sd-modal [title]=\"'core.component.form-builder.set-expression' | translate\">\n <div class=\"c-builder\">\n <div class=\"d-flex justify-content-end\">\n <sd-button prefixIcon=\"calculate\" class=\"mr-4\" [title]=\"'core.component.form-builder.condition-group' | translate\" color=\"primary\" (click)=\"addCombinator(expression.conditions)\"></sd-button>\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.condition' | translate\" color=\"primary\" (click)=\"addCondition(expression.conditions)\" type=\"fill\"></sd-button>\n </div>\n <!-- C\u1EA5p 1 -->\n @for (conditionLv1 of expression.conditions; track conditionLv1.key; let idxLv1 = $index) {\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px;\">\n <div class=\"c-condition\">\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\n @if (idxLv1 === 0) {\n <div class=\"c-where\">WHERE</div>\n }\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\n @if (idxLv1 === 1) {\n <div class=\"c-select\">\n <sd-select\n size=\"sm\"\n [(model)]=\"expression.combinator\"\n [items]=\"[\n { value: '&&', display: 'AND' },\n { value: '||', display: 'OR' }\n ]\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError=\"\"></sd-select>\n </div>\n }\n </div>\n @if (conditionLv1.type === 'condition') {\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"width: 200px;\" [(model)]=\"conditionLv1.field\" [items]=\"attributes\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\n @let fieldAttribute = attribute[conditionLv1.field!];\n <sd-select size=\"sm\" [form]=\"form\" style=\"width: 100px;\" [(model)]=\"conditionLv1.operator\" [items]=\"attributeOperators[fieldAttribute?.type || 'string']\" valueField=\"value\" displayField=\"display\" [disabled]=\"!fieldAttribute?.type\" required hideInlineError></sd-select>\n @if(!!fieldAttribute?.type && conditionLv1.operator && conditionLv1.operator !== 'NULL' && conditionLv1.operator !== 'NOT_NULL') {\n @if(fieldAttribute.type === 'string') {\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input>\n } @else if(fieldAttribute.type === 'number') {\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input-number>\n } @else if(fieldAttribute.type === 'boolean') {\n <sd-select size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" [items]=\"[{value: true, display: fieldAttribute.displayOnTrue}, {value: false, display: fieldAttribute.displayOnFalse}]\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-select>\n }@else if(fieldAttribute.type === 'values') {\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" [items]=\"fieldAttribute.values\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\n }\n }\n <sd-button\n class=\"ml-auto\"\n prefixIcon=\"delete\"\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\n \n } @else if (conditionLv1.type === 'combinator') {\n <div class=\"c-builder\">\n <div class=\"d-flex justify-content-end\">\n <sd-button\n class=\"mr-4\"\n prefixIcon=\"delete\"\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.condition' | translate\" size=\"sm\" color=\"primary\" (click)=\"addCondition(conditionLv1.conditions)\" type=\"fill\"></sd-button>\n </div>\n <!-- C\u1EA5p 2 -->\n @for (conditionLv2 of conditionLv1.conditions; track conditionLv2.key; let idxLv2 = $index) {\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px;\">\n <div class=\"c-condition\">\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\n @if (idxLv2 === 0) {\n <div class=\"c-where\">WHERE</div>\n }\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\n @if (idxLv2 === 1) {\n <div class=\"c-select\">\n <sd-select\n size=\"sm\"\n [(model)]=\"conditionLv1.combinator\"\n [items]=\"[\n { value: '&&', display: 'AND' },\n { value: '||', display: 'OR' }\n ]\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError=\"\"></sd-select>\n </div>\n }\n </div>\n @if (conditionLv2.type === 'condition') {\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"width: 200px;\" [(model)]=\"conditionLv2.field\" [items]=\"attributes\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\n @let fieldAttribute = attribute[conditionLv2.field!];\n <sd-select size=\"sm\" [form]=\"form\" style=\"width: 100px;\" [(model)]=\"conditionLv2.operator\" [items]=\"attributeOperators[fieldAttribute?.type || 'string']\" valueField=\"value\" displayField=\"display\" [disabled]=\"!fieldAttribute?.type\" required hideInlineError></sd-select>\n @if(!!fieldAttribute?.type && conditionLv2.operator && conditionLv2.operator !== 'NULL' && conditionLv2.operator !== 'NOT_NULL') {\n @if(fieldAttribute.type === 'string') {\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" required hideInlineError></sd-input>\n } @else if(fieldAttribute.type === 'number') {\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" required hideInlineError></sd-input-number>\n } @else if(fieldAttribute.type === 'boolean') {\n <sd-select size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" [items]=\"[{value: true, display: fieldAttribute.displayOnTrue}, {value: false, display: fieldAttribute.displayOnFalse}]\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-select>\n }@else if(fieldAttribute.type === 'values') {\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" [items]=\"fieldAttribute.values\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\n }\n }\n <sd-button\n class=\"ml-auto\"\n prefixIcon=\"delete\"\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"remove(conditionLv1.conditions, idxLv1)\"></sd-button>\n \n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\n </ng-container>\n</sd-modal>\n}", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect$1, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "bare", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6593
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SdFeelExpression, deps: [{ token: i0.ChangeDetectorRef }, { token: ExpressionFeelPipe }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
6594
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: SdFeelExpression, isStandalone: true, selector: "sd-feel-expression", inputs: { components: "components", _expression: ["expression", "_expression"], _model: ["model", "_model"] }, outputs: { expressionChange: "expressionChange", modelChange: "modelChange", sdChange: "sdChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{model || '--'}}</a>\n@if (expression) {\n<sd-modal [title]=\"'core.component.form-builder.set-expression' | translate\">\n <div class=\"c-builder\">\n <div class=\"d-flex justify-content-end\">\n <sd-button prefixIcon=\"calculate\" class=\"mr-4\" [title]=\"'core.component.form-builder.condition-group' | translate\" color=\"primary\" (click)=\"addCombinator(expression.conditions)\"></sd-button>\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.condition' | translate\" color=\"primary\" (click)=\"addCondition(expression.conditions)\" type=\"fill\"></sd-button>\n </div>\n <!-- C\u1EA5p 1 -->\n @for (conditionLv1 of expression.conditions; track conditionLv1.key; let idxLv1 = $index) {\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px;\">\n <div class=\"c-condition\">\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\n @if (idxLv1 === 0) {\n <div class=\"c-where\">WHERE</div>\n }\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\n @if (idxLv1 === 1) {\n <div class=\"c-select\">\n <sd-select\n size=\"sm\"\n [(model)]=\"expression.combinator\"\n [items]=\"[\n { value: '&&', display: 'AND' },\n { value: '||', display: 'OR' }\n ]\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError=\"\"></sd-select>\n </div>\n }\n </div>\n @if (conditionLv1.type === 'condition') {\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"width: 200px;\" [(model)]=\"conditionLv1.field\" [items]=\"attributes\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\n @let fieldAttribute = attribute[conditionLv1.field!];\n <sd-select size=\"sm\" [form]=\"form\" style=\"width: 100px;\" [(model)]=\"conditionLv1.operator\" [items]=\"attributeOperators[fieldAttribute?.type || 'string']\" valueField=\"value\" displayField=\"display\" [disabled]=\"!fieldAttribute?.type\" required hideInlineError></sd-select>\n @if(!!fieldAttribute?.type && conditionLv1.operator && conditionLv1.operator !== 'NULL' && conditionLv1.operator !== 'NOT_NULL') {\n @if(fieldAttribute.type === 'string') {\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input>\n } @else if(fieldAttribute.type === 'number') {\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input-number>\n } @else if(fieldAttribute.type === 'boolean') {\n <sd-select size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" [items]=\"[{value: true, display: fieldAttribute.displayOnTrue}, {value: false, display: fieldAttribute.displayOnFalse}]\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-select>\n }@else if(fieldAttribute.type === 'values') {\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" [items]=\"fieldAttribute.values\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\n }\n }\n <sd-button\n class=\"ml-auto\"\n prefixIcon=\"delete\"\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\n \n } @else if (conditionLv1.type === 'combinator') {\n <div class=\"c-builder\">\n <div class=\"d-flex justify-content-end\">\n <sd-button\n class=\"mr-4\"\n prefixIcon=\"delete\"\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.condition' | translate\" size=\"sm\" color=\"primary\" (click)=\"addCondition(conditionLv1.conditions)\" type=\"fill\"></sd-button>\n </div>\n <!-- C\u1EA5p 2 -->\n @for (conditionLv2 of conditionLv1.conditions; track conditionLv2.key; let idxLv2 = $index) {\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px;\">\n <div class=\"c-condition\">\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\n @if (idxLv2 === 0) {\n <div class=\"c-where\">WHERE</div>\n }\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\n @if (idxLv2 === 1) {\n <div class=\"c-select\">\n <sd-select\n size=\"sm\"\n [(model)]=\"conditionLv1.combinator\"\n [items]=\"[\n { value: '&&', display: 'AND' },\n { value: '||', display: 'OR' }\n ]\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError=\"\"></sd-select>\n </div>\n }\n </div>\n @if (conditionLv2.type === 'condition') {\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"width: 200px;\" [(model)]=\"conditionLv2.field\" [items]=\"attributes\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\n @let fieldAttribute = attribute[conditionLv2.field!];\n <sd-select size=\"sm\" [form]=\"form\" style=\"width: 100px;\" [(model)]=\"conditionLv2.operator\" [items]=\"attributeOperators[fieldAttribute?.type || 'string']\" valueField=\"value\" displayField=\"display\" [disabled]=\"!fieldAttribute?.type\" required hideInlineError></sd-select>\n @if(!!fieldAttribute?.type && conditionLv2.operator && conditionLv2.operator !== 'NULL' && conditionLv2.operator !== 'NOT_NULL') {\n @if(fieldAttribute.type === 'string') {\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" required hideInlineError></sd-input>\n } @else if(fieldAttribute.type === 'number') {\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" required hideInlineError></sd-input-number>\n } @else if(fieldAttribute.type === 'boolean') {\n <sd-select size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" [items]=\"[{value: true, display: fieldAttribute.displayOnTrue}, {value: false, display: fieldAttribute.displayOnFalse}]\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-select>\n }@else if(fieldAttribute.type === 'values') {\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" [items]=\"fieldAttribute.values\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\n }\n }\n <sd-button\n class=\"ml-auto\"\n prefixIcon=\"delete\"\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"remove(conditionLv1.conditions, idxLv1)\"></sd-button>\n \n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\n </ng-container>\n</sd-modal>\n}", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect$1, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "clearable", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "clearable", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6686
6595
  }
6687
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdFeelExpression, decorators: [{
6596
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SdFeelExpression, decorators: [{
6688
6597
  type: Component,
6689
6598
  args: [{ selector: 'sd-feel-expression', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdInput$1, SdInputNumber, SdSelect$1, SdAutocomplete$1, SdButton, SdSelect$1, SdModal, TranslatePipe], template: "<a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{model || '--'}}</a>\n@if (expression) {\n<sd-modal [title]=\"'core.component.form-builder.set-expression' | translate\">\n <div class=\"c-builder\">\n <div class=\"d-flex justify-content-end\">\n <sd-button prefixIcon=\"calculate\" class=\"mr-4\" [title]=\"'core.component.form-builder.condition-group' | translate\" color=\"primary\" (click)=\"addCombinator(expression.conditions)\"></sd-button>\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.condition' | translate\" color=\"primary\" (click)=\"addCondition(expression.conditions)\" type=\"fill\"></sd-button>\n </div>\n <!-- C\u1EA5p 1 -->\n @for (conditionLv1 of expression.conditions; track conditionLv1.key; let idxLv1 = $index) {\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px;\">\n <div class=\"c-condition\">\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\n @if (idxLv1 === 0) {\n <div class=\"c-where\">WHERE</div>\n }\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\n @if (idxLv1 === 1) {\n <div class=\"c-select\">\n <sd-select\n size=\"sm\"\n [(model)]=\"expression.combinator\"\n [items]=\"[\n { value: '&&', display: 'AND' },\n { value: '||', display: 'OR' }\n ]\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError=\"\"></sd-select>\n </div>\n }\n </div>\n @if (conditionLv1.type === 'condition') {\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"width: 200px;\" [(model)]=\"conditionLv1.field\" [items]=\"attributes\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\n @let fieldAttribute = attribute[conditionLv1.field!];\n <sd-select size=\"sm\" [form]=\"form\" style=\"width: 100px;\" [(model)]=\"conditionLv1.operator\" [items]=\"attributeOperators[fieldAttribute?.type || 'string']\" valueField=\"value\" displayField=\"display\" [disabled]=\"!fieldAttribute?.type\" required hideInlineError></sd-select>\n @if(!!fieldAttribute?.type && conditionLv1.operator && conditionLv1.operator !== 'NULL' && conditionLv1.operator !== 'NOT_NULL') {\n @if(fieldAttribute.type === 'string') {\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input>\n } @else if(fieldAttribute.type === 'number') {\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input-number>\n } @else if(fieldAttribute.type === 'boolean') {\n <sd-select size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" [items]=\"[{value: true, display: fieldAttribute.displayOnTrue}, {value: false, display: fieldAttribute.displayOnFalse}]\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-select>\n }@else if(fieldAttribute.type === 'values') {\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" [items]=\"fieldAttribute.values\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\n }\n }\n <sd-button\n class=\"ml-auto\"\n prefixIcon=\"delete\"\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\n \n } @else if (conditionLv1.type === 'combinator') {\n <div class=\"c-builder\">\n <div class=\"d-flex justify-content-end\">\n <sd-button\n class=\"mr-4\"\n prefixIcon=\"delete\"\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.condition' | translate\" size=\"sm\" color=\"primary\" (click)=\"addCondition(conditionLv1.conditions)\" type=\"fill\"></sd-button>\n </div>\n <!-- C\u1EA5p 2 -->\n @for (conditionLv2 of conditionLv1.conditions; track conditionLv2.key; let idxLv2 = $index) {\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px;\">\n <div class=\"c-condition\">\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\n @if (idxLv2 === 0) {\n <div class=\"c-where\">WHERE</div>\n }\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\n @if (idxLv2 === 1) {\n <div class=\"c-select\">\n <sd-select\n size=\"sm\"\n [(model)]=\"conditionLv1.combinator\"\n [items]=\"[\n { value: '&&', display: 'AND' },\n { value: '||', display: 'OR' }\n ]\"\n valueField=\"value\"\n displayField=\"display\"\n required\n hideInlineError=\"\"></sd-select>\n </div>\n }\n </div>\n @if (conditionLv2.type === 'condition') {\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"width: 200px;\" [(model)]=\"conditionLv2.field\" [items]=\"attributes\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\n @let fieldAttribute = attribute[conditionLv2.field!];\n <sd-select size=\"sm\" [form]=\"form\" style=\"width: 100px;\" [(model)]=\"conditionLv2.operator\" [items]=\"attributeOperators[fieldAttribute?.type || 'string']\" valueField=\"value\" displayField=\"display\" [disabled]=\"!fieldAttribute?.type\" required hideInlineError></sd-select>\n @if(!!fieldAttribute?.type && conditionLv2.operator && conditionLv2.operator !== 'NULL' && conditionLv2.operator !== 'NOT_NULL') {\n @if(fieldAttribute.type === 'string') {\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" required hideInlineError></sd-input>\n } @else if(fieldAttribute.type === 'number') {\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" required hideInlineError></sd-input-number>\n } @else if(fieldAttribute.type === 'boolean') {\n <sd-select size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" [items]=\"[{value: true, display: fieldAttribute.displayOnTrue}, {value: false, display: fieldAttribute.displayOnFalse}]\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-select>\n }@else if(fieldAttribute.type === 'values') {\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" [items]=\"fieldAttribute.values\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\n }\n }\n <sd-button\n class=\"ml-auto\"\n prefixIcon=\"delete\"\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\n (click)=\"remove(conditionLv1.conditions, idxLv1)\"></sd-button>\n \n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n <ng-container sdFooter>\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\n </ng-container>\n</sd-modal>\n}", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"] }]
6690
6599
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: ExpressionFeelPipe }, { type: FormGenericService }], propDecorators: { modal: [{