@qbs-origin/origin-form 0.8.10 → 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 (27) 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/model-population.helper.mjs +22 -1
  10. package/esm2022/lib/models/flux.model.mjs +1 -1
  11. package/esm2022/lib/models/forms.model.mjs +77 -25
  12. package/esm2022/lib/origin-form.component.mjs +170 -55
  13. package/esm2022/lib/origin-form.module.mjs +11 -1
  14. package/esm2022/lib/services/applicationData.service.mjs +1 -1
  15. package/fesm2022/qbs-origin-origin-form.mjs +518 -151
  16. package/fesm2022/qbs-origin-origin-form.mjs.map +1 -1
  17. package/lib/form-css.helper.d.ts +7 -0
  18. package/lib/formly/form-section-separator.component.d.ts +2 -2
  19. package/lib/formly/formly-dictionary-dropdown-tree/formly-dictionary-dropdown-tree.component.d.ts +2 -1
  20. package/lib/formly/formly-row-spacer.d.ts +6 -0
  21. package/lib/formly/formly-row-wrapper.d.ts +6 -0
  22. package/lib/models/flux.model.d.ts +4 -0
  23. package/lib/models/forms.model.d.ts +22 -6
  24. package/lib/origin-form.component.d.ts +6 -1
  25. package/lib/origin-form.module.d.ts +64 -62
  26. package/lib/services/applicationData.service.d.ts +1 -1
  27. 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]
@@ -5767,6 +5865,27 @@ class ModelPopulationHelper {
5767
5865
  }
5768
5866
  }
5769
5867
  }
5868
+ // Also add inherited fields not matching any flux control
5869
+ // (needed for componentCollected references from parent flows, e.g., Sign phone)
5870
+ if (fillData.inheritedFields) {
5871
+ for (const [key, value] of Object.entries(fillData.inheritedFields)) {
5872
+ if (model[key] !== undefined)
5873
+ continue;
5874
+ if (value === undefined || value === null)
5875
+ continue;
5876
+ if (typeof value === 'object' &&
5877
+ !Array.isArray(value) &&
5878
+ value.dictionaryUUID) {
5879
+ const fv = value.fillValue;
5880
+ if (fv !== undefined && fv !== null) {
5881
+ model[key] = fv;
5882
+ }
5883
+ }
5884
+ else {
5885
+ model[key] = value;
5886
+ }
5887
+ }
5888
+ }
5770
5889
  // Apply precompletion for ManualInput controls
5771
5890
  ModelPopulationHelper.applyPrecompletionToModel(model, flux);
5772
5891
  return model;
@@ -5951,38 +6070,97 @@ class FormCssHelper {
5951
6070
  case '.component-data':
5952
6071
  cssText = this.getSpecificCssForData(key, values, cssRules);
5953
6072
  break;
6073
+ case '.component-dictionary':
6074
+ cssText = this.getSpecificCssForDictionary(key, values, cssRules);
6075
+ break;
5954
6076
  case '.table-details':
5955
6077
  cssText = this.getSpecificCssForTableDetail(values);
5956
6078
  break;
5957
6079
  case '.table-header':
5958
6080
  cssText = this.getSpecificCssForTableHeader(values);
5959
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(' ')} }`;
5960
6098
  }
5961
6099
  return cssText;
5962
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
+ }
5963
6138
  static getSpecificCssForInput(key, values, cssRules) {
5964
6139
  let inputSpecificCss = '';
5965
6140
  let signInputSpecificCss = '';
5966
- const fontStyleForInputText = cssRules['.font-input'];
5967
- if (fontStyleForInputText) {
6141
+ const fontStyleSource = cssRules['.component-text-field-value'] || cssRules['.font-input'];
6142
+ if (fontStyleSource) {
6143
+ const fontStyleForInputText = { ...fontStyleSource };
5968
6144
  //transfer property from component to input
5969
6145
  if (values['text-align']) {
5970
6146
  fontStyleForInputText['text-align'] = values['text-align'];
5971
6147
  }
5972
- fontStyleForInputText['color'] += ' !important';
5973
- inputSpecificCss = this.styleObjectToString(fontStyleForInputText);
5974
- signInputSpecificCss = this.styleObjectToString(fontStyleForInputText, true);
6148
+ fontStyleForInputText['color'] = (fontStyleForInputText['color'] || '') + ' !important';
6149
+ inputSpecificCss = this.styleObjectToString({ ...fontStyleForInputText });
6150
+ signInputSpecificCss = this.styleObjectToString({ ...fontStyleForInputText }, true);
5975
6151
  }
5976
6152
  let labelSpecificCss = '';
5977
6153
  let signLabelSpecificCss = '';
5978
- const fontStyleForLabelText = cssRules['.component-text-field-label'];
5979
- if (fontStyleForLabelText) {
5980
- labelSpecificCss = this.styleObjectToString(fontStyleForLabelText);
5981
- 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);
5982
6158
  }
6159
+ const textareaHeight = values['textarea-height'] || '';
6160
+ const textareaMaxHeight = values['textarea-max-height'] || '';
5983
6161
  var css = `
5984
6162
  .mat-mdc-text-field-wrapper.mdc-text-field {
5985
- ${this.styleObjectToString(values)};
6163
+ ${this.styleObjectToString({ ...values })};
5986
6164
  border-style: solid;
5987
6165
  input {
5988
6166
  ${inputSpecificCss}
@@ -5991,13 +6169,13 @@ class FormCssHelper {
5991
6169
  ${labelSpecificCss}
5992
6170
  }
5993
6171
  .mdc-line-ripple--active::after {
5994
- border-bottom-color: ${fontStyleForLabelText['color']}
6172
+ border-bottom-color: ${labelSource ? labelSource['color'] : 'inherit'}
5995
6173
  }
5996
6174
  }
5997
6175
 
5998
6176
  input.component-text-field {
5999
6177
  border-style: solid !important;
6000
- ${this.styleObjectToString(values, true)};
6178
+ ${this.styleObjectToString({ ...values }, true)};
6001
6179
  ${signInputSpecificCss}
6002
6180
  }
6003
6181
 
@@ -6005,7 +6183,34 @@ class FormCssHelper {
6005
6183
  ${signLabelSpecificCss}
6006
6184
  }
6007
6185
  `;
6008
- 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
+ `;
6009
6214
  }
6010
6215
  static getSpecificCssForTableHeader(values) {
6011
6216
  const backgroundColor = values['background-color'] || '#ffffff';
@@ -6186,7 +6391,8 @@ class FormCssHelper {
6186
6391
  .component-text-field mat-label,
6187
6392
  .component-checkbox mat-label,
6188
6393
  .component-radio mat-label,
6189
- .component-date mat-label {
6394
+ .component-date mat-label,
6395
+ .component-dictionary mat-label {
6190
6396
  ${cssRules['.font-label']
6191
6397
  ? this.styleObjectToString(cssRules['.font-label'])
6192
6398
  : ''}
@@ -6241,21 +6447,22 @@ class FormCssHelper {
6241
6447
  }
6242
6448
  static getSpecificCssForData(key, values, cssRules) {
6243
6449
  let inputSpecificCss = '';
6244
- const fontStyleForInputText = cssRules['.font-list'];
6245
- if (fontStyleForInputText) {
6450
+ const fontStyleSource = cssRules['.component-date-value'] || cssRules['.component-data-value'] || cssRules['.font-list'];
6451
+ if (fontStyleSource) {
6452
+ const fontStyleForInputText = { ...fontStyleSource };
6246
6453
  //transfer property from component to input
6247
6454
  if (values['text-align']) {
6248
6455
  fontStyleForInputText['text-align'] = values['text-align'];
6249
6456
  }
6250
- inputSpecificCss = this.styleObjectToString(fontStyleForInputText);
6457
+ inputSpecificCss = this.styleObjectToString({ ...fontStyleForInputText });
6251
6458
  }
6252
6459
  let labelSpecificCss = '';
6253
- const fontStyleForLabelText = cssRules['.component-data-label'];
6254
- if (fontStyleForLabelText) {
6255
- labelSpecificCss = this.styleObjectToString(fontStyleForLabelText);
6460
+ const labelSource = cssRules['.component-data-label'];
6461
+ if (labelSource) {
6462
+ labelSpecificCss = this.styleObjectToString({ ...labelSource });
6256
6463
  }
6257
6464
  return ` ${key} { .mat-mdc-text-field-wrapper.mdc-text-field {
6258
- ${this.styleObjectToString(values)};
6465
+ ${this.styleObjectToString({ ...values })};
6259
6466
  border-style:solid;
6260
6467
  input{
6261
6468
  ${inputSpecificCss}
@@ -6268,13 +6475,19 @@ class FormCssHelper {
6268
6475
  }
6269
6476
  } `;
6270
6477
  }
6478
+ static { this.INTERNAL_KEYS = ['textarea-height', 'textarea-max-height', 'component-margin-top', 'component-margin-bottom']; }
6271
6479
  static styleObjectToString(values, important = false) {
6272
- values['width'] =
6273
- 'calc(100%' +
6274
- ('margin-left' in values ? ` - ${values['margin-left']}` : '') +
6275
- ('margin-right' in values ? ` - ${values['margin-right']}` : '') +
6276
- ')';
6277
- 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)
6278
6491
  .map(([key, value]) => `${key}: ${value}${important ? ' !important' : ''}`)
6279
6492
  .join('; ');
6280
6493
  }
@@ -7631,9 +7844,10 @@ class CollectorFormComponent {
7631
7844
  }
7632
7845
  }
7633
7846
  }
7634
- resolvedValue = displayValues.length > 0
7635
- ? displayValues.join(', ')
7636
- : (enriched.fillValue ?? String(value));
7847
+ resolvedValue =
7848
+ displayValues.length > 0
7849
+ ? displayValues.join(', ')
7850
+ : (enriched.fillValue ?? String(value));
7637
7851
  }
7638
7852
  else {
7639
7853
  // Single-select
@@ -7750,6 +7964,39 @@ class CollectorFormComponent {
7750
7964
  }
7751
7965
  return actionsExecuted;
7752
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
+ }
7753
8000
  async executeActionStepsAfterCurrentStep(currentStepIndex) {
7754
8001
  if (this.actionStepHandler.isExecutingActions) {
7755
8002
  return false;
@@ -7805,35 +8052,6 @@ class CollectorFormComponent {
7805
8052
  return false;
7806
8053
  }
7807
8054
  }
7808
- async executeLeadingActionSteps() {
7809
- if (!this.appDataUuid || !this.flux || this.flux.length === 0) {
7810
- return;
7811
- }
7812
- const leadingActionSteps = this.actionStepHandler.getActionStepsBeforeFirstVisibleStep(this.flux);
7813
- if (leadingActionSteps.length === 0) {
7814
- return;
7815
- }
7816
- console.log(`🎬 Executing ${leadingActionSteps.length} leading action steps before first visible step`);
7817
- this.isLoading = true;
7818
- try {
7819
- const result = await this.actionStepHandler.executeActionSteps(leadingActionSteps, this.appDataUuid, (step) => {
7820
- const loadingMessage = Utils.findTranslationInfo('loadingMessageTranslations', step.translations, this.currentLanguageIso);
7821
- this.loadingMessage = loadingMessage || null;
7822
- });
7823
- if (result.success) {
7824
- console.log('✅ Leading action steps executed successfully');
7825
- }
7826
- else {
7827
- console.error('❌ Leading action steps failed:', result.error);
7828
- }
7829
- }
7830
- catch (error) {
7831
- console.error('❌ Error executing leading action steps:', error);
7832
- }
7833
- finally {
7834
- this.loadingMessage = null;
7835
- }
7836
- }
7837
8055
  onSelectedPageChanged(index) {
7838
8056
  if (this.formlyConfig[0].fieldGroup) {
7839
8057
  var selectedPage = this.formlyConfig[0].fieldGroup[index];
@@ -8462,15 +8680,47 @@ class CollectorFormComponent {
8462
8680
  if (section.dependentDictionary) {
8463
8681
  this.attachToDependentDictionaryIfNecessary(section.dependentDictionary, separatorFormlyConfig);
8464
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
+ }
8465
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
+ }
8466
8712
  const sectionFormlyConfig = {
8467
8713
  type: 'custom-section',
8468
8714
  props: {
8469
8715
  label: section.title,
8470
8716
  description: section.translations?.find((t) => t.languageIso === this.currentLanguageIso)?.value ?? '',
8471
- 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,
8472
8722
  },
8473
- fieldGroup: await this.buildControlsFieldGroupAsync(step, section.controls || [], section.presentationControls || []),
8723
+ fieldGroup: sectionControls,
8474
8724
  fieldGroupClassName: 'display-flex'
8475
8725
  };
8476
8726
  if (section.dependentDictionary) {
@@ -8534,7 +8784,7 @@ class CollectorFormComponent {
8534
8784
  }
8535
8785
  };
8536
8786
  }
8537
- async buildControlsFieldGroupAsync(step, controls, presentationControls) {
8787
+ async buildControlsFieldGroupAsync(step, controls, presentationControls, initialPendingMarginBottom) {
8538
8788
  const result = [];
8539
8789
  let rowItems = [];
8540
8790
  controls = controls.filter((c) => !c.isOnlyForConfig);
@@ -8546,12 +8796,15 @@ class CollectorFormComponent {
8546
8796
  return false;
8547
8797
  return true;
8548
8798
  });
8549
- const processRow = async (items) => {
8799
+ const processRow = async (items, useFlexWidth = false) => {
8550
8800
  const fields = [];
8551
8801
  const total = 12;
8552
8802
  const built = [];
8553
8803
  const auto = [];
8554
8804
  let used = 0;
8805
+ const getWidthClass = (dim) => useFlexWidth
8806
+ ? this.getFlexWidthClassName(dim)
8807
+ : this.getPercentageClassName(dim);
8555
8808
  for (const i of items) {
8556
8809
  if ('collectionControlIdentifier' in i === true) {
8557
8810
  built.push(await this.buildPresentationFormFieldAsync(step, i));
@@ -8573,53 +8826,118 @@ class CollectorFormComponent {
8573
8826
  else {
8574
8827
  const s = Math.round((c.dimension / 100) * total);
8575
8828
  used += s;
8576
- const percentageClass = this.getPercentageClassName(c.dimension);
8577
- f.className = `${f.className} ${percentageClass}`;
8829
+ f.className = `${f.className} ${getWidthClass(c.dimension)}`;
8578
8830
  }
8579
8831
  }
8580
8832
  else if (c.dimensionType === DimensionType.Pixels) {
8581
8833
  const s = Math.round((c.dimension / window.innerWidth) * total);
8582
8834
  used += s;
8583
- const percentageClass = this.getPercentageClassName((s / total) * 100);
8584
- f.className = `${f.className} ${percentageClass}`;
8835
+ f.className = `${f.className} ${getWidthClass((s / total) * 100)}`;
8585
8836
  }
8586
8837
  else if (c.autoDimension) {
8587
8838
  auto.push({ c, f });
8588
8839
  }
8589
8840
  else {
8590
8841
  used += 1;
8591
- const percentageClass = this.getPercentageClassName((1 / total) * 100);
8592
- f.className = `${f.className} ${percentageClass}`;
8842
+ f.className = `${f.className} ${getWidthClass((1 / total) * 100)}`;
8593
8843
  }
8594
8844
  }
8595
8845
  const rem = total - used;
8596
8846
  if (auto.length > 0) {
8597
8847
  const share = Math.max(Math.floor(rem / auto.length), 1);
8598
8848
  for (const a of auto) {
8599
- const percentageClass = this.getPercentageClassName((share / total) * 100);
8600
- a.f.className = `${a.f.className} ${percentageClass}`;
8849
+ a.f.className = `${a.f.className} ${getWidthClass((share / total) * 100)}`;
8601
8850
  }
8602
8851
  }
8603
8852
  fields.push(...built);
8604
8853
  return fields;
8605
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;
8606
8859
  for (const c of [...controls, ...presentationControls]) {
8607
8860
  if (('type' in c && c.type === StepControlType.NewRow) ||
8608
8861
  c.type == PresentationControlType.NewRow) {
8609
8862
  if (rowItems.length > 0) {
8610
- 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
+ }
8611
8876
  rowItems = [];
8612
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
+ }
8613
8895
  }
8614
8896
  else {
8615
8897
  rowItems.push(c);
8616
8898
  }
8617
8899
  }
8618
8900
  if (rowItems.length > 0) {
8619
- 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
+ });
8620
8921
  }
8621
8922
  return result;
8622
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
+ }
8623
8941
  getPixelClassName(pixelDimension) {
8624
8942
  const className = `pixel-width-${pixelDimension}`;
8625
8943
  if (!document.getElementById(className)) {
@@ -8655,7 +8973,8 @@ class CollectorFormComponent {
8655
8973
  '.component-checkbox',
8656
8974
  '.component-radio',
8657
8975
  '.component-date',
8658
- '.component-data'
8976
+ '.component-data',
8977
+ '.component-dictionary'
8659
8978
  ];
8660
8979
  let formlyConfig = this.getDefaultFormlyFieldConfig(control, initialType, pattern, componentStyleKey, componentsToExcludeFromStyle);
8661
8980
  //control.specificControlData.type === 3 is email
@@ -8679,8 +8998,8 @@ class CollectorFormComponent {
8679
8998
  formlyConfig.type = 'input';
8680
8999
  break;
8681
9000
  case ManualInputControlType.TextArea:
8682
- formlyConfig.type = 'input';
8683
- formlyConfig.props['autosize'] = false;
9001
+ formlyConfig.type = 'textarea';
9002
+ formlyConfig.props['autosize'] = true;
8684
9003
  componentStyleKey = '.component-text-field';
8685
9004
  break;
8686
9005
  case ManualInputControlType.DateTime:
@@ -8700,7 +9019,11 @@ class CollectorFormComponent {
8700
9019
  formlyConfig.type = 'formly-paragraph';
8701
9020
  componentStyleKey = '.component-text-field';
8702
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 || '';
8703
9023
  formlyConfig.defaultValue = translatedDescription;
9024
+ formlyConfig.props['translatedDescription'] = translatedDescription;
9025
+ formlyConfig.props['translatedParagraphTitle'] =
9026
+ translatedParagraphTitle;
8704
9027
  break;
8705
9028
  case StepControlType.CheckBox: // Checkbox
8706
9029
  formlyConfig.type = 'formly-checkbox';
@@ -8709,10 +9032,15 @@ class CollectorFormComponent {
8709
9032
  formlyConfig.props['checked'] = checked;
8710
9033
  break;
8711
9034
  case StepControlType.Dictionary: // Dictionary (dropdown)
8712
- componentStyleKey =
8713
- control.specificControlData.showAsRadioButtonsList === true
8714
- ? '.component-radio'
8715
- : '.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
+ }
8716
9044
  await this.constructDictionary(control, formlyConfig);
8717
9045
  break;
8718
9046
  case StepControlType.Buttons:
@@ -8828,6 +9156,7 @@ class CollectorFormComponent {
8828
9156
  title: control.translations?.find((t) => t.languageIso === this.currentLanguageIso)?.value || '',
8829
9157
  design: this.design,
8830
9158
  required: control.isMandatory,
9159
+ validateThroughApi: control.specificControlData?.isApiValidation,
8831
9160
  attributes: {
8832
9161
  style: componentsToExcludeFromStyle.find((c) => c === componentStyleKey)
8833
9162
  ? ''
@@ -9046,7 +9375,6 @@ class CollectorFormComponent {
9046
9375
  formlyConfig.defaultValue = fillValue ? '&check;' : '&cross;';
9047
9376
  break;
9048
9377
  case 'object':
9049
- // Enriched inherited dictionary format: extract fillValue for display
9050
9378
  if (fillValue.fillValue !== undefined) {
9051
9379
  formlyConfig.defaultValue = fillValue.fillValue;
9052
9380
  }
@@ -10771,11 +11099,11 @@ class FormlyRadioComponent extends FieldType {
10771
11099
  }
10772
11100
  }
10773
11101
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FormlyRadioComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
10774
- 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]" }] }); }
10775
11103
  }
10776
11104
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FormlyRadioComponent, decorators: [{
10777
11105
  type: Component,
10778
- 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"] }]
10779
11107
  }] });
10780
11108
 
10781
11109
  class FormlyCheckboxesComponent extends FieldType {
@@ -10892,11 +11220,10 @@ class FormlyScanIdComponent extends FieldType {
10892
11220
  ngOnInit() {
10893
11221
  const group = this.form;
10894
11222
  group.addControl(this.props['identifier'], this.control);
10895
- this.validFormats = this.props['config'].allowedFormats?.split(',') || [
10896
- '.jpg',
10897
- '.png',
10898
- ];
10899
- 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;
10900
11227
  if (this.props['config'].collected) {
10901
11228
  const controlId = this.props['config'].componentCollected;
10902
11229
  const value = this.form.get(controlId)?.value ?? this.model?.[controlId];
@@ -11224,28 +11551,24 @@ class FormlyScanIdComponent extends FieldType {
11224
11551
  ],
11225
11552
  };
11226
11553
  this.appDataService.scanId(command).subscribe({
11227
- next: async (result) => {
11228
- console.log('Scan ID result:', result);
11554
+ next: async (isValid) => {
11555
+ console.log('Scan ID result:', isValid);
11229
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
+ }
11230
11566
  const appData = await this.appDataService.getSteps(this.props['appDataId']);
11231
- if (appData) {
11232
- const status = this.extractStatusFromAppData(appData);
11233
- console.log('[SCAN-ID] extracted status:', status);
11234
- if (status?.toLowerCase().includes('invalid')) {
11235
- this.fileError =
11236
- this.props['errorMessages']?.invalidStatus ||
11237
- 'Invalid status response.';
11238
- this.canRetry = true;
11239
- this.control.setErrors({ invalidStatus: true });
11240
- this.cdr.detectChanges();
11241
- return;
11242
- }
11243
- this.isScanValid = true;
11244
- this.successMessage = 'Upload successful!';
11245
- this.wizardSteps.forEach((s) => (s.status = 'completed'));
11246
- if (this.props['event']) {
11247
- this.props['event'](appData);
11248
- }
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);
11249
11572
  }
11250
11573
  this.cdr.detectChanges();
11251
11574
  },
@@ -13490,6 +13813,42 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
13490
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"] }]
13491
13814
  }], ctorParameters: () => [{ type: OpenBankingService }, { type: DialogService }, { type: i3$2.DomSanitizer }, { type: i0.ChangeDetectorRef }] });
13492
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
+
13493
13852
  var themeCss = `
13494
13853
  @import url("https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700&display=swap");
13495
13854
  @import url("https://fonts.googleapis.com/icon?family=Material+Icons");
@@ -15787,6 +16146,8 @@ class OriginFormModule {
15787
16146
  FormlyRadioComponent,
15788
16147
  FormlyCheckboxesComponent,
15789
16148
  RowFillerComponent,
16149
+ RowSpacerComponent,
16150
+ RowWrapperComponent,
15790
16151
  FormlyScanIdComponent,
15791
16152
  FormlySignComponent,
15792
16153
  FormlyUploadDocumentsComponent,
@@ -15922,6 +16283,8 @@ class OriginFormModule {
15922
16283
  { name: 'separator', component: FormSectionSeparatorComponent },
15923
16284
  { name: 'custom-section', component: CustomSectionComponent },
15924
16285
  { name: 'row-filler', component: RowFillerComponent },
16286
+ { name: 'row-spacer', component: RowSpacerComponent },
16287
+ { name: 'row-wrapper', component: RowWrapperComponent },
15925
16288
  {
15926
16289
  name: 'formly-identification-component',
15927
16290
  component: FormlyFieldIdentificationComponent,
@@ -15991,6 +16354,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
15991
16354
  FormlyRadioComponent,
15992
16355
  FormlyCheckboxesComponent,
15993
16356
  RowFillerComponent,
16357
+ RowSpacerComponent,
16358
+ RowWrapperComponent,
15994
16359
  FormlyScanIdComponent,
15995
16360
  FormlySignComponent,
15996
16361
  FormlyUploadDocumentsComponent,
@@ -16071,6 +16436,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
16071
16436
  { name: 'separator', component: FormSectionSeparatorComponent },
16072
16437
  { name: 'custom-section', component: CustomSectionComponent },
16073
16438
  { name: 'row-filler', component: RowFillerComponent },
16439
+ { name: 'row-spacer', component: RowSpacerComponent },
16440
+ { name: 'row-wrapper', component: RowWrapperComponent },
16074
16441
  {
16075
16442
  name: 'formly-identification-component',
16076
16443
  component: FormlyFieldIdentificationComponent,