commons-shared-web-ui 0.0.26 → 0.0.28

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.
package/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { OnChanges, EventEmitter, SimpleChanges, ChangeDetectorRef, OnInit, OnDestroy, ElementRef, PipeTransform, AfterViewInit, QueryList, NgZone } from '@angular/core';
3
+ import * as i2 from '@angular/material/snack-bar';
4
+ import { MatSnackBar, MatSnackBarRef } from '@angular/material/snack-bar';
3
5
  import * as i2$1 from '@angular/common';
4
6
  import * as i3$1 from '@angular/forms';
5
7
  import { FormGroup, FormBuilder, FormArray, FormControl, ValidatorFn, ControlValueAccessor, AbstractControl, ValidationErrors } from '@angular/forms';
@@ -7,8 +9,6 @@ import { HttpClient, HttpHeaders } from '@angular/common/http';
7
9
  import * as i3$2 from '@angular/router';
8
10
  import { Router, ActivatedRoute } from '@angular/router';
9
11
  import { BehaviorSubject, Subject, Observable } from 'rxjs';
10
- import * as i2 from '@angular/material/snack-bar';
11
- import { MatSnackBar, MatSnackBarRef } from '@angular/material/snack-bar';
12
12
  import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
13
13
  import * as i1 from '@angular/material/card';
14
14
  import * as i3 from '@angular/material/checkbox';
@@ -58,6 +58,12 @@ interface FormSchema {
58
58
  metadata?: {
59
59
  [key: string]: any;
60
60
  };
61
+ /**
62
+ * When true, top-level GROUP children of sectionConfig are rendered as
63
+ * a horizontal stepper at the top, showing one section at a time.
64
+ * Navigate between sections via the Next/Previous buttons in the host app.
65
+ */
66
+ sectionStepper?: boolean;
61
67
  sectionConfig?: SectionConfig;
62
68
  stepperConfig?: StepperConfig;
63
69
  submitConfig?: SubmitConfig;
@@ -632,8 +638,15 @@ declare class FieldSelectionService {
632
638
  * Initialize the store from a FormSchema.
633
639
  */
634
640
  loadSchema(schema: FormSchema): void;
641
+ /**
642
+ * Load a schema while preserving the expanded/collapsed state of sections and groups.
643
+ * Used when the schema structure hasn't changed but field selections have.
644
+ * This prevents the UI from unexpectedly collapsing sections when the user toggles a field.
645
+ */
646
+ loadSchemaPreservingExpanded(schema: FormSchema): void;
635
647
  /**
636
648
  * Toggle a group's enabled state. Disabling cascades to all sections + fields.
649
+ * When enabling, all fields are selected (unless locked).
637
650
  */
638
651
  toggleGroup(groupIndex: number): void;
639
652
  /**
@@ -658,9 +671,19 @@ declare class FieldSelectionService {
658
671
  */
659
672
  buildUpdatedSchema(): FormSchema | null;
660
673
  private _disableAllSections;
674
+ /**
675
+ * Enable all sections and their fields (except locked ones).
676
+ * Used when toggling a section/group back ON to restore field selections.
677
+ */
678
+ private _enableAllSections;
661
679
  private _toggleSectionAtPath;
662
680
  private _toggleExpandedAtPath;
663
681
  private _toggleFieldAtPath;
682
+ /**
683
+ * Recursively merge expansion state from old sections into new sections.
684
+ * Preserves which sections were expanded/collapsed by the user.
685
+ */
686
+ private _mergeExpandedSections;
664
687
  static ɵfac: i0.ɵɵFactoryDeclaration<FieldSelectionService, never>;
665
688
  static ɵprov: i0.ɵɵInjectableDeclaration<FieldSelectionService>;
666
689
  }
@@ -677,6 +700,11 @@ declare class FieldSelectionComponent implements OnChanges {
677
700
  */
678
701
  hideToggleForOptionTypes: boolean;
679
702
  protected readonly store: FieldSelectionService;
703
+ /**
704
+ * Flag to track if the next schema change is from internal toggles.
705
+ * When true, we'll use loadSchemaPreservingExpanded() to keep user's expansion state.
706
+ */
707
+ private _isInternalChange;
680
708
  ngOnChanges(changes: SimpleChanges): void;
681
709
  onToggleGroup(groupIndex: number): void;
682
710
  onToggleGroupExpanded(groupIndex: number): void;
@@ -887,9 +915,32 @@ declare class ConfiguratorTreeComponent {
887
915
  static ɵcmp: i0.ɵɵComponentDeclaration<ConfiguratorTreeComponent, "lib-configurator-tree", never, { "tree": { "alias": "tree"; "required": false; }; "selectedFieldPath": { "alias": "selectedFieldPath"; "required": false; }; }, { "selectField": "selectField"; "toggleExpanded": "toggleExpanded"; }, never, never, false, never>;
888
916
  }
889
917
 
918
+ type SnackbarVariant = 'success' | 'error' | 'warning' | 'info';
919
+ interface SnackbarConfig {
920
+ message: string;
921
+ variant?: SnackbarVariant;
922
+ duration?: number;
923
+ horizontalPosition?: 'start' | 'center' | 'end' | 'left' | 'right';
924
+ verticalPosition?: 'top' | 'bottom';
925
+ showCloseButton?: boolean;
926
+ }
927
+
928
+ declare class SnackbarService {
929
+ private snackBar;
930
+ constructor(snackBar: MatSnackBar);
931
+ show(config: SnackbarConfig): void;
932
+ success(message: string, duration?: number): void;
933
+ error(message: string, duration?: number): void;
934
+ warning(message: string, duration?: number): void;
935
+ info(message: string, duration?: number): void;
936
+ static ɵfac: i0.ɵɵFactoryDeclaration<SnackbarService, never>;
937
+ static ɵprov: i0.ɵɵInjectableDeclaration<SnackbarService>;
938
+ }
939
+
890
940
  declare class ConfiguratorConfigPanelComponent implements OnChanges {
891
941
  private cdr;
892
- constructor(cdr: ChangeDetectorRef);
942
+ private snackbarService;
943
+ constructor(cdr: ChangeDetectorRef, snackbarService: SnackbarService);
893
944
  selectedField: FieldConfig | null;
894
945
  selectedFieldInfo: ConfiguratorFieldInfo | null;
895
946
  builderFieldType: string | null;
@@ -938,8 +989,14 @@ declare class ConfiguratorConfigPanelComponent implements OnChanges {
938
989
  */
939
990
  private _buildConfigFormForType;
940
991
  /**
941
- * Deep-clones the schema and removes any field whose `name` starts with
942
- * `optionConfig.` and removes entire sections that become empty after that.
992
+ * Deep-clones the schema and removes any field whose `name` matches developer-only fields.
993
+ * This prevents end users from modifying system-level configurations like:
994
+ * - optionConfig.* (API URLs, data paths, etc.)
995
+ * - payloadPath (payload mapping)
996
+ * - className (CSS styling)
997
+ * - name (system identifier)
998
+ *
999
+ * Also removes entire sections that become empty after filtering.
943
1000
  */
944
1001
  private _filterSchemaForOptionConfig;
945
1002
  private _extractInitialValuesFromField;
@@ -993,28 +1050,6 @@ declare class ExpressionService {
993
1050
  static ɵprov: i0.ɵɵInjectableDeclaration<ExpressionService>;
994
1051
  }
995
1052
 
996
- type SnackbarVariant = 'success' | 'error' | 'warning' | 'info';
997
- interface SnackbarConfig {
998
- message: string;
999
- variant?: SnackbarVariant;
1000
- duration?: number;
1001
- horizontalPosition?: 'start' | 'center' | 'end' | 'left' | 'right';
1002
- verticalPosition?: 'top' | 'bottom';
1003
- showCloseButton?: boolean;
1004
- }
1005
-
1006
- declare class SnackbarService {
1007
- private snackBar;
1008
- constructor(snackBar: MatSnackBar);
1009
- show(config: SnackbarConfig): void;
1010
- success(message: string, duration?: number): void;
1011
- error(message: string, duration?: number): void;
1012
- warning(message: string, duration?: number): void;
1013
- info(message: string, duration?: number): void;
1014
- static ɵfac: i0.ɵɵFactoryDeclaration<SnackbarService, never>;
1015
- static ɵprov: i0.ɵɵInjectableDeclaration<SnackbarService>;
1016
- }
1017
-
1018
1053
  declare class SmartFormComponent implements OnInit, OnChanges, OnDestroy {
1019
1054
  private fb;
1020
1055
  controller: SmartFormController;
@@ -1058,6 +1093,15 @@ declare class SmartFormComponent implements OnInit, OnChanges, OnDestroy {
1058
1093
  fileAdded: EventEmitter<any>;
1059
1094
  fileUploadFinished: EventEmitter<any>;
1060
1095
  fileRemoved: EventEmitter<any>;
1096
+ /** Emitted whenever the active section step changes. Carries current state so the
1097
+ * host can show/hide Previous/Next/Submit buttons in its own footer. */
1098
+ stepChange: EventEmitter<{
1099
+ currentStep: number;
1100
+ totalSteps: number;
1101
+ isFirst: boolean;
1102
+ isLast: boolean;
1103
+ stepLabel: string;
1104
+ }>;
1061
1105
  formSchema: FormSchema;
1062
1106
  formGroup: FormGroup;
1063
1107
  fieldList: FieldConfig[];
@@ -1065,9 +1109,27 @@ declare class SmartFormComponent implements OnInit, OnChanges, OnDestroy {
1065
1109
  currentStep: number;
1066
1110
  isLoading: boolean;
1067
1111
  isDraftLoading: boolean;
1112
+ /** True when sectionStepper mode is active (SECTION form with top-level GROUPs as steps). */
1113
+ isSectionStepper: boolean;
1114
+ /** Index of the currently visible section step. */
1115
+ currentSectionStep: number;
1116
+ /** Flat list of top-level GROUP FieldConfigs that become the stepper steps. */
1117
+ sectionSteps: FieldConfig[];
1118
+ /** Validation state per section step — drives badge colour/icon. */
1119
+ stepValidationStates: ('untouched' | 'valid' | 'warning')[];
1120
+ /** Flat field-name lists per step used for targeted validation. */
1121
+ private stepFieldNames;
1122
+ /** Controls skeleton visibility. Stays false until schema is parsed AND
1123
+ * any EDIT-mode data fetch completes, but always shows for at least
1124
+ * SKELETON_MIN_MS so the animation is visible even on fast loads. */
1125
+ isFormReady: boolean;
1126
+ private readonly SKELETON_MIN_MS;
1127
+ private _skeletonStart;
1068
1128
  constructor(fb: FormBuilder, controller: SmartFormController, expressionService: ExpressionService, http: HttpClient, snackbarService: SnackbarService, router: Router);
1069
1129
  ngOnInit(): void;
1070
1130
  loadEditData(): void;
1131
+ /** Flips isFormReady=true after the skeleton has been visible for at least SKELETON_MIN_MS. */
1132
+ private _markReady;
1071
1133
  ngOnChanges(changes: SimpleChanges): void;
1072
1134
  ngOnDestroy(): void;
1073
1135
  parseFormJson(): void;
@@ -1104,6 +1166,25 @@ declare class SmartFormComponent implements OnInit, OnChanges, OnDestroy {
1104
1166
  get canGoNext(): boolean;
1105
1167
  get canGoPrevious(): boolean;
1106
1168
  get currentStepConfig(): FieldConfig | undefined;
1169
+ /** Advance to the next section step. Called by the host footer "Next" button.
1170
+ * Validates the current step first — marks it valid (green) or warning (orange). */
1171
+ navigateToNext(): void;
1172
+ /** Go back to the previous section step. Called by the host footer "Previous" button. */
1173
+ navigateToPrevious(): void;
1174
+ /** Jump directly to a specific section step by index.
1175
+ * Validates the step being left so the badge state updates correctly. */
1176
+ goToSectionStep(index: number): void;
1177
+ get isSectionStepFirst(): boolean;
1178
+ get isSectionStepLast(): boolean;
1179
+ /** Returns the SectionConfig for a given step — passed to lib-form-section.
1180
+ * The outer label is intentionally omitted because the stepper nav already
1181
+ * displays it; showing it again inside the content would be redundant. */
1182
+ getSectionStepConfig(step: FieldConfig): any;
1183
+ private _emitStepChange;
1184
+ /** Marks all controls in the given step as touched and records valid/warning state. */
1185
+ private _validateStep;
1186
+ /** Recursively collects all leaf field names from a set of FieldConfigs. */
1187
+ private _collectFieldNames;
1107
1188
  get nextLabel(): string;
1108
1189
  get submitLabel(): string;
1109
1190
  get previousLabel(): string;
@@ -1117,7 +1198,7 @@ declare class SmartFormComponent implements OnInit, OnChanges, OnDestroy {
1117
1198
  private getButtonByActionKind;
1118
1199
  private navigateTo;
1119
1200
  static ɵfac: i0.ɵɵFactoryDeclaration<SmartFormComponent, never>;
1120
- static ɵcmp: i0.ɵɵComponentDeclaration<SmartFormComponent, "lib-smart-form", never, { "formJson": { "alias": "formJson"; "required": false; }; "initialValues": { "alias": "initialValues"; "required": false; }; "enableDraftAutoSave": { "alias": "enableDraftAutoSave"; "required": false; }; "labels": { "alias": "labels"; "required": false; }; "mode": { "alias": "mode"; "required": false; }; "readOnly": { "alias": "readOnly"; "required": false; }; }, { "submit": "submit"; "draftSave": "draftSave"; "actionClick": "actionClick"; "valueChange": "valueChange"; "fileAdded": "fileAdded"; "fileUploadFinished": "fileUploadFinished"; "fileRemoved": "fileRemoved"; }, never, never, false, never>;
1201
+ static ɵcmp: i0.ɵɵComponentDeclaration<SmartFormComponent, "lib-smart-form", never, { "formJson": { "alias": "formJson"; "required": false; }; "initialValues": { "alias": "initialValues"; "required": false; }; "enableDraftAutoSave": { "alias": "enableDraftAutoSave"; "required": false; }; "labels": { "alias": "labels"; "required": false; }; "mode": { "alias": "mode"; "required": false; }; "readOnly": { "alias": "readOnly"; "required": false; }; }, { "submit": "submit"; "draftSave": "draftSave"; "actionClick": "actionClick"; "valueChange": "valueChange"; "fileAdded": "fileAdded"; "fileUploadFinished": "fileUploadFinished"; "fileRemoved": "fileRemoved"; "stepChange": "stepChange"; }, never, never, false, never>;
1121
1202
  }
1122
1203
 
1123
1204
  declare class FormSectionComponent implements OnInit, OnDestroy {
@@ -1130,6 +1211,8 @@ declare class FormSectionComponent implements OnInit, OnDestroy {
1130
1211
  * Each element is a FormGroup representing one repeater instance.
1131
1212
  */
1132
1213
  repeaterFormArray: FormArray;
1214
+ /** Tracks which accordion panels are open (by index). New instances start expanded. */
1215
+ expandedInstances: Set<number>;
1133
1216
  /**
1134
1217
  * The key under which the FormArray is registered in the root formGroup.
1135
1218
  * Falls back to config.name or a generated key.
@@ -1142,6 +1225,8 @@ declare class FormSectionComponent implements OnInit, OnDestroy {
1142
1225
  private createInstanceGroup;
1143
1226
  addInstance(): void;
1144
1227
  removeInstance(index: number): void;
1228
+ toggleInstance(index: number): void;
1229
+ isExpanded(index: number): boolean;
1145
1230
  getInstanceGroup(index: number): FormGroup;
1146
1231
  get instanceGroups(): FormGroup[];
1147
1232
  /** For non-allowMulti sections we simply pass the root formGroup down */
@@ -1233,6 +1318,8 @@ declare class FormFieldComponent implements OnInit, OnDestroy {
1233
1318
  isExpanded?: boolean;
1234
1319
  }[];
1235
1320
  private _nextInstanceId;
1321
+ /** Tracks open accordion panels for standard (non-multiSave) GROUP repeaters. */
1322
+ expandedGroupInstances: Set<number>;
1236
1323
  /**
1237
1324
  * Key used to register the GROUP control on the parent formGroup.
1238
1325
  * Priority: sectionConfig.name > field.name > camelCase(label) > '__group__'
@@ -1254,6 +1341,8 @@ declare class FormFieldComponent implements OnInit, OnDestroy {
1254
1341
  editGroupInstance(index: number): void;
1255
1342
  toggleExpandGroupInstance(index: number): void;
1256
1343
  removeGroupInstance(index: number, force?: boolean): void;
1344
+ toggleGroupAccordion(index: number): void;
1345
+ isGroupExpanded(index: number): boolean;
1257
1346
  trackByInstanceId(_: number, item: {
1258
1347
  id: number;
1259
1348
  fg: FormGroup;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "commons-shared-web-ui",
3
- "version": "0.0.26",
3
+ "version": "0.0.28",
4
4
  "peerDependencies": {
5
5
  "@angular/animations": "20.3.15",
6
6
  "@angular/cdk": "20.2.14",