@qbs-origin/origin-form 0.8.11 → 0.8.12

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 (26) hide show
  1. package/esm2022/lib/form-css.helper.mjs +122 -28
  2. package/esm2022/lib/formly/custom-section-separator.component.mjs +11 -3
  3. package/esm2022/lib/formly/form-section-separator.component.mjs +34 -11
  4. package/esm2022/lib/formly/formly-dictionary-dropdown-tree/formly-dictionary-dropdown-tree.component.mjs +23 -8
  5. package/esm2022/lib/formly/formly-radio/formly-radio-component.mjs +3 -3
  6. package/esm2022/lib/formly/formly-row-spacer.mjs +12 -0
  7. package/esm2022/lib/formly/formly-row-wrapper.mjs +32 -0
  8. package/esm2022/lib/formly/formly-scan-id/formly-scan-id.component.mjs +21 -26
  9. package/esm2022/lib/models/flux.model.mjs +1 -1
  10. package/esm2022/lib/models/forms.model.mjs +77 -25
  11. package/esm2022/lib/origin-form.component.mjs +170 -55
  12. package/esm2022/lib/origin-form.module.mjs +11 -1
  13. package/esm2022/lib/services/applicationData.service.mjs +1 -1
  14. package/fesm2022/qbs-origin-origin-form.mjs +497 -151
  15. package/fesm2022/qbs-origin-origin-form.mjs.map +1 -1
  16. package/lib/form-css.helper.d.ts +7 -0
  17. package/lib/formly/form-section-separator.component.d.ts +2 -2
  18. package/lib/formly/formly-dictionary-dropdown-tree/formly-dictionary-dropdown-tree.component.d.ts +2 -1
  19. package/lib/formly/formly-row-spacer.d.ts +6 -0
  20. package/lib/formly/formly-row-wrapper.d.ts +6 -0
  21. package/lib/models/flux.model.d.ts +4 -0
  22. package/lib/models/forms.model.d.ts +22 -6
  23. package/lib/origin-form.component.d.ts +6 -1
  24. package/lib/origin-form.module.d.ts +64 -62
  25. package/lib/services/applicationData.service.d.ts +1 -1
  26. package/package.json +1 -1
@@ -95,7 +95,11 @@ import * as i3$2 from '@angular/platform-browser';
95
95
  class CustomSectionComponent extends FieldType {
96
96
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CustomSectionComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
97
97
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: CustomSectionComponent, selector: "formly-custom-section", usesInheritance: true, ngImport: i0, template: `
98
- <div class="custom-section">
98
+ <div
99
+ class="custom-section"
100
+ [style.paddingTop]="props['sectionMarginTop']"
101
+ [style.paddingBottom]="props['sectionMarginBottom']"
102
+ >
99
103
  <ng-container *ngFor="let field of field.fieldGroup">
100
104
  <formly-field
101
105
  [field]="field"
@@ -108,7 +112,11 @@ class CustomSectionComponent extends FieldType {
108
112
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CustomSectionComponent, decorators: [{
109
113
  type: Component,
110
114
  args: [{ selector: 'formly-custom-section', template: `
111
- <div class="custom-section">
115
+ <div
116
+ class="custom-section"
117
+ [style.paddingTop]="props['sectionMarginTop']"
118
+ [style.paddingBottom]="props['sectionMarginBottom']"
119
+ >
112
120
  <ng-container *ngFor="let field of field.fieldGroup">
113
121
  <formly-field
114
122
  [field]="field"
@@ -120,35 +128,58 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
120
128
  }] });
121
129
 
122
130
  class FormSectionSeparatorComponent extends FieldType {
131
+ constructor() {
132
+ super(...arguments);
133
+ this.heading2Style = {};
134
+ this.separatorStyle = {};
135
+ }
123
136
  ngOnInit() {
124
137
  if (this.props['design']) {
125
- this.heading2Style = this.props['design']['.font-heading-2'];
126
- const separatorStyle = this.props['design']['.separator-section'];
127
- if (separatorStyle && separatorStyle['height'] !== '0px') {
128
- this.separatorStyle = separatorStyle;
138
+ // Use the corrected CSS class name for Heading 2
139
+ const heading2Design = this.props['design']['.font-heading-2'];
140
+ if (heading2Design) {
141
+ this.heading2Style = heading2Design;
142
+ }
143
+ // Apply separator section styles
144
+ const separatorDesign = this.props['design']['.separator-section'];
145
+ if (separatorDesign) {
146
+ this.separatorStyle = {
147
+ ...separatorDesign,
148
+ display: separatorDesign.height && separatorDesign.height !== '0px'
149
+ ? 'block'
150
+ : 'none',
151
+ };
129
152
  }
130
153
  }
131
154
  }
132
155
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FormSectionSeparatorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
133
156
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: FormSectionSeparatorComponent, selector: "form-section-separator", usesInheritance: true, ngImport: i0, template: `
134
- <div class="separator" style="margin: 2% ;">
157
+ <div class="separator form-section-title" [style.paddingTop]="props['sectionMarginTop'] || '2%'">
135
158
  <h2 *ngIf="to && to['title']" [ngStyle]="heading2Style">
136
159
  {{ to['title'] }}
137
160
  </h2>
138
- <hr *ngIf="to && to['showSeparator']" [ngStyle]="separatorStyle" />
161
+ <hr
162
+ *ngIf="to && to['showSeparator']"
163
+ [ngStyle]="separatorStyle"
164
+ class="section-separator"
165
+ />
139
166
  </div>
140
- `, isInline: true, styles: [".separator{margin:2% 0}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] }); }
167
+ `, isInline: true, styles: [".separator{padding-bottom:2%}.section-separator{border:none;margin:10px 0}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] }); }
141
168
  }
142
169
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FormSectionSeparatorComponent, decorators: [{
143
170
  type: Component,
144
171
  args: [{ selector: 'form-section-separator', template: `
145
- <div class="separator" style="margin: 2% ;">
172
+ <div class="separator form-section-title" [style.paddingTop]="props['sectionMarginTop'] || '2%'">
146
173
  <h2 *ngIf="to && to['title']" [ngStyle]="heading2Style">
147
174
  {{ to['title'] }}
148
175
  </h2>
149
- <hr *ngIf="to && to['showSeparator']" [ngStyle]="separatorStyle" />
176
+ <hr
177
+ *ngIf="to && to['showSeparator']"
178
+ [ngStyle]="separatorStyle"
179
+ class="section-separator"
180
+ />
150
181
  </div>
151
- `, styles: [".separator{margin:2% 0}\n"] }]
182
+ `, styles: [".separator{padding-bottom:2%}.section-separator{border:none;margin:10px 0}\n"] }]
152
183
  }] });
153
184
 
154
185
  class Partner {
@@ -2756,7 +2787,7 @@ class AppDataStep {
2756
2787
  }
2757
2788
  }
2758
2789
  class AppDataFill {
2759
- constructor(appDataId = '', configurationId = '', currentStepId = '', statusId = '', language = '', flux = [], offerId = '', isSubmitted = false, parentAppDataUuid = '') {
2790
+ constructor(appDataId = '', configurationId = '', currentStepId = '', statusId = '', language = '', flux = [], offerId = '', isSubmitted = false) {
2760
2791
  this.metadata = {
2761
2792
  appDataId: appDataId || '',
2762
2793
  configurationId: configurationId || '',
@@ -2765,7 +2796,6 @@ class AppDataFill {
2765
2796
  language: language || '',
2766
2797
  offerId: offerId || '',
2767
2798
  isSubmitted: isSubmitted || false,
2768
- parentAppDataUuid: parentAppDataUuid || ''
2769
2799
  };
2770
2800
  this.flux = flux || [];
2771
2801
  }
@@ -2778,7 +2808,6 @@ class AppData {
2778
2808
  this.initFlowValues = data.initFlowValues;
2779
2809
  this.withNextStep = data.withNextStep;
2780
2810
  this.blockPreviousStep = data.blockPreviousStep;
2781
- this.parentAppDataUuid = data.parentAppDataUuid;
2782
2811
  if (!data.env) {
2783
2812
  this.env = 'Config';
2784
2813
  }
@@ -2818,8 +2847,10 @@ class FormModelExtenxions {
2818
2847
  const out = [];
2819
2848
  const walk = (node, pathParts) => {
2820
2849
  if (node === null || node === undefined) {
2821
- if (pathParts.length > 0)
2850
+ // Leaf
2851
+ if (pathParts.length > 0) {
2822
2852
  out.push(this.buildInitFlowField(pathParts));
2853
+ }
2823
2854
  return;
2824
2855
  }
2825
2856
  if (Array.isArray(node)) {
@@ -2830,8 +2861,10 @@ class FormModelExtenxions {
2830
2861
  Object.keys(node).forEach((key) => walk(node[key], [...pathParts, key]));
2831
2862
  return;
2832
2863
  }
2833
- if (pathParts.length > 0)
2864
+ // Primitive leaf
2865
+ if (pathParts.length > 0) {
2834
2866
  out.push(this.buildInitFlowField(pathParts));
2867
+ }
2835
2868
  };
2836
2869
  walk(parsed, []);
2837
2870
  for (const f of out) {
@@ -2846,7 +2879,7 @@ class FormModelExtenxions {
2846
2879
  return {
2847
2880
  fieldName: `initFlowValues_${underscorePath}`,
2848
2881
  fieldType: StepControlType.Metadata,
2849
- id: `initFlowValues_${underscorePath}`
2882
+ id: `initFlowValues_${underscorePath}`,
2850
2883
  };
2851
2884
  }
2852
2885
  fluxItems(untilStepIdentifier = undefined) {
@@ -2856,7 +2889,7 @@ class FormModelExtenxions {
2856
2889
  items.push({
2857
2890
  fieldName: fieldValue,
2858
2891
  fieldType: StepControlType.Metadata,
2859
- id: `metadata.${fieldValue}`
2892
+ id: `metadata.${fieldValue}`,
2860
2893
  });
2861
2894
  });
2862
2895
  }
@@ -2884,13 +2917,13 @@ class FormModelExtenxions {
2884
2917
  StepControlType.Buttons,
2885
2918
  StepControlType.NewRow,
2886
2919
  StepControlType.FluxInfo,
2887
- StepControlType.Paragraph
2920
+ StepControlType.Paragraph,
2888
2921
  ].includes(control.type) == false) {
2889
2922
  items.push({
2890
2923
  fieldName: `${step.name} -> ${section.title} -> ${control.title}`,
2891
2924
  fieldType: control.type,
2892
2925
  manulInputControlType: control.specificControlData?.type,
2893
- id: control.identifier
2926
+ id: control.identifier,
2894
2927
  });
2895
2928
  }
2896
2929
  });
@@ -2910,7 +2943,7 @@ class FormModelExtenxions {
2910
2943
  fieldType: step.type,
2911
2944
  id: document?.documentId
2912
2945
  ? `upload.${document.documentId}`
2913
- : `${step.type}.${step.name}`
2946
+ : `${step.type}.${step.name}`,
2914
2947
  });
2915
2948
  });
2916
2949
  }
@@ -2922,7 +2955,7 @@ class FormModelExtenxions {
2922
2955
  fieldType: step.type,
2923
2956
  id: document?.id
2924
2957
  ? `generate.${document.id}`
2925
- : `${step.type}.${step.name}`
2958
+ : `${step.type}.${step.name}`,
2926
2959
  });
2927
2960
  });
2928
2961
  }
@@ -2934,7 +2967,7 @@ class FormModelExtenxions {
2934
2967
  fieldType: step.type,
2935
2968
  id: document?.id
2936
2969
  ? `sign.${document.id}`
2937
- : `${step.type}.${step.name}`
2970
+ : `${step.type}.${step.name}`,
2938
2971
  });
2939
2972
  });
2940
2973
  }
@@ -2945,7 +2978,7 @@ class FormModelExtenxions {
2945
2978
  fieldType: step.type,
2946
2979
  id: document?.id
2947
2980
  ? `system.${document.id}`
2948
- : `${step.type}.${step.name}`
2981
+ : `${step.type}.${step.name}`,
2949
2982
  });
2950
2983
  });
2951
2984
  }
@@ -2953,19 +2986,55 @@ class FormModelExtenxions {
2953
2986
  });
2954
2987
  return items;
2955
2988
  }
2989
+ /**
2990
+ * Returns inherited parent fields as MethodField items.
2991
+ * Reusable across all system step settings components.
2992
+ */
2993
+ static getInheritedMethodFields(formModel) {
2994
+ const result = [];
2995
+ const inheritedFields = formModel.parentChildConfig?.inheritedFields;
2996
+ if (inheritedFields?.length) {
2997
+ inheritedFields.forEach((field) => {
2998
+ result.push({
2999
+ fieldName: `Inherited -> ${field.fieldName}`,
3000
+ fieldType: 'inherited',
3001
+ id: field.id,
3002
+ });
3003
+ });
3004
+ }
3005
+ return result;
3006
+ }
3007
+ /**
3008
+ * Returns flux items + inherited parent fields (no API methods).
3009
+ * Use this in system step settings that need parent field references.
3010
+ */
3011
+ fluxItemsWithInherited(untilStepIdentifier = undefined) {
3012
+ const items = this.fluxItems(untilStepIdentifier);
3013
+ items.push(...FormModelExtenxions.getInheritedMethodFields(this.formModel));
3014
+ return items;
3015
+ }
2956
3016
  fluxItemsWithGetApiMethods(excludedMethodId = '') {
2957
- let items = this.fluxItems();
3017
+ let items = this.fluxItemsWithInherited();
2958
3018
  this.formModel.api.getItems.forEach((apiMethod) => {
2959
3019
  if (apiMethod.id !== excludedMethodId) {
2960
3020
  apiMethod.fields?.forEach((f) => {
2961
3021
  items.push({
2962
3022
  fieldName: `${apiMethod.method} -> ${f.fieldName}`,
2963
3023
  fieldType: StepControlType.ApiMethodField,
2964
- id: f.id
3024
+ id: f.id,
2965
3025
  });
2966
3026
  });
2967
3027
  }
2968
3028
  });
3029
+ this.formModel.api.validationItems.forEach((validateApiMethod) => {
3030
+ validateApiMethod.fields?.forEach((f) => {
3031
+ items.push({
3032
+ fieldName: `${validateApiMethod.method} -> ${f.fieldName}`,
3033
+ fieldType: StepControlType.ApiMethodField,
3034
+ id: f.id,
3035
+ });
3036
+ });
3037
+ });
2969
3038
  return items;
2970
3039
  }
2971
3040
  offerMethodsItems() {
@@ -2980,7 +3049,7 @@ class FormModelExtenxions {
2980
3049
  const allApiItems = [
2981
3050
  ...this.formModel.api.getItems,
2982
3051
  ...this.formModel.api.validationItems,
2983
- ...this.formModel.api.sendItems
3052
+ ...this.formModel.api.sendItems,
2984
3053
  ];
2985
3054
  offerMethodsIds.forEach((methodId) => {
2986
3055
  const apiMethod = allApiItems.find((item) => item.id === methodId);
@@ -2989,7 +3058,7 @@ class FormModelExtenxions {
2989
3058
  items.push({
2990
3059
  fieldName: `${apiMethod.method} -> ${f.fieldName}`,
2991
3060
  fieldType: FluxType.ViewOffer,
2992
- id: `api_${apiMethod.id} -> ${f.id}`
3061
+ id: `api_${apiMethod.id} -> ${f.id}`,
2993
3062
  });
2994
3063
  });
2995
3064
  }
@@ -3003,6 +3072,8 @@ class ApiItem {
3003
3072
  }
3004
3073
  class GetApiItem {
3005
3074
  }
3075
+ class ValidateApiItem {
3076
+ }
3006
3077
  class DesignModel {
3007
3078
  constructor(data) {
3008
3079
  this.fonts = [];
@@ -3119,12 +3190,16 @@ class ComponentConfig {
3119
3190
  this.border = data.border;
3120
3191
  this.borderRadius = data.borderRadius;
3121
3192
  this.labelStyle = data.labelStyle;
3193
+ this.valueStyle = data.valueStyle;
3122
3194
  this.textAlign = data.textAlign;
3123
3195
  this.color = data.color;
3124
3196
  this.weight = data.weight;
3125
3197
  this.startColor = data.startColor;
3126
3198
  this.endColor = data.endColor;
3127
3199
  this.height = data.height;
3200
+ this.textareaMaxHeight = data.textareaMaxHeight;
3201
+ this.marginTop = data.marginTop;
3202
+ this.marginBottom = data.marginBottom;
3128
3203
  }
3129
3204
  }
3130
3205
  }
@@ -3146,7 +3221,7 @@ const initialFormulareState = {
3146
3221
  showNameStep: false,
3147
3222
  showAllSteps: false,
3148
3223
  showProgressBar: false,
3149
- initFlowValues: ''
3224
+ initFlowValues: '',
3150
3225
  },
3151
3226
  design: {
3152
3227
  fonts: [],
@@ -3162,7 +3237,7 @@ const initialFormulareState = {
3162
3237
  marginLeft: '',
3163
3238
  marginRight: '',
3164
3239
  marginTop: '',
3165
- marginBottom: ''
3240
+ marginBottom: '',
3166
3241
  },
3167
3242
  flux: [],
3168
3243
  api: { getItems: [], validationItems: [], sendItems: [] },
@@ -3170,16 +3245,24 @@ const initialFormulareState = {
3170
3245
  documents: [],
3171
3246
  statuses: [],
3172
3247
  display: {
3173
- sections: []
3248
+ sections: [],
3174
3249
  },
3175
3250
  generatedCss: {},
3176
3251
  metadataFields: [],
3177
3252
  errors: {},
3178
3253
  applicationMappings: {
3179
3254
  applicationTypeId: 0,
3180
- columnMappings: []
3255
+ columnMappings: [],
3256
+ },
3257
+ parentChildConfig: {
3258
+ parentApplicationUuid: null,
3259
+ inheritedFields: [],
3260
+ notificationConfig: {
3261
+ enabled: false,
3262
+ titleTemplate: 'Status update: {statusName}',
3263
+ messageTemplate: 'Your application status has been updated to: {statusName}',
3264
+ },
3181
3265
  },
3182
- parentChildConfig: undefined
3183
3266
  },
3184
3267
  selectedTab: 'Date generale',
3185
3268
  canGetFromProd: false,
@@ -3187,7 +3270,7 @@ const initialFormulareState = {
3187
3270
  canPublishInProd: false,
3188
3271
  canPublishInTest: false,
3189
3272
  applicationUuid: '',
3190
- version: ''
3273
+ version: '',
3191
3274
  };
3192
3275
  class PartnerDictionaryMapping {
3193
3276
  }
@@ -3314,7 +3397,7 @@ class StatusModel {
3314
3397
  this.final = final;
3315
3398
  this.isActive = isActive;
3316
3399
  this.actions = actions;
3317
- this.childApplicationUuids = childApplicationUuids || [];
3400
+ this.childApplicationUuids = childApplicationUuids;
3318
3401
  this.sendNotifications = sendNotifications;
3319
3402
  }
3320
3403
  }
@@ -4857,7 +4940,6 @@ class FormlyDictionaryDropdownTreeComponent extends FieldType {
4857
4940
  this.cdRef = cdRef;
4858
4941
  this.formlyKeys = LabelKeys.formly;
4859
4942
  this.selectedValueText = '';
4860
- this.labelStyle = {};
4861
4943
  this.selectedValueIds = [];
4862
4944
  this.valuesIdsToShow = [];
4863
4945
  this.selectedRelatedDictionaries = [];
@@ -4905,9 +4987,7 @@ class FormlyDictionaryDropdownTreeComponent extends FieldType {
4905
4987
  }
4906
4988
  this.currentLanguageIso = this.props['currentLanguageIso'];
4907
4989
  this.currentLanguageId = this.props['currentLanguageId'];
4908
- if (this.props['design']) {
4909
- this.labelStyle = this.props['design']['.component-data-label'] || {};
4910
- }
4990
+ // Design styles are applied via generated CSS (same as Text Field)
4911
4991
  if (this.props['selectedValueIds'] &&
4912
4992
  Array.isArray(this.props['selectedValueIds'])) {
4913
4993
  this.selectedValueIds = this.props['selectedValueIds'];
@@ -5037,8 +5117,9 @@ class FormlyDictionaryDropdownTreeComponent extends FieldType {
5037
5117
  }
5038
5118
  this.onSelectedValueChanged(this.selectedValue);
5039
5119
  }
5120
+ this.filteredText = '';
5040
5121
  if (this.autoInput) {
5041
- this.autoInput.nativeElement.value = this.filteredText = '';
5122
+ this.autoInput.nativeElement.value = this.selectedValueText || '';
5042
5123
  }
5043
5124
  }
5044
5125
  }
@@ -5061,6 +5142,20 @@ class FormlyDictionaryDropdownTreeComponent extends FieldType {
5061
5142
  }
5062
5143
  }
5063
5144
  }
5145
+ onInputFocus() {
5146
+ // Clear the input so user can type to filter; open the dropdown
5147
+ if (this.autoInput) {
5148
+ this.autoInput.nativeElement.value = '';
5149
+ }
5150
+ this.filteredText = '';
5151
+ this.openAutocomplete();
5152
+ }
5153
+ onInputBlur() {
5154
+ // Restore the selected value text when leaving the field
5155
+ if (this.autoInput) {
5156
+ this.autoInput.nativeElement.value = this.selectedValueText || '';
5157
+ }
5158
+ }
5064
5159
  openAutocomplete() {
5065
5160
  if (this.autocompleteTrigger && !this.autocompleteTrigger.panelOpen) {
5066
5161
  this.autocompleteTrigger.openPanel();
@@ -5101,6 +5196,9 @@ class FormlyDictionaryDropdownTreeComponent extends FieldType {
5101
5196
  }
5102
5197
  }
5103
5198
  this.selectedValueText = this.getValueDisplayText(this.selectedValue);
5199
+ if (this.autoInput) {
5200
+ this.autoInput.nativeElement.value = this.selectedValueText;
5201
+ }
5104
5202
  }
5105
5203
  getValueDisplayText(value) {
5106
5204
  if (!value)
@@ -5116,11 +5214,11 @@ class FormlyDictionaryDropdownTreeComponent extends FieldType {
5116
5214
  return this.dictionaryLabels[dictionaryId] || '';
5117
5215
  }
5118
5216
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FormlyDictionaryDropdownTreeComponent, deps: [{ token: DictionaryService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
5119
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: FormlyDictionaryDropdownTreeComponent, selector: "formly-dictionary-dropdown-tree", inputs: { dictionaryId: "dictionaryId" }, outputs: { selectedValue: "selectedValue" }, viewQueries: [{ propertyName: "autocompleteTrigger", first: true, predicate: MatAutocompleteTrigger, descendants: true }, { propertyName: "autoInput", first: true, predicate: ["autoInput"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<form>\n <mat-label class=\"component-data-label m-l-2\" [ngStyle]=\"labelStyle\">\n {{ label }}</mat-label\n >\n <mat-form-field class=\"full-width\">\n <input\n type=\"text\"\n placeholder=\"{{ selectedValueText }}\"\n #autoInput\n aria-label=\"Text\"\n matInput\n [matAutocomplete]=\"auto\"\n (input)=\"filterChanged($event)\"\n (focus)=\"openAutocomplete()\"\n />\n <mat-icon matSuffix (click)=\"toggleAutocomplete($event)\"\n >keyboard_arrow_down</mat-icon\n >\n <mat-autocomplete\n #matAutocomplete=\"matAutocomplete\"\n #auto=\"matAutocomplete\"\n autoActiveFirstOption\n (optionSelected)=\"\n onSelectedDictionaryValuesChanged([$event.option.value])\n \"\n >\n <mat-option disabled>{{\n formlyKeys.selectAnItem | translate\n }}</mat-option>\n <app-dictionaries-tree\n [allowCheckItems]=\"allowMultipleSelection\"\n [drawReferenceDictionariesAsSeparateNode]=\"false\"\n [drawChildDictionariesAsSeparateNode]=\"false\"\n [drawRootNode]=\"false\"\n [filterText]=\"filteredText\"\n [allowSelectNonLeafNodes]=\"true\"\n [selectedValueIds]=\"selectedValueIds\"\n [languageId]=\"currentLanguageId\"\n [valuesIdsToShow]=\"valuesIdsToShow\"\n [selectedRelatedDictionaries]=\"selectedRelatedDictionaries\"\n [dictionaryLabels]=\"dictionaryLabels\"\n [preloadedDictionary]=\"preloadedDictionary\"\n [preloadedDictionaries]=\"preloadedDictionaries\"\n [usePreloadedData]=\"usePreloadedData\"\n (selectedDictionaryValuesChanged)=\"\n onSelectedDictionaryValuesChanged($event)\n \"\n >\n </app-dictionaries-tree>\n </mat-autocomplete>\n </mat-form-field>\n\n <formly-validation-message *ngIf=\"showError\" [field]=\"field\">\n </formly-validation-message>\n</form>\n", styles: ["formly-validation-message{color:red;font-size:12px}::ng-deep .mat-mdc-autocomplete-panel>app-dictionaries-tree>app-treeview>cdk-virtual-scroll-viewport{overflow:hidden}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i4$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i6$2.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i6$3.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i6$2.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "component", type: i6$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i4.ɵFormlyValidationMessage, selector: "formly-validation-message", inputs: ["field"] }, { kind: "component", type: DictionariesTreeComponent, selector: "app-dictionaries-tree", inputs: ["dictionaryId", "selectedValueIds", "allowCheckItems", "allowFilter", "drawReferenceDictionariesAsSeparateNode", "drawChildDictionariesAsSeparateNode", "drawRootNode", "filterText", "allowSelectNonLeafNodes", "languageId", "valuesIdsToShow", "hideParentArrow", "preloadedDictionary", "preloadedDictionaries", "usePreloadedData"], outputs: ["selectedDictionaryValuesChanged"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
5217
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: FormlyDictionaryDropdownTreeComponent, selector: "formly-dictionary-dropdown-tree", inputs: { dictionaryId: "dictionaryId" }, outputs: { selectedValue: "selectedValue" }, viewQueries: [{ propertyName: "autocompleteTrigger", first: true, predicate: MatAutocompleteTrigger, descendants: true }, { propertyName: "autoInput", first: true, predicate: ["autoInput"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<form>\n <mat-form-field class=\"full-width\">\n <mat-label class=\"component-dictionary-label\">{{ label }}</mat-label>\n <input\n type=\"text\"\n #autoInput\n aria-label=\"Text\"\n matInput\n [value]=\"selectedValueText || ''\"\n [matAutocomplete]=\"auto\"\n (input)=\"filterChanged($event)\"\n (focus)=\"onInputFocus()\"\n (blur)=\"onInputBlur()\"\n />\n <mat-icon matSuffix (click)=\"toggleAutocomplete($event)\"\n >keyboard_arrow_down</mat-icon\n >\n <mat-autocomplete\n #matAutocomplete=\"matAutocomplete\"\n #auto=\"matAutocomplete\"\n autoActiveFirstOption\n (optionSelected)=\"\n onSelectedDictionaryValuesChanged([$event.option.value])\n \"\n >\n <mat-option disabled>{{\n formlyKeys.selectAnItem | translate\n }}</mat-option>\n <app-dictionaries-tree\n [allowCheckItems]=\"allowMultipleSelection\"\n [drawReferenceDictionariesAsSeparateNode]=\"false\"\n [drawChildDictionariesAsSeparateNode]=\"false\"\n [drawRootNode]=\"false\"\n [filterText]=\"filteredText\"\n [allowSelectNonLeafNodes]=\"true\"\n [selectedValueIds]=\"selectedValueIds\"\n [languageId]=\"currentLanguageId\"\n [valuesIdsToShow]=\"valuesIdsToShow\"\n [selectedRelatedDictionaries]=\"selectedRelatedDictionaries\"\n [dictionaryLabels]=\"dictionaryLabels\"\n [preloadedDictionary]=\"preloadedDictionary\"\n [preloadedDictionaries]=\"preloadedDictionaries\"\n [usePreloadedData]=\"usePreloadedData\"\n (selectedDictionaryValuesChanged)=\"\n onSelectedDictionaryValuesChanged($event)\n \"\n >\n </app-dictionaries-tree>\n </mat-autocomplete>\n </mat-form-field>\n\n <formly-validation-message *ngIf=\"showError\" [field]=\"field\">\n </formly-validation-message>\n</form>\n", styles: ["formly-validation-message{color:red;font-size:12px}::ng-deep .mat-mdc-autocomplete-panel>app-dictionaries-tree>app-treeview>cdk-virtual-scroll-viewport{overflow:hidden}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i4$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i6$2.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i6$3.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i6$2.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "component", type: i6$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i4.ɵFormlyValidationMessage, selector: "formly-validation-message", inputs: ["field"] }, { kind: "component", type: DictionariesTreeComponent, selector: "app-dictionaries-tree", inputs: ["dictionaryId", "selectedValueIds", "allowCheckItems", "allowFilter", "drawReferenceDictionariesAsSeparateNode", "drawChildDictionariesAsSeparateNode", "drawRootNode", "filterText", "allowSelectNonLeafNodes", "languageId", "valuesIdsToShow", "hideParentArrow", "preloadedDictionary", "preloadedDictionaries", "usePreloadedData"], outputs: ["selectedDictionaryValuesChanged"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
5120
5218
  }
5121
5219
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FormlyDictionaryDropdownTreeComponent, decorators: [{
5122
5220
  type: Component,
5123
- args: [{ selector: 'formly-dictionary-dropdown-tree', template: "<form>\n <mat-label class=\"component-data-label m-l-2\" [ngStyle]=\"labelStyle\">\n {{ label }}</mat-label\n >\n <mat-form-field class=\"full-width\">\n <input\n type=\"text\"\n placeholder=\"{{ selectedValueText }}\"\n #autoInput\n aria-label=\"Text\"\n matInput\n [matAutocomplete]=\"auto\"\n (input)=\"filterChanged($event)\"\n (focus)=\"openAutocomplete()\"\n />\n <mat-icon matSuffix (click)=\"toggleAutocomplete($event)\"\n >keyboard_arrow_down</mat-icon\n >\n <mat-autocomplete\n #matAutocomplete=\"matAutocomplete\"\n #auto=\"matAutocomplete\"\n autoActiveFirstOption\n (optionSelected)=\"\n onSelectedDictionaryValuesChanged([$event.option.value])\n \"\n >\n <mat-option disabled>{{\n formlyKeys.selectAnItem | translate\n }}</mat-option>\n <app-dictionaries-tree\n [allowCheckItems]=\"allowMultipleSelection\"\n [drawReferenceDictionariesAsSeparateNode]=\"false\"\n [drawChildDictionariesAsSeparateNode]=\"false\"\n [drawRootNode]=\"false\"\n [filterText]=\"filteredText\"\n [allowSelectNonLeafNodes]=\"true\"\n [selectedValueIds]=\"selectedValueIds\"\n [languageId]=\"currentLanguageId\"\n [valuesIdsToShow]=\"valuesIdsToShow\"\n [selectedRelatedDictionaries]=\"selectedRelatedDictionaries\"\n [dictionaryLabels]=\"dictionaryLabels\"\n [preloadedDictionary]=\"preloadedDictionary\"\n [preloadedDictionaries]=\"preloadedDictionaries\"\n [usePreloadedData]=\"usePreloadedData\"\n (selectedDictionaryValuesChanged)=\"\n onSelectedDictionaryValuesChanged($event)\n \"\n >\n </app-dictionaries-tree>\n </mat-autocomplete>\n </mat-form-field>\n\n <formly-validation-message *ngIf=\"showError\" [field]=\"field\">\n </formly-validation-message>\n</form>\n", styles: ["formly-validation-message{color:red;font-size:12px}::ng-deep .mat-mdc-autocomplete-panel>app-dictionaries-tree>app-treeview>cdk-virtual-scroll-viewport{overflow:hidden}\n"] }]
5221
+ args: [{ selector: 'formly-dictionary-dropdown-tree', template: "<form>\n <mat-form-field class=\"full-width\">\n <mat-label class=\"component-dictionary-label\">{{ label }}</mat-label>\n <input\n type=\"text\"\n #autoInput\n aria-label=\"Text\"\n matInput\n [value]=\"selectedValueText || ''\"\n [matAutocomplete]=\"auto\"\n (input)=\"filterChanged($event)\"\n (focus)=\"onInputFocus()\"\n (blur)=\"onInputBlur()\"\n />\n <mat-icon matSuffix (click)=\"toggleAutocomplete($event)\"\n >keyboard_arrow_down</mat-icon\n >\n <mat-autocomplete\n #matAutocomplete=\"matAutocomplete\"\n #auto=\"matAutocomplete\"\n autoActiveFirstOption\n (optionSelected)=\"\n onSelectedDictionaryValuesChanged([$event.option.value])\n \"\n >\n <mat-option disabled>{{\n formlyKeys.selectAnItem | translate\n }}</mat-option>\n <app-dictionaries-tree\n [allowCheckItems]=\"allowMultipleSelection\"\n [drawReferenceDictionariesAsSeparateNode]=\"false\"\n [drawChildDictionariesAsSeparateNode]=\"false\"\n [drawRootNode]=\"false\"\n [filterText]=\"filteredText\"\n [allowSelectNonLeafNodes]=\"true\"\n [selectedValueIds]=\"selectedValueIds\"\n [languageId]=\"currentLanguageId\"\n [valuesIdsToShow]=\"valuesIdsToShow\"\n [selectedRelatedDictionaries]=\"selectedRelatedDictionaries\"\n [dictionaryLabels]=\"dictionaryLabels\"\n [preloadedDictionary]=\"preloadedDictionary\"\n [preloadedDictionaries]=\"preloadedDictionaries\"\n [usePreloadedData]=\"usePreloadedData\"\n (selectedDictionaryValuesChanged)=\"\n onSelectedDictionaryValuesChanged($event)\n \"\n >\n </app-dictionaries-tree>\n </mat-autocomplete>\n </mat-form-field>\n\n <formly-validation-message *ngIf=\"showError\" [field]=\"field\">\n </formly-validation-message>\n</form>\n", styles: ["formly-validation-message{color:red;font-size:12px}::ng-deep .mat-mdc-autocomplete-panel>app-dictionaries-tree>app-treeview>cdk-virtual-scroll-viewport{overflow:hidden}\n"] }]
5124
5222
  }], ctorParameters: () => [{ type: DictionaryService }, { type: i0.ChangeDetectorRef }], propDecorators: { autocompleteTrigger: [{
5125
5223
  type: ViewChild,
5126
5224
  args: [MatAutocompleteTrigger]
@@ -5972,38 +6070,97 @@ class FormCssHelper {
5972
6070
  case '.component-data':
5973
6071
  cssText = this.getSpecificCssForData(key, values, cssRules);
5974
6072
  break;
6073
+ case '.component-dictionary':
6074
+ cssText = this.getSpecificCssForDictionary(key, values, cssRules);
6075
+ break;
5975
6076
  case '.table-details':
5976
6077
  cssText = this.getSpecificCssForTableDetail(values);
5977
6078
  break;
5978
6079
  case '.table-header':
5979
6080
  cssText = this.getSpecificCssForTableHeader(values);
5980
6081
  break;
6082
+ case '.component-progress-bar':
6083
+ cssText = this.getSpecificCssForProgressBar(values);
6084
+ break;
6085
+ }
6086
+ // Append component-level margin rules (applies to all 5 margin-enabled components)
6087
+ const marginTop = values['component-margin-top'];
6088
+ const marginBottom = values['component-margin-bottom'];
6089
+ const marginParts = [];
6090
+ if (marginTop && marginTop !== 'none') {
6091
+ marginParts.push(`margin-top: ${marginTop} !important;`);
6092
+ }
6093
+ if (marginBottom && marginBottom !== 'none') {
6094
+ marginParts.push(`margin-bottom: ${marginBottom} !important;`);
6095
+ }
6096
+ if (marginParts.length > 0) {
6097
+ cssText += ` ${key} { ${marginParts.join(' ')} }`;
5981
6098
  }
5982
6099
  return cssText;
5983
6100
  }
6101
+ static getSpecificCssForDictionary(key, values, cssRules) {
6102
+ let inputSpecificCss = '';
6103
+ const fontStyleSource = cssRules['.component-dictionary-value'] || cssRules['.font-input'];
6104
+ if (fontStyleSource) {
6105
+ const fontStyleForInputText = { ...fontStyleSource };
6106
+ if (values['text-align']) {
6107
+ fontStyleForInputText['text-align'] = values['text-align'];
6108
+ }
6109
+ fontStyleForInputText['color'] = (fontStyleForInputText['color'] || '') + ' !important';
6110
+ inputSpecificCss = this.styleObjectToString({ ...fontStyleForInputText });
6111
+ }
6112
+ let labelSpecificCss = '';
6113
+ const labelSource = cssRules['.component-dictionary-label'];
6114
+ if (labelSource) {
6115
+ labelSpecificCss = this.styleObjectToString({ ...labelSource });
6116
+ }
6117
+ var css = `
6118
+ .mat-mdc-text-field-wrapper.mdc-text-field {
6119
+ ${this.styleObjectToString({ ...values })};
6120
+ border-style: solid;
6121
+ input {
6122
+ ${inputSpecificCss}
6123
+ }
6124
+ mat-label {
6125
+ ${labelSpecificCss}
6126
+ }
6127
+ .mdc-line-ripple--active::after {
6128
+ border-bottom-color: ${labelSource ? labelSource['color'] : 'inherit'}
6129
+ }
6130
+ }
6131
+
6132
+ .component-dictionary-label label {
6133
+ ${labelSpecificCss}
6134
+ }
6135
+ `;
6136
+ return `${key} { ${css} }`;
6137
+ }
5984
6138
  static getSpecificCssForInput(key, values, cssRules) {
5985
6139
  let inputSpecificCss = '';
5986
6140
  let signInputSpecificCss = '';
5987
- const fontStyleForInputText = cssRules['.font-input'];
5988
- if (fontStyleForInputText) {
6141
+ const fontStyleSource = cssRules['.component-text-field-value'] || cssRules['.font-input'];
6142
+ if (fontStyleSource) {
6143
+ const fontStyleForInputText = { ...fontStyleSource };
5989
6144
  //transfer property from component to input
5990
6145
  if (values['text-align']) {
5991
6146
  fontStyleForInputText['text-align'] = values['text-align'];
5992
6147
  }
5993
- fontStyleForInputText['color'] += ' !important';
5994
- inputSpecificCss = this.styleObjectToString(fontStyleForInputText);
5995
- signInputSpecificCss = this.styleObjectToString(fontStyleForInputText, true);
6148
+ fontStyleForInputText['color'] = (fontStyleForInputText['color'] || '') + ' !important';
6149
+ inputSpecificCss = this.styleObjectToString({ ...fontStyleForInputText });
6150
+ signInputSpecificCss = this.styleObjectToString({ ...fontStyleForInputText }, true);
5996
6151
  }
5997
6152
  let labelSpecificCss = '';
5998
6153
  let signLabelSpecificCss = '';
5999
- const fontStyleForLabelText = cssRules['.component-text-field-label'];
6000
- if (fontStyleForLabelText) {
6001
- labelSpecificCss = this.styleObjectToString(fontStyleForLabelText);
6002
- signLabelSpecificCss = this.styleObjectToString(fontStyleForLabelText, true);
6154
+ const labelSource = cssRules['.component-text-field-label'];
6155
+ if (labelSource) {
6156
+ labelSpecificCss = this.styleObjectToString({ ...labelSource });
6157
+ signLabelSpecificCss = this.styleObjectToString({ ...labelSource }, true);
6003
6158
  }
6159
+ const textareaHeight = values['textarea-height'] || '';
6160
+ const textareaMaxHeight = values['textarea-max-height'] || '';
6004
6161
  var css = `
6005
6162
  .mat-mdc-text-field-wrapper.mdc-text-field {
6006
- ${this.styleObjectToString(values)};
6163
+ ${this.styleObjectToString({ ...values })};
6007
6164
  border-style: solid;
6008
6165
  input {
6009
6166
  ${inputSpecificCss}
@@ -6012,13 +6169,13 @@ class FormCssHelper {
6012
6169
  ${labelSpecificCss}
6013
6170
  }
6014
6171
  .mdc-line-ripple--active::after {
6015
- border-bottom-color: ${fontStyleForLabelText['color']}
6172
+ border-bottom-color: ${labelSource ? labelSource['color'] : 'inherit'}
6016
6173
  }
6017
6174
  }
6018
6175
 
6019
6176
  input.component-text-field {
6020
6177
  border-style: solid !important;
6021
- ${this.styleObjectToString(values, true)};
6178
+ ${this.styleObjectToString({ ...values }, true)};
6022
6179
  ${signInputSpecificCss}
6023
6180
  }
6024
6181
 
@@ -6026,7 +6183,34 @@ class FormCssHelper {
6026
6183
  ${signLabelSpecificCss}
6027
6184
  }
6028
6185
  `;
6029
- return `${key} { ${css}}`;
6186
+ // Flat explicit rules scoped to textarea only.
6187
+ // :has(textarea) on the infix ensures min-height/max-height do NOT affect
6188
+ // text/numeric inputs that share the same .component-text-field class.
6189
+ const textareaFlatCss = `
6190
+ ${key} .mat-mdc-text-field-wrapper.mdc-text-field:has(textarea) .mat-mdc-form-field-infix {
6191
+ ${textareaHeight ? `min-height: ${textareaHeight} !important;` : ''}
6192
+ }
6193
+ ${key} .mat-mdc-text-field-wrapper.mdc-text-field textarea {
6194
+ ${inputSpecificCss}
6195
+ ${textareaHeight ? `min-height: ${textareaHeight} !important;` : ''}
6196
+ ${textareaMaxHeight && textareaMaxHeight !== 'none' ? `max-height: ${textareaMaxHeight} !important; overflow-y: auto !important;` : ''}
6197
+ resize: none !important;
6198
+ }
6199
+ `;
6200
+ return `${key} { ${css}} ${textareaFlatCss}`;
6201
+ }
6202
+ static getSpecificCssForProgressBar(values) {
6203
+ const startColor = values['startColor'] || '#8848EF';
6204
+ const endColor = values['endColor'] || '#8848EF';
6205
+ const height = values['height'] || '4px';
6206
+ const borderRadius = values['borderRadius'] || '7px';
6207
+ return `
6208
+ .component-progress-bar {
6209
+ background: linear-gradient(to right, ${startColor}, ${endColor}) !important;
6210
+ height: ${height} !important;
6211
+ border-radius: ${borderRadius} !important;
6212
+ }
6213
+ `;
6030
6214
  }
6031
6215
  static getSpecificCssForTableHeader(values) {
6032
6216
  const backgroundColor = values['background-color'] || '#ffffff';
@@ -6207,7 +6391,8 @@ class FormCssHelper {
6207
6391
  .component-text-field mat-label,
6208
6392
  .component-checkbox mat-label,
6209
6393
  .component-radio mat-label,
6210
- .component-date mat-label {
6394
+ .component-date mat-label,
6395
+ .component-dictionary mat-label {
6211
6396
  ${cssRules['.font-label']
6212
6397
  ? this.styleObjectToString(cssRules['.font-label'])
6213
6398
  : ''}
@@ -6262,21 +6447,22 @@ class FormCssHelper {
6262
6447
  }
6263
6448
  static getSpecificCssForData(key, values, cssRules) {
6264
6449
  let inputSpecificCss = '';
6265
- const fontStyleForInputText = cssRules['.font-list'];
6266
- if (fontStyleForInputText) {
6450
+ const fontStyleSource = cssRules['.component-date-value'] || cssRules['.component-data-value'] || cssRules['.font-list'];
6451
+ if (fontStyleSource) {
6452
+ const fontStyleForInputText = { ...fontStyleSource };
6267
6453
  //transfer property from component to input
6268
6454
  if (values['text-align']) {
6269
6455
  fontStyleForInputText['text-align'] = values['text-align'];
6270
6456
  }
6271
- inputSpecificCss = this.styleObjectToString(fontStyleForInputText);
6457
+ inputSpecificCss = this.styleObjectToString({ ...fontStyleForInputText });
6272
6458
  }
6273
6459
  let labelSpecificCss = '';
6274
- const fontStyleForLabelText = cssRules['.component-data-label'];
6275
- if (fontStyleForLabelText) {
6276
- labelSpecificCss = this.styleObjectToString(fontStyleForLabelText);
6460
+ const labelSource = cssRules['.component-data-label'];
6461
+ if (labelSource) {
6462
+ labelSpecificCss = this.styleObjectToString({ ...labelSource });
6277
6463
  }
6278
6464
  return ` ${key} { .mat-mdc-text-field-wrapper.mdc-text-field {
6279
- ${this.styleObjectToString(values)};
6465
+ ${this.styleObjectToString({ ...values })};
6280
6466
  border-style:solid;
6281
6467
  input{
6282
6468
  ${inputSpecificCss}
@@ -6289,13 +6475,19 @@ class FormCssHelper {
6289
6475
  }
6290
6476
  } `;
6291
6477
  }
6478
+ static { this.INTERNAL_KEYS = ['textarea-height', 'textarea-max-height', 'component-margin-top', 'component-margin-bottom']; }
6292
6479
  static styleObjectToString(values, important = false) {
6293
- values['width'] =
6294
- 'calc(100%' +
6295
- ('margin-left' in values ? ` - ${values['margin-left']}` : '') +
6296
- ('margin-right' in values ? ` - ${values['margin-right']}` : '') +
6297
- ')';
6298
- return Object.entries(values)
6480
+ const output = { ...values };
6481
+ // Remove internal keys that are not valid CSS properties
6482
+ this.INTERNAL_KEYS.forEach(k => delete output[k]);
6483
+ if (!output['width']) {
6484
+ output['width'] =
6485
+ 'calc(100%' +
6486
+ ('margin-left' in output ? ` - ${output['margin-left']}` : '') +
6487
+ ('margin-right' in output ? ` - ${output['margin-right']}` : '') +
6488
+ ')';
6489
+ }
6490
+ return Object.entries(output)
6299
6491
  .map(([key, value]) => `${key}: ${value}${important ? ' !important' : ''}`)
6300
6492
  .join('; ');
6301
6493
  }
@@ -7652,9 +7844,10 @@ class CollectorFormComponent {
7652
7844
  }
7653
7845
  }
7654
7846
  }
7655
- resolvedValue = displayValues.length > 0
7656
- ? displayValues.join(', ')
7657
- : (enriched.fillValue ?? String(value));
7847
+ resolvedValue =
7848
+ displayValues.length > 0
7849
+ ? displayValues.join(', ')
7850
+ : (enriched.fillValue ?? String(value));
7658
7851
  }
7659
7852
  else {
7660
7853
  // Single-select
@@ -7771,6 +7964,39 @@ class CollectorFormComponent {
7771
7964
  }
7772
7965
  return actionsExecuted;
7773
7966
  }
7967
+ /**
7968
+ * Executes action/status steps that appear before the first visible step.
7969
+ * Called on form initialization to handle leading action steps.
7970
+ */
7971
+ async executeLeadingActionSteps() {
7972
+ if (!this.appDataUuid || !this.flux || this.flux.length === 0) {
7973
+ return;
7974
+ }
7975
+ const leadingActionSteps = this.actionStepHandler.getActionStepsBeforeFirstVisibleStep(this.flux);
7976
+ if (leadingActionSteps.length === 0) {
7977
+ return;
7978
+ }
7979
+ console.log(`🎬 Executing ${leadingActionSteps.length} leading action steps before first visible step`);
7980
+ this.isLoading = true;
7981
+ try {
7982
+ const result = await this.actionStepHandler.executeActionSteps(leadingActionSteps, this.appDataUuid, (step) => {
7983
+ const loadingMessage = Utils.findTranslationInfo('loadingMessageTranslations', step.translations, this.currentLanguageIso);
7984
+ this.loadingMessage = loadingMessage || null;
7985
+ });
7986
+ if (result.success) {
7987
+ console.log('✅ Leading action steps executed successfully');
7988
+ }
7989
+ else {
7990
+ console.error('❌ Leading action steps failed:', result.error);
7991
+ }
7992
+ }
7993
+ catch (error) {
7994
+ console.error('❌ Error executing leading action steps:', error);
7995
+ }
7996
+ finally {
7997
+ this.loadingMessage = null;
7998
+ }
7999
+ }
7774
8000
  async executeActionStepsAfterCurrentStep(currentStepIndex) {
7775
8001
  if (this.actionStepHandler.isExecutingActions) {
7776
8002
  return false;
@@ -7826,35 +8052,6 @@ class CollectorFormComponent {
7826
8052
  return false;
7827
8053
  }
7828
8054
  }
7829
- async executeLeadingActionSteps() {
7830
- if (!this.appDataUuid || !this.flux || this.flux.length === 0) {
7831
- return;
7832
- }
7833
- const leadingActionSteps = this.actionStepHandler.getActionStepsBeforeFirstVisibleStep(this.flux);
7834
- if (leadingActionSteps.length === 0) {
7835
- return;
7836
- }
7837
- console.log(`🎬 Executing ${leadingActionSteps.length} leading action steps before first visible step`);
7838
- this.isLoading = true;
7839
- try {
7840
- const result = await this.actionStepHandler.executeActionSteps(leadingActionSteps, this.appDataUuid, (step) => {
7841
- const loadingMessage = Utils.findTranslationInfo('loadingMessageTranslations', step.translations, this.currentLanguageIso);
7842
- this.loadingMessage = loadingMessage || null;
7843
- });
7844
- if (result.success) {
7845
- console.log('✅ Leading action steps executed successfully');
7846
- }
7847
- else {
7848
- console.error('❌ Leading action steps failed:', result.error);
7849
- }
7850
- }
7851
- catch (error) {
7852
- console.error('❌ Error executing leading action steps:', error);
7853
- }
7854
- finally {
7855
- this.loadingMessage = null;
7856
- }
7857
- }
7858
8055
  onSelectedPageChanged(index) {
7859
8056
  if (this.formlyConfig[0].fieldGroup) {
7860
8057
  var selectedPage = this.formlyConfig[0].fieldGroup[index];
@@ -8483,15 +8680,47 @@ class CollectorFormComponent {
8483
8680
  if (section.dependentDictionary) {
8484
8681
  this.attachToDependentDictionaryIfNecessary(section.dependentDictionary, separatorFormlyConfig);
8485
8682
  }
8683
+ const sectionAny = section;
8684
+ // When the section has a visible title or separator, sectionMarginTop is passed to
8685
+ // separatorFormlyConfig so it appears ABOVE the title/hr. When neither is shown,
8686
+ // the controls ARE the top of the section, so sectionMarginTop stays on custom-section.
8687
+ const hasTitleOrSeparator = section.showSectionTitle || section.showSectionSeparator;
8688
+ if (hasTitleOrSeparator && sectionAny.marginTop) {
8689
+ separatorFormlyConfig = {
8690
+ ...separatorFormlyConfig,
8691
+ props: {
8692
+ ...separatorFormlyConfig.props,
8693
+ sectionMarginTop: sectionAny.marginTop,
8694
+ }
8695
+ };
8696
+ }
8486
8697
  stepSections.push(separatorFormlyConfig);
8698
+ // firstRowMarginBottom is passed into buildControlsFieldGroupAsync so it ends up
8699
+ // in the spacer AFTER the first row (not before it), matching user expectation.
8700
+ const sectionControls = await this.buildControlsFieldGroupAsync(step, section.controls || [], section.presentationControls || [], sectionAny.firstRowMarginBottom || undefined);
8701
+ // Prepend a spacer only for firstRowMarginTop (space ABOVE row 0).
8702
+ // firstRowMarginBottom is handled inside buildControlsFieldGroupAsync.
8703
+ if (sectionAny.firstRowMarginTop) {
8704
+ sectionControls.unshift({
8705
+ type: 'row-spacer',
8706
+ className: 'percentage-width-12',
8707
+ props: {
8708
+ spacerMarginTop: sectionAny.firstRowMarginTop,
8709
+ }
8710
+ });
8711
+ }
8487
8712
  const sectionFormlyConfig = {
8488
8713
  type: 'custom-section',
8489
8714
  props: {
8490
8715
  label: section.title,
8491
8716
  description: section.translations?.find((t) => t.languageIso === this.currentLanguageIso)?.value ?? '',
8492
- design: this.design
8717
+ design: this.design,
8718
+ // When title/separator is shown, sectionMarginTop lives on separatorFormlyConfig above.
8719
+ // When neither is shown, the controls are the top of section so keep margin here.
8720
+ sectionMarginTop: hasTitleOrSeparator ? undefined : (sectionAny.marginTop || undefined),
8721
+ sectionMarginBottom: sectionAny.marginBottom || undefined,
8493
8722
  },
8494
- fieldGroup: await this.buildControlsFieldGroupAsync(step, section.controls || [], section.presentationControls || []),
8723
+ fieldGroup: sectionControls,
8495
8724
  fieldGroupClassName: 'display-flex'
8496
8725
  };
8497
8726
  if (section.dependentDictionary) {
@@ -8555,7 +8784,7 @@ class CollectorFormComponent {
8555
8784
  }
8556
8785
  };
8557
8786
  }
8558
- async buildControlsFieldGroupAsync(step, controls, presentationControls) {
8787
+ async buildControlsFieldGroupAsync(step, controls, presentationControls, initialPendingMarginBottom) {
8559
8788
  const result = [];
8560
8789
  let rowItems = [];
8561
8790
  controls = controls.filter((c) => !c.isOnlyForConfig);
@@ -8567,12 +8796,15 @@ class CollectorFormComponent {
8567
8796
  return false;
8568
8797
  return true;
8569
8798
  });
8570
- const processRow = async (items) => {
8799
+ const processRow = async (items, useFlexWidth = false) => {
8571
8800
  const fields = [];
8572
8801
  const total = 12;
8573
8802
  const built = [];
8574
8803
  const auto = [];
8575
8804
  let used = 0;
8805
+ const getWidthClass = (dim) => useFlexWidth
8806
+ ? this.getFlexWidthClassName(dim)
8807
+ : this.getPercentageClassName(dim);
8576
8808
  for (const i of items) {
8577
8809
  if ('collectionControlIdentifier' in i === true) {
8578
8810
  built.push(await this.buildPresentationFormFieldAsync(step, i));
@@ -8594,53 +8826,118 @@ class CollectorFormComponent {
8594
8826
  else {
8595
8827
  const s = Math.round((c.dimension / 100) * total);
8596
8828
  used += s;
8597
- const percentageClass = this.getPercentageClassName(c.dimension);
8598
- f.className = `${f.className} ${percentageClass}`;
8829
+ f.className = `${f.className} ${getWidthClass(c.dimension)}`;
8599
8830
  }
8600
8831
  }
8601
8832
  else if (c.dimensionType === DimensionType.Pixels) {
8602
8833
  const s = Math.round((c.dimension / window.innerWidth) * total);
8603
8834
  used += s;
8604
- const percentageClass = this.getPercentageClassName((s / total) * 100);
8605
- f.className = `${f.className} ${percentageClass}`;
8835
+ f.className = `${f.className} ${getWidthClass((s / total) * 100)}`;
8606
8836
  }
8607
8837
  else if (c.autoDimension) {
8608
8838
  auto.push({ c, f });
8609
8839
  }
8610
8840
  else {
8611
8841
  used += 1;
8612
- const percentageClass = this.getPercentageClassName((1 / total) * 100);
8613
- f.className = `${f.className} ${percentageClass}`;
8842
+ f.className = `${f.className} ${getWidthClass((1 / total) * 100)}`;
8614
8843
  }
8615
8844
  }
8616
8845
  const rem = total - used;
8617
8846
  if (auto.length > 0) {
8618
8847
  const share = Math.max(Math.floor(rem / auto.length), 1);
8619
8848
  for (const a of auto) {
8620
- const percentageClass = this.getPercentageClassName((share / total) * 100);
8621
- a.f.className = `${a.f.className} ${percentageClass}`;
8849
+ a.f.className = `${a.f.className} ${getWidthClass((share / total) * 100)}`;
8622
8850
  }
8623
8851
  }
8624
8852
  fields.push(...built);
8625
8853
  return fields;
8626
8854
  };
8855
+ // pendingPrevRowMarginBottom: carries the marginBottom of the preceding row into the
8856
+ // next spacer's marginTop so that "row margin bottom" appears BELOW the row, not above it.
8857
+ let pendingPrevRowMarginBottom = initialPendingMarginBottom;
8858
+ let pendingJustifyContent = undefined;
8627
8859
  for (const c of [...controls, ...presentationControls]) {
8628
8860
  if (('type' in c && c.type === StepControlType.NewRow) ||
8629
8861
  c.type == PresentationControlType.NewRow) {
8630
8862
  if (rowItems.length > 0) {
8631
- result.push(...(await processRow(rowItems)));
8863
+ const jc = pendingJustifyContent;
8864
+ if (jc) {
8865
+ const rowFields = await processRow(rowItems, true);
8866
+ result.push({
8867
+ type: 'row-wrapper',
8868
+ className: 'percentage-width-12',
8869
+ props: { justifyContent: jc },
8870
+ fieldGroup: rowFields
8871
+ });
8872
+ }
8873
+ else {
8874
+ result.push(...(await processRow(rowItems)));
8875
+ }
8632
8876
  rowItems = [];
8633
8877
  }
8878
+ const newRowControl = c;
8879
+ pendingJustifyContent = newRowControl.rowJustifyContent || undefined;
8880
+ // spacerMarginTop = bottom margin of the PREVIOUS row (space below it)
8881
+ // spacerMarginBottom = top margin of the CURRENT row (space above it)
8882
+ const spacerTop = pendingPrevRowMarginBottom;
8883
+ const spacerBottom = newRowControl.rowMarginTop || undefined;
8884
+ pendingPrevRowMarginBottom = newRowControl.rowMarginBottom || undefined;
8885
+ if (spacerTop || spacerBottom) {
8886
+ result.push({
8887
+ type: 'row-spacer',
8888
+ className: 'percentage-width-12',
8889
+ props: {
8890
+ spacerMarginTop: spacerTop,
8891
+ spacerMarginBottom: spacerBottom,
8892
+ }
8893
+ });
8894
+ }
8634
8895
  }
8635
8896
  else {
8636
8897
  rowItems.push(c);
8637
8898
  }
8638
8899
  }
8639
8900
  if (rowItems.length > 0) {
8640
- result.push(...(await processRow(rowItems)));
8901
+ if (pendingJustifyContent) {
8902
+ const rowFields = await processRow(rowItems, true);
8903
+ result.push({
8904
+ type: 'row-wrapper',
8905
+ className: 'percentage-width-12',
8906
+ props: { justifyContent: pendingJustifyContent },
8907
+ fieldGroup: rowFields
8908
+ });
8909
+ }
8910
+ else {
8911
+ result.push(...(await processRow(rowItems)));
8912
+ }
8913
+ }
8914
+ // Trailing spacer for the last row's marginBottom
8915
+ if (pendingPrevRowMarginBottom) {
8916
+ result.push({
8917
+ type: 'row-spacer',
8918
+ className: 'percentage-width-12',
8919
+ props: { spacerMarginTop: pendingPrevRowMarginBottom }
8920
+ });
8641
8921
  }
8642
8922
  return result;
8643
8923
  }
8924
+ getFlexWidthClassName(percentageDimension) {
8925
+ const span = Math.round((percentageDimension / 100) * 12);
8926
+ const className = `flex-width-${span}`;
8927
+ if (!document.getElementById(className)) {
8928
+ const style = document.createElement('style');
8929
+ style.type = 'text/css';
8930
+ style.id = className;
8931
+ style.innerHTML = `
8932
+ .${className} {
8933
+ width: ${Math.round((span / 12) * 100)}%;
8934
+ flex-shrink: 1;
8935
+ }
8936
+ `;
8937
+ document.head.appendChild(style);
8938
+ }
8939
+ return className;
8940
+ }
8644
8941
  getPixelClassName(pixelDimension) {
8645
8942
  const className = `pixel-width-${pixelDimension}`;
8646
8943
  if (!document.getElementById(className)) {
@@ -8676,7 +8973,8 @@ class CollectorFormComponent {
8676
8973
  '.component-checkbox',
8677
8974
  '.component-radio',
8678
8975
  '.component-date',
8679
- '.component-data'
8976
+ '.component-data',
8977
+ '.component-dictionary'
8680
8978
  ];
8681
8979
  let formlyConfig = this.getDefaultFormlyFieldConfig(control, initialType, pattern, componentStyleKey, componentsToExcludeFromStyle);
8682
8980
  //control.specificControlData.type === 3 is email
@@ -8700,8 +8998,8 @@ class CollectorFormComponent {
8700
8998
  formlyConfig.type = 'input';
8701
8999
  break;
8702
9000
  case ManualInputControlType.TextArea:
8703
- formlyConfig.type = 'input';
8704
- formlyConfig.props['autosize'] = false;
9001
+ formlyConfig.type = 'textarea';
9002
+ formlyConfig.props['autosize'] = true;
8705
9003
  componentStyleKey = '.component-text-field';
8706
9004
  break;
8707
9005
  case ManualInputControlType.DateTime:
@@ -8721,7 +9019,11 @@ class CollectorFormComponent {
8721
9019
  formlyConfig.type = 'formly-paragraph';
8722
9020
  componentStyleKey = '.component-text-field';
8723
9021
  const translatedDescription = control.specificControlData?.descriptionTranslations?.find((d) => d.languageIso === this.currentLanguageIso)?.value || '';
9022
+ const translatedParagraphTitle = control.translations?.find((d) => d.languageIso === this.currentLanguageIso)?.value || '';
8724
9023
  formlyConfig.defaultValue = translatedDescription;
9024
+ formlyConfig.props['translatedDescription'] = translatedDescription;
9025
+ formlyConfig.props['translatedParagraphTitle'] =
9026
+ translatedParagraphTitle;
8725
9027
  break;
8726
9028
  case StepControlType.CheckBox: // Checkbox
8727
9029
  formlyConfig.type = 'formly-checkbox';
@@ -8730,10 +9032,15 @@ class CollectorFormComponent {
8730
9032
  formlyConfig.props['checked'] = checked;
8731
9033
  break;
8732
9034
  case StepControlType.Dictionary: // Dictionary (dropdown)
8733
- componentStyleKey =
8734
- control.specificControlData.showAsRadioButtonsList === true
8735
- ? '.component-radio'
8736
- : '.component-data';
9035
+ if (control.specificControlData.showAsCheckboxes === true) {
9036
+ componentStyleKey = '.component-checkbox';
9037
+ }
9038
+ else if (control.specificControlData.showAsRadioButtonsList === true) {
9039
+ componentStyleKey = '.component-radio';
9040
+ }
9041
+ else {
9042
+ componentStyleKey = '.component-dictionary';
9043
+ }
8737
9044
  await this.constructDictionary(control, formlyConfig);
8738
9045
  break;
8739
9046
  case StepControlType.Buttons:
@@ -8849,6 +9156,7 @@ class CollectorFormComponent {
8849
9156
  title: control.translations?.find((t) => t.languageIso === this.currentLanguageIso)?.value || '',
8850
9157
  design: this.design,
8851
9158
  required: control.isMandatory,
9159
+ validateThroughApi: control.specificControlData?.isApiValidation,
8852
9160
  attributes: {
8853
9161
  style: componentsToExcludeFromStyle.find((c) => c === componentStyleKey)
8854
9162
  ? ''
@@ -9067,7 +9375,6 @@ class CollectorFormComponent {
9067
9375
  formlyConfig.defaultValue = fillValue ? '&check;' : '&cross;';
9068
9376
  break;
9069
9377
  case 'object':
9070
- // Enriched inherited dictionary format: extract fillValue for display
9071
9378
  if (fillValue.fillValue !== undefined) {
9072
9379
  formlyConfig.defaultValue = fillValue.fillValue;
9073
9380
  }
@@ -10792,11 +11099,11 @@ class FormlyRadioComponent extends FieldType {
10792
11099
  }
10793
11100
  }
10794
11101
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FormlyRadioComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
10795
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: FormlyRadioComponent, selector: "formly-radio", usesInheritance: true, ngImport: i0, template: "<div class=\"mat-mdc-text-field-wrapper mdc-radiobox-field\" appExternalLink>\n <label>\n <markdown [data]=\"title\"></markdown>\n </label>\n <div *ngIf=\"radioOptionsList.length > 0\">\n <mat-radio-group [value]=\"formControl.value?.id\"\n (change)=\"onRadioChange($event)\">\n <ng-container *ngFor=\"let option of radioOptionsList\">\n <div>\n <mat-radio-button [value]=\"option.value.id\">\n {{ option.label }}\n </mat-radio-button>\n </div>\n </ng-container>\n </mat-radio-group>\n </div>\n <formly-validation-message *ngIf=\"showError\" [field]=\"field\">\n </formly-validation-message>\n</div>\n", styles: ["formly-validation-message{color:red;font-size:12px}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.MarkdownComponent, selector: "markdown, [markdown]", inputs: ["data", "src", "disableSanitizer", "inline", "clipboard", "clipboardButtonComponent", "clipboardButtonTemplate", "emoji", "katex", "katexOptions", "mermaid", "mermaidOptions", "lineHighlight", "line", "lineOffset", "lineNumbers", "start", "commandLine", "filterOutput", "host", "prompt", "output", "user"], outputs: ["error", "load", "ready"] }, { kind: "directive", type: i3$1.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i3$1.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "component", type: i4.ɵFormlyValidationMessage, selector: "formly-validation-message", inputs: ["field"] }, { kind: "directive", type: ExternalLinkDirective, selector: "[appExternalLink]" }] }); }
11102
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: FormlyRadioComponent, selector: "formly-radio", usesInheritance: true, ngImport: i0, template: "<div class=\"mat-mdc-text-field-wrapper mdc-radiobox-field\" appExternalLink>\n <label [ngStyle]=\"props['design']?.['.font-label']\">\n <markdown [data]=\"title\"></markdown>\n </label>\n <div *ngIf=\"radioOptionsList.length > 0\">\n <mat-radio-group [value]=\"formControl.value?.id\"\n (change)=\"onRadioChange($event)\">\n <ng-container *ngFor=\"let option of radioOptionsList\">\n <div>\n <mat-radio-button [value]=\"option.value.id\">\n {{ option.label }}\n </mat-radio-button>\n </div>\n </ng-container>\n </mat-radio-group>\n </div>\n <formly-validation-message *ngIf=\"showError\" [field]=\"field\">\n </formly-validation-message>\n</div>\n", styles: ["formly-validation-message{color:red;font-size:12px}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i2.MarkdownComponent, selector: "markdown, [markdown]", inputs: ["data", "src", "disableSanitizer", "inline", "clipboard", "clipboardButtonComponent", "clipboardButtonTemplate", "emoji", "katex", "katexOptions", "mermaid", "mermaidOptions", "lineHighlight", "line", "lineOffset", "lineNumbers", "start", "commandLine", "filterOutput", "host", "prompt", "output", "user"], outputs: ["error", "load", "ready"] }, { kind: "directive", type: i3$1.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i3$1.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "component", type: i4.ɵFormlyValidationMessage, selector: "formly-validation-message", inputs: ["field"] }, { kind: "directive", type: ExternalLinkDirective, selector: "[appExternalLink]" }] }); }
10796
11103
  }
10797
11104
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FormlyRadioComponent, decorators: [{
10798
11105
  type: Component,
10799
- args: [{ selector: 'formly-radio', template: "<div class=\"mat-mdc-text-field-wrapper mdc-radiobox-field\" appExternalLink>\n <label>\n <markdown [data]=\"title\"></markdown>\n </label>\n <div *ngIf=\"radioOptionsList.length > 0\">\n <mat-radio-group [value]=\"formControl.value?.id\"\n (change)=\"onRadioChange($event)\">\n <ng-container *ngFor=\"let option of radioOptionsList\">\n <div>\n <mat-radio-button [value]=\"option.value.id\">\n {{ option.label }}\n </mat-radio-button>\n </div>\n </ng-container>\n </mat-radio-group>\n </div>\n <formly-validation-message *ngIf=\"showError\" [field]=\"field\">\n </formly-validation-message>\n</div>\n", styles: ["formly-validation-message{color:red;font-size:12px}\n"] }]
11106
+ args: [{ selector: 'formly-radio', template: "<div class=\"mat-mdc-text-field-wrapper mdc-radiobox-field\" appExternalLink>\n <label [ngStyle]=\"props['design']?.['.font-label']\">\n <markdown [data]=\"title\"></markdown>\n </label>\n <div *ngIf=\"radioOptionsList.length > 0\">\n <mat-radio-group [value]=\"formControl.value?.id\"\n (change)=\"onRadioChange($event)\">\n <ng-container *ngFor=\"let option of radioOptionsList\">\n <div>\n <mat-radio-button [value]=\"option.value.id\">\n {{ option.label }}\n </mat-radio-button>\n </div>\n </ng-container>\n </mat-radio-group>\n </div>\n <formly-validation-message *ngIf=\"showError\" [field]=\"field\">\n </formly-validation-message>\n</div>\n", styles: ["formly-validation-message{color:red;font-size:12px}\n"] }]
10800
11107
  }] });
10801
11108
 
10802
11109
  class FormlyCheckboxesComponent extends FieldType {
@@ -10913,11 +11220,10 @@ class FormlyScanIdComponent extends FieldType {
10913
11220
  ngOnInit() {
10914
11221
  const group = this.form;
10915
11222
  group.addControl(this.props['identifier'], this.control);
10916
- this.validFormats = this.props['config'].allowedFormats?.split(',') || [
10917
- '.jpg',
10918
- '.png',
10919
- ];
10920
- this.maxFileSizeKB = this.props['config'].maxFileSizeKB || 2000;
11223
+ this.validFormats = this.props['config'].fileFormats
11224
+ ? this.props['config'].fileFormats.split(',').map((f) => '.' + f.trim().replace(/^[*.]+/, ''))
11225
+ : ['.jpg', '.png'];
11226
+ this.maxFileSizeKB = this.props['config'].fileMaxSize || 2000;
10921
11227
  if (this.props['config'].collected) {
10922
11228
  const controlId = this.props['config'].componentCollected;
10923
11229
  const value = this.form.get(controlId)?.value ?? this.model?.[controlId];
@@ -11245,28 +11551,24 @@ class FormlyScanIdComponent extends FieldType {
11245
11551
  ],
11246
11552
  };
11247
11553
  this.appDataService.scanId(command).subscribe({
11248
- next: async (result) => {
11249
- console.log('Scan ID result:', result);
11554
+ next: async (isValid) => {
11555
+ console.log('Scan ID result:', isValid);
11250
11556
  this.isLoading = false;
11557
+ if (!isValid) {
11558
+ this.fileError =
11559
+ this.props['errorMessages']?.invalidStatus ||
11560
+ 'Invalid status response.';
11561
+ this.canRetry = true;
11562
+ this.control.setErrors({ invalidStatus: true });
11563
+ this.cdr.detectChanges();
11564
+ return;
11565
+ }
11251
11566
  const appData = await this.appDataService.getSteps(this.props['appDataId']);
11252
- if (appData) {
11253
- const status = this.extractStatusFromAppData(appData);
11254
- console.log('[SCAN-ID] extracted status:', status);
11255
- if (status?.toLowerCase().includes('invalid')) {
11256
- this.fileError =
11257
- this.props['errorMessages']?.invalidStatus ||
11258
- 'Invalid status response.';
11259
- this.canRetry = true;
11260
- this.control.setErrors({ invalidStatus: true });
11261
- this.cdr.detectChanges();
11262
- return;
11263
- }
11264
- this.isScanValid = true;
11265
- this.successMessage = 'Upload successful!';
11266
- this.wizardSteps.forEach((s) => (s.status = 'completed'));
11267
- if (this.props['event']) {
11268
- this.props['event'](appData);
11269
- }
11567
+ this.isScanValid = true;
11568
+ this.successMessage = 'Upload successful!';
11569
+ this.wizardSteps.forEach((s) => (s.status = 'completed'));
11570
+ if (this.props['event'] && appData) {
11571
+ this.props['event'](appData);
11270
11572
  }
11271
11573
  this.cdr.detectChanges();
11272
11574
  },
@@ -13511,6 +13813,42 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
13511
13813
  args: [{ selector: 'app-formly-open-banking', template: "<div class=\"open-banking-container\">\n <!-- Initial State -->\n <div *ngIf=\"isInitialState\" class=\"state-initial\">\n <div class=\"message-container\">\n <p class=\"message\">{{ initialMessage }}</p>\n <button mat-raised-button color=\"primary\" (click)=\"proceedToNextStep()\" [disabled]=\"isLoadingSubject | async\">\n {{ nextButtonLabel }}\n </button>\n </div>\n </div>\n\n <!-- Bank Selection State -->\n <div *ngIf=\"isBankSelectionState\" class=\"state-bank-selection\">\n <h3 class=\"section-title\">{{ selectBankTitle }}</h3>\n\n <!-- Bank Grid -->\n <div class=\"banks-grid\" *ngIf=\"banks.length > 0\">\n <div\n *ngFor=\"let bank of banks\"\n class=\"bank-card\"\n [class.selected]=\"selectedBank === bank.bankCode\"\n (click)=\"selectBank(bank)\">\n <div class=\"bank-logo\" *ngIf=\"bank.logoUrl\">\n <img [src]=\"bank.logoUrl\" [alt]=\"bank.displayName\">\n </div>\n <div class=\"bank-info\">\n <h4>{{ bank.displayName }}</h4>\n <span class=\"bank-code\">{{ bank.bankCode }}</span>\n </div>\n <mat-icon class=\"check-icon\" *ngIf=\"selectedBank === bank.bankCode\">check_circle</mat-icon>\n </div>\n </div>\n\n <button\n mat-raised-button\n color=\"primary\"\n (click)=\"proceedToNextStep()\"\n [disabled]=\"!selectedBank || (isLoadingSubject | async)\"\n class=\"m-t-16\">\n {{ continueButtonLabel }}\n </button>\n </div>\n\n <!-- Consent State -->\n <div *ngIf=\"isConsentState\" class=\"state-consent\">\n <div class=\"consent-header\">\n <h3>{{ consentTitle }}</h3>\n <p>{{ consentDescription }}</p>\n </div>\n\n <!-- Show iframe only if we have an authorization URL -->\n <div class=\"consent-container\" *ngIf=\"authorizationUrl\">\n <iframe\n [src]=\"authorizationUrl\"\n class=\"consent-iframe\"\n frameborder=\"0\"\n allowfullscreen\n sandbox=\"allow-forms allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox allow-top-navigation\">\n </iframe>\n </div>\n\n <!-- Show waiting message when consent is in popup or iframe failed -->\n <div class=\"consent-waiting\" *ngIf=\"!authorizationUrl\">\n <mat-spinner diameter=\"40\"></mat-spinner>\n <p>{{ waitingForAuthorizationText }}</p>\n <p class=\"consent-popup-hint\">\n <mat-icon>open_in_new</mat-icon>\n <span>{{ popupWindowMessage }}</span>\n </p>\n <p class=\"consent-popup-note\">\n {{ popupBlockerMessage }}\n </p>\n </div>\n </div>\n\n <!-- Processing State -->\n <div *ngIf=\"isProcessingState\" class=\"state-processing\">\n <div class=\"loading-container\">\n <mat-spinner diameter=\"50\"></mat-spinner>\n <p class=\"loading-message\">{{ waitingMessage }}</p>\n <div class=\"progress-details\">\n <p *ngIf=\"accounts.length > 0\">\n {{ accountsRetrievedLabel }}: {{ accounts.length }}\n </p>\n <p *ngIf=\"transactions.length > 0\">\n {{ transactionsRetrievedLabel }}: {{ transactions.length }}\n </p>\n </div>\n </div>\n </div>\n\n <!-- Error State -->\n <div *ngIf=\"isErrorState\" class=\"state-error\">\n <div class=\"error-container\">\n <mat-icon color=\"warn\" class=\"error-icon\">error_outline</mat-icon>\n <p class=\"error-message\">{{ errorMessage }}</p>\n <button mat-raised-button color=\"primary\" (click)=\"retry()\">\n {{ retryButtonLabel }}\n </button>\n </div>\n </div>\n\n <!-- Complete State -->\n <div *ngIf=\"isCompleteState\" class=\"state-complete\">\n <div class=\"success-container\">\n <mat-icon color=\"primary\" class=\"success-icon\">check_circle</mat-icon>\n <p class=\"success-message\">{{ completionMessage }}</p>\n\n <!-- Display summary of accounts found -->\n <div class=\"accounts-summary\" *ngIf=\"accounts.length > 0\">\n <h4>{{ accountsSummaryText }}</h4>\n <div class=\"accounts-list\">\n <div class=\"account-card\" *ngFor=\"let account of accounts\">\n <div class=\"account-header\">\n <mat-icon class=\"account-icon\">account_balance</mat-icon>\n <div class=\"account-info\">\n <div class=\"account-name\">{{ account.name || 'Account' }}</div>\n <div class=\"account-iban\">{{ account.iban }}</div>\n </div>\n </div>\n <div class=\"account-details\">\n <div class=\"account-balance\">\n <span class=\"balance-amount\">{{ account.balance | currency:account.currency:'symbol':'1.2-2' }}</span>\n </div>\n <div class=\"account-holder\">{{ account.accountHolderName }}</div>\n </div>\n </div>\n </div>\n\n <div class=\"transaction-summary\" *ngIf=\"transactions.length > 0\">\n <p>{{ transactionsSummaryText }}</p>\n </div>\n </div>\n </div>\n </div>\n</div>", styles: [".open-banking-container{padding:20px;min-height:400px}.open-banking-container .section-title{margin-bottom:20px;font-size:1.25rem;font-weight:500;color:#000000de}.open-banking-container .message-container,.open-banking-container .loading-container,.open-banking-container .error-container,.open-banking-container .success-container{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;min-height:200px}.open-banking-container .message,.open-banking-container .loading-message,.open-banking-container .error-message,.open-banking-container .success-message{font-size:1rem;margin:20px 0;max-width:600px;line-height:1.5}.open-banking-container .error-message{color:#f44336}.open-banking-container .success-message{color:#4caf50}.open-banking-container .error-icon,.open-banking-container .success-icon{font-size:48px;width:48px;height:48px}.open-banking-container .state-bank-selection .banks-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:16px;margin-bottom:24px}.open-banking-container .state-bank-selection .bank-card{border:2px solid #e0e0e0;border-radius:8px;padding:16px;cursor:pointer;transition:all .3s ease;position:relative;background:#fff;min-height:120px;display:flex;flex-direction:column;align-items:center;justify-content:center}.open-banking-container .state-bank-selection .bank-card:hover{border-color:#3f51b5;box-shadow:0 4px 8px #0000001a;transform:translateY(-2px)}.open-banking-container .state-bank-selection .bank-card.selected{border-color:#3f51b5;background:#f5f7ff}.open-banking-container .state-bank-selection .bank-card .bank-logo{width:80px;height:40px;margin-bottom:8px;display:flex;align-items:center;justify-content:center}.open-banking-container .state-bank-selection .bank-card .bank-logo img{max-width:100%;max-height:100%;object-fit:contain}.open-banking-container .state-bank-selection .bank-card .bank-info{text-align:center}.open-banking-container .state-bank-selection .bank-card .bank-info h4{margin:0;font-size:.9rem;font-weight:500;color:#333}.open-banking-container .state-bank-selection .bank-card .bank-info .bank-code{font-size:.75rem;color:#666;margin-top:4px;display:block}.open-banking-container .state-bank-selection .bank-card .check-icon{position:absolute;top:8px;right:8px;color:#3f51b5;font-size:20px}.open-banking-container .state-bank-selection .bank-dropdown{margin:20px 0}.open-banking-container .state-bank-selection .bank-selector{width:100%;max-width:400px}.open-banking-container .state-consent .consent-header{text-align:center;margin-bottom:20px}.open-banking-container .state-consent .consent-header h3{font-size:1.25rem;font-weight:500;margin-bottom:8px}.open-banking-container .state-consent .consent-header p{color:#666;font-size:.95rem}.open-banking-container .state-consent .consent-container{width:100%;height:600px;border:1px solid #e0e0e0;border-radius:4px;overflow:hidden;background:#fff}.open-banking-container .state-consent .consent-iframe{width:100%;height:100%}.open-banking-container .state-consent .consent-waiting{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:300px}.open-banking-container .state-consent .consent-waiting p{margin-top:16px;color:#666}.open-banking-container .state-consent .consent-waiting .consent-popup-hint{display:flex;align-items:center;gap:8px;margin-top:24px;font-size:1.1rem;color:#333}.open-banking-container .state-consent .consent-waiting .consent-popup-hint mat-icon{color:#3f51b5}.open-banking-container .state-consent .consent-waiting .consent-popup-note{margin-top:12px;font-size:.9rem;color:#999;font-style:italic}.open-banking-container .progress-details{margin-top:20px}.open-banking-container .progress-details p{font-size:.9rem;color:#666;margin:4px 0}.open-banking-container .accounts-summary{margin-top:30px;width:100%;max-width:800px}.open-banking-container .accounts-summary h4{font-size:1.15rem;font-weight:500;margin-bottom:20px;color:#000000de}.open-banking-container .accounts-summary .accounts-list{display:flex;flex-direction:column;gap:16px}.open-banking-container .accounts-summary .account-card{border:1px solid #e0e0e0;border-radius:8px;padding:16px;background:#fff;box-shadow:0 1px 3px #0000001a;transition:box-shadow .2s ease}.open-banking-container .accounts-summary .account-card:hover{box-shadow:0 2px 6px #00000026}.open-banking-container .accounts-summary .account-header{display:flex;align-items:flex-start;gap:12px;margin-bottom:12px}.open-banking-container .accounts-summary .account-icon{color:#3f51b5;margin-top:2px}.open-banking-container .accounts-summary .account-info{flex:1}.open-banking-container .accounts-summary .account-name{font-weight:500;font-size:1rem;color:#333;margin-bottom:4px}.open-banking-container .accounts-summary .account-iban{font-size:.85rem;color:#666;font-family:Courier New,monospace;letter-spacing:.5px}.open-banking-container .accounts-summary .account-details{display:flex;justify-content:space-between;align-items:center;padding-left:36px}.open-banking-container .accounts-summary .account-balance{display:flex;flex-direction:column}.open-banking-container .accounts-summary .balance-amount{font-size:1.25rem;font-weight:600;color:#4caf50}.open-banking-container .accounts-summary .account-holder{font-size:.9rem;color:#666;text-align:right}.open-banking-container .accounts-summary .transaction-summary{margin-top:16px;padding:12px;background:#e8f5e9;border-radius:4px}.open-banking-container .accounts-summary .transaction-summary p{margin:0;color:#2e7d32;font-size:.95rem}.open-banking-container ::ng-deep .mat-spinner{margin:0 auto}.open-banking-container ::ng-deep .mat-progress-spinner circle,.open-banking-container ::ng-deep .mat-spinner circle{stroke:#3f51b5}@media (max-width: 768px){.open-banking-container{padding:10px}.open-banking-container .state-bank-selection .banks-grid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:12px}.open-banking-container .state-bank-selection .bank-card{min-height:100px;padding:12px}.open-banking-container .state-bank-selection .bank-card .bank-logo{width:60px;height:30px}.open-banking-container .consent-container{height:500px}.open-banking-container .accounts-summary{max-width:100%}}@media (max-width: 480px){.open-banking-container .state-bank-selection .banks-grid{grid-template-columns:1fr}}\n"] }]
13512
13814
  }], ctorParameters: () => [{ type: OpenBankingService }, { type: DialogService }, { type: i3$2.DomSanitizer }, { type: i0.ChangeDetectorRef }] });
13513
13815
 
13816
+ class RowSpacerComponent extends FieldType {
13817
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RowSpacerComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
13818
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: RowSpacerComponent, selector: "formly-row-spacer", usesInheritance: true, ngImport: i0, template: `<div class="row-spacer" [style.paddingTop]="props['spacerMarginTop']" [style.paddingBottom]="props['spacerMarginBottom']"></div>`, isInline: true, styles: [".row-spacer{width:100%}\n"] }); }
13819
+ }
13820
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RowSpacerComponent, decorators: [{
13821
+ type: Component,
13822
+ args: [{ selector: 'formly-row-spacer', template: `<div class="row-spacer" [style.paddingTop]="props['spacerMarginTop']" [style.paddingBottom]="props['spacerMarginBottom']"></div>`, styles: [".row-spacer{width:100%}\n"] }]
13823
+ }] });
13824
+
13825
+ class RowWrapperComponent extends FieldType {
13826
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RowWrapperComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
13827
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: RowWrapperComponent, selector: "formly-row-wrapper", usesInheritance: true, ngImport: i0, template: `
13828
+ <div
13829
+ class="row-wrapper"
13830
+ [style.justifyContent]="props['justifyContent'] || 'flex-start'"
13831
+ >
13832
+ <ng-container *ngFor="let f of field.fieldGroup">
13833
+ <formly-field [field]="f" [ngClass]="f.className"></formly-field>
13834
+ </ng-container>
13835
+ </div>
13836
+ `, isInline: true, styles: [".row-wrapper{display:flex;width:100%;gap:5px;grid-column:span 12}\n"], dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: i4.FormlyField, selector: "formly-field", inputs: ["field"] }] }); }
13837
+ }
13838
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RowWrapperComponent, decorators: [{
13839
+ type: Component,
13840
+ args: [{ selector: 'formly-row-wrapper', template: `
13841
+ <div
13842
+ class="row-wrapper"
13843
+ [style.justifyContent]="props['justifyContent'] || 'flex-start'"
13844
+ >
13845
+ <ng-container *ngFor="let f of field.fieldGroup">
13846
+ <formly-field [field]="f" [ngClass]="f.className"></formly-field>
13847
+ </ng-container>
13848
+ </div>
13849
+ `, styles: [".row-wrapper{display:flex;width:100%;gap:5px;grid-column:span 12}\n"] }]
13850
+ }] });
13851
+
13514
13852
  var themeCss = `
13515
13853
  @import url("https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700&display=swap");
13516
13854
  @import url("https://fonts.googleapis.com/icon?family=Material+Icons");
@@ -15808,6 +16146,8 @@ class OriginFormModule {
15808
16146
  FormlyRadioComponent,
15809
16147
  FormlyCheckboxesComponent,
15810
16148
  RowFillerComponent,
16149
+ RowSpacerComponent,
16150
+ RowWrapperComponent,
15811
16151
  FormlyScanIdComponent,
15812
16152
  FormlySignComponent,
15813
16153
  FormlyUploadDocumentsComponent,
@@ -15943,6 +16283,8 @@ class OriginFormModule {
15943
16283
  { name: 'separator', component: FormSectionSeparatorComponent },
15944
16284
  { name: 'custom-section', component: CustomSectionComponent },
15945
16285
  { name: 'row-filler', component: RowFillerComponent },
16286
+ { name: 'row-spacer', component: RowSpacerComponent },
16287
+ { name: 'row-wrapper', component: RowWrapperComponent },
15946
16288
  {
15947
16289
  name: 'formly-identification-component',
15948
16290
  component: FormlyFieldIdentificationComponent,
@@ -16012,6 +16354,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
16012
16354
  FormlyRadioComponent,
16013
16355
  FormlyCheckboxesComponent,
16014
16356
  RowFillerComponent,
16357
+ RowSpacerComponent,
16358
+ RowWrapperComponent,
16015
16359
  FormlyScanIdComponent,
16016
16360
  FormlySignComponent,
16017
16361
  FormlyUploadDocumentsComponent,
@@ -16092,6 +16436,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
16092
16436
  { name: 'separator', component: FormSectionSeparatorComponent },
16093
16437
  { name: 'custom-section', component: CustomSectionComponent },
16094
16438
  { name: 'row-filler', component: RowFillerComponent },
16439
+ { name: 'row-spacer', component: RowSpacerComponent },
16440
+ { name: 'row-wrapper', component: RowWrapperComponent },
16095
16441
  {
16096
16442
  name: 'formly-identification-component',
16097
16443
  component: FormlyFieldIdentificationComponent,