commons-shared-web-ui 0.0.76 → 0.0.77

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.
@@ -1616,6 +1616,12 @@ class FormFieldComponent {
1616
1616
  defaultStateSnapshot = { options: [], currentPage: 0, totalCount: 0, hasMorePages: false };
1617
1617
  /** Tracks whether the current localOptionList is filtered by an active server-side search query */
1618
1618
  _isServerSearchActive = false;
1619
+ /** True from the moment "Select All" is turned on until the user deselects a single option,
1620
+ * toggles it back off, or starts a new search. While active, each newly-arrived paginated
1621
+ * page (loadMoreDropdownOptions) is auto-merged into the selection — see loadDropdownOptions
1622
+ * — so the selected count keeps pace with what's been scrolled into view (e.g. 10 -> 20 -> 34)
1623
+ * instead of freezing at whatever was loaded the moment "Select All" was clicked. */
1624
+ _selectAllActive = false;
1619
1625
  /** Dedicated cache of currently selected option objects */
1620
1626
  selectedItems = [];
1621
1627
  /** Cache of the latest dependency parameters for server-side autocomplete filtering */
@@ -2854,6 +2860,11 @@ class FormFieldComponent {
2854
2860
  }
2855
2861
  if (this.isDropdown) {
2856
2862
  this.filteredOptionList = [...this.localOptionList];
2863
+ // Sticky "Select All": a newly-arrived paginated page gets auto-selected too, so
2864
+ // selection keeps pace with what's been scrolled/loaded into view.
2865
+ if (isLoadMore) {
2866
+ this.applySelectAllToLoadedOptions();
2867
+ }
2857
2868
  }
2858
2869
  },
2859
2870
  error: err => console.error('Failed to load dropdown options:', err)
@@ -2951,6 +2962,11 @@ class FormFieldComponent {
2951
2962
  onCheckboxListChange(code, checked) {
2952
2963
  if (!this.config.name)
2953
2964
  return;
2965
+ if (!checked) {
2966
+ // Manually deselecting one item breaks the "everything loaded is selected" invariant —
2967
+ // stop auto-including future paginated pages until Select All is explicitly re-toggled.
2968
+ this._selectAllActive = false;
2969
+ }
2954
2970
  const currentValue = (this.allowMulti
2955
2971
  ? (this.formGroup.get(this.config.name)?.value)
2956
2972
  : this.controller.getFieldValue(this.config.name)) || [];
@@ -3217,6 +3233,9 @@ class FormFieldComponent {
3217
3233
  executeDropdownSearch(query) {
3218
3234
  const searchConfig = this.config.optionConfig?.searchConfig;
3219
3235
  const mode = searchConfig?.mode || 'local';
3236
+ // A new search (server or local) narrows to an unrelated result set — don't carry over a
3237
+ // prior "Select All" and auto-select whatever this new query happens to load/show.
3238
+ this._selectAllActive = false;
3220
3239
  if (mode === 'server') {
3221
3240
  // A dependent field (optionConfig.dependencies) with no parent value yet has nothing to
3222
3241
  // search against — searching now would fire with the parent filter missing entirely and
@@ -3474,6 +3493,7 @@ class FormFieldComponent {
3474
3493
  toggleSelectAll(checked) {
3475
3494
  if (!this.config.name)
3476
3495
  return;
3496
+ this._selectAllActive = checked;
3477
3497
  const currentValue = Array.isArray(this.value) ? [...this.value] : [];
3478
3498
  const filteredCodes = this.filteredOptionList.map(opt => opt.code);
3479
3499
  let newValue;
@@ -3488,6 +3508,18 @@ class FormFieldComponent {
3488
3508
  }
3489
3509
  this.updateValue(newValue);
3490
3510
  }
3511
+ /** Merges every currently-loaded filtered option into the selection — used to keep an
3512
+ * already-active "Select All" in sync as more paginated pages arrive (see loadDropdownOptions). */
3513
+ applySelectAllToLoadedOptions() {
3514
+ if (!this.config.name || !this._selectAllActive)
3515
+ return;
3516
+ const currentValue = Array.isArray(this.value) ? this.value : [];
3517
+ const filteredCodes = this.filteredOptionList.map(opt => opt.code);
3518
+ const toAdd = filteredCodes.filter(code => !currentValue.includes(code));
3519
+ if (toAdd.length === 0)
3520
+ return;
3521
+ this.updateValue([...currentValue, ...toAdd]);
3522
+ }
3491
3523
  // ── Type guards ──────────────────────────────────────────────────────────
3492
3524
  get isTextField() { return this.config.type === 'TEXT_INPUT'; }
3493
3525
  get isNumberField() { return this.config.type === 'NUMBER_INPUT'; }
@@ -5816,6 +5848,7 @@ class SmartFormComponent {
5816
5848
  showLoader: raw['showLoader'] ?? raw['field']?.['showLoader'] ?? false,
5817
5849
  searchConfig: fi['searchConfig'],
5818
5850
  pagination: fi['pagination'],
5851
+ sortBy: da['sortBy'],
5819
5852
  };
5820
5853
  }
5821
5854
  // Legacy flat format (backward compatibility with existing geographyConfig JSON)
@@ -5847,6 +5880,7 @@ class SmartFormComponent {
5847
5880
  showLoader: raw['showLoader'] ?? false,
5848
5881
  searchConfig: raw['searchConfig'],
5849
5882
  pagination: raw['pagination'],
5883
+ sortBy: raw['sortBy'],
5850
5884
  };
5851
5885
  }
5852
5886
  _fetchHierarchyTemplate(cfg) {
@@ -5921,6 +5955,16 @@ class SmartFormComponent {
5921
5955
  labelPath: cfg.labelPath,
5922
5956
  valuePath: cfg.valuePath,
5923
5957
  showLoader: cfg.showLoader,
5958
+ // Every GEOGRAPHY_DYNAMIC level (Country/State/District/...) generates its own
5959
+ // optionConfig here rather than being declared in JSON, so a per-field "sortBy" in the
5960
+ // form config can never reach it — form-field.component.ts already supports sortBy for
5961
+ // any optionConfig, this was just never being set for hierarchy-generated fields.
5962
+ // Sorting by the same labelPath used to render the option is a reasonable default for
5963
+ // any geography list; override via geographyConfig.dataApi.sortBy if a specific
5964
+ // template needs different (or no) ordering.
5965
+ // ?? (not ||) so an explicit empty-string sortBy (opt out of sorting) isn't clobbered
5966
+ // back to the labelPath default.
5967
+ sortBy: cfg.sortBy ?? cfg.labelPath,
5924
5968
  };
5925
5969
  // Search/pagination are opt-in via geographyConfig.field.searchConfig/pagination — every
5926
5970
  // generated level (Country/State/District/…) gets the same behavior since they all hit
@@ -6618,6 +6662,11 @@ class DropdownComponent {
6618
6662
  selectionChange = new EventEmitter();
6619
6663
  searchTermChange = new EventEmitter();
6620
6664
  loadMore = new EventEmitter();
6665
+ // Fires every time the panel opens — lets a serverSearch consumer know it should reset
6666
+ // back to the unfiltered/first page, since reopening after a search otherwise keeps
6667
+ // showing that search's narrowed result set forever (this component doesn't own `options`
6668
+ // in serverSearch mode, so it can't refetch that on its own).
6669
+ opened = new EventEmitter();
6621
6670
  viewport;
6622
6671
  searchInput;
6623
6672
  triggerEl;
@@ -6629,6 +6678,12 @@ class DropdownComponent {
6629
6678
  menuPosition = { top: 0, left: 0, width: 0 };
6630
6679
  onChange = () => { };
6631
6680
  onTouched = () => { };
6681
+ // True from the moment "Select All" is turned on until the user either turns it back off
6682
+ // or manually deselects a single option. While active, every newly lazy-loaded page is
6683
+ // auto-merged into the selection (see ngOnChanges) so the count of selected items keeps
6684
+ // matching what's on screen (10 -> 20 -> ... -> 34) instead of freezing at whatever was
6685
+ // loaded at the moment "Select All" was clicked.
6686
+ selectAllActive = false;
6632
6687
  search$ = new Subject();
6633
6688
  constructor(el) {
6634
6689
  this.el = el;
@@ -6652,6 +6707,11 @@ class DropdownComponent {
6652
6707
  }
6653
6708
  if (changes['config'] || changes['options']) {
6654
6709
  this.filteredOptions = this.serverSearch ? this.options : this.validOptions;
6710
+ // Sticky "Select All": a newly-arrived lazy-loaded page gets auto-selected too,
6711
+ // so selection keeps pace with what's been scrolled into view.
6712
+ if (changes['options'] && !changes['options'].isFirstChange() && this.selectAllActive) {
6713
+ this.applySelectAllToLoadedOptions();
6714
+ }
6655
6715
  }
6656
6716
  if (changes['selectedValue']) {
6657
6717
  const incoming = changes['selectedValue'].currentValue;
@@ -6749,6 +6809,15 @@ class DropdownComponent {
6749
6809
  this.isOpen = !this.isOpen;
6750
6810
  if (this.isOpen) {
6751
6811
  this.focusedIndex = -1;
6812
+ // Reset any previous search so reopening shows the full/unfiltered list again
6813
+ // rather than whatever narrowed result was last searched for.
6814
+ if (this.searchTerm) {
6815
+ this.searchTerm = '';
6816
+ if (this.searchInput)
6817
+ this.searchInput.nativeElement.value = '';
6818
+ if (!this.serverSearch)
6819
+ this.filteredOptions = this.validOptions;
6820
+ }
6752
6821
  setTimeout(() => {
6753
6822
  if (this.searchable && this.searchInput) {
6754
6823
  this.searchInput.nativeElement.focus();
@@ -6757,6 +6826,7 @@ class DropdownComponent {
6757
6826
  this.viewport.elementRef.nativeElement.focus();
6758
6827
  }
6759
6828
  });
6829
+ this.opened.emit();
6760
6830
  }
6761
6831
  else {
6762
6832
  this.onTouched();
@@ -6784,9 +6854,28 @@ class DropdownComponent {
6784
6854
  if (selectable.length === 0)
6785
6855
  return;
6786
6856
  const currentValues = Array.isArray(this.value) ? this.value : [];
6787
- this.value = this.isAllFilteredSelected
6788
- ? currentValues.filter(v => !selectable.includes(v))
6789
- : [...currentValues, ...selectable.filter(v => !currentValues.includes(v))];
6857
+ if (this.isAllFilteredSelected) {
6858
+ this.selectAllActive = false;
6859
+ this.value = currentValues.filter(v => !selectable.includes(v));
6860
+ }
6861
+ else {
6862
+ this.selectAllActive = true;
6863
+ this.value = [...currentValues, ...selectable.filter(v => !currentValues.includes(v))];
6864
+ }
6865
+ this.onChange(this.value);
6866
+ this.selectionChange.emit(this.value);
6867
+ }
6868
+ /** Merges every currently-loaded selectable option into the selection — used to keep a
6869
+ * "Select All" that's already active in sync as more lazy-loaded pages arrive. */
6870
+ applySelectAllToLoadedOptions() {
6871
+ const selectable = this.filteredOptions.filter(o => !o.disabled).map(o => o.value);
6872
+ if (selectable.length === 0)
6873
+ return;
6874
+ const currentValues = Array.isArray(this.value) ? this.value : [];
6875
+ const merged = [...currentValues, ...selectable.filter(v => !currentValues.includes(v))];
6876
+ if (merged.length === currentValues.length)
6877
+ return;
6878
+ this.value = merged;
6790
6879
  this.onChange(this.value);
6791
6880
  this.selectionChange.emit(this.value);
6792
6881
  }
@@ -6798,6 +6887,10 @@ class DropdownComponent {
6798
6887
  const index = currentValues.indexOf(option.value);
6799
6888
  if (index > -1) {
6800
6889
  currentValues.splice(index, 1);
6890
+ // Manually deselecting one item breaks the "everything loaded is selected"
6891
+ // invariant — stop auto-including future lazy-loaded pages until Select All
6892
+ // is explicitly re-toggled.
6893
+ this.selectAllActive = false;
6801
6894
  }
6802
6895
  else {
6803
6896
  currentValues.push(option.value);
@@ -6820,6 +6913,9 @@ class DropdownComponent {
6820
6913
  onSearch(term) {
6821
6914
  this.searchTerm = term;
6822
6915
  if (this.serverSearch) {
6916
+ // A new server search yields an unrelated result set — don't carry over a prior
6917
+ // "Select All" and auto-select whatever this new query happens to load.
6918
+ this.selectAllActive = false;
6823
6919
  this.search$.next(term);
6824
6920
  this.focusedIndex = -1;
6825
6921
  return;
@@ -6955,7 +7051,7 @@ class DropdownComponent {
6955
7051
  };
6956
7052
  }
6957
7053
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DropdownComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
6958
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: DropdownComponent, isStandalone: false, selector: "lib-dropdown", inputs: { config: "config", labels: "labels", options: "options", selectedValue: "selectedValue", placeholder: "placeholder", label: "label", multiple: "multiple", searchable: "searchable", clearable: "clearable", disabled: "disabled", required: "required", errorMessage: "errorMessage", serverSearch: "serverSearch", searchDebounceMs: "searchDebounceMs", lazyLoad: "lazyLoad", loading: "loading", loadingMore: "loadingMore", hasMore: "hasMore", width: "width", height: "height", borderRadius: "borderRadius", fontSize: "fontSize", gap: "gap", fontFamily: "fontFamily", labelColor: "labelColor", labelFontSize: "labelFontSize", labelFontWeight: "labelFontWeight", backgroundColor: "backgroundColor", borderColor: "borderColor", borderWidth: "borderWidth", padding: "padding", fontWeight: "fontWeight", color: "color", placeholderColor: "placeholderColor", focusBorderColor: "focusBorderColor", errorColor: "errorColor", disabledBackgroundColor: "disabledBackgroundColor", disabledColor: "disabledColor", boxShadow: "boxShadow" }, outputs: { selectionChange: "selectionChange", searchTermChange: "searchTermChange", loadMore: "loadMore" }, host: { listeners: { "keydown": "handleKeyboardEvent($event)" } }, providers: [
7054
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: DropdownComponent, isStandalone: false, selector: "lib-dropdown", inputs: { config: "config", labels: "labels", options: "options", selectedValue: "selectedValue", placeholder: "placeholder", label: "label", multiple: "multiple", searchable: "searchable", clearable: "clearable", disabled: "disabled", required: "required", errorMessage: "errorMessage", serverSearch: "serverSearch", searchDebounceMs: "searchDebounceMs", lazyLoad: "lazyLoad", loading: "loading", loadingMore: "loadingMore", hasMore: "hasMore", width: "width", height: "height", borderRadius: "borderRadius", fontSize: "fontSize", gap: "gap", fontFamily: "fontFamily", labelColor: "labelColor", labelFontSize: "labelFontSize", labelFontWeight: "labelFontWeight", backgroundColor: "backgroundColor", borderColor: "borderColor", borderWidth: "borderWidth", padding: "padding", fontWeight: "fontWeight", color: "color", placeholderColor: "placeholderColor", focusBorderColor: "focusBorderColor", errorColor: "errorColor", disabledBackgroundColor: "disabledBackgroundColor", disabledColor: "disabledColor", boxShadow: "boxShadow" }, outputs: { selectionChange: "selectionChange", searchTermChange: "searchTermChange", loadMore: "loadMore", opened: "opened" }, host: { listeners: { "keydown": "handleKeyboardEvent($event)" } }, providers: [
6959
7055
  {
6960
7056
  provide: NG_VALUE_ACCESSOR,
6961
7057
  useExisting: forwardRef(() => DropdownComponent),
@@ -7056,6 +7152,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
7056
7152
  type: Output
7057
7153
  }], loadMore: [{
7058
7154
  type: Output
7155
+ }], opened: [{
7156
+ type: Output
7059
7157
  }], viewport: [{
7060
7158
  type: ViewChild,
7061
7159
  args: [CdkVirtualScrollViewport]
@@ -8833,16 +8931,35 @@ class FormSchemaTreeService {
8833
8931
  }
8834
8932
  }
8835
8933
  const isVisible = field.isEnabled ?? field.visible ?? true;
8934
+ const enabled = isVisible && field.disabled !== true;
8935
+ // A section acts as a true parent checkbox: when it's off, none of its descendants can be
8936
+ // "on" in the UI, no matter what the raw schema says for them individually. Backend data can
8937
+ // disagree (e.g. a prior save wrote the section's own isEnabled=false but never cascaded that
8938
+ // down to every leaf field's isEnabled) — that's exactly the state that made Field
8939
+ // Configuration silently drop selected-looking fields, since the build step below prunes the
8940
+ // whole disabled branch regardless of children. Normalizing here keeps what the checkboxes
8941
+ // show in sync with what will actually survive into the next step.
8942
+ const normalizedFields = enabled ? fields : fields.map(f => ({ ...f, selected: false }));
8943
+ const normalizedSubsections = enabled ? subsections : this._disableSectionsDeep(subsections);
8836
8944
  return {
8837
8945
  label: field.sectionConfig?.label || field.label || field.name || 'Section',
8838
8946
  sectionConfig: field.sectionConfig ?? null,
8839
8947
  parentFieldConfig: field,
8840
- enabled: isVisible && field.disabled !== true,
8948
+ enabled,
8841
8949
  expanded: false, // Collapse by default for better UX - user can expand as needed
8842
- fields,
8843
- subsections,
8950
+ fields: normalizedFields,
8951
+ subsections: normalizedSubsections,
8844
8952
  };
8845
8953
  }
8954
+ /** Recursively forces enabled=false and selected=false through an already-built subtree. */
8955
+ _disableSectionsDeep(sections) {
8956
+ return sections.map(s => ({
8957
+ ...s,
8958
+ enabled: false,
8959
+ fields: s.fields.map(f => ({ ...f, selected: false })),
8960
+ subsections: this._disableSectionsDeep(s.subsections),
8961
+ }));
8962
+ }
8846
8963
  _createDefaultSection(fields) {
8847
8964
  return {
8848
8965
  label: 'Fields',
@@ -8880,7 +8997,8 @@ class FormSchemaTreeService {
8880
8997
  * on the parent GEOGRAPHY_DYNAMIC field, so they carry a distinguishing `name` for name-keyed
8881
8998
  * matching in _applyGeographyNodeSelections rather than object identity. */
8882
8999
  _buildGeographyFieldNodes(field) {
8883
- const nodes = [this._buildFieldNode(field)];
9000
+ const masterNode = this._buildFieldNode(field);
9001
+ const nodes = [masterNode];
8884
9002
  const geoNodes = field.geographyConfig?.field?.nodes ?? {};
8885
9003
  for (const classCode of Object.keys(geoNodes)) {
8886
9004
  const cfg = geoNodes[classCode] ?? {};
@@ -8889,7 +9007,19 @@ class FormSchemaTreeService {
8889
9007
  label: cfg.label ?? classCode,
8890
9008
  type: 'GEOGRAPHY_NODE',
8891
9009
  };
8892
- nodes.push({ fieldConfig: synthetic, selected: cfg.hidden !== true, isLocked: false });
9010
+ nodes.push({
9011
+ fieldConfig: synthetic,
9012
+ // A level can't be meaningfully selected while its master field is off — the
9013
+ // Configurator tree/actual form prune the whole GEOGRAPHY_DYNAMIC field, children
9014
+ // included, the moment the master is disabled. Live toggling already enforces this
9015
+ // (see FieldSelectionService._toggleFieldAtPath's nodePrefix cascade), but a schema
9016
+ // parsed straight from persisted data (page load, not a toggle) has to enforce it here
9017
+ // too, or a level whose own `hidden` flag was left `false` from before the master was
9018
+ // turned off would show checked under an unchecked parent.
9019
+ selected: masterNode.selected && cfg.hidden !== true,
9020
+ isLocked: false,
9021
+ isGeographyLevel: true,
9022
+ });
8893
9023
  }
8894
9024
  return nodes;
8895
9025
  }
@@ -9238,7 +9368,7 @@ class FieldSelectionService {
9238
9368
  * Initialize the store from a FormSchema.
9239
9369
  */
9240
9370
  loadSchema(schema) {
9241
- const groups = this.treeService.parseSchemaToSelectionGroups(schema);
9371
+ const groups = this._reconcileGroupsFromChildren(this.treeService.parseSchemaToSelectionGroups(schema));
9242
9372
  this._state.set({ groups, originalSchema: schema });
9243
9373
  }
9244
9374
  /**
@@ -9248,7 +9378,7 @@ class FieldSelectionService {
9248
9378
  */
9249
9379
  loadSchemaPreservingExpanded(schema) {
9250
9380
  const oldGroups = this._state().groups;
9251
- const newGroups = this.treeService.parseSchemaToSelectionGroups(schema);
9381
+ const newGroups = this._reconcileGroupsFromChildren(this.treeService.parseSchemaToSelectionGroups(schema));
9252
9382
  // Merge old expansion states into new groups
9253
9383
  const mergedGroups = newGroups.map((newGroup, gi) => ({
9254
9384
  ...newGroup,
@@ -9257,6 +9387,28 @@ class FieldSelectionService {
9257
9387
  }));
9258
9388
  this._state.set({ groups: mergedGroups, originalSchema: schema });
9259
9389
  }
9390
+ /**
9391
+ * A freshly-parsed group/section's `enabled` comes straight from its persisted
9392
+ * FieldConfig.isEnabled — unlike toggleField()/toggleSection(), which always follow a mutation
9393
+ * with `_recomputeEnabledFromChildren()` to keep the section/group toggle in sync with its
9394
+ * children's actual selected state. Without this, a schema saved with e.g. Address.isEnabled:
9395
+ * false but its Country/State/District checkboxes individually selected (a state that toggling
9396
+ * from within the UI can never itself produce, but stale/pre-fix persisted data can) loads with
9397
+ * checked child boxes sitting under a section toggle that shows OFF — contradicting what the
9398
+ * checkboxes say and, worse, matching what the Configurator tree/actual form use to prune the
9399
+ * whole section. Runs the same reconciliation parse-time gets on every load, so the toggle
9400
+ * always reflects reality regardless of how the persisted schema got into this state.
9401
+ */
9402
+ _reconcileGroupsFromChildren(groups) {
9403
+ return groups.map(g => {
9404
+ const sections = this._recomputeEnabledFromChildren(g.sections);
9405
+ return {
9406
+ ...g,
9407
+ sections,
9408
+ enabled: sections.length === 0 ? g.enabled : (sections.some(s => s.enabled) || g.enabled),
9409
+ };
9410
+ });
9411
+ }
9260
9412
  /**
9261
9413
  * Toggle a group's enabled state. Disabling cascades to all sections + fields.
9262
9414
  * When enabling, all fields are selected (unless locked).
@@ -9286,9 +9438,11 @@ class FieldSelectionService {
9286
9438
  groups: s.groups.map((g, gi) => {
9287
9439
  if (gi !== groupIndex)
9288
9440
  return g;
9441
+ const sections = this._recomputeEnabledFromChildren(this._toggleSectionAtPath(g.sections, sectionPath, 0));
9289
9442
  return {
9290
9443
  ...g,
9291
- sections: this._toggleSectionAtPath(g.sections, sectionPath, 0),
9444
+ sections,
9445
+ enabled: sections.some(sec => sec.enabled),
9292
9446
  };
9293
9447
  }),
9294
9448
  }));
@@ -9327,9 +9481,11 @@ class FieldSelectionService {
9327
9481
  groups: s.groups.map((g, gi) => {
9328
9482
  if (gi !== groupIndex)
9329
9483
  return g;
9484
+ const sections = this._recomputeEnabledFromChildren(this._toggleFieldAtPath(g.sections, sectionPath, 0, fieldIndex));
9330
9485
  return {
9331
9486
  ...g,
9332
- sections: this._toggleFieldAtPath(g.sections, sectionPath, 0, fieldIndex),
9487
+ sections,
9488
+ enabled: sections.some(sec => sec.enabled),
9333
9489
  };
9334
9490
  }),
9335
9491
  }));
@@ -9364,6 +9520,30 @@ class FieldSelectionService {
9364
9520
  subsections: this._enableAllSections(s.subsections),
9365
9521
  }));
9366
9522
  }
9523
+ /**
9524
+ * Re-derives `enabled` bottom-up for every section in the list, from its own current
9525
+ * fields/subsections — mirroring "Master Toggle Reflects Children" (already true for the
9526
+ * GROUP toggle vs. its sections) at every level: a section is ON as long as at least one of
9527
+ * its fields is selected or a subsection is ON. Without this, re-selecting a single field
9528
+ * after its parent section was switched off left the section's own toggle stuck OFF even
9529
+ * though a child was visibly selected again.
9530
+ */
9531
+ _recomputeEnabledFromChildren(sections) {
9532
+ return sections.map(s => {
9533
+ const subsections = this._recomputeEnabledFromChildren(s.subsections);
9534
+ // A locked field can't be deselected by the user and is always effectively active
9535
+ // regardless of its raw `selected` value — see _toggleSectionAtPath's enable branch,
9536
+ // which sets `selected: !f.isLocked` (locked fields keep `selected: false` but still
9537
+ // render, so they must still count here or their section would wrongly derive as OFF).
9538
+ const anyFieldActive = s.fields.some(f => f.selected || f.isLocked);
9539
+ const anySubsectionEnabled = subsections.some(sub => sub.enabled);
9540
+ return {
9541
+ ...s,
9542
+ enabled: anyFieldActive || anySubsectionEnabled,
9543
+ subsections,
9544
+ };
9545
+ });
9546
+ }
9367
9547
  _toggleSectionAtPath(sections, path, depth) {
9368
9548
  return sections.map((s, i) => {
9369
9549
  if (i !== path[depth])
@@ -9405,11 +9585,49 @@ class FieldSelectionService {
9405
9585
  if (i !== sectionPath[depth])
9406
9586
  return s;
9407
9587
  if (depth === sectionPath.length - 1) {
9588
+ const target = s.fields[fieldIndex];
9589
+ if (!target || target.isLocked)
9590
+ return s;
9591
+ const newSelected = !target.selected;
9592
+ const masterName = target.fieldConfig?.type === 'GEOGRAPHY_DYNAMIC'
9593
+ ? target.fieldConfig.name
9594
+ : null;
9595
+ const nodePrefix = masterName ? `${masterName}__node__` : null;
9596
+ // If the toggled field is itself a synthetic per-level node (name pattern
9597
+ // `${master}__node__${classCode}`), find its master so it can be auto-selected
9598
+ // below — a level can't be meaningfully "on" while its parent field is off.
9599
+ // classCode itself commonly contains underscores (e.g. "GREF.REGION_COUNTRY"), so the
9600
+ // suffix after "__node__" can't be restricted to a no-underscore character class — that
9601
+ // previously made this match fail for every real geography level, silently breaking the
9602
+ // master-field cascade below (Country/State/District showed checked in Field Selection
9603
+ // but the whole Address field stayed disabled and got pruned from the Configurator tree
9604
+ // and the actual form).
9605
+ const ownNodeMatch = /^(.*)__node__.+$/.exec(target.fieldConfig.name ?? '');
9606
+ const ownMasterName = ownNodeMatch ? ownNodeMatch[1] : null;
9408
9607
  return {
9409
9608
  ...s,
9410
- fields: s.fields.map((f, fi) => fi === fieldIndex && !f.isLocked
9411
- ? { ...f, selected: !f.selected }
9412
- : f),
9609
+ fields: s.fields.map((f, fi) => {
9610
+ if (fi === fieldIndex) {
9611
+ return { ...f, selected: newSelected };
9612
+ }
9613
+ // Toggling the GEOGRAPHY_DYNAMIC master field cascades to its synthetic
9614
+ // per-level children so a level can never be left "selected" while the
9615
+ // parent field it belongs to is disabled (which the Configurator tree
9616
+ // treats as pruning the whole field, children included).
9617
+ if (nodePrefix && f.fieldConfig.name?.startsWith(nodePrefix) && !f.isLocked) {
9618
+ return { ...f, selected: newSelected };
9619
+ }
9620
+ // Turning a per-level node ON re-enables its (currently off) master field
9621
+ // for the same reason, in the opposite direction.
9622
+ if (ownMasterName &&
9623
+ newSelected &&
9624
+ f.fieldConfig.name === ownMasterName &&
9625
+ !f.selected &&
9626
+ !f.isLocked) {
9627
+ return { ...f, selected: true };
9628
+ }
9629
+ return f;
9630
+ }),
9413
9631
  };
9414
9632
  }
9415
9633
  return {
@@ -9490,15 +9708,27 @@ class SelectionFieldNodeComponent {
9490
9708
  * pre-configured by the developer and shouldn't be toggled by business users.
9491
9709
  */
9492
9710
  hideToggleForOptionTypes = false;
9711
+ /**
9712
+ * Set when the enclosing section is off. A field can never be meaningfully "selected" while
9713
+ * its parent section is disabled — the Field Configuration step prunes the whole disabled
9714
+ * branch regardless of individual field state — so the checkbox is locked out here to make
9715
+ * that constraint visible instead of letting the user set a checked state that won't survive.
9716
+ */
9717
+ disabled = false;
9718
+ onCheckedChange() {
9719
+ if (this.disabled)
9720
+ return;
9721
+ this.toggleSelected.emit();
9722
+ }
9493
9723
  get isOptionDrivenType() {
9494
9724
  return OPTION_DRIVEN_FIELD_TYPES.has((this.field?.fieldConfig?.type ?? '').toUpperCase());
9495
9725
  }
9496
9726
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SelectionFieldNodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
9497
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: SelectionFieldNodeComponent, isStandalone: false, selector: "lib-selection-field-node", inputs: { field: "field", hideToggleForOptionTypes: "hideToggleForOptionTypes" }, outputs: { toggleSelected: "toggleSelected" }, ngImport: i0, template: "<div\r\n class=\"fb-selection-field\"\r\n [class.fb-selection-field--selected]=\"field.selected\"\r\n [class.fb-selection-field--locked]=\"field.isLocked\"\r\n [class.fb-selection-field--option-type]=\"hideToggleForOptionTypes && isOptionDrivenType\"\r\n>\r\n <span class=\"fb-selection-field__label\">\r\n {{ field.fieldConfig.label || field.fieldConfig.name }}\r\n </span>\r\n\r\n @if (field.isLocked) {\r\n <span class=\"fb-selection-field__lock\" title=\"This field is locked\">\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else if (hideToggleForOptionTypes && isOptionDrivenType) {\r\n <!-- Option-driven type: toggle hidden by config, show a badge instead -->\r\n <span class=\"fb-selection-field__option-badge\" title=\"Options are pre-configured\">\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\r\n <polyline points=\"12 8 12 12 14 14\"></polyline>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-checkbox\r\n [checked]=\"field.selected\"\r\n [disabled]=\"false\"\r\n (checkedChange)=\"toggleSelected.emit()\"\r\n />\r\n }\r\n</div>\r\n", styles: [".fb-selection-field{display:flex;align-items:center;justify-content:space-between;padding:var(--fb-fs-field-padding, 8px 12px);margin-bottom:var(--fb-fs-field-gap, 2px);border-radius:var(--fb-fs-field-radius, 6px);background:var(--fb-fs-field-bg, #ffffff);border:1px solid var(--fb-fs-field-border, #e5e7eb);transition:all .15s}.fb-selection-field:hover:not(.fb-selection-field--locked):not(.fb-selection-field--option-type){border-color:var(--fb-fs-field-hover-border, #3b82f6);background:var(--fb-fs-field-hover-bg, #f8fafc)}.fb-selection-field--selected{background:var(--fb-fs-field-selected-bg, #eff6ff);border-color:var(--fb-fs-field-selected-border, #bfdbfe)}.fb-selection-field--locked{background:var(--fb-fs-field-locked-bg, #f3f4f6);cursor:not-allowed}.fb-selection-field--locked .fb-selection-field__label{color:var(--fb-fs-field-locked-color, #6b7280);font-weight:500}.fb-selection-field--option-type{background:var(--fb-fs-field-option-type-bg, #f9fafb);border-color:var(--fb-fs-field-option-type-border, #e5e7eb);cursor:default}.fb-selection-field--option-type .fb-selection-field__label{color:var(--fb-fs-field-option-type-color, #374151)}.fb-selection-field__label{font-size:var(--fb-fs-field-label-size, 13px);color:var(--fb-fs-field-label-color, #111827);flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-selection-field__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}.fb-selection-field__option-badge{display:flex;align-items:center;color:var(--fb-fs-option-badge-color, #9ca3af);padding:2px;flex-shrink:0}\n"], dependencies: [{ kind: "component", type: CheckboxComponent, selector: "lib-checkbox", inputs: ["config", "labels", "label", "checked", "disabled", "required", "indeterminate", "options", "labelPosition", "color", "borderRadius", "value", "errorMessage", "width", "height", "fontSize", "fontWeight", "labelColor", "labelFontSize", "labelFontWeight", "gap", "fontFamily", "backgroundColor", "borderColor", "borderWidth", "padding", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow", "size", "checkedColor", "uncheckedColor", "groupLabelColor", "groupLabelFontSize", "groupLabelFontWeight"], outputs: ["checkedChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9727
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: SelectionFieldNodeComponent, isStandalone: false, selector: "lib-selection-field-node", inputs: { field: "field", hideToggleForOptionTypes: "hideToggleForOptionTypes", disabled: "disabled" }, outputs: { toggleSelected: "toggleSelected" }, ngImport: i0, template: "<div\r\n class=\"fb-selection-field\"\r\n [class.fb-selection-field--selected]=\"field.selected\"\r\n [class.fb-selection-field--locked]=\"field.isLocked\"\r\n [class.fb-selection-field--option-type]=\"hideToggleForOptionTypes && isOptionDrivenType\"\r\n [class.fb-selection-field--parent-disabled]=\"disabled\"\r\n>\r\n <span class=\"fb-selection-field__label\">\r\n {{ field.fieldConfig.label || field.fieldConfig.name }}\r\n </span>\r\n\r\n @if (field.isLocked) {\r\n <span class=\"fb-selection-field__lock\" title=\"This field is locked\">\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else if (hideToggleForOptionTypes && isOptionDrivenType) {\r\n <!-- Option-driven type: toggle hidden by config, show a badge instead -->\r\n <span class=\"fb-selection-field__option-badge\" title=\"Options are pre-configured\">\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\r\n <polyline points=\"12 8 12 12 14 14\"></polyline>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-checkbox\r\n [checked]=\"field.selected\"\r\n [disabled]=\"disabled\"\r\n (checkedChange)=\"onCheckedChange()\"\r\n />\r\n }\r\n</div>\r\n", styles: [".fb-selection-field{display:flex;align-items:center;justify-content:space-between;padding:var(--fb-fs-field-padding, 8px 12px);margin-bottom:var(--fb-fs-field-gap, 2px);border-radius:var(--fb-fs-field-radius, 6px);background:var(--fb-fs-field-bg, #ffffff);border:1px solid var(--fb-fs-field-border, #e5e7eb);transition:all .15s}.fb-selection-field:hover:not(.fb-selection-field--locked):not(.fb-selection-field--option-type){border-color:var(--fb-fs-field-hover-border, #3b82f6);background:var(--fb-fs-field-hover-bg, #f8fafc)}.fb-selection-field--selected{background:var(--fb-fs-field-selected-bg, #eff6ff);border-color:var(--fb-fs-field-selected-border, #bfdbfe)}.fb-selection-field--locked{background:var(--fb-fs-field-locked-bg, #f3f4f6);cursor:not-allowed}.fb-selection-field--locked .fb-selection-field__label{color:var(--fb-fs-field-locked-color, #6b7280);font-weight:500}.fb-selection-field--parent-disabled{opacity:.55;cursor:not-allowed}.fb-selection-field--option-type{background:var(--fb-fs-field-option-type-bg, #f9fafb);border-color:var(--fb-fs-field-option-type-border, #e5e7eb);cursor:default}.fb-selection-field--option-type .fb-selection-field__label{color:var(--fb-fs-field-option-type-color, #374151)}.fb-selection-field__label{font-size:var(--fb-fs-field-label-size, 13px);color:var(--fb-fs-field-label-color, #111827);flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-selection-field__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}.fb-selection-field__option-badge{display:flex;align-items:center;color:var(--fb-fs-option-badge-color, #9ca3af);padding:2px;flex-shrink:0}\n"], dependencies: [{ kind: "component", type: CheckboxComponent, selector: "lib-checkbox", inputs: ["config", "labels", "label", "checked", "disabled", "required", "indeterminate", "options", "labelPosition", "color", "borderRadius", "value", "errorMessage", "width", "height", "fontSize", "fontWeight", "labelColor", "labelFontSize", "labelFontWeight", "gap", "fontFamily", "backgroundColor", "borderColor", "borderWidth", "padding", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow", "size", "checkedColor", "uncheckedColor", "groupLabelColor", "groupLabelFontSize", "groupLabelFontWeight"], outputs: ["checkedChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9498
9728
  }
9499
9729
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SelectionFieldNodeComponent, decorators: [{
9500
9730
  type: Component,
9501
- args: [{ selector: 'lib-selection-field-node', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n class=\"fb-selection-field\"\r\n [class.fb-selection-field--selected]=\"field.selected\"\r\n [class.fb-selection-field--locked]=\"field.isLocked\"\r\n [class.fb-selection-field--option-type]=\"hideToggleForOptionTypes && isOptionDrivenType\"\r\n>\r\n <span class=\"fb-selection-field__label\">\r\n {{ field.fieldConfig.label || field.fieldConfig.name }}\r\n </span>\r\n\r\n @if (field.isLocked) {\r\n <span class=\"fb-selection-field__lock\" title=\"This field is locked\">\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else if (hideToggleForOptionTypes && isOptionDrivenType) {\r\n <!-- Option-driven type: toggle hidden by config, show a badge instead -->\r\n <span class=\"fb-selection-field__option-badge\" title=\"Options are pre-configured\">\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\r\n <polyline points=\"12 8 12 12 14 14\"></polyline>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-checkbox\r\n [checked]=\"field.selected\"\r\n [disabled]=\"false\"\r\n (checkedChange)=\"toggleSelected.emit()\"\r\n />\r\n }\r\n</div>\r\n", styles: [".fb-selection-field{display:flex;align-items:center;justify-content:space-between;padding:var(--fb-fs-field-padding, 8px 12px);margin-bottom:var(--fb-fs-field-gap, 2px);border-radius:var(--fb-fs-field-radius, 6px);background:var(--fb-fs-field-bg, #ffffff);border:1px solid var(--fb-fs-field-border, #e5e7eb);transition:all .15s}.fb-selection-field:hover:not(.fb-selection-field--locked):not(.fb-selection-field--option-type){border-color:var(--fb-fs-field-hover-border, #3b82f6);background:var(--fb-fs-field-hover-bg, #f8fafc)}.fb-selection-field--selected{background:var(--fb-fs-field-selected-bg, #eff6ff);border-color:var(--fb-fs-field-selected-border, #bfdbfe)}.fb-selection-field--locked{background:var(--fb-fs-field-locked-bg, #f3f4f6);cursor:not-allowed}.fb-selection-field--locked .fb-selection-field__label{color:var(--fb-fs-field-locked-color, #6b7280);font-weight:500}.fb-selection-field--option-type{background:var(--fb-fs-field-option-type-bg, #f9fafb);border-color:var(--fb-fs-field-option-type-border, #e5e7eb);cursor:default}.fb-selection-field--option-type .fb-selection-field__label{color:var(--fb-fs-field-option-type-color, #374151)}.fb-selection-field__label{font-size:var(--fb-fs-field-label-size, 13px);color:var(--fb-fs-field-label-color, #111827);flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-selection-field__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}.fb-selection-field__option-badge{display:flex;align-items:center;color:var(--fb-fs-option-badge-color, #9ca3af);padding:2px;flex-shrink:0}\n"] }]
9731
+ args: [{ selector: 'lib-selection-field-node', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n class=\"fb-selection-field\"\r\n [class.fb-selection-field--selected]=\"field.selected\"\r\n [class.fb-selection-field--locked]=\"field.isLocked\"\r\n [class.fb-selection-field--option-type]=\"hideToggleForOptionTypes && isOptionDrivenType\"\r\n [class.fb-selection-field--parent-disabled]=\"disabled\"\r\n>\r\n <span class=\"fb-selection-field__label\">\r\n {{ field.fieldConfig.label || field.fieldConfig.name }}\r\n </span>\r\n\r\n @if (field.isLocked) {\r\n <span class=\"fb-selection-field__lock\" title=\"This field is locked\">\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else if (hideToggleForOptionTypes && isOptionDrivenType) {\r\n <!-- Option-driven type: toggle hidden by config, show a badge instead -->\r\n <span class=\"fb-selection-field__option-badge\" title=\"Options are pre-configured\">\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\r\n <polyline points=\"12 8 12 12 14 14\"></polyline>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-checkbox\r\n [checked]=\"field.selected\"\r\n [disabled]=\"disabled\"\r\n (checkedChange)=\"onCheckedChange()\"\r\n />\r\n }\r\n</div>\r\n", styles: [".fb-selection-field{display:flex;align-items:center;justify-content:space-between;padding:var(--fb-fs-field-padding, 8px 12px);margin-bottom:var(--fb-fs-field-gap, 2px);border-radius:var(--fb-fs-field-radius, 6px);background:var(--fb-fs-field-bg, #ffffff);border:1px solid var(--fb-fs-field-border, #e5e7eb);transition:all .15s}.fb-selection-field:hover:not(.fb-selection-field--locked):not(.fb-selection-field--option-type){border-color:var(--fb-fs-field-hover-border, #3b82f6);background:var(--fb-fs-field-hover-bg, #f8fafc)}.fb-selection-field--selected{background:var(--fb-fs-field-selected-bg, #eff6ff);border-color:var(--fb-fs-field-selected-border, #bfdbfe)}.fb-selection-field--locked{background:var(--fb-fs-field-locked-bg, #f3f4f6);cursor:not-allowed}.fb-selection-field--locked .fb-selection-field__label{color:var(--fb-fs-field-locked-color, #6b7280);font-weight:500}.fb-selection-field--parent-disabled{opacity:.55;cursor:not-allowed}.fb-selection-field--option-type{background:var(--fb-fs-field-option-type-bg, #f9fafb);border-color:var(--fb-fs-field-option-type-border, #e5e7eb);cursor:default}.fb-selection-field--option-type .fb-selection-field__label{color:var(--fb-fs-field-option-type-color, #374151)}.fb-selection-field__label{font-size:var(--fb-fs-field-label-size, 13px);color:var(--fb-fs-field-label-color, #111827);flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-selection-field__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}.fb-selection-field__option-badge{display:flex;align-items:center;color:var(--fb-fs-option-badge-color, #9ca3af);padding:2px;flex-shrink:0}\n"] }]
9502
9732
  }], propDecorators: { field: [{
9503
9733
  type: Input,
9504
9734
  args: [{ required: true }]
@@ -9506,6 +9736,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
9506
9736
  type: Output
9507
9737
  }], hideToggleForOptionTypes: [{
9508
9738
  type: Input
9739
+ }], disabled: [{
9740
+ type: Input
9509
9741
  }] } });
9510
9742
 
9511
9743
  class SelectionSectionNodeComponent {
@@ -9548,15 +9780,38 @@ class SelectionSectionNodeComponent {
9548
9780
  trackByFieldIndex(index) {
9549
9781
  return index;
9550
9782
  }
9783
+ /**
9784
+ * A GEOGRAPHY_DYNAMIC field's per-level nodes (Country/State/District/...) are built as flat
9785
+ * entries immediately following their master in `section.fields` (see
9786
+ * FormSchemaTreeService._buildGeographyFieldNodes) — there's no real nested schema structure
9787
+ * to walk, so "master" here just means the nearest preceding non-level field.
9788
+ */
9789
+ masterFieldFor(index) {
9790
+ for (let i = index - 1; i >= 0; i--) {
9791
+ const candidate = this.section.fields[i];
9792
+ if (!candidate.isGeographyLevel)
9793
+ return candidate;
9794
+ }
9795
+ return null;
9796
+ }
9797
+ /** True for a geography level whose master field is currently unselected — locked out so the
9798
+ * user can't leave an individually-checked level under an unchecked (and therefore pruned)
9799
+ * master; see masterFieldFor(). */
9800
+ isFieldDisabled(field, index) {
9801
+ if (!field.isGeographyLevel)
9802
+ return false;
9803
+ const master = this.masterFieldFor(index);
9804
+ return !!master && !master.selected;
9805
+ }
9551
9806
  trackBySubsectionIndex(index) {
9552
9807
  return index;
9553
9808
  }
9554
9809
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SelectionSectionNodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
9555
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: SelectionSectionNodeComponent, isStandalone: false, selector: "lib-selection-section-node", inputs: { section: "section", sectionIndex: "sectionIndex", depth: "depth", hideToggleForOptionTypes: "hideToggleForOptionTypes" }, outputs: { toggleEnabled: "toggleEnabled", toggleExpanded: "toggleExpanded", fieldToggle: "fieldToggle" }, ngImport: i0, template: "<div\r\n class=\"fb-selection-section\"\r\n [class.fb-selection-section--disabled]=\"!section.enabled\"\r\n [class.fb-selection-section--nested]=\"depth > 0\"\r\n>\r\n <div class=\"fb-selection-section__header\">\r\n <button\r\n class=\"fb-selection-section__expand-btn\"\r\n (click)=\"onToggleExpanded()\"\r\n [attr.aria-expanded]=\"section.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-selection-section__chevron\"\r\n [class.fb-selection-section__chevron--open]=\"section.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-selection-section__meta\">\r\n <span class=\"fb-selection-section__label\">{{ section.label }}</span>\r\n </div>\r\n\r\n @if (isLocked) {\r\n <span class=\"fb-selection-section__lock\" title=\"This section is locked\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-toggle\r\n [checked]=\"section.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + section.label\"\r\n (toggleChange)=\"onToggleEnabled()\"\r\n />\r\n }\r\n </div>\r\n\r\n @if (section.expanded) {\r\n <div class=\"fb-selection-section__body\">\r\n @for (field of section.fields; track trackByFieldIndex($index); let fi = $index) {\r\n <lib-selection-field-node\r\n [field]=\"field\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleSelected)=\"onFieldToggle(fi)\"\r\n />\r\n }\r\n\r\n @for (sub of section.subsections; track trackBySubsectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"sub\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"depth + 1\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onSubsectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSubsectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onSubsectionFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-selection-section{border:1px solid var(--fb-fs-section-border, #e5e7eb);border-radius:var(--fb-fs-section-radius, 10px);background:var(--fb-fs-section-bg, #ffffff);overflow:hidden}@media(max-width:640px){.fb-selection-section{border-radius:6px}}.fb-selection-section--disabled .fb-selection-section__label{opacity:.55}.fb-selection-section--nested{border-color:var(--fb-fs-section-nested-border, #f3f4f6);background:var(--fb-fs-section-nested-bg, #fafafa)}.fb-selection-section__header{display:flex;align-items:center;gap:8px;padding:var(--fb-fs-section-header-padding, 10px 14px);cursor:pointer;-webkit-user-select:none;user-select:none}@media(max-width:640px){.fb-selection-section__header{padding:8px 10px;gap:6px}}.fb-selection-section__header:hover{background:var(--fb-fs-section-header-hover, #f9fafb)}.fb-selection-section__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}@media(max-width:640px){.fb-selection-section__expand-btn{padding:0}}.fb-selection-section__chevron{transition:transform .2s}.fb-selection-section__chevron--open{transform:rotate(180deg)}.fb-selection-section__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}@media(max-width:640px){.fb-selection-section__meta{gap:6px}}.fb-selection-section__label{font-size:var(--fb-fs-section-label-size, 13px);font-weight:600;color:var(--fb-fs-section-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@media(max-width:640px){.fb-selection-section__label{font-size:12px}}.fb-selection-section__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}.fb-selection-section__body{padding:var(--fb-fs-section-body-padding, 4px 14px 14px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-field-gap, 6px)}@media(max-width:768px){.fb-selection-section__body{padding:4px 12px 12px 24px;gap:5px}}@media(max-width:640px){.fb-selection-section__body{padding:4px 10px 10px 20px;gap:4px}}\n"], dependencies: [{ kind: "component", type: ToggleComponent, selector: "lib-toggle", inputs: ["config", "labels", "label", "checked", "disabled", "required", "labelPosition", "color", "labelColor", "uncheckedColor", "checkedColor", "thumbColor", "checkedThumbColor", "fontSize", "fontWeight", "fontFamily", "toggleWidth", "toggleHeight", "gap", "sliderColor", "labelFontSize", "labelFontWeight", "disabledColor"], outputs: ["toggleChange"] }, { kind: "component", type: SelectionSectionNodeComponent, selector: "lib-selection-section-node", inputs: ["section", "sectionIndex", "depth", "hideToggleForOptionTypes"], outputs: ["toggleEnabled", "toggleExpanded", "fieldToggle"] }, { kind: "component", type: SelectionFieldNodeComponent, selector: "lib-selection-field-node", inputs: ["field", "hideToggleForOptionTypes"], outputs: ["toggleSelected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9810
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: SelectionSectionNodeComponent, isStandalone: false, selector: "lib-selection-section-node", inputs: { section: "section", sectionIndex: "sectionIndex", depth: "depth", hideToggleForOptionTypes: "hideToggleForOptionTypes" }, outputs: { toggleEnabled: "toggleEnabled", toggleExpanded: "toggleExpanded", fieldToggle: "fieldToggle" }, ngImport: i0, template: "<div\r\n class=\"fb-selection-section\"\r\n [class.fb-selection-section--disabled]=\"!section.enabled\"\r\n [class.fb-selection-section--nested]=\"depth > 0\"\r\n>\r\n <div class=\"fb-selection-section__header\">\r\n <button\r\n class=\"fb-selection-section__expand-btn\"\r\n (click)=\"onToggleExpanded()\"\r\n [attr.aria-expanded]=\"section.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-selection-section__chevron\"\r\n [class.fb-selection-section__chevron--open]=\"section.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-selection-section__meta\">\r\n <span class=\"fb-selection-section__label\">{{ section.label }}</span>\r\n </div>\r\n\r\n @if (isLocked) {\r\n <span class=\"fb-selection-section__lock\" title=\"This section is locked\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-toggle\r\n [checked]=\"section.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + section.label\"\r\n (toggleChange)=\"onToggleEnabled()\"\r\n />\r\n }\r\n </div>\r\n\r\n @if (section.expanded) {\r\n <div class=\"fb-selection-section__body\">\r\n @for (field of section.fields; track trackByFieldIndex($index); let fi = $index) {\r\n <lib-selection-field-node\r\n [field]=\"field\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n [disabled]=\"isFieldDisabled(field, fi)\"\r\n [class.fb-selection-section__field--geo-level]=\"field.isGeographyLevel\"\r\n (toggleSelected)=\"onFieldToggle(fi)\"\r\n />\r\n }\r\n\r\n @for (sub of section.subsections; track trackBySubsectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"sub\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"depth + 1\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onSubsectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSubsectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onSubsectionFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-selection-section{border:1px solid var(--fb-fs-section-border, #e5e7eb);border-radius:var(--fb-fs-section-radius, 10px);background:var(--fb-fs-section-bg, #ffffff);overflow:hidden}@media(max-width:640px){.fb-selection-section{border-radius:6px}}.fb-selection-section--disabled .fb-selection-section__label{opacity:.55}.fb-selection-section--nested{border-color:var(--fb-fs-section-nested-border, #f3f4f6);background:var(--fb-fs-section-nested-bg, #fafafa)}.fb-selection-section__header{display:flex;align-items:center;gap:8px;padding:var(--fb-fs-section-header-padding, 10px 14px);cursor:pointer;-webkit-user-select:none;user-select:none}@media(max-width:640px){.fb-selection-section__header{padding:8px 10px;gap:6px}}.fb-selection-section__header:hover{background:var(--fb-fs-section-header-hover, #f9fafb)}.fb-selection-section__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}@media(max-width:640px){.fb-selection-section__expand-btn{padding:0}}.fb-selection-section__chevron{transition:transform .2s}.fb-selection-section__chevron--open{transform:rotate(180deg)}.fb-selection-section__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}@media(max-width:640px){.fb-selection-section__meta{gap:6px}}.fb-selection-section__label{font-size:var(--fb-fs-section-label-size, 13px);font-weight:600;color:var(--fb-fs-section-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@media(max-width:640px){.fb-selection-section__label{font-size:12px}}.fb-selection-section__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}.fb-selection-section__body{padding:var(--fb-fs-section-body-padding, 4px 14px 14px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-field-gap, 6px)}@media(max-width:768px){.fb-selection-section__body{padding:4px 12px 12px 24px;gap:5px}}@media(max-width:640px){.fb-selection-section__body{padding:4px 10px 10px 20px;gap:4px}}.fb-selection-section__body ::ng-deep .fb-selection-section__field--geo-level{margin-left:var(--fb-fs-geo-level-indent, 20px);position:relative}.fb-selection-section__body ::ng-deep .fb-selection-section__field--geo-level:before{content:\"\";position:absolute;left:-12px;top:50%;width:8px;height:1px;background:var(--fb-fs-section-nested-border, #d1d5db)}\n"], dependencies: [{ kind: "component", type: ToggleComponent, selector: "lib-toggle", inputs: ["config", "labels", "label", "checked", "disabled", "required", "labelPosition", "color", "labelColor", "uncheckedColor", "checkedColor", "thumbColor", "checkedThumbColor", "fontSize", "fontWeight", "fontFamily", "toggleWidth", "toggleHeight", "gap", "sliderColor", "labelFontSize", "labelFontWeight", "disabledColor"], outputs: ["toggleChange"] }, { kind: "component", type: SelectionSectionNodeComponent, selector: "lib-selection-section-node", inputs: ["section", "sectionIndex", "depth", "hideToggleForOptionTypes"], outputs: ["toggleEnabled", "toggleExpanded", "fieldToggle"] }, { kind: "component", type: SelectionFieldNodeComponent, selector: "lib-selection-field-node", inputs: ["field", "hideToggleForOptionTypes", "disabled"], outputs: ["toggleSelected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9556
9811
  }
9557
9812
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: SelectionSectionNodeComponent, decorators: [{
9558
9813
  type: Component,
9559
- args: [{ selector: 'lib-selection-section-node', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n class=\"fb-selection-section\"\r\n [class.fb-selection-section--disabled]=\"!section.enabled\"\r\n [class.fb-selection-section--nested]=\"depth > 0\"\r\n>\r\n <div class=\"fb-selection-section__header\">\r\n <button\r\n class=\"fb-selection-section__expand-btn\"\r\n (click)=\"onToggleExpanded()\"\r\n [attr.aria-expanded]=\"section.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-selection-section__chevron\"\r\n [class.fb-selection-section__chevron--open]=\"section.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-selection-section__meta\">\r\n <span class=\"fb-selection-section__label\">{{ section.label }}</span>\r\n </div>\r\n\r\n @if (isLocked) {\r\n <span class=\"fb-selection-section__lock\" title=\"This section is locked\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-toggle\r\n [checked]=\"section.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + section.label\"\r\n (toggleChange)=\"onToggleEnabled()\"\r\n />\r\n }\r\n </div>\r\n\r\n @if (section.expanded) {\r\n <div class=\"fb-selection-section__body\">\r\n @for (field of section.fields; track trackByFieldIndex($index); let fi = $index) {\r\n <lib-selection-field-node\r\n [field]=\"field\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleSelected)=\"onFieldToggle(fi)\"\r\n />\r\n }\r\n\r\n @for (sub of section.subsections; track trackBySubsectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"sub\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"depth + 1\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onSubsectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSubsectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onSubsectionFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-selection-section{border:1px solid var(--fb-fs-section-border, #e5e7eb);border-radius:var(--fb-fs-section-radius, 10px);background:var(--fb-fs-section-bg, #ffffff);overflow:hidden}@media(max-width:640px){.fb-selection-section{border-radius:6px}}.fb-selection-section--disabled .fb-selection-section__label{opacity:.55}.fb-selection-section--nested{border-color:var(--fb-fs-section-nested-border, #f3f4f6);background:var(--fb-fs-section-nested-bg, #fafafa)}.fb-selection-section__header{display:flex;align-items:center;gap:8px;padding:var(--fb-fs-section-header-padding, 10px 14px);cursor:pointer;-webkit-user-select:none;user-select:none}@media(max-width:640px){.fb-selection-section__header{padding:8px 10px;gap:6px}}.fb-selection-section__header:hover{background:var(--fb-fs-section-header-hover, #f9fafb)}.fb-selection-section__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}@media(max-width:640px){.fb-selection-section__expand-btn{padding:0}}.fb-selection-section__chevron{transition:transform .2s}.fb-selection-section__chevron--open{transform:rotate(180deg)}.fb-selection-section__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}@media(max-width:640px){.fb-selection-section__meta{gap:6px}}.fb-selection-section__label{font-size:var(--fb-fs-section-label-size, 13px);font-weight:600;color:var(--fb-fs-section-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@media(max-width:640px){.fb-selection-section__label{font-size:12px}}.fb-selection-section__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}.fb-selection-section__body{padding:var(--fb-fs-section-body-padding, 4px 14px 14px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-field-gap, 6px)}@media(max-width:768px){.fb-selection-section__body{padding:4px 12px 12px 24px;gap:5px}}@media(max-width:640px){.fb-selection-section__body{padding:4px 10px 10px 20px;gap:4px}}\n"] }]
9814
+ args: [{ selector: 'lib-selection-section-node', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n class=\"fb-selection-section\"\r\n [class.fb-selection-section--disabled]=\"!section.enabled\"\r\n [class.fb-selection-section--nested]=\"depth > 0\"\r\n>\r\n <div class=\"fb-selection-section__header\">\r\n <button\r\n class=\"fb-selection-section__expand-btn\"\r\n (click)=\"onToggleExpanded()\"\r\n [attr.aria-expanded]=\"section.expanded\"\r\n type=\"button\"\r\n >\r\n <svg\r\n class=\"fb-selection-section__chevron\"\r\n [class.fb-selection-section__chevron--open]=\"section.expanded\"\r\n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n >\r\n <polyline points=\"6 9 12 15 18 9\" stroke=\"currentColor\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n\r\n <div class=\"fb-selection-section__meta\">\r\n <span class=\"fb-selection-section__label\">{{ section.label }}</span>\r\n </div>\r\n\r\n @if (isLocked) {\r\n <span class=\"fb-selection-section__lock\" title=\"This section is locked\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n <rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect>\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path>\r\n </svg>\r\n </span>\r\n } @else {\r\n <lib-toggle\r\n [checked]=\"section.enabled\"\r\n [disabled]=\"false\"\r\n [attr.aria-label]=\"'Enable ' + section.label\"\r\n (toggleChange)=\"onToggleEnabled()\"\r\n />\r\n }\r\n </div>\r\n\r\n @if (section.expanded) {\r\n <div class=\"fb-selection-section__body\">\r\n @for (field of section.fields; track trackByFieldIndex($index); let fi = $index) {\r\n <lib-selection-field-node\r\n [field]=\"field\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n [disabled]=\"isFieldDisabled(field, fi)\"\r\n [class.fb-selection-section__field--geo-level]=\"field.isGeographyLevel\"\r\n (toggleSelected)=\"onFieldToggle(fi)\"\r\n />\r\n }\r\n\r\n @for (sub of section.subsections; track trackBySubsectionIndex($index); let si = $index) {\r\n <lib-selection-section-node\r\n [section]=\"sub\"\r\n [sectionIndex]=\"si\"\r\n [depth]=\"depth + 1\"\r\n [hideToggleForOptionTypes]=\"hideToggleForOptionTypes\"\r\n (toggleEnabled)=\"onSubsectionToggleEnabled(si, $event)\"\r\n (toggleExpanded)=\"onSubsectionToggleExpanded(si, $event)\"\r\n (fieldToggle)=\"onSubsectionFieldToggle(si, $event)\"\r\n />\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".fb-selection-section{border:1px solid var(--fb-fs-section-border, #e5e7eb);border-radius:var(--fb-fs-section-radius, 10px);background:var(--fb-fs-section-bg, #ffffff);overflow:hidden}@media(max-width:640px){.fb-selection-section{border-radius:6px}}.fb-selection-section--disabled .fb-selection-section__label{opacity:.55}.fb-selection-section--nested{border-color:var(--fb-fs-section-nested-border, #f3f4f6);background:var(--fb-fs-section-nested-bg, #fafafa)}.fb-selection-section__header{display:flex;align-items:center;gap:8px;padding:var(--fb-fs-section-header-padding, 10px 14px);cursor:pointer;-webkit-user-select:none;user-select:none}@media(max-width:640px){.fb-selection-section__header{padding:8px 10px;gap:6px}}.fb-selection-section__header:hover{background:var(--fb-fs-section-header-hover, #f9fafb)}.fb-selection-section__expand-btn{background:none;border:none;cursor:pointer;padding:2px;display:flex;color:var(--fb-fs-chevron-color, #9ca3af);flex-shrink:0}@media(max-width:640px){.fb-selection-section__expand-btn{padding:0}}.fb-selection-section__chevron{transition:transform .2s}.fb-selection-section__chevron--open{transform:rotate(180deg)}.fb-selection-section__meta{flex:1;display:flex;align-items:center;gap:8px;min-width:0}@media(max-width:640px){.fb-selection-section__meta{gap:6px}}.fb-selection-section__label{font-size:var(--fb-fs-section-label-size, 13px);font-weight:600;color:var(--fb-fs-section-label-color, #111827);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@media(max-width:640px){.fb-selection-section__label{font-size:12px}}.fb-selection-section__lock{display:flex;color:var(--fb-fs-lock-color, #9ca3af);padding:2px}.fb-selection-section__body{padding:var(--fb-fs-section-body-padding, 4px 14px 14px 28px);display:flex;flex-direction:column;gap:var(--fb-fs-field-gap, 6px)}@media(max-width:768px){.fb-selection-section__body{padding:4px 12px 12px 24px;gap:5px}}@media(max-width:640px){.fb-selection-section__body{padding:4px 10px 10px 20px;gap:4px}}.fb-selection-section__body ::ng-deep .fb-selection-section__field--geo-level{margin-left:var(--fb-fs-geo-level-indent, 20px);position:relative}.fb-selection-section__body ::ng-deep .fb-selection-section__field--geo-level:before{content:\"\";position:absolute;left:-12px;top:50%;width:8px;height:1px;background:var(--fb-fs-section-nested-border, #d1d5db)}\n"] }]
9560
9815
  }], propDecorators: { section: [{
9561
9816
  type: Input,
9562
9817
  args: [{ required: true }]
@@ -12364,7 +12619,7 @@ class FilterSidebarComponent {
12364
12619
  useExisting: forwardRef(() => FilterSidebarComponent),
12365
12620
  multi: true
12366
12621
  }
12367
- ], ngImport: i0, template: "<div class=\"cc-filter-sidebar\" [ngStyle]=\"sidebarStyles\" [class.collapsed]=\"isCollapsed\">\r\n\r\n <!-- Header -->\r\n <div class=\"cc-filter-header\" *ngIf=\"config.header?.visible !== false\">\r\n <div class=\"cc-header-content\">\r\n <span class=\"cc-header-title\" *ngIf=\"config.header?.title\">\r\n <span *ngIf=\"config.header?.icon\" [class]=\"config.header?.icon\" class=\"cc-header-icon material-icons\">\r\n <!-- {{config.header?.icon }} -->\r\n </span>\r\n {{ config.header?.title }}\r\n </span>\r\n <ng-content select=\"[header-actions]\"></ng-content>\r\n </div>\r\n <button type=\"button\" *ngIf=\"config.settings?.collapsible\" (click)=\"toggleCollapse()\" class=\"cc-icon-btn\"\r\n [attr.aria-label]=\"isCollapsed ? config.labels?.expandAriaLabel : config.labels?.collapseAriaLabel\">\r\n <span class=\"material-icons\">{{ isCollapsed ? 'menu_open' : 'menu' }}</span>\r\n </button>\r\n <button type=\"button\" *ngIf=\"config.header?.showClose && !isCollapsed\" (click)=\"onClose()\"\r\n class=\"cc-icon-btn cc-close-btn\" [attr.aria-label]=\"config.labels?.closeAriaLabel\">\r\n <span class=\"material-icons\">close</span>\r\n </button>\r\n <!-- Code snippet debug (optional) -->\r\n <button type=\"button\" *ngIf=\"config.settings?.showCodeSnippet\" (click)=\"onShowCodeSnippet()\" class=\"cc-icon-btn\"\r\n [attr.aria-label]=\"config.labels?.codeSnippetAriaLabel\">\r\n <span class=\"material-icons\">code</span>\r\n </button>\r\n </div>\r\n\r\n <!-- Content (Scrollable) -->\r\n <div class=\"cc-filter-content\" [class.hidden]=\"isCollapsed\">\r\n <ng-container *ngFor=\"let item of config.items; trackBy: trackByFn\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { item: item }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"cc-filter-footer\" *ngIf=\"config.footer?.visible !== false && !isCollapsed\">\r\n <lib-button variant=\"outline\" color=\"warn\" class=\"cc-btn-clear\"\r\n *ngIf=\"config.footer?.clearButton?.visible !== false\" (click)=\"clearFilters()\">\r\n {{ config.footer?.clearButton?.label }}\r\n </lib-button>\r\n <lib-button variant=\"primary\" color=\"warn\" class=\"cc-btn-apply\"\r\n *ngIf=\"config.footer?.applyButton?.visible !== false\" [disabled]=\"config.footer?.applyButton?.disabled ?? false\"\r\n (click)=\"applyFilters()\">\r\n {{ config.footer?.applyButton?.label }}\r\n </lib-button>\r\n </div>\r\n</div>\r\n\r\n<!-- Recursive Template for Items -->\r\n<ng-template #itemTemplate let-item=\"item\">\r\n <div class=\"cc-filter-item\" [ngClass]=\"['type-' + item.type]\"\r\n [style.display]=\"item.visible === false ? 'none' : 'block'\" [ngStyle]=\"item.styles\">\r\n\r\n <ng-container [ngSwitch]=\"item.type\">\r\n\r\n <!-- Input -->\r\n <lib-input *ngSwitchCase=\"'input'\" [config]=\"item.inputConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (valueChange)=\"onValueChange(item.key, $event)\">\r\n </lib-input>\r\n\r\n <!-- Dropdown -->\r\n <lib-dropdown *ngSwitchCase=\"'dropdown'\" [config]=\"item.dropdownConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (selectionChange)=\"onValueChange(item.key, $event)\">\r\n </lib-dropdown>\r\n\r\n <!-- Checkbox -->\r\n <lib-checkbox *ngSwitchCase=\"'checkbox'\" [config]=\"item.checkboxConfig\" [label]=\"item.label\"\r\n [checked]=\"!!filters[item.key]\" (checkedChange)=\"onValueChange(item.key, $event)\">\r\n </lib-checkbox>\r\n\r\n <!-- Radio -->\r\n <lib-radio *ngSwitchCase=\"'radio'\" [config]=\"item.radioConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (selectionChange)=\"onValueChange(item.key, $event)\">\r\n </lib-radio>\r\n\r\n <!-- Toggle -->\r\n <lib-toggle *ngSwitchCase=\"'toggle'\" [config]=\"item.toggleConfig\" [label]=\"item.label\"\r\n [checked]=\"filters[item.key]\" (toggleChange)=\"onValueChange(item.key, $event)\">\r\n </lib-toggle>\r\n\r\n <!-- Datepicker -->\r\n <lib-datepicker *ngSwitchCase=\"'datepicker'\" [config]=\"item.datepickerConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (dateChange)=\"onValueChange(item.key, $event)\">\r\n </lib-datepicker>\r\n\r\n <!-- Search -->\r\n <lib-search *ngSwitchCase=\"'active-search'\" [config]=\"item.searchConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (search)=\"onValueChange(item.key, $event)\">\r\n </lib-search>\r\n\r\n <!-- Group / Accordion -->\r\n <div *ngSwitchCase=\"'group'\" class=\"cc-accordion-item\" [class.expanded]=\"item.expanded\">\r\n <button type=\"button\" class=\"cc-accordion-header\" (click)=\"item.expanded = !item.expanded\">\r\n <span class=\"cc-accordion-title\">{{ item.label }}</span>\r\n <span class=\"material-icons cc-accordion-icon\">{{ item.expanded ? 'expand_less' : 'expand_more'\r\n }}</span>\r\n </button>\r\n\r\n <div class=\"cc-accordion-body\" *ngIf=\"item.expanded\">\r\n <ng-container *ngFor=\"let child of item.children; trackBy: trackByFn\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { item: child }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- Custom Divider -->\r\n <div *ngSwitchCase=\"'divider'\" class=\"cc-filter-divider\"></div>\r\n\r\n </ng-container>\r\n </div>\r\n</ng-template>", styles: [":host{display:block;height:100%;--cc-filter-sidebar-width: 100%;--cc-filter-sidebar-padding: 1.5rem;--cc-filter-sidebar-gap: 1.5rem;--cc-filter-sidebar-bg: #FEFEFE;--cc-filter-sidebar-border-radius: 0;--cc-filter-header-height: 3rem;--cc-filter-header-title-size: 1.125rem;--cc-filter-header-title-weight: 500;--cc-filter-header-title-color: #202124;--cc-filter-footer-padding: 1rem 0 0 0;--cc-filter-footer-gap: 1rem}.cc-filter-sidebar{display:flex;flex-direction:column;height:100%;width:var(--cc-filter-sidebar-width, 280px);background-color:var(--cc-filter-sidebar-bg, #FEFEFE);padding:var(--cc-filter-sidebar-padding, 1.5rem);box-sizing:border-box;overflow:hidden;border-radius:var(--cc-filter-sidebar-border-radius, 0);transition:width .3s ease,padding .3s ease}.cc-filter-sidebar.collapsed{width:60px!important;padding:1.5rem .5rem}.cc-filter-sidebar.collapsed .cc-filter-header{justify-content:center;margin-bottom:0}.cc-filter-sidebar.collapsed .cc-filter-header .cc-header-content,.cc-filter-sidebar.collapsed .cc-filter-header .cc-close-btn,.cc-filter-sidebar.collapsed .cc-filter-content{display:none}.cc-filter-header{display:flex;align-items:center;justify-content:space-between;min-height:var(--cc-filter-header-height, 3rem);margin-bottom:1rem;flex-shrink:0}.cc-filter-header .cc-header-content{display:flex;align-items:center;gap:.5rem;flex:1}.cc-filter-header .cc-header-title{font-size:var(--cc-filter-header-title-size, 1.125rem);font-weight:var(--cc-filter-header-title-weight, 500);color:var(--cc-filter-header-title-color, #202124);display:flex;align-items:center;gap:.5rem}.cc-filter-content{flex:1;overflow-y:auto;display:flex;flex-direction:column;gap:var(--cc-filter-sidebar-gap, 1.5rem);padding-right:.25rem}.cc-filter-content::-webkit-scrollbar{width:6px}.cc-filter-content::-webkit-scrollbar-thumb{background-color:#e0e0e0;border-radius:3px}.cc-accordion-item{border-bottom:1px solid #E0E0E0}.cc-accordion-item:last-child{border-bottom:none}.cc-accordion-item .cc-accordion-header{display:flex;align-items:center;justify-content:space-between;width:100%;padding:.75rem 0;background:none;border:none;cursor:pointer;text-align:left;outline:none}.cc-accordion-item .cc-accordion-header .cc-accordion-title{font-size:.875rem;font-weight:500;color:#202124}.cc-accordion-item .cc-accordion-header .cc-accordion-icon{color:#5f6368;transition:transform .2s}.cc-accordion-item .cc-accordion-body{padding:0 0 1rem;display:flex;flex-direction:column;gap:1rem;animation:slideDown .2s ease-out}@keyframes slideDown{0%{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:translateY(0)}}.cc-group-content{display:flex;flex-direction:column;gap:1rem}.cc-filter-divider{height:1px;background-color:#e0e0e0;margin:.5rem 0}.cc-filter-footer{display:flex;gap:var(--cc-filter-footer-gap, 1rem);padding:var(--cc-filter-footer-padding, 1rem 0 0 0);margin-top:auto;flex-shrink:0}.cc-filter-footer button{flex:1}.cc-icon-btn{background:none;border:none;cursor:pointer;color:#5f6368;padding:.5rem;border-radius:50%;display:flex;align-items:center;justify-content:center}.cc-icon-btn:hover{background-color:#0000000a}.cc-close-btn{margin-right:-.5rem}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: InputComponent, selector: "lib-input", inputs: ["config", "labels", "type", "label", "placeholder", "disabled", "required", "readonly", "clearable", "maxLength", "minLength", "min", "max", "pattern", "errorMessage", "helperText", "rows", "prefixIcon", "suffixIcon", "value", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "padding", "fontWeight", "color", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["valueChange", "inputBlur", "inputFocus"] }, { kind: "component", type: DropdownComponent, selector: "lib-dropdown", inputs: ["config", "labels", "options", "selectedValue", "placeholder", "label", "multiple", "searchable", "clearable", "disabled", "required", "errorMessage", "serverSearch", "searchDebounceMs", "lazyLoad", "loading", "loadingMore", "hasMore", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "padding", "fontWeight", "color", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["selectionChange", "searchTermChange", "loadMore"] }, { kind: "component", type: CheckboxComponent, selector: "lib-checkbox", inputs: ["config", "labels", "label", "checked", "disabled", "required", "indeterminate", "options", "labelPosition", "color", "borderRadius", "value", "errorMessage", "width", "height", "fontSize", "fontWeight", "labelColor", "labelFontSize", "labelFontWeight", "gap", "fontFamily", "backgroundColor", "borderColor", "borderWidth", "padding", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow", "size", "checkedColor", "uncheckedColor", "groupLabelColor", "groupLabelFontSize", "groupLabelFontWeight"], outputs: ["checkedChange"] }, { kind: "component", type: RadioComponent, selector: "lib-radio", inputs: ["config", "label", "options", "disabled", "required", "labelPosition", "color", "layout", "labels", "gap", "labelColor", "checkedColor", "uncheckedColor", "fontSize", "fontWeight", "fontFamily", "groupLabelColor", "groupLabelFontSize", "groupLabelFontWeight", "disabledColor", "errorColor", "size", "borderRadius", "labelFontSize", "labelFontWeight"], outputs: ["selectionChange"] }, { kind: "component", type: ToggleComponent, selector: "lib-toggle", inputs: ["config", "labels", "label", "checked", "disabled", "required", "labelPosition", "color", "labelColor", "uncheckedColor", "checkedColor", "thumbColor", "checkedThumbColor", "fontSize", "fontWeight", "fontFamily", "toggleWidth", "toggleHeight", "gap", "sliderColor", "labelFontSize", "labelFontWeight", "disabledColor"], outputs: ["toggleChange"] }, { kind: "component", type: DatepickerComponent, selector: "lib-datepicker", inputs: ["config", "labels", "label", "placeholder", "disabled", "required", "minDate", "maxDate", "isRange", "startView", "value", "startDate", "endDate", "errorMessage", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "padding", "fontWeight", "color", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["dateChange"] }, { kind: "component", type: SearchComponent, selector: "lib-search", inputs: ["config", "labels", "placeholder", "label", "disabled", "debounceMs", "clearable", "value", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "border", "padding", "fontWeight", "color", "textColor", "iconColor", "placeholderColor", "focusBorderColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["search", "clear"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }] });
12622
+ ], ngImport: i0, template: "<div class=\"cc-filter-sidebar\" [ngStyle]=\"sidebarStyles\" [class.collapsed]=\"isCollapsed\">\r\n\r\n <!-- Header -->\r\n <div class=\"cc-filter-header\" *ngIf=\"config.header?.visible !== false\">\r\n <div class=\"cc-header-content\">\r\n <span class=\"cc-header-title\" *ngIf=\"config.header?.title\">\r\n <span *ngIf=\"config.header?.icon\" [class]=\"config.header?.icon\" class=\"cc-header-icon material-icons\">\r\n <!-- {{config.header?.icon }} -->\r\n </span>\r\n {{ config.header?.title }}\r\n </span>\r\n <ng-content select=\"[header-actions]\"></ng-content>\r\n </div>\r\n <button type=\"button\" *ngIf=\"config.settings?.collapsible\" (click)=\"toggleCollapse()\" class=\"cc-icon-btn\"\r\n [attr.aria-label]=\"isCollapsed ? config.labels?.expandAriaLabel : config.labels?.collapseAriaLabel\">\r\n <span class=\"material-icons\">{{ isCollapsed ? 'menu_open' : 'menu' }}</span>\r\n </button>\r\n <button type=\"button\" *ngIf=\"config.header?.showClose && !isCollapsed\" (click)=\"onClose()\"\r\n class=\"cc-icon-btn cc-close-btn\" [attr.aria-label]=\"config.labels?.closeAriaLabel\">\r\n <span class=\"material-icons\">close</span>\r\n </button>\r\n <!-- Code snippet debug (optional) -->\r\n <button type=\"button\" *ngIf=\"config.settings?.showCodeSnippet\" (click)=\"onShowCodeSnippet()\" class=\"cc-icon-btn\"\r\n [attr.aria-label]=\"config.labels?.codeSnippetAriaLabel\">\r\n <span class=\"material-icons\">code</span>\r\n </button>\r\n </div>\r\n\r\n <!-- Content (Scrollable) -->\r\n <div class=\"cc-filter-content\" [class.hidden]=\"isCollapsed\">\r\n <ng-container *ngFor=\"let item of config.items; trackBy: trackByFn\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { item: item }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"cc-filter-footer\" *ngIf=\"config.footer?.visible !== false && !isCollapsed\">\r\n <lib-button variant=\"outline\" color=\"warn\" class=\"cc-btn-clear\"\r\n *ngIf=\"config.footer?.clearButton?.visible !== false\" (click)=\"clearFilters()\">\r\n {{ config.footer?.clearButton?.label }}\r\n </lib-button>\r\n <lib-button variant=\"primary\" color=\"warn\" class=\"cc-btn-apply\"\r\n *ngIf=\"config.footer?.applyButton?.visible !== false\" [disabled]=\"config.footer?.applyButton?.disabled ?? false\"\r\n (click)=\"applyFilters()\">\r\n {{ config.footer?.applyButton?.label }}\r\n </lib-button>\r\n </div>\r\n</div>\r\n\r\n<!-- Recursive Template for Items -->\r\n<ng-template #itemTemplate let-item=\"item\">\r\n <div class=\"cc-filter-item\" [ngClass]=\"['type-' + item.type]\"\r\n [style.display]=\"item.visible === false ? 'none' : 'block'\" [ngStyle]=\"item.styles\">\r\n\r\n <ng-container [ngSwitch]=\"item.type\">\r\n\r\n <!-- Input -->\r\n <lib-input *ngSwitchCase=\"'input'\" [config]=\"item.inputConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (valueChange)=\"onValueChange(item.key, $event)\">\r\n </lib-input>\r\n\r\n <!-- Dropdown -->\r\n <lib-dropdown *ngSwitchCase=\"'dropdown'\" [config]=\"item.dropdownConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (selectionChange)=\"onValueChange(item.key, $event)\">\r\n </lib-dropdown>\r\n\r\n <!-- Checkbox -->\r\n <lib-checkbox *ngSwitchCase=\"'checkbox'\" [config]=\"item.checkboxConfig\" [label]=\"item.label\"\r\n [checked]=\"!!filters[item.key]\" (checkedChange)=\"onValueChange(item.key, $event)\">\r\n </lib-checkbox>\r\n\r\n <!-- Radio -->\r\n <lib-radio *ngSwitchCase=\"'radio'\" [config]=\"item.radioConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (selectionChange)=\"onValueChange(item.key, $event)\">\r\n </lib-radio>\r\n\r\n <!-- Toggle -->\r\n <lib-toggle *ngSwitchCase=\"'toggle'\" [config]=\"item.toggleConfig\" [label]=\"item.label\"\r\n [checked]=\"filters[item.key]\" (toggleChange)=\"onValueChange(item.key, $event)\">\r\n </lib-toggle>\r\n\r\n <!-- Datepicker -->\r\n <lib-datepicker *ngSwitchCase=\"'datepicker'\" [config]=\"item.datepickerConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (dateChange)=\"onValueChange(item.key, $event)\">\r\n </lib-datepicker>\r\n\r\n <!-- Search -->\r\n <lib-search *ngSwitchCase=\"'active-search'\" [config]=\"item.searchConfig\" [label]=\"item.label\"\r\n [ngModel]=\"filters[item.key]\" (search)=\"onValueChange(item.key, $event)\">\r\n </lib-search>\r\n\r\n <!-- Group / Accordion -->\r\n <div *ngSwitchCase=\"'group'\" class=\"cc-accordion-item\" [class.expanded]=\"item.expanded\">\r\n <button type=\"button\" class=\"cc-accordion-header\" (click)=\"item.expanded = !item.expanded\">\r\n <span class=\"cc-accordion-title\">{{ item.label }}</span>\r\n <span class=\"material-icons cc-accordion-icon\">{{ item.expanded ? 'expand_less' : 'expand_more'\r\n }}</span>\r\n </button>\r\n\r\n <div class=\"cc-accordion-body\" *ngIf=\"item.expanded\">\r\n <ng-container *ngFor=\"let child of item.children; trackBy: trackByFn\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { item: child }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- Custom Divider -->\r\n <div *ngSwitchCase=\"'divider'\" class=\"cc-filter-divider\"></div>\r\n\r\n </ng-container>\r\n </div>\r\n</ng-template>", styles: [":host{display:block;height:100%;--cc-filter-sidebar-width: 100%;--cc-filter-sidebar-padding: 1.5rem;--cc-filter-sidebar-gap: 1.5rem;--cc-filter-sidebar-bg: #FEFEFE;--cc-filter-sidebar-border-radius: 0;--cc-filter-header-height: 3rem;--cc-filter-header-title-size: 1.125rem;--cc-filter-header-title-weight: 500;--cc-filter-header-title-color: #202124;--cc-filter-footer-padding: 1rem 0 0 0;--cc-filter-footer-gap: 1rem}.cc-filter-sidebar{display:flex;flex-direction:column;height:100%;width:var(--cc-filter-sidebar-width, 280px);background-color:var(--cc-filter-sidebar-bg, #FEFEFE);padding:var(--cc-filter-sidebar-padding, 1.5rem);box-sizing:border-box;overflow:hidden;border-radius:var(--cc-filter-sidebar-border-radius, 0);transition:width .3s ease,padding .3s ease}.cc-filter-sidebar.collapsed{width:60px!important;padding:1.5rem .5rem}.cc-filter-sidebar.collapsed .cc-filter-header{justify-content:center;margin-bottom:0}.cc-filter-sidebar.collapsed .cc-filter-header .cc-header-content,.cc-filter-sidebar.collapsed .cc-filter-header .cc-close-btn,.cc-filter-sidebar.collapsed .cc-filter-content{display:none}.cc-filter-header{display:flex;align-items:center;justify-content:space-between;min-height:var(--cc-filter-header-height, 3rem);margin-bottom:1rem;flex-shrink:0}.cc-filter-header .cc-header-content{display:flex;align-items:center;gap:.5rem;flex:1}.cc-filter-header .cc-header-title{font-size:var(--cc-filter-header-title-size, 1.125rem);font-weight:var(--cc-filter-header-title-weight, 500);color:var(--cc-filter-header-title-color, #202124);display:flex;align-items:center;gap:.5rem}.cc-filter-content{flex:1;overflow-y:auto;display:flex;flex-direction:column;gap:var(--cc-filter-sidebar-gap, 1.5rem);padding-right:.25rem}.cc-filter-content::-webkit-scrollbar{width:6px}.cc-filter-content::-webkit-scrollbar-thumb{background-color:#e0e0e0;border-radius:3px}.cc-accordion-item{border-bottom:1px solid #E0E0E0}.cc-accordion-item:last-child{border-bottom:none}.cc-accordion-item .cc-accordion-header{display:flex;align-items:center;justify-content:space-between;width:100%;padding:.75rem 0;background:none;border:none;cursor:pointer;text-align:left;outline:none}.cc-accordion-item .cc-accordion-header .cc-accordion-title{font-size:.875rem;font-weight:500;color:#202124}.cc-accordion-item .cc-accordion-header .cc-accordion-icon{color:#5f6368;transition:transform .2s}.cc-accordion-item .cc-accordion-body{padding:0 0 1rem;display:flex;flex-direction:column;gap:1rem;animation:slideDown .2s ease-out}@keyframes slideDown{0%{opacity:0;transform:translateY(-5px)}to{opacity:1;transform:translateY(0)}}.cc-group-content{display:flex;flex-direction:column;gap:1rem}.cc-filter-divider{height:1px;background-color:#e0e0e0;margin:.5rem 0}.cc-filter-footer{display:flex;gap:var(--cc-filter-footer-gap, 1rem);padding:var(--cc-filter-footer-padding, 1rem 0 0 0);margin-top:auto;flex-shrink:0}.cc-filter-footer button{flex:1}.cc-icon-btn{background:none;border:none;cursor:pointer;color:#5f6368;padding:.5rem;border-radius:50%;display:flex;align-items:center;justify-content:center}.cc-icon-btn:hover{background-color:#0000000a}.cc-close-btn{margin-right:-.5rem}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: InputComponent, selector: "lib-input", inputs: ["config", "labels", "type", "label", "placeholder", "disabled", "required", "readonly", "clearable", "maxLength", "minLength", "min", "max", "pattern", "errorMessage", "helperText", "rows", "prefixIcon", "suffixIcon", "value", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "padding", "fontWeight", "color", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["valueChange", "inputBlur", "inputFocus"] }, { kind: "component", type: DropdownComponent, selector: "lib-dropdown", inputs: ["config", "labels", "options", "selectedValue", "placeholder", "label", "multiple", "searchable", "clearable", "disabled", "required", "errorMessage", "serverSearch", "searchDebounceMs", "lazyLoad", "loading", "loadingMore", "hasMore", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "padding", "fontWeight", "color", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["selectionChange", "searchTermChange", "loadMore", "opened"] }, { kind: "component", type: CheckboxComponent, selector: "lib-checkbox", inputs: ["config", "labels", "label", "checked", "disabled", "required", "indeterminate", "options", "labelPosition", "color", "borderRadius", "value", "errorMessage", "width", "height", "fontSize", "fontWeight", "labelColor", "labelFontSize", "labelFontWeight", "gap", "fontFamily", "backgroundColor", "borderColor", "borderWidth", "padding", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow", "size", "checkedColor", "uncheckedColor", "groupLabelColor", "groupLabelFontSize", "groupLabelFontWeight"], outputs: ["checkedChange"] }, { kind: "component", type: RadioComponent, selector: "lib-radio", inputs: ["config", "label", "options", "disabled", "required", "labelPosition", "color", "layout", "labels", "gap", "labelColor", "checkedColor", "uncheckedColor", "fontSize", "fontWeight", "fontFamily", "groupLabelColor", "groupLabelFontSize", "groupLabelFontWeight", "disabledColor", "errorColor", "size", "borderRadius", "labelFontSize", "labelFontWeight"], outputs: ["selectionChange"] }, { kind: "component", type: ToggleComponent, selector: "lib-toggle", inputs: ["config", "labels", "label", "checked", "disabled", "required", "labelPosition", "color", "labelColor", "uncheckedColor", "checkedColor", "thumbColor", "checkedThumbColor", "fontSize", "fontWeight", "fontFamily", "toggleWidth", "toggleHeight", "gap", "sliderColor", "labelFontSize", "labelFontWeight", "disabledColor"], outputs: ["toggleChange"] }, { kind: "component", type: DatepickerComponent, selector: "lib-datepicker", inputs: ["config", "labels", "label", "placeholder", "disabled", "required", "minDate", "maxDate", "isRange", "startView", "value", "startDate", "endDate", "errorMessage", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "padding", "fontWeight", "color", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["dateChange"] }, { kind: "component", type: SearchComponent, selector: "lib-search", inputs: ["config", "labels", "placeholder", "label", "disabled", "debounceMs", "clearable", "value", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "border", "padding", "fontWeight", "color", "textColor", "iconColor", "placeholderColor", "focusBorderColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["search", "clear"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }] });
12368
12623
  }
12369
12624
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterSidebarComponent, decorators: [{
12370
12625
  type: Component,
@@ -13357,7 +13612,7 @@ class FilterComponent {
13357
13612
  return item.key || index;
13358
13613
  }
13359
13614
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterComponent, deps: [{ token: i0.ElementRef }, { token: i1$4.Router }, { token: i1$4.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Component });
13360
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: FilterComponent, isStandalone: false, selector: "lib-filter", inputs: { config: "config", activeFilters: "activeFilters", columns: "columns", labels: "labels", theme: "theme" }, outputs: { filterChange: "filterChange", columnChange: "columnChange", toggle: "toggle" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, ngImport: i0, template: "<div class=\"cc-filter-container\" [class.is-open]=\"isOpen\" [ngStyle]=\"containerStyles\">\r\n\r\n <!-- Trigger Button -->\r\n <lib-button variant=\"outline\" (click)=\"togglePanel()\" class=\"cc-filter-trigger\"\r\n [class.active]=\"activeFilterCount > 0\">\r\n <span class=\"fas fa-filter\"></span> {{ labels?.filterBtn || 'Filter' }}\r\n <span *ngIf=\"activeFilterCount > 0\" class=\"cc-badge\">{{ activeFilterCount }}</span>\r\n </lib-button>\r\n\r\n <!-- Dropdown Panel -->\r\n <div class=\"cc-filter-panel mat-elevation-z4\" *ngIf=\"isOpen\" (click)=\"$event.stopPropagation()\">\r\n\r\n <!-- Header / Tabs -->\r\n <div class=\"cc-panel-header\">\r\n <div class=\"cc-tabs\">\r\n <div class=\"cc-tab\" [class.active]=\"activeTab === 'filters'\" (click)=\"setActiveTab('filters')\">\r\n {{ labels.filterBtn }}\r\n </div>\r\n <!-- Hide columns tab if no columns config provided -->\r\n <div class=\"cc-tab\" [class.active]=\"activeTab === 'columns'\" (click)=\"setActiveTab('columns')\"\r\n *ngIf=\"columns?.length\">\r\n {{ labels.columns }}\r\n </div>\r\n </div>\r\n <button type=\"button\" class=\"cc-icon-btn\" (click)=\"togglePanel()\">\r\n <span class=\"material-icons\">close</span>\r\n </button>\r\n </div>\r\n\r\n <!-- Filters Tab Content -->\r\n <div class=\"cc-panel-content\" *ngIf=\"activeTab === 'filters'\">\r\n\r\n <!-- Dynamic Items -->\r\n <ng-container *ngFor=\"let item of config.items; trackBy: trackByFn\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { item: item }\"></ng-container>\r\n </ng-container>\r\n\r\n </div>\r\n\r\n <!-- Columns Tab Content -->\r\n <div class=\"cc-panel-content\" *ngIf=\"activeTab === 'columns'\">\r\n <div class=\"cc-columns-actions\">\r\n <lib-button variant=\"outline\" class=\"cc-btn-text\" (click)=\"toggleAllColumns(true)\">{{ labels.showAll\r\n }}</lib-button>\r\n <lib-button variant=\"outline\" class=\"cc-btn-text\" (click)=\"toggleAllColumns(false)\">{{ labels.hideAll\r\n }}</lib-button>\r\n </div>\r\n <div class=\"cc-columns-list\">\r\n <div *ngFor=\"let col of tempColumns\" class=\"cc-column-item\">\r\n <lib-checkbox [label]=\"col.label\" [checked]=\"col.visible\" (checkedChange)=\"toggleColumn(col.id)\">\r\n </lib-checkbox>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Footer Actions -->\r\n <div class=\"cc-panel-footer\">\r\n <lib-button variant=\"outline\" color=\"warn\" class=\"cc-btn-text text-danger\" (click)=\"clearAll()\">\r\n {{ labels.clear }}\r\n </lib-button>\r\n <lib-button class=\"ms-2\" variant=\"primary\" (click)=\"apply()\">\r\n {{ labels.apply }}\r\n </lib-button>\r\n </div>\r\n\r\n </div>\r\n</div>\r\n\r\n<!-- Recursive Template for Items -->\r\n<ng-template #itemTemplate let-item=\"item\">\r\n <div class=\"cc-filter-item\" [ngClass]=\"['type-' + item.type]\"\r\n [style.display]=\"item.visible === false ? 'none' : 'block'\" [ngStyle]=\"item.styles\">\r\n\r\n <ng-container [ngSwitch]=\"item.type\">\r\n\r\n <!-- Input -->\r\n <lib-input *ngSwitchCase=\"'input'\" [config]=\"item.inputConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (valueChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-input>\r\n\r\n <!-- Dropdown -->\r\n <lib-dropdown *ngSwitchCase=\"'dropdown'\" [config]=\"item.dropdownConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (selectionChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-dropdown>\r\n\r\n <!-- Checkbox -->\r\n <lib-checkbox *ngSwitchCase=\"'checkbox'\" [config]=\"item.checkboxConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (checkedChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-checkbox>\r\n\r\n <!-- Radio -->\r\n <lib-radio *ngSwitchCase=\"'radio'\" [config]=\"item.radioConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (selectionChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-radio>\r\n\r\n <!-- Toggle -->\r\n <lib-toggle *ngSwitchCase=\"'toggle'\" [config]=\"item.toggleConfig\" [label]=\"item.label\"\r\n [checked]=\"tempFilters[item.key]\" (toggleChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-toggle>\r\n\r\n <!-- Datepicker -->\r\n <lib-datepicker *ngSwitchCase=\"'datepicker'\" [config]=\"item.datepickerConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (dateChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-datepicker>\r\n\r\n <!-- Search -->\r\n <lib-search *ngSwitchCase=\"'active-search'\" [config]=\"item.searchConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (search)=\"onFilterChange(item.key, $event)\">\r\n </lib-search>\r\n\r\n <!-- Group / Accordion -->\r\n <div *ngSwitchCase=\"'group'\" class=\"cc-accordion-item\" [class.expanded]=\"item.expanded\">\r\n <button type=\"button\" class=\"cc-accordion-header\" (click)=\"item.expanded = !item.expanded\">\r\n <span class=\"cc-accordion-title\">{{ item.label }}</span>\r\n <span class=\"material-icons cc-accordion-icon\">{{ item.expanded ? 'expand_less' : 'expand_more'\r\n }}</span>\r\n </button>\r\n\r\n <div class=\"cc-accordion-body\" *ngIf=\"item.expanded\">\r\n <ng-container *ngFor=\"let child of item.children; trackBy: trackByFn\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { item: child }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- Custom Divider -->\r\n <div *ngSwitchCase=\"'divider'\" class=\"cc-filter-divider\"></div>\r\n\r\n </ng-container>\r\n </div>\r\n</ng-template>", styles: [".cc-filter-container{position:relative;display:inline-block;font-family:var(--cc-filter-font-family, \"Roboto\", sans-serif)}.cc-filter-container .cc-filter-trigger ::ng-deep button{display:inline-flex;align-items:center;justify-content:center;gap:8px;width:var(--cc-filter-btn-width, 103px);height:var(--cc-filter-btn-height, 44px);padding:0 16px;background-color:var(--cc-filter-btn-bg, #FCFCFB);border:var(--cc-filter-btn-border, 1px solid #E8EAED);border-radius:var(--cc-filter-btn-radius, 8px);color:var(--cc-filter-btn-text-color, #5F6368);font-size:14px;font-weight:500;transition:all .2s ease}.cc-filter-container .cc-filter-trigger ::ng-deep button mat-icon,.cc-filter-container .cc-filter-trigger ::ng-deep button .material-icons{color:#5f6368}.cc-filter-container .cc-filter-trigger ::ng-deep button:hover{background-color:var(--cc-filter-btn-hover-bg, #f1f3f4)}.cc-filter-container .cc-filter-trigger.active ::ng-deep button{background-color:var(--cc-filter-btn-active-bg, #e3f2fd);color:var(--cc-filter-btn-active-text, #1976d2);border-color:var(--cc-filter-btn-active-text, #1976d2)}.cc-filter-container .cc-filter-trigger.active ::ng-deep button mat-icon,.cc-filter-container .cc-filter-trigger.active ::ng-deep button .material-icons{color:var(--cc-filter-btn-active-text, #1976d2)}.cc-filter-container .cc-filter-trigger .cc-badge{background-color:var(--cc-filter-btn-badge-bg, #f44336);color:var(--cc-filter-btn-badge-text, #fff);font-size:10px;font-weight:700;padding:2px 6px;border-radius:10px;min-width:16px;text-align:center;margin-left:4px;line-height:1}.cc-filter-container .cc-filter-panel{position:absolute;top:calc(100% + 8px);right:0;z-index:1000;width:var(--cc-filter-panel-width, 320px);min-width:var(--cc-filter-panel-min-width, 480px)!important;padding:var(--cc-filter-panel-padding, 0);background-color:var(--cc-filter-panel-bg, #fff);border:var(--cc-filter-panel-border, 1px solid #e0e0e0);box-shadow:var(--cc-filter-panel-shadow, 0 4px 12px rgba(0, 0, 0, .15));border-radius:var(--cc-filter-panel-radius, 8px);display:flex;flex-direction:column;overflow:hidden}.cc-filter-container .cc-filter-panel.hidden{display:none}.cc-filter-container .cc-filter-panel .cc-panel-header{display:flex;align-items:center;justify-content:space-between;padding:0 1rem;height:var(--cc-filter-panel-header-height, 48px);border-bottom:1px solid #E0E0E0;background-color:var(--cc-filter-panel-header-bg, #fafafa)}.cc-filter-container .cc-tabs{display:flex;gap:1rem}.cc-filter-container .cc-tabs .cc-tab{cursor:pointer;padding:.5rem 0;font-weight:500;color:#5f6368;border-bottom:2px solid transparent;font-size:14px}.cc-filter-container .cc-tabs .cc-tab.active{color:var(--cc-filter-tab-active-text, #1976d2);border-bottom:var(--cc-filter-tab-border-bottom, 2px solid #1976d2)}.cc-filter-container .cc-icon-btn{background:none;border:none;cursor:pointer;color:#5f6368;padding:.25rem;border-radius:50%;display:flex;align-items:center;justify-content:center}.cc-filter-container .cc-icon-btn:hover{background-color:#0000000a}.cc-filter-container .cc-panel-content{padding:16px;max-height:400px;overflow-y:auto;display:flex;flex-direction:column;gap:var(--cc-filter-panel-gap, 1rem)}.cc-filter-container .cc-filter-section{margin-bottom:16px}.cc-filter-container .cc-filter-section .cc-section-title{font-size:13px;font-weight:600;margin-bottom:8px;color:var(--cc-filter-section-title, #333);text-transform:uppercase;letter-spacing:.5px}.cc-filter-container .cc-filter-section .cc-control-group{display:flex;flex-direction:column;gap:8px}.cc-filter-container .cc-filter-section .cc-control-group label{display:flex;align-items:center;gap:8px;font-size:14px;color:var(--cc-filter-option-text, #555);cursor:pointer}.cc-filter-container .cc-filter-section .cc-control-group label:hover{color:#000}.cc-filter-container .cc-accordion-item{border-bottom:1px solid #E0E0E0}.cc-filter-container .cc-accordion-item:last-child{border-bottom:none}.cc-filter-container .cc-accordion-item .cc-accordion-header{display:flex;align-items:center;justify-content:space-between;width:100%;padding:.75rem 0;background:none;border:none;cursor:pointer;text-align:left;outline:none}.cc-filter-container .cc-accordion-item .cc-accordion-header .cc-accordion-title{font-size:.875rem;font-weight:500;color:#202124}.cc-filter-container .cc-accordion-item .cc-accordion-header .cc-accordion-icon{color:#5f6368;transition:transform .2s}.cc-filter-container .cc-accordion-item .cc-accordion-body{padding:0 0 1rem;display:flex;flex-direction:column;gap:1rem;animation:slideDown .2s ease-out}.cc-filter-container .cc-filter-divider{height:1px;background-color:#e0e0e0;margin:.5rem 0}.cc-filter-container .cc-panel-footer{padding:12px 16px;background-color:var(--cc-filter-footer-bg, #fff);border-top:var(--cc-filter-footer-border-top, 1px solid #e0e0e0);display:flex;justify-content:flex-end;align-items:center;gap:10px}.cc-filter-container .cc-columns-actions{display:flex;gap:.5rem;margin-bottom:.5rem}.cc-filter-container .cc-columns-list{display:flex;flex-direction:column;gap:.5rem}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: InputComponent, selector: "lib-input", inputs: ["config", "labels", "type", "label", "placeholder", "disabled", "required", "readonly", "clearable", "maxLength", "minLength", "min", "max", "pattern", "errorMessage", "helperText", "rows", "prefixIcon", "suffixIcon", "value", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "padding", "fontWeight", "color", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["valueChange", "inputBlur", "inputFocus"] }, { kind: "component", type: DropdownComponent, selector: "lib-dropdown", inputs: ["config", "labels", "options", "selectedValue", "placeholder", "label", "multiple", "searchable", "clearable", "disabled", "required", "errorMessage", "serverSearch", "searchDebounceMs", "lazyLoad", "loading", "loadingMore", "hasMore", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "padding", "fontWeight", "color", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["selectionChange", "searchTermChange", "loadMore"] }, { kind: "component", type: CheckboxComponent, selector: "lib-checkbox", inputs: ["config", "labels", "label", "checked", "disabled", "required", "indeterminate", "options", "labelPosition", "color", "borderRadius", "value", "errorMessage", "width", "height", "fontSize", "fontWeight", "labelColor", "labelFontSize", "labelFontWeight", "gap", "fontFamily", "backgroundColor", "borderColor", "borderWidth", "padding", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow", "size", "checkedColor", "uncheckedColor", "groupLabelColor", "groupLabelFontSize", "groupLabelFontWeight"], outputs: ["checkedChange"] }, { kind: "component", type: RadioComponent, selector: "lib-radio", inputs: ["config", "label", "options", "disabled", "required", "labelPosition", "color", "layout", "labels", "gap", "labelColor", "checkedColor", "uncheckedColor", "fontSize", "fontWeight", "fontFamily", "groupLabelColor", "groupLabelFontSize", "groupLabelFontWeight", "disabledColor", "errorColor", "size", "borderRadius", "labelFontSize", "labelFontWeight"], outputs: ["selectionChange"] }, { kind: "component", type: ToggleComponent, selector: "lib-toggle", inputs: ["config", "labels", "label", "checked", "disabled", "required", "labelPosition", "color", "labelColor", "uncheckedColor", "checkedColor", "thumbColor", "checkedThumbColor", "fontSize", "fontWeight", "fontFamily", "toggleWidth", "toggleHeight", "gap", "sliderColor", "labelFontSize", "labelFontWeight", "disabledColor"], outputs: ["toggleChange"] }, { kind: "component", type: DatepickerComponent, selector: "lib-datepicker", inputs: ["config", "labels", "label", "placeholder", "disabled", "required", "minDate", "maxDate", "isRange", "startView", "value", "startDate", "endDate", "errorMessage", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "padding", "fontWeight", "color", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["dateChange"] }, { kind: "component", type: SearchComponent, selector: "lib-search", inputs: ["config", "labels", "placeholder", "label", "disabled", "debounceMs", "clearable", "value", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "border", "padding", "fontWeight", "color", "textColor", "iconColor", "placeholderColor", "focusBorderColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["search", "clear"] }] });
13615
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.15", type: FilterComponent, isStandalone: false, selector: "lib-filter", inputs: { config: "config", activeFilters: "activeFilters", columns: "columns", labels: "labels", theme: "theme" }, outputs: { filterChange: "filterChange", columnChange: "columnChange", toggle: "toggle" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, ngImport: i0, template: "<div class=\"cc-filter-container\" [class.is-open]=\"isOpen\" [ngStyle]=\"containerStyles\">\r\n\r\n <!-- Trigger Button -->\r\n <lib-button variant=\"outline\" (click)=\"togglePanel()\" class=\"cc-filter-trigger\"\r\n [class.active]=\"activeFilterCount > 0\">\r\n <span class=\"fas fa-filter\"></span> {{ labels?.filterBtn || 'Filter' }}\r\n <span *ngIf=\"activeFilterCount > 0\" class=\"cc-badge\">{{ activeFilterCount }}</span>\r\n </lib-button>\r\n\r\n <!-- Dropdown Panel -->\r\n <div class=\"cc-filter-panel mat-elevation-z4\" *ngIf=\"isOpen\" (click)=\"$event.stopPropagation()\">\r\n\r\n <!-- Header / Tabs -->\r\n <div class=\"cc-panel-header\">\r\n <div class=\"cc-tabs\">\r\n <div class=\"cc-tab\" [class.active]=\"activeTab === 'filters'\" (click)=\"setActiveTab('filters')\">\r\n {{ labels.filterBtn }}\r\n </div>\r\n <!-- Hide columns tab if no columns config provided -->\r\n <div class=\"cc-tab\" [class.active]=\"activeTab === 'columns'\" (click)=\"setActiveTab('columns')\"\r\n *ngIf=\"columns?.length\">\r\n {{ labels.columns }}\r\n </div>\r\n </div>\r\n <button type=\"button\" class=\"cc-icon-btn\" (click)=\"togglePanel()\">\r\n <span class=\"material-icons\">close</span>\r\n </button>\r\n </div>\r\n\r\n <!-- Filters Tab Content -->\r\n <div class=\"cc-panel-content\" *ngIf=\"activeTab === 'filters'\">\r\n\r\n <!-- Dynamic Items -->\r\n <ng-container *ngFor=\"let item of config.items; trackBy: trackByFn\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { item: item }\"></ng-container>\r\n </ng-container>\r\n\r\n </div>\r\n\r\n <!-- Columns Tab Content -->\r\n <div class=\"cc-panel-content\" *ngIf=\"activeTab === 'columns'\">\r\n <div class=\"cc-columns-actions\">\r\n <lib-button variant=\"outline\" class=\"cc-btn-text\" (click)=\"toggleAllColumns(true)\">{{ labels.showAll\r\n }}</lib-button>\r\n <lib-button variant=\"outline\" class=\"cc-btn-text\" (click)=\"toggleAllColumns(false)\">{{ labels.hideAll\r\n }}</lib-button>\r\n </div>\r\n <div class=\"cc-columns-list\">\r\n <div *ngFor=\"let col of tempColumns\" class=\"cc-column-item\">\r\n <lib-checkbox [label]=\"col.label\" [checked]=\"col.visible\" (checkedChange)=\"toggleColumn(col.id)\">\r\n </lib-checkbox>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Footer Actions -->\r\n <div class=\"cc-panel-footer\">\r\n <lib-button variant=\"outline\" color=\"warn\" class=\"cc-btn-text text-danger\" (click)=\"clearAll()\">\r\n {{ labels.clear }}\r\n </lib-button>\r\n <lib-button class=\"ms-2\" variant=\"primary\" (click)=\"apply()\">\r\n {{ labels.apply }}\r\n </lib-button>\r\n </div>\r\n\r\n </div>\r\n</div>\r\n\r\n<!-- Recursive Template for Items -->\r\n<ng-template #itemTemplate let-item=\"item\">\r\n <div class=\"cc-filter-item\" [ngClass]=\"['type-' + item.type]\"\r\n [style.display]=\"item.visible === false ? 'none' : 'block'\" [ngStyle]=\"item.styles\">\r\n\r\n <ng-container [ngSwitch]=\"item.type\">\r\n\r\n <!-- Input -->\r\n <lib-input *ngSwitchCase=\"'input'\" [config]=\"item.inputConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (valueChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-input>\r\n\r\n <!-- Dropdown -->\r\n <lib-dropdown *ngSwitchCase=\"'dropdown'\" [config]=\"item.dropdownConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (selectionChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-dropdown>\r\n\r\n <!-- Checkbox -->\r\n <lib-checkbox *ngSwitchCase=\"'checkbox'\" [config]=\"item.checkboxConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (checkedChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-checkbox>\r\n\r\n <!-- Radio -->\r\n <lib-radio *ngSwitchCase=\"'radio'\" [config]=\"item.radioConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (selectionChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-radio>\r\n\r\n <!-- Toggle -->\r\n <lib-toggle *ngSwitchCase=\"'toggle'\" [config]=\"item.toggleConfig\" [label]=\"item.label\"\r\n [checked]=\"tempFilters[item.key]\" (toggleChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-toggle>\r\n\r\n <!-- Datepicker -->\r\n <lib-datepicker *ngSwitchCase=\"'datepicker'\" [config]=\"item.datepickerConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (dateChange)=\"onFilterChange(item.key, $event)\">\r\n </lib-datepicker>\r\n\r\n <!-- Search -->\r\n <lib-search *ngSwitchCase=\"'active-search'\" [config]=\"item.searchConfig\" [label]=\"item.label\"\r\n [ngModel]=\"tempFilters[item.key]\" (search)=\"onFilterChange(item.key, $event)\">\r\n </lib-search>\r\n\r\n <!-- Group / Accordion -->\r\n <div *ngSwitchCase=\"'group'\" class=\"cc-accordion-item\" [class.expanded]=\"item.expanded\">\r\n <button type=\"button\" class=\"cc-accordion-header\" (click)=\"item.expanded = !item.expanded\">\r\n <span class=\"cc-accordion-title\">{{ item.label }}</span>\r\n <span class=\"material-icons cc-accordion-icon\">{{ item.expanded ? 'expand_less' : 'expand_more'\r\n }}</span>\r\n </button>\r\n\r\n <div class=\"cc-accordion-body\" *ngIf=\"item.expanded\">\r\n <ng-container *ngFor=\"let child of item.children; trackBy: trackByFn\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { item: child }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <!-- Custom Divider -->\r\n <div *ngSwitchCase=\"'divider'\" class=\"cc-filter-divider\"></div>\r\n\r\n </ng-container>\r\n </div>\r\n</ng-template>", styles: [".cc-filter-container{position:relative;display:inline-block;font-family:var(--cc-filter-font-family, \"Roboto\", sans-serif)}.cc-filter-container .cc-filter-trigger ::ng-deep button{display:inline-flex;align-items:center;justify-content:center;gap:8px;width:var(--cc-filter-btn-width, 103px);height:var(--cc-filter-btn-height, 44px);padding:0 16px;background-color:var(--cc-filter-btn-bg, #FCFCFB);border:var(--cc-filter-btn-border, 1px solid #E8EAED);border-radius:var(--cc-filter-btn-radius, 8px);color:var(--cc-filter-btn-text-color, #5F6368);font-size:14px;font-weight:500;transition:all .2s ease}.cc-filter-container .cc-filter-trigger ::ng-deep button mat-icon,.cc-filter-container .cc-filter-trigger ::ng-deep button .material-icons{color:#5f6368}.cc-filter-container .cc-filter-trigger ::ng-deep button:hover{background-color:var(--cc-filter-btn-hover-bg, #f1f3f4)}.cc-filter-container .cc-filter-trigger.active ::ng-deep button{background-color:var(--cc-filter-btn-active-bg, #e3f2fd);color:var(--cc-filter-btn-active-text, #1976d2);border-color:var(--cc-filter-btn-active-text, #1976d2)}.cc-filter-container .cc-filter-trigger.active ::ng-deep button mat-icon,.cc-filter-container .cc-filter-trigger.active ::ng-deep button .material-icons{color:var(--cc-filter-btn-active-text, #1976d2)}.cc-filter-container .cc-filter-trigger .cc-badge{background-color:var(--cc-filter-btn-badge-bg, #f44336);color:var(--cc-filter-btn-badge-text, #fff);font-size:10px;font-weight:700;padding:2px 6px;border-radius:10px;min-width:16px;text-align:center;margin-left:4px;line-height:1}.cc-filter-container .cc-filter-panel{position:absolute;top:calc(100% + 8px);right:0;z-index:1000;width:var(--cc-filter-panel-width, 320px);min-width:var(--cc-filter-panel-min-width, 480px)!important;padding:var(--cc-filter-panel-padding, 0);background-color:var(--cc-filter-panel-bg, #fff);border:var(--cc-filter-panel-border, 1px solid #e0e0e0);box-shadow:var(--cc-filter-panel-shadow, 0 4px 12px rgba(0, 0, 0, .15));border-radius:var(--cc-filter-panel-radius, 8px);display:flex;flex-direction:column;overflow:hidden}.cc-filter-container .cc-filter-panel.hidden{display:none}.cc-filter-container .cc-filter-panel .cc-panel-header{display:flex;align-items:center;justify-content:space-between;padding:0 1rem;height:var(--cc-filter-panel-header-height, 48px);border-bottom:1px solid #E0E0E0;background-color:var(--cc-filter-panel-header-bg, #fafafa)}.cc-filter-container .cc-tabs{display:flex;gap:1rem}.cc-filter-container .cc-tabs .cc-tab{cursor:pointer;padding:.5rem 0;font-weight:500;color:#5f6368;border-bottom:2px solid transparent;font-size:14px}.cc-filter-container .cc-tabs .cc-tab.active{color:var(--cc-filter-tab-active-text, #1976d2);border-bottom:var(--cc-filter-tab-border-bottom, 2px solid #1976d2)}.cc-filter-container .cc-icon-btn{background:none;border:none;cursor:pointer;color:#5f6368;padding:.25rem;border-radius:50%;display:flex;align-items:center;justify-content:center}.cc-filter-container .cc-icon-btn:hover{background-color:#0000000a}.cc-filter-container .cc-panel-content{padding:16px;max-height:400px;overflow-y:auto;display:flex;flex-direction:column;gap:var(--cc-filter-panel-gap, 1rem)}.cc-filter-container .cc-filter-section{margin-bottom:16px}.cc-filter-container .cc-filter-section .cc-section-title{font-size:13px;font-weight:600;margin-bottom:8px;color:var(--cc-filter-section-title, #333);text-transform:uppercase;letter-spacing:.5px}.cc-filter-container .cc-filter-section .cc-control-group{display:flex;flex-direction:column;gap:8px}.cc-filter-container .cc-filter-section .cc-control-group label{display:flex;align-items:center;gap:8px;font-size:14px;color:var(--cc-filter-option-text, #555);cursor:pointer}.cc-filter-container .cc-filter-section .cc-control-group label:hover{color:#000}.cc-filter-container .cc-accordion-item{border-bottom:1px solid #E0E0E0}.cc-filter-container .cc-accordion-item:last-child{border-bottom:none}.cc-filter-container .cc-accordion-item .cc-accordion-header{display:flex;align-items:center;justify-content:space-between;width:100%;padding:.75rem 0;background:none;border:none;cursor:pointer;text-align:left;outline:none}.cc-filter-container .cc-accordion-item .cc-accordion-header .cc-accordion-title{font-size:.875rem;font-weight:500;color:#202124}.cc-filter-container .cc-accordion-item .cc-accordion-header .cc-accordion-icon{color:#5f6368;transition:transform .2s}.cc-filter-container .cc-accordion-item .cc-accordion-body{padding:0 0 1rem;display:flex;flex-direction:column;gap:1rem;animation:slideDown .2s ease-out}.cc-filter-container .cc-filter-divider{height:1px;background-color:#e0e0e0;margin:.5rem 0}.cc-filter-container .cc-panel-footer{padding:12px 16px;background-color:var(--cc-filter-footer-bg, #fff);border-top:var(--cc-filter-footer-border-top, 1px solid #e0e0e0);display:flex;justify-content:flex-end;align-items:center;gap:10px}.cc-filter-container .cc-columns-actions{display:flex;gap:.5rem;margin-bottom:.5rem}.cc-filter-container .cc-columns-list{display:flex;flex-direction:column;gap:.5rem}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ButtonComponent, selector: "lib-button", inputs: ["variant", "type", "disabled", "width", "height", "borderRadius", "fontSize", "fontWeight", "backgroundColor", "color", "border", "icon", "labels"] }, { kind: "component", type: InputComponent, selector: "lib-input", inputs: ["config", "labels", "type", "label", "placeholder", "disabled", "required", "readonly", "clearable", "maxLength", "minLength", "min", "max", "pattern", "errorMessage", "helperText", "rows", "prefixIcon", "suffixIcon", "value", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "padding", "fontWeight", "color", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["valueChange", "inputBlur", "inputFocus"] }, { kind: "component", type: DropdownComponent, selector: "lib-dropdown", inputs: ["config", "labels", "options", "selectedValue", "placeholder", "label", "multiple", "searchable", "clearable", "disabled", "required", "errorMessage", "serverSearch", "searchDebounceMs", "lazyLoad", "loading", "loadingMore", "hasMore", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "padding", "fontWeight", "color", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["selectionChange", "searchTermChange", "loadMore", "opened"] }, { kind: "component", type: CheckboxComponent, selector: "lib-checkbox", inputs: ["config", "labels", "label", "checked", "disabled", "required", "indeterminate", "options", "labelPosition", "color", "borderRadius", "value", "errorMessage", "width", "height", "fontSize", "fontWeight", "labelColor", "labelFontSize", "labelFontWeight", "gap", "fontFamily", "backgroundColor", "borderColor", "borderWidth", "padding", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow", "size", "checkedColor", "uncheckedColor", "groupLabelColor", "groupLabelFontSize", "groupLabelFontWeight"], outputs: ["checkedChange"] }, { kind: "component", type: RadioComponent, selector: "lib-radio", inputs: ["config", "label", "options", "disabled", "required", "labelPosition", "color", "layout", "labels", "gap", "labelColor", "checkedColor", "uncheckedColor", "fontSize", "fontWeight", "fontFamily", "groupLabelColor", "groupLabelFontSize", "groupLabelFontWeight", "disabledColor", "errorColor", "size", "borderRadius", "labelFontSize", "labelFontWeight"], outputs: ["selectionChange"] }, { kind: "component", type: ToggleComponent, selector: "lib-toggle", inputs: ["config", "labels", "label", "checked", "disabled", "required", "labelPosition", "color", "labelColor", "uncheckedColor", "checkedColor", "thumbColor", "checkedThumbColor", "fontSize", "fontWeight", "fontFamily", "toggleWidth", "toggleHeight", "gap", "sliderColor", "labelFontSize", "labelFontWeight", "disabledColor"], outputs: ["toggleChange"] }, { kind: "component", type: DatepickerComponent, selector: "lib-datepicker", inputs: ["config", "labels", "label", "placeholder", "disabled", "required", "minDate", "maxDate", "isRange", "startView", "value", "startDate", "endDate", "errorMessage", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "padding", "fontWeight", "color", "placeholderColor", "focusBorderColor", "errorColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["dateChange"] }, { kind: "component", type: SearchComponent, selector: "lib-search", inputs: ["config", "labels", "placeholder", "label", "disabled", "debounceMs", "clearable", "value", "width", "height", "borderRadius", "fontSize", "gap", "fontFamily", "labelColor", "labelFontSize", "labelFontWeight", "backgroundColor", "borderColor", "borderWidth", "border", "padding", "fontWeight", "color", "textColor", "iconColor", "placeholderColor", "focusBorderColor", "disabledBackgroundColor", "disabledColor", "boxShadow"], outputs: ["search", "clear"] }] });
13361
13616
  }
13362
13617
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: FilterComponent, decorators: [{
13363
13618
  type: Component,