commons-shared-web-ui 0.0.76 → 0.0.78

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
@@ -526,6 +526,33 @@ interface OptionConfig$1 {
526
526
  * pagination is added.
527
527
  */
528
528
  customUI?: boolean;
529
+ /** Edit-mode lookup for resolving primitive initial values (id/code) into full option objects via targeted API call. */
530
+ lookupConfig?: LookupConfig;
531
+ }
532
+ /**
533
+ * Configuration for resolving primitive initial values (id/code) into full
534
+ * option objects during edit-mode form initialization.
535
+ * Only fires when selectedOptionsData is absent and initialValues contains
536
+ * a primitive (not a full object).
537
+ */
538
+ interface LookupConfig {
539
+ /** Endpoint URL. Supports {value} placeholder for single-item GET. */
540
+ apiUrl: string;
541
+ /** HTTP method. Default: 'GET'. Same convention as OptionConfig.apiMethod. */
542
+ apiMethod?: 'GET' | 'POST';
543
+ /** Static base payload for POST. Lookup value(s) merged via paramName key. */
544
+ apiPayload?: any;
545
+ /** Parameter key for the lookup value.
546
+ * GET: query param (?id=2415 or ?ids=5,12,18)
547
+ * POST: body key ({ "codes": ["MATH_01"] })
548
+ * Default: 'id' (single) / 'ids' (multiple). */
549
+ paramName?: string;
550
+ /** Response path to extract results. Falls back to parent optionConfig.dataPath. */
551
+ dataPath?: string;
552
+ /** Custom HTTP headers. Same convention as AutocompleteConfig.headers. */
553
+ headers?: {
554
+ [key: string]: string;
555
+ };
529
556
  }
530
557
  interface AutocompleteDisplayField {
531
558
  /** Dot-notation path to the value in the API response item (e.g. 'login', 'contact.phone'). */
@@ -883,6 +910,10 @@ interface SelectionFieldNode {
883
910
  selected: boolean;
884
911
  /** If true, the field cannot be deselected by the user */
885
912
  isLocked: boolean;
913
+ /** True for a synthetic per-level node under a GEOGRAPHY_DYNAMIC master field (Country/State/
914
+ * District/...) — lets the UI render it nested under its master and disable it while the
915
+ * master is off, instead of showing it as an unrelated flat sibling. */
916
+ isGeographyLevel?: boolean;
886
917
  }
887
918
  /**
888
919
  * Wraps a section (SUBFIELDS / nested sectionConfig) with toggle + tree metadata.
@@ -942,6 +973,19 @@ declare class FieldSelectionService {
942
973
  * This prevents the UI from unexpectedly collapsing sections when the user toggles a field.
943
974
  */
944
975
  loadSchemaPreservingExpanded(schema: FormSchema): void;
976
+ /**
977
+ * A freshly-parsed group/section's `enabled` comes straight from its persisted
978
+ * FieldConfig.isEnabled — unlike toggleField()/toggleSection(), which always follow a mutation
979
+ * with `_recomputeEnabledFromChildren()` to keep the section/group toggle in sync with its
980
+ * children's actual selected state. Without this, a schema saved with e.g. Address.isEnabled:
981
+ * false but its Country/State/District checkboxes individually selected (a state that toggling
982
+ * from within the UI can never itself produce, but stale/pre-fix persisted data can) loads with
983
+ * checked child boxes sitting under a section toggle that shows OFF — contradicting what the
984
+ * checkboxes say and, worse, matching what the Configurator tree/actual form use to prune the
985
+ * whole section. Runs the same reconciliation parse-time gets on every load, so the toggle
986
+ * always reflects reality regardless of how the persisted schema got into this state.
987
+ */
988
+ private _reconcileGroupsFromChildren;
945
989
  /**
946
990
  * Toggle a group's enabled state. Disabling cascades to all sections + fields.
947
991
  * When enabling, all fields are selected (unless locked).
@@ -974,6 +1018,15 @@ declare class FieldSelectionService {
974
1018
  * Used when toggling a section/group back ON to restore field selections.
975
1019
  */
976
1020
  private _enableAllSections;
1021
+ /**
1022
+ * Re-derives `enabled` bottom-up for every section in the list, from its own current
1023
+ * fields/subsections — mirroring "Master Toggle Reflects Children" (already true for the
1024
+ * GROUP toggle vs. its sections) at every level: a section is ON as long as at least one of
1025
+ * its fields is selected or a subsection is ON. Without this, re-selecting a single field
1026
+ * after its parent section was switched off left the section's own toggle stuck OFF even
1027
+ * though a child was visibly selected again.
1028
+ */
1029
+ private _recomputeEnabledFromChildren;
977
1030
  private _toggleSectionAtPath;
978
1031
  private _toggleExpandedAtPath;
979
1032
  private _toggleFieldAtPath;
@@ -1210,6 +1263,17 @@ declare class SelectionSectionNodeComponent {
1210
1263
  get selectedCount(): number;
1211
1264
  get isLocked(): boolean;
1212
1265
  trackByFieldIndex(index: number): number;
1266
+ /**
1267
+ * A GEOGRAPHY_DYNAMIC field's per-level nodes (Country/State/District/...) are built as flat
1268
+ * entries immediately following their master in `section.fields` (see
1269
+ * FormSchemaTreeService._buildGeographyFieldNodes) — there's no real nested schema structure
1270
+ * to walk, so "master" here just means the nearest preceding non-level field.
1271
+ */
1272
+ private masterFieldFor;
1273
+ /** True for a geography level whose master field is currently unselected — locked out so the
1274
+ * user can't leave an individually-checked level under an unchecked (and therefore pruned)
1275
+ * master; see masterFieldFor(). */
1276
+ isFieldDisabled(field: SelectionFieldNode, index: number): boolean;
1213
1277
  trackBySubsectionIndex(index: number): number;
1214
1278
  static ɵfac: i0.ɵɵFactoryDeclaration<SelectionSectionNodeComponent, never>;
1215
1279
  static ɵcmp: i0.ɵɵComponentDeclaration<SelectionSectionNodeComponent, "lib-selection-section-node", never, { "section": { "alias": "section"; "required": true; }; "sectionIndex": { "alias": "sectionIndex"; "required": true; }; "depth": { "alias": "depth"; "required": false; }; "hideToggleForOptionTypes": { "alias": "hideToggleForOptionTypes"; "required": false; }; }, { "toggleEnabled": "toggleEnabled"; "toggleExpanded": "toggleExpanded"; "fieldToggle": "fieldToggle"; }, never, never, false, never>;
@@ -1224,9 +1288,17 @@ declare class SelectionFieldNodeComponent {
1224
1288
  * pre-configured by the developer and shouldn't be toggled by business users.
1225
1289
  */
1226
1290
  hideToggleForOptionTypes: boolean;
1291
+ /**
1292
+ * Set when the enclosing section is off. A field can never be meaningfully "selected" while
1293
+ * its parent section is disabled — the Field Configuration step prunes the whole disabled
1294
+ * branch regardless of individual field state — so the checkbox is locked out here to make
1295
+ * that constraint visible instead of letting the user set a checked state that won't survive.
1296
+ */
1297
+ disabled: boolean;
1298
+ onCheckedChange(): void;
1227
1299
  get isOptionDrivenType(): boolean;
1228
1300
  static ɵfac: i0.ɵɵFactoryDeclaration<SelectionFieldNodeComponent, never>;
1229
- static ɵcmp: i0.ɵɵComponentDeclaration<SelectionFieldNodeComponent, "lib-selection-field-node", never, { "field": { "alias": "field"; "required": true; }; "hideToggleForOptionTypes": { "alias": "hideToggleForOptionTypes"; "required": false; }; }, { "toggleSelected": "toggleSelected"; }, never, never, false, never>;
1301
+ static ɵcmp: i0.ɵɵComponentDeclaration<SelectionFieldNodeComponent, "lib-selection-field-node", never, { "field": { "alias": "field"; "required": true; }; "hideToggleForOptionTypes": { "alias": "hideToggleForOptionTypes"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; }, { "toggleSelected": "toggleSelected"; }, never, never, false, never>;
1230
1302
  }
1231
1303
 
1232
1304
  declare class ConfiguratorTreeComponent {
@@ -1515,6 +1587,7 @@ declare class FormFieldComponent implements OnInit, AfterViewInit, OnDestroy {
1515
1587
  private hostRef;
1516
1588
  private overlay;
1517
1589
  private dateAdapter;
1590
+ private cdr;
1518
1591
  config: FieldConfig;
1519
1592
  controller: SmartFormController;
1520
1593
  /**
@@ -1663,6 +1736,12 @@ declare class FormFieldComponent implements OnInit, AfterViewInit, OnDestroy {
1663
1736
  private defaultStateSnapshot;
1664
1737
  /** Tracks whether the current localOptionList is filtered by an active server-side search query */
1665
1738
  private _isServerSearchActive;
1739
+ /** True from the moment "Select All" is turned on until the user deselects a single option,
1740
+ * toggles it back off, or starts a new search. While active, each newly-arrived paginated
1741
+ * page (loadMoreDropdownOptions) is auto-merged into the selection — see loadDropdownOptions
1742
+ * — so the selected count keeps pace with what's been scrolled into view (e.g. 10 -> 20 -> 34)
1743
+ * instead of freezing at whatever was loaded the moment "Select All" was clicked. */
1744
+ private _selectAllActive;
1666
1745
  /** Dedicated cache of currently selected option objects */
1667
1746
  selectedItems: any[];
1668
1747
  /** Cache of the latest dependency parameters for server-side autocomplete filtering */
@@ -1716,7 +1795,7 @@ declare class FormFieldComponent implements OnInit, AfterViewInit, OnDestroy {
1716
1795
  */
1717
1796
  get groupKey(): string;
1718
1797
  readonly dropdownScrollStrategy: ScrollStrategy;
1719
- constructor(fb: FormBuilder, expressionService: ExpressionService, http: HttpClient, hostRef: ElementRef<HTMLElement>, overlay: Overlay, dateAdapter: DateAdapter<Date>);
1798
+ constructor(fb: FormBuilder, expressionService: ExpressionService, http: HttpClient, hostRef: ElementRef<HTMLElement>, overlay: Overlay, dateAdapter: DateAdapter<Date>, cdr: ChangeDetectorRef);
1720
1799
  isFieldVisible(field: FieldConfig, rowController?: SmartFormController): boolean;
1721
1800
  /** Portal root, resolved from this component's own node rather than the global document. */
1722
1801
  private get portalRoot();
@@ -1922,6 +2001,12 @@ declare class FormFieldComponent implements OnInit, AfterViewInit, OnDestroy {
1922
2001
  resetDropdownSearch(forceLoad?: boolean, bypassCache?: boolean): void;
1923
2002
  /** Merges option(s) from selectedOptionsData into the local dropdown options list */
1924
2003
  mergeSelectedOptionsIntoList(): void;
2004
+ /**
2005
+ * If the field's initial value is a primitive (not an object) and no
2006
+ * selectedOptionsData was provided, uses lookupConfig to fire a targeted
2007
+ * API call to resolve the display label for edit-mode prefilling.
2008
+ */
2009
+ private _resolveLookupIfNeeded;
1925
2010
  /**
1926
2011
  * Extracts option(s) and their corresponding raw codes from an initial value object or array of objects.
1927
2012
  * If the value is a primitive but initialLabelField is configured, it looks up the sibling field value.
@@ -1936,6 +2021,9 @@ declare class FormFieldComponent implements OnInit, AfterViewInit, OnDestroy {
1936
2021
  isSomeSelected(): boolean;
1937
2022
  /** Toggles selection of all filtered options. */
1938
2023
  toggleSelectAll(checked: boolean): void;
2024
+ /** Merges every currently-loaded filtered option into the selection — used to keep an
2025
+ * already-active "Select All" in sync as more paginated pages arrive (see loadDropdownOptions). */
2026
+ private applySelectAllToLoadedOptions;
1939
2027
  get isTextField(): boolean;
1940
2028
  get isNumberField(): boolean;
1941
2029
  get isDateField(): boolean;
@@ -2760,6 +2848,7 @@ declare class DropdownComponent implements ControlValueAccessor, OnInit, OnChang
2760
2848
  selectionChange: EventEmitter<any>;
2761
2849
  searchTermChange: EventEmitter<string>;
2762
2850
  loadMore: EventEmitter<void>;
2851
+ opened: EventEmitter<void>;
2763
2852
  viewport?: CdkVirtualScrollViewport;
2764
2853
  searchInput?: ElementRef;
2765
2854
  triggerEl?: ElementRef;
@@ -2775,6 +2864,7 @@ declare class DropdownComponent implements ControlValueAccessor, OnInit, OnChang
2775
2864
  };
2776
2865
  onChange: (value: any) => void;
2777
2866
  onTouched: () => void;
2867
+ private selectAllActive;
2778
2868
  private search$;
2779
2869
  constructor(el: ElementRef);
2780
2870
  ngOnInit(): void;
@@ -2798,6 +2888,9 @@ declare class DropdownComponent implements ControlValueAccessor, OnInit, OnChang
2798
2888
  close(): void;
2799
2889
  get isAllFilteredSelected(): boolean;
2800
2890
  toggleSelectAll(): void;
2891
+ /** Merges every currently-loaded selectable option into the selection — used to keep a
2892
+ * "Select All" that's already active in sync as more lazy-loaded pages arrive. */
2893
+ private applySelectAllToLoadedOptions;
2801
2894
  selectOption(option: DropdownOption): void;
2802
2895
  isSelected(option: DropdownOption): boolean;
2803
2896
  onSearch(term: string): void;
@@ -2820,7 +2913,7 @@ declare class DropdownComponent implements ControlValueAccessor, OnInit, OnChang
2820
2913
  [key: string]: string | undefined;
2821
2914
  };
2822
2915
  static ɵfac: i0.ɵɵFactoryDeclaration<DropdownComponent, never>;
2823
- static ɵcmp: i0.ɵɵComponentDeclaration<DropdownComponent, "lib-dropdown", never, { "config": { "alias": "config"; "required": false; }; "labels": { "alias": "labels"; "required": false; }; "options": { "alias": "options"; "required": false; }; "selectedValue": { "alias": "selectedValue"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "label": { "alias": "label"; "required": false; }; "multiple": { "alias": "multiple"; "required": false; }; "searchable": { "alias": "searchable"; "required": false; }; "clearable": { "alias": "clearable"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "required": { "alias": "required"; "required": false; }; "errorMessage": { "alias": "errorMessage"; "required": false; }; "serverSearch": { "alias": "serverSearch"; "required": false; }; "searchDebounceMs": { "alias": "searchDebounceMs"; "required": false; }; "lazyLoad": { "alias": "lazyLoad"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "loadingMore": { "alias": "loadingMore"; "required": false; }; "hasMore": { "alias": "hasMore"; "required": false; }; "width": { "alias": "width"; "required": false; }; "height": { "alias": "height"; "required": false; }; "borderRadius": { "alias": "borderRadius"; "required": false; }; "fontSize": { "alias": "fontSize"; "required": false; }; "gap": { "alias": "gap"; "required": false; }; "fontFamily": { "alias": "fontFamily"; "required": false; }; "labelColor": { "alias": "labelColor"; "required": false; }; "labelFontSize": { "alias": "labelFontSize"; "required": false; }; "labelFontWeight": { "alias": "labelFontWeight"; "required": false; }; "backgroundColor": { "alias": "backgroundColor"; "required": false; }; "borderColor": { "alias": "borderColor"; "required": false; }; "borderWidth": { "alias": "borderWidth"; "required": false; }; "padding": { "alias": "padding"; "required": false; }; "fontWeight": { "alias": "fontWeight"; "required": false; }; "color": { "alias": "color"; "required": false; }; "placeholderColor": { "alias": "placeholderColor"; "required": false; }; "focusBorderColor": { "alias": "focusBorderColor"; "required": false; }; "errorColor": { "alias": "errorColor"; "required": false; }; "disabledBackgroundColor": { "alias": "disabledBackgroundColor"; "required": false; }; "disabledColor": { "alias": "disabledColor"; "required": false; }; "boxShadow": { "alias": "boxShadow"; "required": false; }; }, { "selectionChange": "selectionChange"; "searchTermChange": "searchTermChange"; "loadMore": "loadMore"; }, never, never, false, never>;
2916
+ static ɵcmp: i0.ɵɵComponentDeclaration<DropdownComponent, "lib-dropdown", never, { "config": { "alias": "config"; "required": false; }; "labels": { "alias": "labels"; "required": false; }; "options": { "alias": "options"; "required": false; }; "selectedValue": { "alias": "selectedValue"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "label": { "alias": "label"; "required": false; }; "multiple": { "alias": "multiple"; "required": false; }; "searchable": { "alias": "searchable"; "required": false; }; "clearable": { "alias": "clearable"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "required": { "alias": "required"; "required": false; }; "errorMessage": { "alias": "errorMessage"; "required": false; }; "serverSearch": { "alias": "serverSearch"; "required": false; }; "searchDebounceMs": { "alias": "searchDebounceMs"; "required": false; }; "lazyLoad": { "alias": "lazyLoad"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "loadingMore": { "alias": "loadingMore"; "required": false; }; "hasMore": { "alias": "hasMore"; "required": false; }; "width": { "alias": "width"; "required": false; }; "height": { "alias": "height"; "required": false; }; "borderRadius": { "alias": "borderRadius"; "required": false; }; "fontSize": { "alias": "fontSize"; "required": false; }; "gap": { "alias": "gap"; "required": false; }; "fontFamily": { "alias": "fontFamily"; "required": false; }; "labelColor": { "alias": "labelColor"; "required": false; }; "labelFontSize": { "alias": "labelFontSize"; "required": false; }; "labelFontWeight": { "alias": "labelFontWeight"; "required": false; }; "backgroundColor": { "alias": "backgroundColor"; "required": false; }; "borderColor": { "alias": "borderColor"; "required": false; }; "borderWidth": { "alias": "borderWidth"; "required": false; }; "padding": { "alias": "padding"; "required": false; }; "fontWeight": { "alias": "fontWeight"; "required": false; }; "color": { "alias": "color"; "required": false; }; "placeholderColor": { "alias": "placeholderColor"; "required": false; }; "focusBorderColor": { "alias": "focusBorderColor"; "required": false; }; "errorColor": { "alias": "errorColor"; "required": false; }; "disabledBackgroundColor": { "alias": "disabledBackgroundColor"; "required": false; }; "disabledColor": { "alias": "disabledColor"; "required": false; }; "boxShadow": { "alias": "boxShadow"; "required": false; }; }, { "selectionChange": "selectionChange"; "searchTermChange": "searchTermChange"; "loadMore": "loadMore"; "opened": "opened"; }, never, never, false, never>;
2824
2917
  }
2825
2918
 
2826
2919
  interface CheckboxOption {
@@ -5330,6 +5423,10 @@ interface HierarchyCfg {
5330
5423
  /** Passed straight through onto every generated level's DROPDOWN optionConfig — same shape as
5331
5424
  * optionConfig.pagination documented in smart-form.md (loadMore/infiniteScroll). */
5332
5425
  pagination?: any;
5426
+ /** optionConfig.sortBy path applied to every generated level (Country/State/District/...).
5427
+ * Defaults to `labelPath` when not set — see _buildHierarchyFields(). Set explicitly (or to
5428
+ * an empty string to opt out) if a template needs different, or no, ordering. */
5429
+ sortBy?: string;
5333
5430
  }
5334
5431
 
5335
5432
  declare class ValidationUtils {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "commons-shared-web-ui",
3
- "version": "0.0.76",
3
+ "version": "0.0.78",
4
4
  "peerDependencies": {
5
5
  "@angular/animations": "20.3.15",
6
6
  "@angular/cdk": "20.2.14",