@snabcentr/client-ui 3.52.1 → 3.52.3

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.
@@ -1,20 +1,20 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, Injectable, NgZone, signal, EventEmitter, ChangeDetectorRef, Directive, Input, Output, Pipe, ElementRef, HostListener, Renderer2, ContentChildren, NgModule, input, computed, Component, ChangeDetectionStrategy, Inject, HostBinding, model, output, SkipSelf, DestroyRef, effect, ContentChild, ViewChild, viewChild, Optional, forwardRef } from '@angular/core';
2
+ import { InjectionToken, inject, Injectable, NgZone, signal, EventEmitter, ChangeDetectorRef, Directive, Input, Output, Pipe, ElementRef, HostListener, Renderer2, ContentChildren, NgModule, input, computed, Component, ChangeDetectionStrategy, Inject, HostBinding, model, output, SkipSelf, DestroyRef, effect, ContentChild, ViewChild, viewChild, Optional, contentChild, TemplateRef, forwardRef } from '@angular/core';
3
3
  import * as i1 from '@snabcentr/client-core';
4
4
  import { ScContactsService, ScUserService, ScLocationsService, ScAuthService, SEARCH_TERM, ScUnitsHelper, ScImageHelper, SC_PATH_IMAGE_NOT_FOUND, ScImage, ScPhoneService, ScUserMetrikaService, ScUserMetrikaGoalsEnum, IS_RUNNING_ON_TERMINAL, ScVCardService, ScVerificationService, ScISuggestionType, SC_MIN_LENGTH_SEARCH_TERM, ScConvertersService, ScOpfList, ScReferencesService, ScContragentService, ScBannerService, ScMediaImageTransformerPipe, ScCartService, ScUploadedFile, SC_ORDER_LOADER, ScMimeTypes, ScCatalogService, SC_URLS, IS_SERVER, ScWarehouseService, SEARCH_TERM_PROVIDERS, ScPaginationService, SC_NEXT_PAGE_PAGINATION_CLICK, SC_PRODUCT_PAGINATION_OPTIONS, ScCatalogFilterService, ScIdOrSlugPipe, SC_CATEGORY_INFO, ScConfiguratorService, RESPONSE, ScIconTypesEnum, ScDocumentInfoTypesEnum, ScOrderDraftsService, ScRouteKeys, ScSeoService, scOrderIsLoaded, ScFrequentlyAskedQuestionsService, SC_COMPANY_INFO, ScFeedbackService } from '@snabcentr/client-core';
5
5
  import * as i5$1 from 'rxjs';
6
- import { EMPTY, BehaviorSubject, switchMap, of, shareReplay, map, Subject, filter, tap, catchError, finalize, startWith, share, timer, scan, takeWhile, endWith, distinctUntilChanged, debounceTime, throwError, combineLatest, Observable, pairwise, merge, skip, from, concatMap, noop, first } from 'rxjs';
6
+ import { EMPTY, BehaviorSubject, switchMap, of, shareReplay, map, Subject, filter, tap, catchError, finalize, startWith, share, timer, scan, takeWhile, endWith, distinctUntilChanged, debounceTime, throwError, combineLatest, Observable, pairwise, Subscription, merge, skip, from, concatMap, noop, first } from 'rxjs';
7
7
  import { WA_WINDOW } from '@ng-web-apis/common';
8
8
  import { takeUntilDestroyed, toSignal, outputFromObservable, toObservable } from '@angular/core/rxjs-interop';
9
9
  import * as i4$1 from '@taiga-ui/cdk';
10
10
  import { TuiDay, TuiTime, TuiValueTransformer, TUI_IS_MOBILE, tuiControlValue, tuiIsPresent, tuiMarkControlAsTouchedAndValidate, tuiIsFalsy, TuiAutoFocus, TuiRepeatTimes, TuiHovered, TuiDayRange, TuiMonth, tuiPure, tuiProvide, TUI_WINDOW_SIZE, TuiValidationError, TUI_TRUE_HANDLER } from '@taiga-ui/cdk';
11
11
  import * as i2$1 from '@taiga-ui/kit';
12
- import { TUI_DATE_VALUE_TRANSFORMER, TuiPreview, TuiAvatar, TuiAccordionItem, TuiElasticContainer, TuiAccordion, TuiFieldErrorPipe, TuiFilterByInputPipe, TuiStringifyContentPipe, TuiDataListWrapper, TuiButtonLoading, TuiSortCountriesPipe, TuiStepper, TuiCarousel, TuiPush, TuiCheckbox, TuiFiles, TuiChip, TuiInputNumber, TuiBadge, TuiTooltip, TuiHighlight, TuiLineClamp, TuiRadio, TuiInputRange, tuiInputNumberOptionsProvider, TuiDataListWrapperComponent, TuiChevron, TuiSelect, TuiInputSlider, TuiTreeService, TuiTreeItemContent, TUI_TREE_START, TUI_TREE_CONTENT, TUI_TREE_LOADING, TUI_TREE_LOADER, TuiTree, TuiPreviewDialogService, TUI_CONFIRM, tuiItemsHandlersProvider as tuiItemsHandlersProvider$1, TuiPagination, TuiAccordionDirective, TuiAccordionItemContent, tuiFilesAccepted } from '@taiga-ui/kit';
12
+ import { TUI_DATE_VALUE_TRANSFORMER, TuiPreview, TuiAvatar, TuiAccordionItem, TuiElasticContainer, TuiAccordion, TuiFieldErrorPipe, TuiFilterByInputPipe, TuiStringifyContentPipe, TuiDataListWrapper, TuiButtonLoading, TuiSortCountriesPipe, TuiStepper, TuiCarousel, TuiPush, TuiCheckbox, TuiFiles, TuiChip, TuiInputNumber, TuiBadge, TuiTooltip, TuiHighlight, TuiLineClamp, TuiFade, TuiRange, tuiInputNumberOptionsProvider, TuiDataListWrapperComponent, TuiChevron, TuiSelect, TuiInputSlider, TuiTreeService, TuiTreeItemContent, TUI_TREE_START, TUI_TREE_CONTENT, TUI_TREE_LOADING, TUI_TREE_LOADER, TuiTree, TuiPreviewDialogService, TUI_CONFIRM, tuiItemsHandlersProvider as tuiItemsHandlersProvider$1, TuiPagination, TuiAccordionDirective, TuiAccordionItemContent, tuiFilesAccepted } from '@taiga-ui/kit';
13
13
  import { HttpClient, HttpErrorResponse } from '@angular/common/http';
14
14
  import * as i1$1 from '@angular/forms';
15
15
  import { FormControl, FormGroupDirective, NgControl, FormGroup, Validators, FormArray, FormsModule, ReactiveFormsModule } from '@angular/forms';
16
16
  import * as i1$2 from '@taiga-ui/core';
17
- import { TuiButton, TuiDialog, TuiDialogService, TuiLink, TuiFallbackSrcPipe, TuiInitialsPipe, TuiIcon, TuiAppearance, TuiWithAppearance, TuiIcons, TuiWithIcons, TUI_DATA_LIST_HOST, tuiDropdownOptionsProvider, TuiLabel, TuiError, TuiLoader, TuiDataList, TuiNotification, TuiTextfield, TuiTitle, TuiNumberFormat, TuiHint, TUI_MONTHS, tuiNumberFormatProvider, tuiItemsHandlersProvider, tuiTextfieldOptionsProvider, tuiHintOptionsProvider, TuiFormatNumberPipe, TuiHintDriver, TuiHintHover, TuiHintPosition, TuiHintDirective, TUI_BUTTON_OPTIONS, TUI_BUTTON_DEFAULT_OPTIONS, TuiScrollbar, TuiSurface, tuiFadeIn } from '@taiga-ui/core';
17
+ import { TuiButton, TuiDialog, TuiDialogService, TuiLink, TuiFallbackSrcPipe, TuiInitialsPipe, TuiIcon, TuiAppearance, TuiWithAppearance, TuiIcons, TuiWithIcons, TUI_DATA_LIST_HOST, tuiDropdownOptionsProvider, TuiLabel, TuiError, TuiLoader, TuiDataList, TuiNotification, TuiTextfield, TuiTitle, TuiNumberFormat, TuiHint, TUI_MONTHS, TuiScrollbar, tuiNumberFormatProvider, tuiItemsHandlersProvider, tuiTextfieldOptionsProvider, tuiHintOptionsProvider, TuiFormatNumberPipe, TuiHintDriver, TuiHintHover, TuiHintPosition, TuiHintDirective, TUI_BUTTON_OPTIONS, TUI_BUTTON_DEFAULT_OPTIONS, TuiSurface, tuiFadeIn } from '@taiga-ui/core';
18
18
  import { isValidPhoneNumber } from 'libphonenumber-js/max';
19
19
  import * as i4 from '@taiga-ui/legacy/components/primitive-textfield';
20
20
  import * as i3 from '@taiga-ui/legacy';
@@ -25,7 +25,7 @@ import * as i5 from '@taiga-ui/core/components/label';
25
25
  import * as i8 from '@maskito/angular';
26
26
  import { MaskitoDirective } from '@maskito/angular';
27
27
  import * as i2$2 from '@angular/common';
28
- import { DOCUMENT, CommonModule, NgIf, AsyncPipe, DecimalPipe, NgFor, NgClass } from '@angular/common';
28
+ import { DOCUMENT, CommonModule, NgIf, AsyncPipe, NgTemplateOutlet, DecimalPipe, NgFor, NgClass } from '@angular/common';
29
29
  import * as i2$3 from '@taiga-ui/polymorpheus';
30
30
  import { POLYMORPHEUS_CONTEXT, PolymorpheusComponent, PolymorpheusTemplate, PolymorpheusOutlet, injectContext } from '@taiga-ui/polymorpheus';
31
31
  import * as i2 from 'angularx-qrcode';
@@ -46,10 +46,10 @@ import { TuiCardLarge, TuiBlockStatus, TuiHeader } from '@taiga-ui/layout';
46
46
  import { __decorate } from 'tslib';
47
47
  import * as i4$2 from '@taiga-ui/addon-charts';
48
48
  import { TuiLineDaysChart, TuiLineDaysChartHint, TuiAxes } from '@taiga-ui/addon-charts';
49
- import * as i2$5 from '@taiga-ui/experimental/components/expand';
50
49
  import * as i5$2 from '@taiga-ui/kit/components/slider';
51
50
  import * as i9 from 'angular8-yandex-maps';
52
51
  import { AngularYandexMapsModule } from 'angular8-yandex-maps';
52
+ import * as i2$5 from '@taiga-ui/experimental/components/expand';
53
53
  import * as i3$3 from '@taiga-ui/kit/components/data-list-wrapper';
54
54
  import { TuiGroup } from '@taiga-ui/core/directives/group';
55
55
  import * as i4$3 from 'ng-recaptcha-2';
@@ -5627,6 +5627,60 @@ const SC_CATALOG_PRODUCTS_FILTERS = new InjectionToken('SC_CATALOG_PRODUCTS_FILT
5627
5627
  */
5628
5628
  const SC_CATALOG_SHOW_PRODUCTS_RECURSIVELY = new InjectionToken('SC_CATALOG_SHOW_PRODUCTS_RECURSIVELY');
5629
5629
 
5630
+ /**
5631
+ * Контейнер сворачивания для длинного списка вариантов фильтра.
5632
+ *
5633
+ * Когда число элементов превышает порог: свёрнут — fade с обрезкой, развёрнут — scrollbar.
5634
+ * Иначе рендерит контент без обёртки и кнопки переключения.
5635
+ *
5636
+ * Контент проецируется как `<ng-template>` — это сохраняет инжектор `ControlContainer`
5637
+ * родителя для `formControlName`/`formGroupName` внутри проецируемого фрагмента.
5638
+ */
5639
+ class ScCatalogFilterCollapsibleComponent {
5640
+ constructor() {
5641
+ /**
5642
+ * Число элементов содержимого, по которому решается необходимость сворачивания.
5643
+ */
5644
+ this.itemsCount = input.required();
5645
+ /**
5646
+ * Показывать ли кнопку сброса значений группы.
5647
+ */
5648
+ this.showReset = input(false);
5649
+ /**
5650
+ * Событие нажатия на кнопку сброса группы.
5651
+ */
5652
+ this.resetGroup = output();
5653
+ /**
5654
+ * Проецируемое содержимое (объявляется в шаблоне родителя как `<ng-template>`).
5655
+ */
5656
+ this.contentTpl = contentChild.required(TemplateRef);
5657
+ /**
5658
+ * Развёрнут ли список.
5659
+ */
5660
+ this.isExpanded = signal(false);
5661
+ /**
5662
+ * Нужно ли сворачивание для текущего числа элементов.
5663
+ */
5664
+ this.isCollapsible = computed(() => this.itemsCount() > ScCatalogFilterCollapsibleComponent.COLLAPSE_THRESHOLD);
5665
+ }
5666
+ /**
5667
+ * Порог числа вариантов, после которого включается сворачивание с {@link TuiFade}.
5668
+ */
5669
+ static { this.COLLAPSE_THRESHOLD = 5; }
5670
+ /**
5671
+ * Переключает развёрнутость списка.
5672
+ */
5673
+ toggle() {
5674
+ this.isExpanded.update((value) => !value);
5675
+ }
5676
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScCatalogFilterCollapsibleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5677
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ScCatalogFilterCollapsibleComponent, isStandalone: true, selector: "sc-catalog-filter-collapsible", inputs: { itemsCount: { classPropertyName: "itemsCount", publicName: "itemsCount", isSignal: true, isRequired: true, transformFunction: null }, showReset: { classPropertyName: "showReset", publicName: "showReset", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { resetGroup: "resetGroup" }, queries: [{ propertyName: "contentTpl", first: true, predicate: TemplateRef, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"flex flex-col gap-2\">\n @if (isCollapsible()) {\n @if (isExpanded()) {\n <tui-scrollbar [style.max-block-size]=\"'11rem'\">\n <ng-container *ngTemplateOutlet=\"contentTpl()\" />\n </tui-scrollbar>\n } @else {\n <div\n class=\"filter-group-fade\"\n tuiFade=\"vertical\"\n tuiFadeHeight=\"0.25rem\"\n tuiFadeOffset=\"0.25rem\"\n >\n <ng-container *ngTemplateOutlet=\"contentTpl()\" />\n </div>\n }\n\n <div class=\"flex items-center justify-between\">\n <button\n tuiLink\n type=\"button\"\n class=\"text-start !text-body-s\"\n [style.text-decoration-line]=\"'underline'\"\n (click)=\"toggle()\"\n >\n @if (isExpanded()) {\n \u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C\n } @else {\n \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0435\u0449\u0451\n }\n </button>\n @if (showReset()) {\n <button\n tuiLink\n appearance=\"\"\n [style.color]=\"'var(--tui-status-negative)'\"\n [style.text-decoration-line]=\"'underline'\"\n type=\"button\"\n class=\"!text-body-s\"\n (click)=\"resetGroup.emit()\"\n >\n \u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C\n </button>\n }\n </div>\n } @else {\n <ng-container *ngTemplateOutlet=\"contentTpl()\" />\n @if (showReset()) {\n <button\n tuiLink\n type=\"button\"\n class=\"text-start !text-body-s\"\n (click)=\"resetGroup.emit()\"\n >\n \u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C\n </button>\n }\n }\n</div>\n", styles: [".filter-group-fade{box-sizing:border-box;max-block-size:9rem;overflow:hidden!important;transition:none!important}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: TuiFade, selector: "[tuiFade]", inputs: ["tuiFadeHeight", "tuiFadeSize", "tuiFadeOffset", "tuiFade"] }, { kind: "directive", type: TuiLink, selector: "a[tuiLink], button[tuiLink]", inputs: ["pseudo"] }, { kind: "component", type: TuiScrollbar, selector: "tui-scrollbar", inputs: ["hidden"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5678
+ }
5679
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScCatalogFilterCollapsibleComponent, decorators: [{
5680
+ type: Component,
5681
+ args: [{ standalone: true, selector: 'sc-catalog-filter-collapsible', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgTemplateOutlet, TuiFade, TuiLink, TuiScrollbar], template: "<div class=\"flex flex-col gap-2\">\n @if (isCollapsible()) {\n @if (isExpanded()) {\n <tui-scrollbar [style.max-block-size]=\"'11rem'\">\n <ng-container *ngTemplateOutlet=\"contentTpl()\" />\n </tui-scrollbar>\n } @else {\n <div\n class=\"filter-group-fade\"\n tuiFade=\"vertical\"\n tuiFadeHeight=\"0.25rem\"\n tuiFadeOffset=\"0.25rem\"\n >\n <ng-container *ngTemplateOutlet=\"contentTpl()\" />\n </div>\n }\n\n <div class=\"flex items-center justify-between\">\n <button\n tuiLink\n type=\"button\"\n class=\"text-start !text-body-s\"\n [style.text-decoration-line]=\"'underline'\"\n (click)=\"toggle()\"\n >\n @if (isExpanded()) {\n \u0421\u0432\u0435\u0440\u043D\u0443\u0442\u044C\n } @else {\n \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0435\u0449\u0451\n }\n </button>\n @if (showReset()) {\n <button\n tuiLink\n appearance=\"\"\n [style.color]=\"'var(--tui-status-negative)'\"\n [style.text-decoration-line]=\"'underline'\"\n type=\"button\"\n class=\"!text-body-s\"\n (click)=\"resetGroup.emit()\"\n >\n \u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C\n </button>\n }\n </div>\n } @else {\n <ng-container *ngTemplateOutlet=\"contentTpl()\" />\n @if (showReset()) {\n <button\n tuiLink\n type=\"button\"\n class=\"text-start !text-body-s\"\n (click)=\"resetGroup.emit()\"\n >\n \u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C\n </button>\n }\n }\n</div>\n", styles: [".filter-group-fade{box-sizing:border-box;max-block-size:9rem;overflow:hidden!important;transition:none!important}\n"] }]
5682
+ }] });
5683
+
5630
5684
  /* eslint-disable class-methods-use-this */
5631
5685
  /**
5632
5686
  * Компонент вывода фильтров каталога.
@@ -5637,9 +5691,9 @@ class ScCatalogFiltersComponent {
5637
5691
  */
5638
5692
  constructor() {
5639
5693
  /**
5640
- * Состояние открытия accordion.
5694
+ * Подписки синхронизации контролов формы (range slider, single-select checkbox).
5641
5695
  */
5642
- this.isOpenAccordion = input(false);
5696
+ this.formSyncs = new Subscription();
5643
5697
  /**
5644
5698
  * Сервис для работы с фильтрами каталога.
5645
5699
  */
@@ -5657,16 +5711,33 @@ class ScCatalogFiltersComponent {
5657
5711
  */
5658
5712
  this.isRecursively = inject(SC_CATALOG_SHOW_PRODUCTS_RECURSIVELY);
5659
5713
  /**
5660
- * {@link Observable} фильтров категории.
5714
+ * Показывать ли кнопку «Показать результаты».
5661
5715
  */
5662
- this.filters = toSignal(inject(SC_CATEGORY_INFO).pipe(catchError(() => EMPTY), filter(tuiIsPresent), switchMap((category) => this.catalogFilterService.getFilters$(this.idOrSlugPipe.transform(category), this.isRecursively)), map((filters) => filters.filter((item) => item.type !== 'range' || item.min !== item.max)), tap((filters) => {
5663
- this.updateFormControls(filters);
5664
- }), share()));
5716
+ this.showResultsButton = input(false);
5717
+ /**
5718
+ * Событие нажатия на кнопку сброса всех фильтров.
5719
+ */
5720
+ this.resetFilters = output();
5721
+ /**
5722
+ * Событие нажатия на кнопку показа результатов.
5723
+ */
5724
+ this.showResults = output();
5665
5725
  /**
5666
5726
  * FormGroup для фильтров.
5667
5727
  */
5668
5728
  this.form = new FormGroup({});
5669
- this.form.valueChanges.pipe(takeUntilDestroyed()).subscribe((filters) => {
5729
+ /**
5730
+ * {@link Observable} фильтров категории.
5731
+ */
5732
+ this.filters = toSignal(inject(SC_CATEGORY_INFO).pipe(catchError(() => EMPTY), filter(tuiIsPresent), switchMap((category) => this.catalogFilterService.getFilters$(this.idOrSlugPipe.transform(category), this.isRecursively)), filter(tuiIsPresent), map((filters) => filters
5733
+ .filter((item) => item.type !== 'range' || item.min !== item.max)
5734
+ .map((item) => (item.type === 'checkbox' ? { ...item, values: [...item.values].sort((a, b) => a.label.localeCompare(b.label)) } : item))), tap((filters) => {
5735
+ this.updateFormControls(filters);
5736
+ }), share()));
5737
+ inject(DestroyRef).onDestroy(() => {
5738
+ this.formSyncs.unsubscribe();
5739
+ });
5740
+ this.form.valueChanges.pipe(debounceTime(0), takeUntilDestroyed()).subscribe((filters) => {
5670
5741
  this.catalogProductsFilters$.next(this.buildPropertyFilters(filters));
5671
5742
  });
5672
5743
  }
@@ -5676,17 +5747,28 @@ class ScCatalogFiltersComponent {
5676
5747
  * @param filters Массив фильтров для создания контролов.
5677
5748
  */
5678
5749
  updateFormControls(filters) {
5750
+ this.formSyncs.unsubscribe();
5751
+ this.formSyncs = new Subscription();
5679
5752
  Object.keys(this.form.controls).forEach((key) => {
5680
5753
  this.form.removeControl(key, { emitEvent: false });
5681
5754
  });
5682
5755
  filters.forEach((item) => {
5683
5756
  switch (item.type) {
5684
- case 'checkbox':
5685
- this.form.addControl(item.id, this.createCheckboxFormControl(item), { emitEvent: false });
5757
+ case 'checkbox': {
5758
+ const checkboxControl = this.createCheckboxFormControl(item);
5759
+ this.form.addControl(item.id, checkboxControl, { emitEvent: false });
5760
+ // Single-select для !isMultiple: при выборе одного остальные снимаются.
5761
+ if (!item.isMultiple && item.values.length > 1) {
5762
+ this.formSyncs.add(this.syncSingleSelectCheckbox(checkboxControl));
5763
+ }
5686
5764
  break;
5687
- case 'range':
5688
- this.form.addControl(item.id, this.createRangeFormControl(item), { emitEvent: false });
5765
+ }
5766
+ case 'range': {
5767
+ const rangeControl = this.createRangeFormControl(item);
5768
+ this.form.addControl(item.id, rangeControl, { emitEvent: false });
5769
+ this.formSyncs.add(this.syncRangeFromToAndSlider(rangeControl));
5689
5770
  break;
5771
+ }
5690
5772
  case 'toggle':
5691
5773
  this.form.addControl(item.id, this.createToggleFormControl(item), { emitEvent: false });
5692
5774
  break;
@@ -5710,7 +5792,7 @@ class ScCatalogFiltersComponent {
5710
5792
  }
5711
5793
  switch (filterItem.type) {
5712
5794
  case 'checkbox':
5713
- this.processCheckboxFilter(result, filterItem.id, controlValue);
5795
+ this.processCheckboxFilter(result, filterItem, controlValue);
5714
5796
  break;
5715
5797
  case 'range':
5716
5798
  this.processRangeFilter(result, filterItem.id, controlValue);
@@ -5725,31 +5807,107 @@ class ScCatalogFiltersComponent {
5725
5807
  return result;
5726
5808
  }
5727
5809
  /**
5728
- * Создает контрол формы для фильтра типа checkbox.
5810
+ * Создаёт FormGroup для checkbox: на каждый {@code value.id} — булевый контрол.
5729
5811
  *
5730
- * Если `isMultiple === false` возвращает {@link FormControl} строкового идентификатора (логика radio),
5731
- * иначе {@link FormGroup} независимых булевых контролов по идентификаторам значений.
5812
+ * Единый формат и для одного, и для множества значений: шаблон рендерит их одинаково.
5813
+ * Различие в API-выводе для одиночного значения (boolean вместо массива) обрабатывается в {@link processCheckboxFilter}.
5732
5814
  *
5733
5815
  * @param checkboxFilter Фильтр типа checkbox.
5734
5816
  */
5735
5817
  createCheckboxFormControl(checkboxFilter) {
5736
- if (!checkboxFilter.isMultiple) {
5737
- return new FormControl(null);
5738
- }
5818
+ const isSelected = (id) => checkboxFilter.selectedValues?.includes(id) ?? false;
5739
5819
  const controls = {};
5740
5820
  checkboxFilter.values.forEach((value) => {
5741
- controls[value.id] = new FormControl(false, { nonNullable: true });
5821
+ controls[value.id] = new FormControl(isSelected(value.id), { nonNullable: true });
5742
5822
  });
5743
5823
  return new FormGroup(controls);
5744
5824
  }
5745
5825
  /**
5746
- * Создает FormControl для range.
5826
+ * Создаёт {@link FormGroup} для range: {@code from}, {@code to}, {@code slider} (кортеж для {@link TuiRange}).
5747
5827
  *
5748
5828
  * @param rangeFilter Фильтр типа range.
5749
5829
  */
5750
5830
  createRangeFormControl(rangeFilter) {
5751
- // TODO: Добавить updateOn: 'blur' после исправления бага в taiga-ui.
5752
- return new FormControl([Number(rangeFilter.selectedMin ?? rangeFilter.min), Number(rangeFilter.selectedMax ?? rangeFilter.max)], { nonNullable: true });
5831
+ const fromValue = Number(rangeFilter.selectedMin ?? rangeFilter.min);
5832
+ const toValue = Number(rangeFilter.selectedMax ?? rangeFilter.max);
5833
+ return new FormGroup({
5834
+ from: new FormControl(fromValue, { nonNullable: true }),
5835
+ to: new FormControl(toValue, { nonNullable: true }),
5836
+ slider: new FormControl([fromValue, toValue], { nonNullable: true }),
5837
+ });
5838
+ }
5839
+ /**
5840
+ * Реализует single-select поведение для FormGroup с булевыми контролами:
5841
+ * при появлении нового true остальные контролы группы сбрасываются в false.
5842
+ *
5843
+ * Сохраняет последнее «стабильное» состояние и сравнивает следующее значение с ним —
5844
+ * новый true (отсутствовал в prev) считается выбранным, остальные сбрасываются через setValue.
5845
+ *
5846
+ * @param group FormGroup checkbox-фильтра (id → boolean).
5847
+ */
5848
+ syncSingleSelectCheckbox(group) {
5849
+ let previousState = group.getRawValue();
5850
+ return group.valueChanges.subscribe((value) => {
5851
+ const current = value;
5852
+ const newlyChecked = Object.entries(current).find(([id, isChecked]) => {
5853
+ // eslint-disable-next-line security/detect-object-injection
5854
+ return isChecked && !previousState[id];
5855
+ })?.[0];
5856
+ if (!newlyChecked) {
5857
+ previousState = { ...current };
5858
+ return;
5859
+ }
5860
+ const next = {};
5861
+ Object.keys(group.controls).forEach((id) => {
5862
+ // eslint-disable-next-line security/detect-object-injection
5863
+ next[id] = id === newlyChecked;
5864
+ });
5865
+ previousState = next;
5866
+ group.setValue(next);
5867
+ });
5868
+ }
5869
+ /**
5870
+ * Связывает поля «от»/«до» с контролом слайдера.
5871
+ *
5872
+ * @param group FormGroup range-фильтра.
5873
+ */
5874
+ syncRangeFromToAndSlider(group) {
5875
+ const from = group.get('from');
5876
+ const to = group.get('to');
5877
+ const slider = group.get('slider');
5878
+ if (!from || !to || !slider) {
5879
+ return new Subscription();
5880
+ }
5881
+ const sub = new Subscription();
5882
+ // Инпуты → слайдер; если «от» > «до», поднимаем «до» до «от».
5883
+ const applySliderFromInputs = () => {
5884
+ const low = Number(from.value);
5885
+ let high = Number(to.value);
5886
+ if (low > high) {
5887
+ high = low;
5888
+ to.setValue(high, { emitEvent: false });
5889
+ }
5890
+ const currentPair = slider.value;
5891
+ if (currentPair[0] !== low || currentPair[1] !== high) {
5892
+ slider.setValue([low, high], { emitEvent: false });
5893
+ slider.markAsDirty();
5894
+ }
5895
+ };
5896
+ sub.add(merge(from.valueChanges, to.valueChanges).subscribe(applySliderFromInputs));
5897
+ sub.add(slider.valueChanges.subscribe((value) => {
5898
+ const [low, high] = value;
5899
+ if (from.value !== low) {
5900
+ from.setValue(low, { emitEvent: false });
5901
+ from.markAsDirty();
5902
+ }
5903
+ if (to.value !== high) {
5904
+ to.setValue(high, { emitEvent: false });
5905
+ to.markAsDirty();
5906
+ }
5907
+ }));
5908
+ // Совпасть с полями при первом показе (уже совпадает при создании, но на всякий случай).
5909
+ applySliderFromInputs();
5910
+ return sub;
5753
5911
  }
5754
5912
  /**
5755
5913
  * Создает FormControl для toggle.
@@ -5760,45 +5918,36 @@ class ScCatalogFiltersComponent {
5760
5918
  return new FormControl(toggleFilter.selectedValue ?? false, { nonNullable: true });
5761
5919
  }
5762
5920
  /**
5763
- * Обрабатывает checkbox фильтр.
5921
+ * Обрабатывает checkbox: FormGroup → string[] выбранных id; для единственного значения — boolean (как toggle).
5764
5922
  *
5765
5923
  * @param result Объект результата для заполнения.
5766
- * @param filterId Идентификатор фильтра.
5767
- * @param controlValue Значение контрола формы.
5924
+ * @param checkboxFilter Метафильтр checkbox.
5925
+ * @param controlValue Значение контрола формы (запись id → boolean).
5768
5926
  */
5769
- processCheckboxFilter(result, filterId, controlValue) {
5770
- // Для isMultiple === false: FormControl<string | null> -> string[] из одного выбранного ID.
5771
- if (typeof controlValue === 'string') {
5772
- if (controlValue) {
5773
- // eslint-disable-next-line security/detect-object-injection, no-param-reassign
5774
- result[filterId] = [controlValue];
5775
- }
5776
- return;
5777
- }
5778
- // Для checkbox: FormGroup с FormControl<boolean> -> string[] (массив ID выбранных значений).
5927
+ processCheckboxFilter(result, checkboxFilter, controlValue) {
5779
5928
  const selectedIds = Object.entries(controlValue)
5780
5929
  .filter(([, isSelected]) => isSelected)
5781
5930
  .map(([id]) => id);
5782
- if (selectedIds.length > 0) {
5783
- // eslint-disable-next-line security/detect-object-injection, no-param-reassign
5784
- result[filterId] = selectedIds;
5931
+ if (selectedIds.length === 0) {
5932
+ return;
5785
5933
  }
5934
+ // eslint-disable-next-line security/detect-object-injection, no-param-reassign
5935
+ result[checkboxFilter.id] = selectedIds;
5786
5936
  }
5787
5937
  /**
5788
5938
  * Обрабатывает range фильтр.
5789
5939
  *
5790
5940
  * @param result Объект результата для заполнения.
5791
5941
  * @param filterId Идентификатор фильтра.
5792
- * @param controlValue Значение контрола формы.
5793
- * @param controlValue.0 Начальное значение диапазона.
5794
- * @param controlValue.1 Конечное значение диапазона.
5942
+ * @param range Значение контрола формы (объект с границами).
5943
+ * @param range.from Начальное значение диапазона.
5944
+ * @param range.to Конечное значение диапазона.
5795
5945
  */
5796
- processRangeFilter(result, filterId, [from, to]) {
5797
- // Для range: FormControl<[number, number]> -> { from?: string; to?: string; }
5946
+ processRangeFilter(result, filterId, range) {
5798
5947
  // eslint-disable-next-line security/detect-object-injection, no-param-reassign
5799
5948
  result[filterId] = {
5800
- from: String(from),
5801
- to: String(to),
5949
+ from: String(range.from),
5950
+ to: String(range.to),
5802
5951
  };
5803
5952
  }
5804
5953
  /**
@@ -5809,18 +5958,111 @@ class ScCatalogFiltersComponent {
5809
5958
  * @param controlValue Значение контрола формы.
5810
5959
  */
5811
5960
  processToggleFilter(result, filterId, controlValue) {
5812
- // Для toggle: FormControl<boolean> -> boolean
5813
5961
  if (controlValue) {
5814
5962
  // eslint-disable-next-line security/detect-object-injection, no-param-reassign
5815
5963
  result[filterId] = controlValue;
5816
5964
  }
5817
5965
  }
5966
+ /**
5967
+ * Сбрасывает поле «от» диапазона к минимальному значению фильтра.
5968
+ *
5969
+ * @param filterId Идентификатор фильтра.
5970
+ * @param min Минимальное значение диапазона.
5971
+ */
5972
+ resetRangeFrom(filterId, min) {
5973
+ this.form.get(filterId)?.get('from')?.reset(+min);
5974
+ }
5975
+ /**
5976
+ * Сбрасывает поле «до» диапазона к максимальному значению фильтра.
5977
+ *
5978
+ * @param filterId Идентификатор фильтра.
5979
+ * @param max Максимальное значение диапазона.
5980
+ */
5981
+ resetRangeTo(filterId, max) {
5982
+ this.form.get(filterId)?.get('to')?.reset(+max);
5983
+ }
5984
+ /**
5985
+ * Сбрасывает все чекбоксы группы в `false`.
5986
+ *
5987
+ * @param filterId Идентификатор фильтра (ключ FormGroup в форме).
5988
+ */
5989
+ resetCheckboxGroup(filterId) {
5990
+ const group = this.form.get(filterId);
5991
+ if (!group) {
5992
+ return;
5993
+ }
5994
+ const resetValue = {};
5995
+ Object.keys(group.controls).forEach((id) => {
5996
+ // eslint-disable-next-line security/detect-object-injection
5997
+ resetValue[id] = false;
5998
+ });
5999
+ group.reset(resetValue);
6000
+ }
6001
+ /**
6002
+ * Сбрасывает все фильтры и оповещает родителя о нажатии кнопки сброса.
6003
+ */
6004
+ onResetFiltersClick() {
6005
+ this.resetAllFilters();
6006
+ this.resetFilters.emit();
6007
+ }
6008
+ /**
6009
+ * Оповещает родителя о нажатии кнопки показа результатов.
6010
+ */
6011
+ onShowResultsClick() {
6012
+ this.showResults.emit();
6013
+ }
6014
+ /**
6015
+ * Сбрасывает все фильтры к исходным значениям.
6016
+ */
6017
+ resetAllFilters() {
6018
+ this.filters()?.forEach((filterItem) => {
6019
+ const control = this.form.get(filterItem.id);
6020
+ if (!control) {
6021
+ return;
6022
+ }
6023
+ switch (filterItem.type) {
6024
+ case 'checkbox': {
6025
+ const group = control;
6026
+ const resetValue = {};
6027
+ Object.keys(group.controls).forEach((id) => {
6028
+ // eslint-disable-next-line security/detect-object-injection
6029
+ resetValue[id] = false;
6030
+ });
6031
+ group.reset(resetValue);
6032
+ break;
6033
+ }
6034
+ case 'toggle':
6035
+ control.reset(false);
6036
+ break;
6037
+ case 'range': {
6038
+ const group = control;
6039
+ const min = +filterItem.min;
6040
+ const max = +filterItem.max;
6041
+ group.reset({ from: min, to: max, slider: [min, max] });
6042
+ break;
6043
+ }
6044
+ default:
6045
+ break;
6046
+ }
6047
+ });
6048
+ }
5818
6049
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScCatalogFiltersComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5819
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ScCatalogFiltersComponent, isStandalone: true, selector: "sc-catalog-filters", inputs: { isOpenAccordion: { classPropertyName: "isOpenAccordion", publicName: "isOpenAccordion", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (filters()?.length) {\n <div class=\"bg-tui-base-01 shadow-sc flex flex-col items-center gap-3 rounded-xl\">\n <tui-accordion class=\"accordion\">\n <button\n [tuiAccordion]=\"isOpenAccordion()\"\n appearance=\"primary\"\n >\n \u0424\u0438\u043B\u044C\u0442\u0440\u044B\n </button>\n <tui-expand>\n <form\n [formGroup]=\"form\"\n class=\"flex flex-col gap-4 pb-1\"\n >\n @for (filter of filters(); track filter.id) {\n <div class=\"flex flex-col gap-2\">\n <label class=\"text-body-s font-medium\">{{ filter.label }}</label>\n\n @if (filter.type === 'checkbox') {\n @if (filter.isMultiple === false) {\n <div class=\"flex flex-col gap-2\">\n @for (value of filter.values; track value.id) {\n @let formControl = form.get(filter.id);\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"filter.id\"\n [value]=\"value.id\"\n tuiRadio\n (click)=\"formControl?.setValue(formControl?.value === value.id ? null : value.id)\"\n type=\"radio\"\n />\n <span class=\"text-body-s\">{{ value.label }}</span>\n </label>\n }\n </div>\n } @else {\n <div\n [formGroupName]=\"filter.id\"\n class=\"flex flex-col gap-2\"\n >\n @for (value of filter.values; track value.id) {\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"value.id\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span class=\"text-body-s\">{{ value.label }}</span>\n </label>\n }\n </div>\n }\n }\n\n @if (filter.type === 'range') {\n <tui-input-range\n [formControlName]=\"filter.id\"\n [min]=\"+filter.min\"\n [max]=\"+filter.max\"\n />\n }\n\n @if (filter.type === 'toggle') {\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"filter.id\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span class=\"text-body-s\">\u0414\u0430</span>\n </label>\n }\n </div>\n }\n </form>\n </tui-expand>\n </tui-accordion>\n </div>\n}\n", styles: [".accordion [tuiAccordion]{border:none;mask:none}.accordion tui-expand{box-shadow:none}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: TuiCheckbox, selector: "input[type=\"checkbox\"][tuiCheckbox]", inputs: ["size"] }, { kind: "component", type: i2$1.TuiRadioComponent, selector: "input[type=\"radio\"][tuiRadio]", inputs: ["size"] }, { kind: "component", type: i2$1.TuiInputRangeComponent, selector: "tui-input-range", inputs: ["min", "max", "step", "segments", "keySteps", "prefix", "postfix", "quantum", "content"] }, { kind: "component", type: i1$3.TuiAccordionComponent, selector: "tui-accordion", inputs: ["closeOthers", "size"] }, { kind: "directive", type: i1$3.TuiAccordionDirective, selector: "button[tuiAccordion]", inputs: ["tuiAccordion"], outputs: ["tuiAccordionChange"] }, { kind: "component", type: i2$5.TuiExpand, selector: "tui-expand", inputs: ["expanded"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6050
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ScCatalogFiltersComponent, isStandalone: true, selector: "sc-catalog-filters", inputs: { showResultsButton: { classPropertyName: "showResultsButton", publicName: "showResultsButton", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { resetFilters: "resetFilters", showResults: "showResults" }, ngImport: i0, template: "@if (filters()?.length) {\n <form\n [formGroup]=\"form\"\n class=\"flex flex-col pb-1\"\n >\n @for (filter of filters(); track filter.id; let isFirst = $first) {\n @if (!isFirst) {\n <hr class=\"my-3 w-full h-px\" />\n }\n\n <div class=\"flex flex-col gap-2\">\n <!-- \u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u0433\u0440\u0443\u043F\u043F\u044B. \u0414\u043B\u044F toggle \u043F\u043E\u0434\u043F\u0438\u0441\u0438 \u043D\u0435\u0442: \u043C\u0435\u0442\u043A\u0430 \u0438\u0434\u0451\u0442 \u043F\u0440\u044F\u043C\u043E \u0440\u044F\u0434\u043E\u043C \u0441 \u0441\u0430\u043C\u0438\u043C checkbox. -->\n @if (filter.type !== 'toggle') {\n <label class=\"text-body-s-bold\">{{ filter.label }}</label>\n }\n\n <!-- Checkbox: FormGroup(value.id \u2192 boolean) \u0434\u043B\u044F \u043B\u044E\u0431\u043E\u0433\u043E \u0447\u0438\u0441\u043B\u0430 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0439.\n \u0420\u0430\u0437\u0432\u0438\u043B\u043A\u0430 \u043E\u0434\u043D\u043E/\u043C\u043D\u043E\u0433\u043E \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0439 \u0432\u044B\u043D\u0435\u0441\u0435\u043D\u0430 \u0432 TS (\u0441\u043C. processCheckboxFilter).\n ng-template \u0432\u043D\u0443\u0442\u0440\u0438 formGroupName: \u0438\u043D\u0430\u0447\u0435 reactive forms \u043D\u0435 \u043D\u0430\u0439\u0434\u0451\u0442 ControlContainer \u043F\u0440\u0438 \u043F\u0440\u043E\u0435\u043A\u0446\u0438\u0438 \u0432 \u0434\u043E\u0447\u0435\u0440\u043D\u0438\u0439 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442. -->\n @if (filter.type === 'checkbox') {\n <div\n class=\"flex flex-col gap-2\"\n [formGroupName]=\"filter.id\"\n >\n <sc-catalog-filter-collapsible\n [itemsCount]=\"filter.values.length\"\n [showReset]=\"form.get(filter.id)?.dirty ?? false\"\n (resetGroup)=\"resetCheckboxGroup(filter.id)\"\n >\n <ng-template>\n <div class=\"flex flex-col gap-2\">\n @for (value of filter.values; track value.id) {\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"value.id\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span class=\"text-body-s\">{{ value.label }}</span>\n </label>\n }\n </div>\n </ng-template>\n </sc-catalog-filter-collapsible>\n </div>\n\n <!-- Toggle: \u043E\u0434\u0438\u043D boolean \u043D\u0430 \u043A\u043E\u0440\u043D\u0435 \u0444\u043E\u0440\u043C\u044B, \u043F\u043E\u0434\u043F\u0438\u0441\u044C = filter.label -->\n } @else if (filter.type === 'toggle') {\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"filter.id\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span class=\"text-body-s-bold\">{{ filter.label }}</span>\n </label>\n\n <!-- Range: FormGroup(from, to, slider) \u0441 \u0434\u0432\u0443\u0441\u0442\u043E\u0440\u043E\u043D\u043D\u0435\u0439 \u0441\u0438\u043D\u0445\u0440\u043E\u043D\u0438\u0437\u0430\u0446\u0438\u0435\u0439 -->\n } @else if (filter.type === 'range') {\n <div\n [formGroupName]=\"filter.id\"\n class=\"flex flex-col gap-3\"\n >\n <div class=\"flex gap-3 px-1\">\n <label\n tuiLabel\n class=\"min-w-0 flex-1\"\n >\n \u041E\u0442\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n scSelectOnFocusin\n tuiInputNumber\n formControlName=\"from\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [min]=\"+filter.min\"\n [max]=\"+filter.max\"\n autocomplete=\"off\"\n />\n @if (form.get(filter.id)?.get('from')?.dirty) {\n <button\n tuiIconButton\n type=\"button\"\n size=\"xs\"\n appearance=\"icon\"\n iconStart=\"@tui.x\"\n (click)=\"resetRangeFrom(filter.id, filter.min)\"\n ></button>\n }\n </tui-textfield>\n </label>\n <label\n tuiLabel\n class=\"min-w-0 flex-1\"\n >\n \u0414\u043E\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n scSelectOnFocusin\n tuiInputNumber\n formControlName=\"to\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [min]=\"+filter.min\"\n [max]=\"+filter.max\"\n autocomplete=\"off\"\n />\n @if (form.get(filter.id)?.get('to')?.dirty) {\n <button\n tuiIconButton\n type=\"button\"\n size=\"xs\"\n appearance=\"icon\"\n iconStart=\"@tui.x\"\n (click)=\"resetRangeTo(filter.id, filter.max)\"\n ></button>\n }\n </tui-textfield>\n </label>\n </div>\n\n <tui-range\n size=\"m\"\n formControlName=\"slider\"\n [min]=\"+filter.min\"\n [max]=\"+filter.max\"\n [style.--tui-thickness.rem]=\"0.25\"\n />\n </div>\n }\n </div>\n }\n <button\n tuiButton\n appearance=\"secondary\"\n type=\"button\"\n class=\"mt-2\"\n (click)=\"onResetFiltersClick()\"\n >\n \u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C \u0444\u0438\u043B\u044C\u0442\u0440\u044B\n </button>\n @if (showResultsButton()) {\n <button\n tuiButton\n appearance=\"primary\"\n type=\"button\"\n class=\"mt-2\"\n (click)=\"onShowResultsClick()\"\n >\n \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B\n </button>\n }\n </form>\n}\n", styles: [".accordion [tuiAccordion]{border:none;mask:none}.accordion tui-expand{box-shadow:none}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i5.TuiLabel, selector: "label[tuiLabel]" }, { kind: "component", type: i1$2.TuiTextfieldComponent, selector: "tui-textfield:not([multi])" }, { kind: "directive", type: i1$2.TuiTextfieldOptionsDirective, selector: "[tuiTextfieldAppearance],[tuiTextfieldSize],[tuiTextfieldCleaner]", inputs: ["tuiTextfieldAppearance", "tuiTextfieldSize", "tuiTextfieldCleaner"] }, { kind: "directive", type: ScSelectOnFocusinDirective, selector: "tui-input-number, tui-input, tui-input-phone, tui-input-date, tui-input-password, input[tuiInputNumber], input[tuiTextfield], input[tuiInputSlider]" }, { kind: "component", type: ScCatalogFilterCollapsibleComponent, selector: "sc-catalog-filter-collapsible", inputs: ["itemsCount", "showReset"], outputs: ["resetGroup"] }, { kind: "directive", type: TuiNumberFormat, selector: "[tuiNumberFormat]", inputs: ["tuiNumberFormat"] }, { kind: "component", type: TuiCheckbox, selector: "input[type=\"checkbox\"][tuiCheckbox]", inputs: ["size"] }, { kind: "directive", type: i2$1.TuiInputNumberDirective, selector: "input[tuiInputNumber]", inputs: ["min", "max", "prefix", "postfix"] }, { kind: "component", type: TuiRange, selector: "tui-range", inputs: ["min", "max", "step", "size", "segments", "keySteps", "focusable", "margin", "limit"] }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5820
6051
  }
5821
6052
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScCatalogFiltersComponent, decorators: [{
5822
6053
  type: Component,
5823
- args: [{ standalone: true, selector: 'sc-catalog-filters', changeDetection: ChangeDetectionStrategy.OnPush, imports: [FormsModule, TuiTextfield, TuiCheckbox, TuiRadio, TuiInputRange, TuiAccordion$1, ReactiveFormsModule], template: "@if (filters()?.length) {\n <div class=\"bg-tui-base-01 shadow-sc flex flex-col items-center gap-3 rounded-xl\">\n <tui-accordion class=\"accordion\">\n <button\n [tuiAccordion]=\"isOpenAccordion()\"\n appearance=\"primary\"\n >\n \u0424\u0438\u043B\u044C\u0442\u0440\u044B\n </button>\n <tui-expand>\n <form\n [formGroup]=\"form\"\n class=\"flex flex-col gap-4 pb-1\"\n >\n @for (filter of filters(); track filter.id) {\n <div class=\"flex flex-col gap-2\">\n <label class=\"text-body-s font-medium\">{{ filter.label }}</label>\n\n @if (filter.type === 'checkbox') {\n @if (filter.isMultiple === false) {\n <div class=\"flex flex-col gap-2\">\n @for (value of filter.values; track value.id) {\n @let formControl = form.get(filter.id);\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"filter.id\"\n [value]=\"value.id\"\n tuiRadio\n (click)=\"formControl?.setValue(formControl?.value === value.id ? null : value.id)\"\n type=\"radio\"\n />\n <span class=\"text-body-s\">{{ value.label }}</span>\n </label>\n }\n </div>\n } @else {\n <div\n [formGroupName]=\"filter.id\"\n class=\"flex flex-col gap-2\"\n >\n @for (value of filter.values; track value.id) {\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"value.id\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span class=\"text-body-s\">{{ value.label }}</span>\n </label>\n }\n </div>\n }\n }\n\n @if (filter.type === 'range') {\n <tui-input-range\n [formControlName]=\"filter.id\"\n [min]=\"+filter.min\"\n [max]=\"+filter.max\"\n />\n }\n\n @if (filter.type === 'toggle') {\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"filter.id\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span class=\"text-body-s\">\u0414\u0430</span>\n </label>\n }\n </div>\n }\n </form>\n </tui-expand>\n </tui-accordion>\n </div>\n}\n", styles: [".accordion [tuiAccordion]{border:none;mask:none}.accordion tui-expand{box-shadow:none}\n"] }]
6054
+ args: [{ standalone: true, selector: 'sc-catalog-filters', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
6055
+ ReactiveFormsModule,
6056
+ TuiTextfield,
6057
+ ScSelectOnFocusinDirective,
6058
+ ScCatalogFilterCollapsibleComponent,
6059
+ TuiLabel,
6060
+ TuiNumberFormat,
6061
+ TuiCheckbox,
6062
+ TuiInputNumber,
6063
+ TuiRange,
6064
+ TuiButton,
6065
+ ], template: "@if (filters()?.length) {\n <form\n [formGroup]=\"form\"\n class=\"flex flex-col pb-1\"\n >\n @for (filter of filters(); track filter.id; let isFirst = $first) {\n @if (!isFirst) {\n <hr class=\"my-3 w-full h-px\" />\n }\n\n <div class=\"flex flex-col gap-2\">\n <!-- \u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u0433\u0440\u0443\u043F\u043F\u044B. \u0414\u043B\u044F toggle \u043F\u043E\u0434\u043F\u0438\u0441\u0438 \u043D\u0435\u0442: \u043C\u0435\u0442\u043A\u0430 \u0438\u0434\u0451\u0442 \u043F\u0440\u044F\u043C\u043E \u0440\u044F\u0434\u043E\u043C \u0441 \u0441\u0430\u043C\u0438\u043C checkbox. -->\n @if (filter.type !== 'toggle') {\n <label class=\"text-body-s-bold\">{{ filter.label }}</label>\n }\n\n <!-- Checkbox: FormGroup(value.id \u2192 boolean) \u0434\u043B\u044F \u043B\u044E\u0431\u043E\u0433\u043E \u0447\u0438\u0441\u043B\u0430 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0439.\n \u0420\u0430\u0437\u0432\u0438\u043B\u043A\u0430 \u043E\u0434\u043D\u043E/\u043C\u043D\u043E\u0433\u043E \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0439 \u0432\u044B\u043D\u0435\u0441\u0435\u043D\u0430 \u0432 TS (\u0441\u043C. processCheckboxFilter).\n ng-template \u0432\u043D\u0443\u0442\u0440\u0438 formGroupName: \u0438\u043D\u0430\u0447\u0435 reactive forms \u043D\u0435 \u043D\u0430\u0439\u0434\u0451\u0442 ControlContainer \u043F\u0440\u0438 \u043F\u0440\u043E\u0435\u043A\u0446\u0438\u0438 \u0432 \u0434\u043E\u0447\u0435\u0440\u043D\u0438\u0439 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442. -->\n @if (filter.type === 'checkbox') {\n <div\n class=\"flex flex-col gap-2\"\n [formGroupName]=\"filter.id\"\n >\n <sc-catalog-filter-collapsible\n [itemsCount]=\"filter.values.length\"\n [showReset]=\"form.get(filter.id)?.dirty ?? false\"\n (resetGroup)=\"resetCheckboxGroup(filter.id)\"\n >\n <ng-template>\n <div class=\"flex flex-col gap-2\">\n @for (value of filter.values; track value.id) {\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"value.id\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span class=\"text-body-s\">{{ value.label }}</span>\n </label>\n }\n </div>\n </ng-template>\n </sc-catalog-filter-collapsible>\n </div>\n\n <!-- Toggle: \u043E\u0434\u0438\u043D boolean \u043D\u0430 \u043A\u043E\u0440\u043D\u0435 \u0444\u043E\u0440\u043C\u044B, \u043F\u043E\u0434\u043F\u0438\u0441\u044C = filter.label -->\n } @else if (filter.type === 'toggle') {\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"filter.id\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span class=\"text-body-s-bold\">{{ filter.label }}</span>\n </label>\n\n <!-- Range: FormGroup(from, to, slider) \u0441 \u0434\u0432\u0443\u0441\u0442\u043E\u0440\u043E\u043D\u043D\u0435\u0439 \u0441\u0438\u043D\u0445\u0440\u043E\u043D\u0438\u0437\u0430\u0446\u0438\u0435\u0439 -->\n } @else if (filter.type === 'range') {\n <div\n [formGroupName]=\"filter.id\"\n class=\"flex flex-col gap-3\"\n >\n <div class=\"flex gap-3 px-1\">\n <label\n tuiLabel\n class=\"min-w-0 flex-1\"\n >\n \u041E\u0442\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n scSelectOnFocusin\n tuiInputNumber\n formControlName=\"from\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [min]=\"+filter.min\"\n [max]=\"+filter.max\"\n autocomplete=\"off\"\n />\n @if (form.get(filter.id)?.get('from')?.dirty) {\n <button\n tuiIconButton\n type=\"button\"\n size=\"xs\"\n appearance=\"icon\"\n iconStart=\"@tui.x\"\n (click)=\"resetRangeFrom(filter.id, filter.min)\"\n ></button>\n }\n </tui-textfield>\n </label>\n <label\n tuiLabel\n class=\"min-w-0 flex-1\"\n >\n \u0414\u043E\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n scSelectOnFocusin\n tuiInputNumber\n formControlName=\"to\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [min]=\"+filter.min\"\n [max]=\"+filter.max\"\n autocomplete=\"off\"\n />\n @if (form.get(filter.id)?.get('to')?.dirty) {\n <button\n tuiIconButton\n type=\"button\"\n size=\"xs\"\n appearance=\"icon\"\n iconStart=\"@tui.x\"\n (click)=\"resetRangeTo(filter.id, filter.max)\"\n ></button>\n }\n </tui-textfield>\n </label>\n </div>\n\n <tui-range\n size=\"m\"\n formControlName=\"slider\"\n [min]=\"+filter.min\"\n [max]=\"+filter.max\"\n [style.--tui-thickness.rem]=\"0.25\"\n />\n </div>\n }\n </div>\n }\n <button\n tuiButton\n appearance=\"secondary\"\n type=\"button\"\n class=\"mt-2\"\n (click)=\"onResetFiltersClick()\"\n >\n \u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C \u0444\u0438\u043B\u044C\u0442\u0440\u044B\n </button>\n @if (showResultsButton()) {\n <button\n tuiButton\n appearance=\"primary\"\n type=\"button\"\n class=\"mt-2\"\n (click)=\"onShowResultsClick()\"\n >\n \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B\n </button>\n }\n </form>\n}\n", styles: [".accordion [tuiAccordion]{border:none;mask:none}.accordion tui-expand{box-shadow:none}\n"] }]
5824
6066
  }], ctorParameters: () => [] });
5825
6067
 
5826
6068
  /* eslint-disable @typescript-eslint/unbound-method */
@@ -9929,5 +10171,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
9929
10171
  * Generated bundle index. Do not edit.
9930
10172
  */
9931
10173
 
9932
- export { AbstractScPriceCard, AuthMethod, CURRENT_COUNTRY_ID, CostWithDiscountComponent, FilesAndDocumentsComponent, FilesAndDocumentsModule, FinishDateTimeTransformerDirective, IDLE_ITEM_STATE, IS_DEFAULT_COUNTRY, MAX_FILES_IN_FORM_INPUT, SC_ALLOW_SELECT_TERMINATED, SC_BANNER_DURATION, SC_CATALOG_PRODUCTS_FILTERS, SC_CATALOG_SHOW_PRODUCTS_RECURSIVELY, SC_DATE_FORMATTER, SC_DEBOUNCE_TIME_DEFAULT, SC_DIALOG_SERVICE_TOKEN, SC_ERROR_CHANGE_HANDLER, SC_HELP_NOTIFICATION_CLOSE, SC_HELP_NOTIFICATION_LIMIT, SC_HIDDEN_PRINT_ELEMENTS, SC_MANAGER_QR_HANDLER, SC_NOTIFY_WHEN_IN_STOCK_REQUIRED_FIELDS, SC_ORDER_OPTIONS, SC_PAGE_SIZE_OPTIONS$1 as SC_PAGE_SIZE_OPTIONS, SC_SHOW_HELP_NOTIFICATION_IN_PHONE_INPUT, SC_USER_CITY_INFO, SC_USER_INFO, SC_USER_PROVIDERS, SC_VERIFICATION_CODE_TIMEOUT, ScAccordionComponent, ScAccordionContentDirective, ScAccordionModule, ScAddContactDialogComponent, ScAddContragentBankAccountsDialogComponent, ScAddContragentDialogComponent, ScAddDeliveryAddressDialogComponent, ScAddOrEditingCartItemDialogComponent, ScAddOrEditingCartItemFormComponent, ScAddressesSelectionFieldComponent, ScAuthModule, ScBannerComponent, ScBannerModule, ScBrandsListComponent, ScBrandsListModule, ScCartAddProductsFromCsvDialogComponent, ScCatalogFiltersComponent, ScCatalogModule, ScCategoryCardComponent, ScContactsAccordionComponent, ScContactsModule, ScContragentsAccordionComponent, ScContragentsAccordionItemComponent, ScContragentsModule, ScDeliveryAddressAccordionComponent, ScDeliveryAddressAccordionItemComponent, ScDeliveryAddressModule, ScDownloadPriceListComponent, ScDraftComponent, ScEmailLinkDirective, ScErrorBlockStatusComponent, ScErrorHandlerComponent, ScFavoriteButtonComponent, ScFeedbackFormComponent, ScFocusFirstInvalidFieldDirective, ScFormFieldsModule, ScFormatDatePipe, ScFrequentlyAskedQuestionsComponent, ScFrequentlyAskedQuestionsGroupSelectorComponent, ScFrequentlyAskedQuestionsWithGroupsComponent, ScGratitudeComponent, ScHelpNotificationService, ScHoverImageCarouselComponent, ScInputQuantityComponent, ScLinks, ScManagerCardComponent, ScManagerCardPushComponent, ScNewContactFormComponent, ScNewContragentBankAccountsFormComponent, ScNewContragentFormComponent, ScNewsCardComponent, ScNewsCardSkeletonComponent, ScNewsModule, ScNextInputFocusDirective, ScNextInputFocusModule, ScNoindexDirective, ScNoindexWrapperComponent, ScNotifyWhenInStockDialogComponent, ScOrderAccessorDirective, ScOrderItemComponent, ScOrderItemsByDirection, ScOrderItemsListByDirectionsComponent, ScOrderItemsListByStockComponent, ScOrderItemsListComponent, ScOrderModule, ScPaymentStatusComponent, ScPersonalDataProcessingPolicyComponent, ScPhoneFormatPipe, ScPreviewSampleComponent, ScPreviewSampleModule, ScPreviewSamplesMosquitoComponent, ScPriceCardComponent, ScPriceCardInlineComponent, ScPriceHistoryComponent, ScPriceListPaginationComponent, ScPriceWarehouseStockComponent, ScPrintDirective, ScPrintService, ScPrivacyPolicyComponent, ScProductInAllWarehousesPipe, ScProfileAccordionsContentComponent, ScProfileModule, ScPublicOfferComponent, ScQRCodeDialogComponent, ScQRCodeModule, ScResetUserPasswordComponent, ScResourcePreviewComponent, ScSandwichComponent, ScSandwichM2Component, ScSandwichM2SkeletonComponent, ScSandwichSkeletonComponent, ScSelectOnFocusinDirective, ScSeoTagsComponent, ScShareButtonComponent, ScShareButtonModule, ScSignInFormByEmailComponent, ScSignInFormByPhoneComponent, ScSignInFormComponent, ScSignUpFormComponent, ScSimpleSignUpFormComponent, ScSuggestionFieldComponent, ScTelLinkDirective, ScTerminalLinkDirective, ScUpdateUserInfoDialogComponent, ScUserManagersComponent, ScUserModule, ScUserPhoneApproveDialogComponent, ScVerificationModule, ScVerificationPhoneCheckFormComponent, TreeDirective, TreeIconService, TreeLoaderService, TreeTopDirective, phoneValidator, scAtLeastOneRequiredValidator, scBicValidator, scClientUiIconsName, scCorrespondentAccountValidator, scGetCurrentRoute, scPasswordConfirmMatchingValidator, stepValidator, tuiDateValueTransformerDefaultProvider };
10174
+ export { AbstractScPriceCard, AuthMethod, CURRENT_COUNTRY_ID, CostWithDiscountComponent, FilesAndDocumentsComponent, FilesAndDocumentsModule, FinishDateTimeTransformerDirective, IDLE_ITEM_STATE, IS_DEFAULT_COUNTRY, MAX_FILES_IN_FORM_INPUT, SC_ALLOW_SELECT_TERMINATED, SC_BANNER_DURATION, SC_CATALOG_PRODUCTS_FILTERS, SC_CATALOG_SHOW_PRODUCTS_RECURSIVELY, SC_DATE_FORMATTER, SC_DEBOUNCE_TIME_DEFAULT, SC_DIALOG_SERVICE_TOKEN, SC_ERROR_CHANGE_HANDLER, SC_HELP_NOTIFICATION_CLOSE, SC_HELP_NOTIFICATION_LIMIT, SC_HIDDEN_PRINT_ELEMENTS, SC_MANAGER_QR_HANDLER, SC_NOTIFY_WHEN_IN_STOCK_REQUIRED_FIELDS, SC_ORDER_OPTIONS, SC_PAGE_SIZE_OPTIONS$1 as SC_PAGE_SIZE_OPTIONS, SC_SHOW_HELP_NOTIFICATION_IN_PHONE_INPUT, SC_USER_CITY_INFO, SC_USER_INFO, SC_USER_PROVIDERS, SC_VERIFICATION_CODE_TIMEOUT, ScAccordionComponent, ScAccordionContentDirective, ScAccordionModule, ScAddContactDialogComponent, ScAddContragentBankAccountsDialogComponent, ScAddContragentDialogComponent, ScAddDeliveryAddressDialogComponent, ScAddOrEditingCartItemDialogComponent, ScAddOrEditingCartItemFormComponent, ScAddressesSelectionFieldComponent, ScAuthModule, ScBannerComponent, ScBannerModule, ScBrandsListComponent, ScBrandsListModule, ScCartAddProductsFromCsvDialogComponent, ScCatalogFilterCollapsibleComponent, ScCatalogFiltersComponent, ScCatalogModule, ScCategoryCardComponent, ScContactsAccordionComponent, ScContactsModule, ScContragentsAccordionComponent, ScContragentsAccordionItemComponent, ScContragentsModule, ScDeliveryAddressAccordionComponent, ScDeliveryAddressAccordionItemComponent, ScDeliveryAddressModule, ScDownloadPriceListComponent, ScDraftComponent, ScEmailLinkDirective, ScErrorBlockStatusComponent, ScErrorHandlerComponent, ScFavoriteButtonComponent, ScFeedbackFormComponent, ScFocusFirstInvalidFieldDirective, ScFormFieldsModule, ScFormatDatePipe, ScFrequentlyAskedQuestionsComponent, ScFrequentlyAskedQuestionsGroupSelectorComponent, ScFrequentlyAskedQuestionsWithGroupsComponent, ScGratitudeComponent, ScHelpNotificationService, ScHoverImageCarouselComponent, ScInputQuantityComponent, ScLinks, ScManagerCardComponent, ScManagerCardPushComponent, ScNewContactFormComponent, ScNewContragentBankAccountsFormComponent, ScNewContragentFormComponent, ScNewsCardComponent, ScNewsCardSkeletonComponent, ScNewsModule, ScNextInputFocusDirective, ScNextInputFocusModule, ScNoindexDirective, ScNoindexWrapperComponent, ScNotifyWhenInStockDialogComponent, ScOrderAccessorDirective, ScOrderItemComponent, ScOrderItemsByDirection, ScOrderItemsListByDirectionsComponent, ScOrderItemsListByStockComponent, ScOrderItemsListComponent, ScOrderModule, ScPaymentStatusComponent, ScPersonalDataProcessingPolicyComponent, ScPhoneFormatPipe, ScPreviewSampleComponent, ScPreviewSampleModule, ScPreviewSamplesMosquitoComponent, ScPriceCardComponent, ScPriceCardInlineComponent, ScPriceHistoryComponent, ScPriceListPaginationComponent, ScPriceWarehouseStockComponent, ScPrintDirective, ScPrintService, ScPrivacyPolicyComponent, ScProductInAllWarehousesPipe, ScProfileAccordionsContentComponent, ScProfileModule, ScPublicOfferComponent, ScQRCodeDialogComponent, ScQRCodeModule, ScResetUserPasswordComponent, ScResourcePreviewComponent, ScSandwichComponent, ScSandwichM2Component, ScSandwichM2SkeletonComponent, ScSandwichSkeletonComponent, ScSelectOnFocusinDirective, ScSeoTagsComponent, ScShareButtonComponent, ScShareButtonModule, ScSignInFormByEmailComponent, ScSignInFormByPhoneComponent, ScSignInFormComponent, ScSignUpFormComponent, ScSimpleSignUpFormComponent, ScSuggestionFieldComponent, ScTelLinkDirective, ScTerminalLinkDirective, ScUpdateUserInfoDialogComponent, ScUserManagersComponent, ScUserModule, ScUserPhoneApproveDialogComponent, ScVerificationModule, ScVerificationPhoneCheckFormComponent, TreeDirective, TreeIconService, TreeLoaderService, TreeTopDirective, phoneValidator, scAtLeastOneRequiredValidator, scBicValidator, scClientUiIconsName, scCorrespondentAccountValidator, scGetCurrentRoute, scPasswordConfirmMatchingValidator, stepValidator, tuiDateValueTransformerDefaultProvider };
9933
10175
  //# sourceMappingURL=snabcentr-client-ui.mjs.map