@snabcentr/client-ui 4.6.0 → 4.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/cart/add-or-editing-cart-item-dialog/add-or-editing-cart-item-form/sc-add-or-editing-cart-item-form.component.d.ts +1 -5
  2. package/catalog/catalog-filters/collapsible/sc-catalog-filter-collapsible.component.d.ts +47 -0
  3. package/catalog/catalog-filters/index.d.ts +1 -0
  4. package/catalog/catalog-filters/sc-catalog-filters.component.d.ts +97 -19
  5. package/directives/abstract-price-card/abstract-sc-price-card.directive.d.ts +2 -2
  6. package/directives/next-input-focus/sc-next-input-focus.directive.d.ts +14 -5
  7. package/esm2022/cart/add-or-editing-cart-item-dialog/add-or-editing-cart-item-form/sc-add-or-editing-cart-item-form.component.mjs +7 -11
  8. package/esm2022/cart/add-or-editing-cart-item-dialog/sc-add-or-editing-cart-item-dialog.component.mjs +4 -5
  9. package/esm2022/catalog/catalog-filters/collapsible/sc-catalog-filter-collapsible.component.mjs +59 -0
  10. package/esm2022/catalog/catalog-filters/index.mjs +2 -1
  11. package/esm2022/catalog/catalog-filters/sc-catalog-filters.component.mjs +247 -58
  12. package/esm2022/catalog/price-card/sc-price-card.component.mjs +3 -3
  13. package/esm2022/catalog/price-card-inline/sc-price-card-inline.component.mjs +3 -3
  14. package/esm2022/configurators/sandwich_m2/sc-sandwich-m2.component.mjs +5 -4
  15. package/esm2022/dialogs/sc-resource-preview/sc-resource-preview.component.mjs +6 -1
  16. package/esm2022/directives/abstract-price-card/abstract-sc-price-card.directive.mjs +3 -3
  17. package/esm2022/directives/next-input-focus/sc-next-input-focus.directive.mjs +39 -12
  18. package/esm2022/order/order-item/sc-order-item.component.mjs +3 -3
  19. package/esm2022/order/order-items-list/sc-order-items-list.component.mjs +3 -4
  20. package/esm2022/providers/cleanup-recaptcha-artifacts.mjs +30 -0
  21. package/esm2022/providers/index.mjs +2 -1
  22. package/fesm2022/snabcentr-client-ui.mjs +390 -90
  23. package/fesm2022/snabcentr-client-ui.mjs.map +1 -1
  24. package/package.json +2 -2
  25. package/providers/cleanup-recaptcha-artifacts.d.ts +7 -0
  26. package/providers/index.d.ts +1 -0
  27. package/release_notes.tmp +10 -7
  28. package/styles/tailwind/tailwind.scss +17 -4
@@ -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
- 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';
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, loadingPlaceholder, 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';
@@ -346,6 +346,36 @@ const SC_HIDDEN_PRINT_ELEMENTS = new InjectionToken('SC_HIDDEN_PRINT_ELEMENTS',
346
346
  providedIn: 'root',
347
347
  });
348
348
 
349
+ /**
350
+ * Селектор iframe reCAPTCHA.
351
+ */
352
+ const RECAPTCHA_IFRAME_SELECTOR = 'iframe[src*="recaptcha"]';
353
+ /**
354
+ * Селектор хоста reCAPTCHA.
355
+ */
356
+ const RECAPTCHA_HOST_SELECTOR = 're-captcha';
357
+ /**
358
+ * Освобождает ресурсы reCAPTCHA и удаляет осиротевшие iframe после смены маршрута.
359
+ *
360
+ * @param documentReference Объект документа.
361
+ * @param windowReference Объект окна браузера.
362
+ */
363
+ function cleanupRecaptchaArtifacts(documentReference, windowReference) {
364
+ const windowWithRecaptcha = windowReference;
365
+ try {
366
+ windowWithRecaptcha.grecaptcha?.reset();
367
+ }
368
+ catch {
369
+ // Ошибки reCAPTCHA не должны блокировать навигацию.
370
+ }
371
+ documentReference.querySelectorAll(RECAPTCHA_IFRAME_SELECTOR).forEach((iframe) => {
372
+ if (iframe.closest(RECAPTCHA_HOST_SELECTOR)) {
373
+ return;
374
+ }
375
+ iframe.remove();
376
+ });
377
+ }
378
+
349
379
  /**
350
380
  * Сервис по работе с печатью страницы.
351
381
  */
@@ -535,9 +565,9 @@ class AbstractScPriceCard {
535
565
  */
536
566
  this.autoFocuseQuantityInput = signal(false);
537
567
  /**
538
- * Экземпляр класса-помощника для работы со значениями единиц измерения товара.
568
+ * Класс-помощник для работы со значениями единиц измерения товара.
539
569
  */
540
- this.unitsHelper = inject(ScUnitsHelper);
570
+ this.ScUnitsHelper = ScUnitsHelper;
541
571
  /**
542
572
  * Хелпер для работы с изображениями товара.
543
573
  */
@@ -838,36 +868,63 @@ const ScLinks = [ScTelLinkDirective, ScEmailLinkDirective, ScPhoneFormatPipe];
838
868
  /* eslint-disable lodash/prefer-lodash-method */
839
869
  /**
840
870
  * Директива для перехода по нажатию клавиши enter на следующее поле ввода формы.
871
+ * Поддерживает как legacy Taiga UI v3 контролы (AbstractTuiControl), так и новые v4
872
+ * (tui-textfield + нативные input) — через DOM-fallback.
841
873
  */
842
874
  class ScNextInputFocusDirective {
875
+ constructor() {
876
+ /**
877
+ * Элемент формы.
878
+ */
879
+ this.el = inject(ElementRef);
880
+ }
843
881
  /**
844
- * Слушатель нажатия на клавишу enter. Предотвращает событие submit, выполняет смену фокуса на следующее поле ввода TuiFocusableElementAccessor.
882
+ * По Enter переход на следующее редактируемое поле формы.
883
+ * Сначала пробует legacy Taiga UI v3 контролы, затем DOM fallback для v4.
845
884
  *
846
- * @param event Объект события нажатия на клавишу.
885
+ * @param event Событие нажатия клавиши.
847
886
  */
848
887
  onFormKeyDownEnter(event) {
849
888
  if (event.code !== 'Enter' && event.key !== 'Enter') {
850
889
  return;
851
890
  }
852
891
  event.preventDefault();
853
- const elements = this.focusableElements.toArray();
854
- const focusedIndex = elements.findIndex((control) => control.focused);
855
- if (focusedIndex !== -1) {
856
- const nextElement = elements[focusedIndex + 1]?.nativeFocusableElement;
857
- if (nextElement) {
858
- nextElement.focus();
892
+ // Taiga UI v3: переход через AbstractTuiControl (legacy-обёртки tui-input, tui-input-number и др.).
893
+ const legacy = this.legacyControls.toArray();
894
+ const legacyIndex = legacy.findIndex((control) => control.focused);
895
+ if (legacyIndex !== -1) {
896
+ const next = legacy[legacyIndex + 1]?.nativeFocusableElement;
897
+ if (next) {
898
+ next.focus();
899
+ return;
859
900
  }
860
901
  }
902
+ // Taiga UI v4: переход через DOM — ищем нативные input внутри формы (tui-textfield + директивы).
903
+ const { target } = event;
904
+ if (!(target instanceof HTMLInputElement) || target.type === 'range') {
905
+ return;
906
+ }
907
+ // eslint-disable-next-line unicorn/prefer-spread
908
+ const inputs = Array.from(this.el.nativeElement.querySelectorAll('input')).filter((element) => element.type !== 'range' && !element.readOnly && !element.disabled);
909
+ const currentIndex = inputs.indexOf(target);
910
+ if (currentIndex === -1) {
911
+ return;
912
+ }
913
+ const nextInput = inputs.at(currentIndex + 1);
914
+ if (nextInput) {
915
+ nextInput.focus();
916
+ nextInput.select();
917
+ }
861
918
  }
862
919
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScNextInputFocusDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
863
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: ScNextInputFocusDirective, selector: "form[ScNextInputFocus]", host: { listeners: { "keydown": "onFormKeyDownEnter($event)" } }, queries: [{ propertyName: "focusableElements", predicate: AbstractTuiControl, descendants: true }], ngImport: i0 }); }
920
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: ScNextInputFocusDirective, selector: "form[ScNextInputFocus]", host: { listeners: { "keydown": "onFormKeyDownEnter($event)" } }, queries: [{ propertyName: "legacyControls", predicate: AbstractTuiControl, descendants: true }], ngImport: i0 }); }
864
921
  }
865
922
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScNextInputFocusDirective, decorators: [{
866
923
  type: Directive,
867
924
  args: [{
868
925
  selector: 'form[ScNextInputFocus]',
869
926
  }]
870
- }], propDecorators: { focusableElements: [{
927
+ }], propDecorators: { legacyControls: [{
871
928
  type: ContentChildren,
872
929
  args: [AbstractTuiControl, { descendants: true }]
873
930
  }], onFormKeyDownEnter: [{
@@ -4187,11 +4244,11 @@ class ScAddOrEditingCartItemFormComponent {
4187
4244
  /**
4188
4245
  * Признак возможности продажи товара на метраж.
4189
4246
  */
4190
- this.productIsMeasurable = computed(() => this.unitsHelper.productIsMeasurable(this.product()));
4247
+ this.productIsMeasurable = computed(() => ScUnitsHelper.productIsMeasurable(this.product()));
4191
4248
  /**
4192
4249
  * Кратность количества для товара.
4193
4250
  */
4194
- this.productMultiplicity = computed(() => this.unitsHelper.productMultiplicity(this.product()));
4251
+ this.productMultiplicity = computed(() => ScUnitsHelper.getProductMultiplicity(this.product()));
4195
4252
  /**
4196
4253
  * Минимальный метраж для товара.
4197
4254
  */
@@ -4203,7 +4260,7 @@ class ScAddOrEditingCartItemFormComponent {
4203
4260
  /**
4204
4261
  * Шаг изменения метража.
4205
4262
  */
4206
- this.lengthStep = computed(() => this.product().properties?.lengthStep ?? (this.product().ignoreMinCountCheck ? 0 : this.product().minCount));
4263
+ this.lengthStep = computed(() => ScUnitsHelper.getProductLengthMultiplicity(this.product()));
4207
4264
  /**
4208
4265
  * Подсказка по минимальному и максимальному метражу товара.
4209
4266
  */
@@ -4221,10 +4278,6 @@ class ScAddOrEditingCartItemFormComponent {
4221
4278
  * {@link Output} события редактирования товара в корзине.
4222
4279
  */
4223
4280
  this.editCartItem = output();
4224
- /**
4225
- * Объект-помощник для работы со значениями единиц измерения товара.
4226
- */
4227
- this.unitsHelper = inject(ScUnitsHelper);
4228
4281
  /**
4229
4282
  * Сервис для сбора метрик о действиях пользователей.
4230
4283
  */
@@ -4246,7 +4299,7 @@ class ScAddOrEditingCartItemFormComponent {
4246
4299
  }
4247
4300
  // Устанавливаем количество из корзины или кратности товара.
4248
4301
  this.form.patchValue({
4249
- quantity: this.orderItem()?.quantity ?? this.unitsHelper.productMultiplicity(this.product()),
4302
+ quantity: this.orderItem()?.quantity ?? ScUnitsHelper.getProductMultiplicity(this.product()),
4250
4303
  marker: this.orderItem()?.marker ?? '',
4251
4304
  });
4252
4305
  const step = this.lengthStep();
@@ -4255,9 +4308,9 @@ class ScAddOrEditingCartItemFormComponent {
4255
4308
  this.form.controls.length?.patchValue(this.form.controls.quantity.value * step);
4256
4309
  }
4257
4310
  // Добавляем валидацию шага для количества.
4258
- this.form.controls.quantity.addValidators(stepValidator(this.unitsHelper.productStepForValidator(this.product())));
4311
+ this.form.controls.quantity.addValidators(stepValidator(ScUnitsHelper.getProductMultiplicity(this.product())));
4259
4312
  // Добавляем валидацию шага для длины.
4260
- this.form.get('length')?.addValidators(stepValidator(this.product().properties?.lengthStep ?? (this.product().ignoreMinCountCheck ? 0 : (this.product().minCount ?? 0))));
4313
+ this.form.get('length')?.addValidators(stepValidator(ScUnitsHelper.getProductLengthMultiplicity(this.product())));
4261
4314
  // Считаем итоговую стоимость заказа.
4262
4315
  this.totalCost$ = tuiControlValue(this.form).pipe(debounceTime(0), // Исправляем ошибку NG0950.
4263
4316
  filter(() => this.form.valid), distinctUntilChanged((previous, current) => previous.length === current.length && previous.quantity === current.quantity), // Только при изменении значений
@@ -4401,11 +4454,11 @@ class ScAddOrEditingCartItemDialogComponent {
4401
4454
  this.formComponent().form.markAsDirty();
4402
4455
  }
4403
4456
  return of();
4404
- }))), startWith(), share());
4457
+ }), startWith(loadingPlaceholder))), share());
4405
4458
  /**
4406
4459
  * {@link Observable} изменения состояния загрузки данных.
4407
4460
  */
4408
- this.loading = toSignal(this.submit$.pipe(map(tuiIsFalsy)), { initialValue: false });
4461
+ this.loading = toSignal(this.submit$.pipe(map((data) => data === loadingPlaceholder)), { initialValue: false });
4409
4462
  /**
4410
4463
  * Контекст диалогового окна.
4411
4464
  */
@@ -5235,7 +5288,7 @@ class ScPriceCardComponent extends AbstractScPriceCard {
5235
5288
  }
5236
5289
  }
5237
5290
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScPriceCardComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
5238
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ScPriceCardComponent, isStandalone: true, selector: "sc-price-card", inputs: { size: "size" }, host: { properties: { "attr.data-size": "this.size" } }, providers: [SEARCH_TERM_PROVIDERS], usesInheritance: true, ngImport: i0, template: "<div\n *ngIf=\"product; else skeleton\"\n class=\"card-wrapper relative flex h-full w-auto flex-col rounded-xl p-1\"\n>\n <sc-noindex-wrapper>\n <div class=\"flex min-h-8 items-center justify-between\">\n <span\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"code text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B: {{ product.code }}\n </span>\n\n <div class=\"flex items-center\">\n <tui-icon\n *ngIf=\"product.isPreviouslyOrdered\"\n icon=\"@tui.history\"\n class=\"text-lg\"\n [style.color]=\"'var(--tui-text-action)'\"\n />\n <sc-favorite-button\n *ngIf=\"authStatus$ | async\"\n (clickEvent)=\"clickFavoriteEvent.emit()\"\n [showLoader]=\"favoriteShowLoader()\"\n [isFavorite]=\"product.isFavorite\"\n [disabled]=\"!!product.primaryCategory?.isFavorite\"\n />\n </div>\n </div>\n </sc-noindex-wrapper>\n\n <sc-hover-image-carousel\n (click)=\"clickCardEvent.emit()\"\n [images]=\"!isMobile ? getCardImagePreviewList(product) : [getCardImagePreview()]\"\n class=\"cursor-pointer\"\n />\n\n <div\n class=\"flex grow flex-col justify-end\"\n [class.gap-1]=\"size === 'm'\"\n >\n <div\n class=\"flex grow flex-col\"\n [class.gap-1]=\"size === 'm'\"\n >\n <a\n tuiLink\n [attr.href]=\"href ?? null\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n (click)=\"$event.preventDefault(); clickCardEvent.emit()\"\n class=\"name mb-auto\"\n >\n {{ product.name }}\n </a>\n\n <sc-noindex-wrapper>\n <span\n *ngIf=\"product.supplierSku\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044F: {{ product.supplierSku }}\n </span>\n\n <div\n *ngIf=\"product?.pack\"\n class=\"flex items-center gap-1 text-tui-text-02\"\n >\n \u041D\u043E\u0440\u043C\u0430 \u0443\u043F\u0430\u043A\u043E\u0432\u043A\u0438: {{ product.pack }}\n <tui-icon\n *ngIf=\"product.ignoreMinCountCheck\"\n icon=\"@tui.package\"\n [tuiHint]=\"minCountHint\"\n [tuiHintShowDelay]=\"100\"\n class=\"text-body-xl text-tui-text-01 opacity-90\"\n tuiHintDirection=\"top\"\n />\n <ng-template #minCountHint>\n \u0414\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0437\u0430\u043A\u0430\u0437 <br />\n \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u044C\u043D\u043E\u0433\u043E <br />\n \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430\n </ng-template>\n </div>\n </sc-noindex-wrapper>\n\n <sc-cost-with-discount\n [product]=\"product\"\n [size]=\"size\"\n />\n\n <sc-noindex-wrapper>\n <sc-price-warehouse-stock [product]=\"product\" />\n </sc-noindex-wrapper>\n </div>\n\n <sc-noindex-wrapper>\n <div class=\"mt-2 flex gap-2\">\n <button\n *ngIf=\"!showQuantityControl\"\n tuiButton\n (click)=\"clickAddToCartEvent.emit(product)\"\n [loading]=\"showLoader()\"\n [size]=\"getToCartButtonSize()\"\n class=\"grow !font-extrabold\"\n iconStart=\"@tui.shopping-cart\"\n >\n \u0412 \u043A\u043E\u0440\u0437\u0438\u043D\u0443\n </button>\n <sc-input-quantity\n #inputQuantity\n *ngIf=\"showQuantityControl\"\n [formControl]=\"quantityControl\"\n [size]=\"size\"\n [step]=\"unitsHelper.productMultiplicity(product)\"\n [ignoreStepValidators]=\"product.ignoreMinCountCheck\"\n [showLoader]=\"showLoader()\"\n (clickClearEvent)=\"clickClearEvent.emit(orderItem)\"\n (keydown.enter)=\"inputQuantity.nativeFocusableElement?.blur()\"\n class=\"w-full\"\n />\n <tui-avatar\n *ngIf=\"orderItem && !showQuantityControl\"\n src=\"@tui.check\"\n size=\"s\"\n [style.background]=\"'var(--tui-status-warning-pale)'\"\n [style.color]=\"'var(--tui-background-accent-1)'\"\n />\n </div>\n </sc-noindex-wrapper>\n </div>\n</div>\n\n<ng-template #skeleton>\n <div class=\"card-wrapper relative flex h-full w-auto flex-col rounded-xl p-1\"></div>\n</ng-template>\n", styles: [":host tui-badge{--t-padding: .25rem !important}:host .name{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4}:host[data-size=s] .card-wrapper{font-size:.6875rem;line-height:1rem;font-weight:500}:host[data-size=s] .card-wrapper .name,:host[data-size=s] .card-wrapper .cost{font-size:.8125rem;line-height:1.25rem;font-weight:800}:host[data-size=m] .card-wrapper{font-size:.8125rem;line-height:1.25rem;font-weight:500}:host[data-size=m] .card-wrapper .name,:host[data-size=m] .card-wrapper .cost{font-size:.9375rem;line-height:1.5rem;font-weight:800}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2$2.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiIcon, selector: "tui-icon", inputs: ["icon", "background"] }, { kind: "directive", type: i1$2.TuiHintDirective, selector: "[tuiHint]:not(ng-container):not(ng-template)", inputs: ["tuiHintContext", "tuiHintAppearance", "tuiHint"], outputs: ["tuiHintVisible"] }, { kind: "directive", type: TuiLink, selector: "a[tuiLink], button[tuiLink]", inputs: ["pseudo"] }, { kind: "directive", type: TuiHighlight, selector: "[tuiHighlight]", inputs: ["tuiHighlight", "tuiHighlightColor"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "component", type: TuiAvatar, selector: "tui-avatar,button[tuiAvatar],a[tuiAvatar]", inputs: ["size", "round", "src"] }, { kind: "component", type: ScHoverImageCarouselComponent, selector: "sc-hover-image-carousel", inputs: ["images", "isShowActions", "productName"] }, { kind: "component", type: CostWithDiscountComponent, selector: "sc-cost-with-discount", inputs: ["product", "size"] }, { kind: "component", type: ScPriceWarehouseStockComponent, selector: "sc-price-warehouse-stock", inputs: ["classList", "product", "withStockHint", "fromMain"] }, { kind: "component", type: ScFavoriteButtonComponent, selector: "sc-favorite-button", inputs: ["isFavorite", "showLoader", "disabled"], outputs: ["clickEvent"] }, { kind: "component", type: ScInputQuantityComponent, selector: "sc-input-quantity", inputs: ["step", "showLoader", "showCross", "ignoreStepValidators", "appearance", "isDisabled", "size"], outputs: ["clickClearEvent"] }, { kind: "component", type: ScNoindexWrapperComponent, selector: "sc-noindex-wrapper" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5291
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ScPriceCardComponent, isStandalone: true, selector: "sc-price-card", inputs: { size: "size" }, host: { properties: { "attr.data-size": "this.size" } }, providers: [SEARCH_TERM_PROVIDERS], usesInheritance: true, ngImport: i0, template: "<div\n *ngIf=\"product; else skeleton\"\n class=\"card-wrapper relative flex h-full w-auto flex-col rounded-xl p-1\"\n>\n <sc-noindex-wrapper>\n <div class=\"flex min-h-8 items-center justify-between\">\n <span\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"code text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B: {{ product.code }}\n </span>\n\n <div class=\"flex items-center\">\n <tui-icon\n *ngIf=\"product.isPreviouslyOrdered\"\n icon=\"@tui.history\"\n class=\"text-lg\"\n [style.color]=\"'var(--tui-text-action)'\"\n />\n <sc-favorite-button\n *ngIf=\"authStatus$ | async\"\n (clickEvent)=\"clickFavoriteEvent.emit()\"\n [showLoader]=\"favoriteShowLoader()\"\n [isFavorite]=\"product.isFavorite\"\n [disabled]=\"!!product.primaryCategory?.isFavorite\"\n />\n </div>\n </div>\n </sc-noindex-wrapper>\n\n <sc-hover-image-carousel\n (click)=\"clickCardEvent.emit()\"\n [images]=\"!isMobile ? getCardImagePreviewList(product) : [getCardImagePreview()]\"\n class=\"cursor-pointer\"\n />\n\n <div\n class=\"flex grow flex-col justify-end\"\n [class.gap-1]=\"size === 'm'\"\n >\n <div\n class=\"flex grow flex-col\"\n [class.gap-1]=\"size === 'm'\"\n >\n <a\n tuiLink\n [attr.href]=\"href ?? null\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n (click)=\"$event.preventDefault(); clickCardEvent.emit()\"\n class=\"name mb-auto\"\n >\n {{ product.name }}\n </a>\n\n <sc-noindex-wrapper>\n <span\n *ngIf=\"product.supplierSku\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044F: {{ product.supplierSku }}\n </span>\n\n <div\n *ngIf=\"product?.pack\"\n class=\"flex items-center gap-1 text-tui-text-02\"\n >\n \u041D\u043E\u0440\u043C\u0430 \u0443\u043F\u0430\u043A\u043E\u0432\u043A\u0438: {{ product.pack }}\n <tui-icon\n *ngIf=\"product.ignoreMinCountCheck\"\n icon=\"@tui.package\"\n [tuiHint]=\"minCountHint\"\n [tuiHintShowDelay]=\"100\"\n class=\"text-body-xl text-tui-text-01 opacity-90\"\n tuiHintDirection=\"top\"\n />\n <ng-template #minCountHint>\n \u0414\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0437\u0430\u043A\u0430\u0437 <br />\n \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u044C\u043D\u043E\u0433\u043E <br />\n \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430\n </ng-template>\n </div>\n </sc-noindex-wrapper>\n\n <sc-cost-with-discount\n [product]=\"product\"\n [size]=\"size\"\n />\n\n <sc-noindex-wrapper>\n <sc-price-warehouse-stock [product]=\"product\" />\n </sc-noindex-wrapper>\n </div>\n\n <sc-noindex-wrapper>\n <div class=\"mt-2 flex gap-2\">\n <button\n *ngIf=\"!showQuantityControl\"\n tuiButton\n (click)=\"clickAddToCartEvent.emit(product)\"\n [loading]=\"showLoader()\"\n [size]=\"getToCartButtonSize()\"\n class=\"grow !font-extrabold\"\n iconStart=\"@tui.shopping-cart\"\n >\n \u0412 \u043A\u043E\u0440\u0437\u0438\u043D\u0443\n </button>\n <sc-input-quantity\n #inputQuantity\n *ngIf=\"showQuantityControl\"\n [formControl]=\"quantityControl\"\n [size]=\"size\"\n [step]=\"ScUnitsHelper.getProductMultiplicity(product)\"\n [ignoreStepValidators]=\"product.ignoreMinCountCheck\"\n [showLoader]=\"showLoader()\"\n (clickClearEvent)=\"clickClearEvent.emit(orderItem)\"\n (keydown.enter)=\"inputQuantity.nativeFocusableElement?.blur()\"\n class=\"w-full\"\n />\n <tui-avatar\n *ngIf=\"orderItem && !showQuantityControl\"\n src=\"@tui.check\"\n size=\"s\"\n [style.background]=\"'var(--tui-status-warning-pale)'\"\n [style.color]=\"'var(--tui-background-accent-1)'\"\n />\n </div>\n </sc-noindex-wrapper>\n </div>\n</div>\n\n<ng-template #skeleton>\n <div class=\"card-wrapper relative flex h-full w-auto flex-col rounded-xl p-1\"></div>\n</ng-template>\n", styles: [":host tui-badge{--t-padding: .25rem !important}:host .name{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4}:host[data-size=s] .card-wrapper{font-size:.6875rem;line-height:1rem;font-weight:500}:host[data-size=s] .card-wrapper .name,:host[data-size=s] .card-wrapper .cost{font-size:.8125rem;line-height:1.25rem;font-weight:800}:host[data-size=m] .card-wrapper{font-size:.8125rem;line-height:1.25rem;font-weight:500}:host[data-size=m] .card-wrapper .name,:host[data-size=m] .card-wrapper .cost{font-size:.9375rem;line-height:1.5rem;font-weight:800}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2$2.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiIcon, selector: "tui-icon", inputs: ["icon", "background"] }, { kind: "directive", type: i1$2.TuiHintDirective, selector: "[tuiHint]:not(ng-container):not(ng-template)", inputs: ["tuiHintContext", "tuiHintAppearance", "tuiHint"], outputs: ["tuiHintVisible"] }, { kind: "directive", type: TuiLink, selector: "a[tuiLink], button[tuiLink]", inputs: ["pseudo"] }, { kind: "directive", type: TuiHighlight, selector: "[tuiHighlight]", inputs: ["tuiHighlight", "tuiHighlightColor"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "component", type: TuiAvatar, selector: "tui-avatar,button[tuiAvatar],a[tuiAvatar]", inputs: ["size", "round", "src"] }, { kind: "component", type: ScHoverImageCarouselComponent, selector: "sc-hover-image-carousel", inputs: ["images", "isShowActions", "productName"] }, { kind: "component", type: CostWithDiscountComponent, selector: "sc-cost-with-discount", inputs: ["product", "size"] }, { kind: "component", type: ScPriceWarehouseStockComponent, selector: "sc-price-warehouse-stock", inputs: ["classList", "product", "withStockHint", "fromMain"] }, { kind: "component", type: ScFavoriteButtonComponent, selector: "sc-favorite-button", inputs: ["isFavorite", "showLoader", "disabled"], outputs: ["clickEvent"] }, { kind: "component", type: ScInputQuantityComponent, selector: "sc-input-quantity", inputs: ["step", "showLoader", "showCross", "ignoreStepValidators", "appearance", "isDisabled", "size"], outputs: ["clickClearEvent"] }, { kind: "component", type: ScNoindexWrapperComponent, selector: "sc-noindex-wrapper" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5239
5292
  }
5240
5293
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScPriceCardComponent, decorators: [{
5241
5294
  type: Component,
@@ -5256,7 +5309,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
5256
5309
  ScFavoriteButtonComponent,
5257
5310
  ScInputQuantityComponent,
5258
5311
  ScNoindexWrapperComponent,
5259
- ], template: "<div\n *ngIf=\"product; else skeleton\"\n class=\"card-wrapper relative flex h-full w-auto flex-col rounded-xl p-1\"\n>\n <sc-noindex-wrapper>\n <div class=\"flex min-h-8 items-center justify-between\">\n <span\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"code text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B: {{ product.code }}\n </span>\n\n <div class=\"flex items-center\">\n <tui-icon\n *ngIf=\"product.isPreviouslyOrdered\"\n icon=\"@tui.history\"\n class=\"text-lg\"\n [style.color]=\"'var(--tui-text-action)'\"\n />\n <sc-favorite-button\n *ngIf=\"authStatus$ | async\"\n (clickEvent)=\"clickFavoriteEvent.emit()\"\n [showLoader]=\"favoriteShowLoader()\"\n [isFavorite]=\"product.isFavorite\"\n [disabled]=\"!!product.primaryCategory?.isFavorite\"\n />\n </div>\n </div>\n </sc-noindex-wrapper>\n\n <sc-hover-image-carousel\n (click)=\"clickCardEvent.emit()\"\n [images]=\"!isMobile ? getCardImagePreviewList(product) : [getCardImagePreview()]\"\n class=\"cursor-pointer\"\n />\n\n <div\n class=\"flex grow flex-col justify-end\"\n [class.gap-1]=\"size === 'm'\"\n >\n <div\n class=\"flex grow flex-col\"\n [class.gap-1]=\"size === 'm'\"\n >\n <a\n tuiLink\n [attr.href]=\"href ?? null\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n (click)=\"$event.preventDefault(); clickCardEvent.emit()\"\n class=\"name mb-auto\"\n >\n {{ product.name }}\n </a>\n\n <sc-noindex-wrapper>\n <span\n *ngIf=\"product.supplierSku\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044F: {{ product.supplierSku }}\n </span>\n\n <div\n *ngIf=\"product?.pack\"\n class=\"flex items-center gap-1 text-tui-text-02\"\n >\n \u041D\u043E\u0440\u043C\u0430 \u0443\u043F\u0430\u043A\u043E\u0432\u043A\u0438: {{ product.pack }}\n <tui-icon\n *ngIf=\"product.ignoreMinCountCheck\"\n icon=\"@tui.package\"\n [tuiHint]=\"minCountHint\"\n [tuiHintShowDelay]=\"100\"\n class=\"text-body-xl text-tui-text-01 opacity-90\"\n tuiHintDirection=\"top\"\n />\n <ng-template #minCountHint>\n \u0414\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0437\u0430\u043A\u0430\u0437 <br />\n \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u044C\u043D\u043E\u0433\u043E <br />\n \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430\n </ng-template>\n </div>\n </sc-noindex-wrapper>\n\n <sc-cost-with-discount\n [product]=\"product\"\n [size]=\"size\"\n />\n\n <sc-noindex-wrapper>\n <sc-price-warehouse-stock [product]=\"product\" />\n </sc-noindex-wrapper>\n </div>\n\n <sc-noindex-wrapper>\n <div class=\"mt-2 flex gap-2\">\n <button\n *ngIf=\"!showQuantityControl\"\n tuiButton\n (click)=\"clickAddToCartEvent.emit(product)\"\n [loading]=\"showLoader()\"\n [size]=\"getToCartButtonSize()\"\n class=\"grow !font-extrabold\"\n iconStart=\"@tui.shopping-cart\"\n >\n \u0412 \u043A\u043E\u0440\u0437\u0438\u043D\u0443\n </button>\n <sc-input-quantity\n #inputQuantity\n *ngIf=\"showQuantityControl\"\n [formControl]=\"quantityControl\"\n [size]=\"size\"\n [step]=\"unitsHelper.productMultiplicity(product)\"\n [ignoreStepValidators]=\"product.ignoreMinCountCheck\"\n [showLoader]=\"showLoader()\"\n (clickClearEvent)=\"clickClearEvent.emit(orderItem)\"\n (keydown.enter)=\"inputQuantity.nativeFocusableElement?.blur()\"\n class=\"w-full\"\n />\n <tui-avatar\n *ngIf=\"orderItem && !showQuantityControl\"\n src=\"@tui.check\"\n size=\"s\"\n [style.background]=\"'var(--tui-status-warning-pale)'\"\n [style.color]=\"'var(--tui-background-accent-1)'\"\n />\n </div>\n </sc-noindex-wrapper>\n </div>\n</div>\n\n<ng-template #skeleton>\n <div class=\"card-wrapper relative flex h-full w-auto flex-col rounded-xl p-1\"></div>\n</ng-template>\n", styles: [":host tui-badge{--t-padding: .25rem !important}:host .name{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4}:host[data-size=s] .card-wrapper{font-size:.6875rem;line-height:1rem;font-weight:500}:host[data-size=s] .card-wrapper .name,:host[data-size=s] .card-wrapper .cost{font-size:.8125rem;line-height:1.25rem;font-weight:800}:host[data-size=m] .card-wrapper{font-size:.8125rem;line-height:1.25rem;font-weight:500}:host[data-size=m] .card-wrapper .name,:host[data-size=m] .card-wrapper .cost{font-size:.9375rem;line-height:1.5rem;font-weight:800}\n"] }]
5312
+ ], template: "<div\n *ngIf=\"product; else skeleton\"\n class=\"card-wrapper relative flex h-full w-auto flex-col rounded-xl p-1\"\n>\n <sc-noindex-wrapper>\n <div class=\"flex min-h-8 items-center justify-between\">\n <span\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"code text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B: {{ product.code }}\n </span>\n\n <div class=\"flex items-center\">\n <tui-icon\n *ngIf=\"product.isPreviouslyOrdered\"\n icon=\"@tui.history\"\n class=\"text-lg\"\n [style.color]=\"'var(--tui-text-action)'\"\n />\n <sc-favorite-button\n *ngIf=\"authStatus$ | async\"\n (clickEvent)=\"clickFavoriteEvent.emit()\"\n [showLoader]=\"favoriteShowLoader()\"\n [isFavorite]=\"product.isFavorite\"\n [disabled]=\"!!product.primaryCategory?.isFavorite\"\n />\n </div>\n </div>\n </sc-noindex-wrapper>\n\n <sc-hover-image-carousel\n (click)=\"clickCardEvent.emit()\"\n [images]=\"!isMobile ? getCardImagePreviewList(product) : [getCardImagePreview()]\"\n class=\"cursor-pointer\"\n />\n\n <div\n class=\"flex grow flex-col justify-end\"\n [class.gap-1]=\"size === 'm'\"\n >\n <div\n class=\"flex grow flex-col\"\n [class.gap-1]=\"size === 'm'\"\n >\n <a\n tuiLink\n [attr.href]=\"href ?? null\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n (click)=\"$event.preventDefault(); clickCardEvent.emit()\"\n class=\"name mb-auto\"\n >\n {{ product.name }}\n </a>\n\n <sc-noindex-wrapper>\n <span\n *ngIf=\"product.supplierSku\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044F: {{ product.supplierSku }}\n </span>\n\n <div\n *ngIf=\"product?.pack\"\n class=\"flex items-center gap-1 text-tui-text-02\"\n >\n \u041D\u043E\u0440\u043C\u0430 \u0443\u043F\u0430\u043A\u043E\u0432\u043A\u0438: {{ product.pack }}\n <tui-icon\n *ngIf=\"product.ignoreMinCountCheck\"\n icon=\"@tui.package\"\n [tuiHint]=\"minCountHint\"\n [tuiHintShowDelay]=\"100\"\n class=\"text-body-xl text-tui-text-01 opacity-90\"\n tuiHintDirection=\"top\"\n />\n <ng-template #minCountHint>\n \u0414\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0437\u0430\u043A\u0430\u0437 <br />\n \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u044C\u043D\u043E\u0433\u043E <br />\n \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430\n </ng-template>\n </div>\n </sc-noindex-wrapper>\n\n <sc-cost-with-discount\n [product]=\"product\"\n [size]=\"size\"\n />\n\n <sc-noindex-wrapper>\n <sc-price-warehouse-stock [product]=\"product\" />\n </sc-noindex-wrapper>\n </div>\n\n <sc-noindex-wrapper>\n <div class=\"mt-2 flex gap-2\">\n <button\n *ngIf=\"!showQuantityControl\"\n tuiButton\n (click)=\"clickAddToCartEvent.emit(product)\"\n [loading]=\"showLoader()\"\n [size]=\"getToCartButtonSize()\"\n class=\"grow !font-extrabold\"\n iconStart=\"@tui.shopping-cart\"\n >\n \u0412 \u043A\u043E\u0440\u0437\u0438\u043D\u0443\n </button>\n <sc-input-quantity\n #inputQuantity\n *ngIf=\"showQuantityControl\"\n [formControl]=\"quantityControl\"\n [size]=\"size\"\n [step]=\"ScUnitsHelper.getProductMultiplicity(product)\"\n [ignoreStepValidators]=\"product.ignoreMinCountCheck\"\n [showLoader]=\"showLoader()\"\n (clickClearEvent)=\"clickClearEvent.emit(orderItem)\"\n (keydown.enter)=\"inputQuantity.nativeFocusableElement?.blur()\"\n class=\"w-full\"\n />\n <tui-avatar\n *ngIf=\"orderItem && !showQuantityControl\"\n src=\"@tui.check\"\n size=\"s\"\n [style.background]=\"'var(--tui-status-warning-pale)'\"\n [style.color]=\"'var(--tui-background-accent-1)'\"\n />\n </div>\n </sc-noindex-wrapper>\n </div>\n</div>\n\n<ng-template #skeleton>\n <div class=\"card-wrapper relative flex h-full w-auto flex-col rounded-xl p-1\"></div>\n</ng-template>\n", styles: [":host tui-badge{--t-padding: .25rem !important}:host .name{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4}:host[data-size=s] .card-wrapper{font-size:.6875rem;line-height:1rem;font-weight:500}:host[data-size=s] .card-wrapper .name,:host[data-size=s] .card-wrapper .cost{font-size:.8125rem;line-height:1.25rem;font-weight:800}:host[data-size=m] .card-wrapper{font-size:.8125rem;line-height:1.25rem;font-weight:500}:host[data-size=m] .card-wrapper .name,:host[data-size=m] .card-wrapper .cost{font-size:.9375rem;line-height:1.5rem;font-weight:800}\n"] }]
5260
5313
  }], propDecorators: { size: [{
5261
5314
  type: Input
5262
5315
  }, {
@@ -5273,7 +5326,7 @@ class ScPriceCardInlineComponent extends AbstractScPriceCard {
5273
5326
  this.type = input('catalogItem');
5274
5327
  }
5275
5328
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScPriceCardInlineComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
5276
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.14", type: ScPriceCardInlineComponent, isStandalone: true, selector: "sc-price-card-inline", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null } }, providers: [SEARCH_TERM_PROVIDERS], usesInheritance: true, ngImport: i0, template: "<div\n *ngIf=\"product; else skeleton\"\n class=\"card-wrapper relative flex w-full gap-4 rounded-xl p-1 hover:bg-tui-background-neutral-1\"\n>\n <sc-hover-image-carousel\n (click)=\"clickCardEvent.emit()\"\n [images]=\"!isMobile ? getCardImagePreviewList(product) : [getCardImagePreview()]\"\n [isShowActions]=\"false\"\n class=\"size-24 shrink-0 cursor-pointer self-center\"\n />\n <div class=\"flex grow flex-col gap-1\">\n <sc-noindex-wrapper>\n <div\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B: {{ product.code }}\n </div>\n </sc-noindex-wrapper>\n\n <div class=\"flex flex-col gap-1\">\n <a\n tuiLink\n [attr.href]=\"href ?? null\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n (click)=\"$event.preventDefault(); clickCardEvent.emit()\"\n class=\"!text-body-m-bold\"\n >\n {{ product.name }}\n </a>\n\n <sc-noindex-wrapper>\n <span\n *ngIf=\"product.supplierSku\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044F: {{ product.supplierSku }}\n </span>\n\n <div\n *ngIf=\"product?.pack\"\n class=\"flex items-center gap-1 text-tui-text-02\"\n >\n \u041D\u043E\u0440\u043C\u0430 \u0443\u043F\u0430\u043A\u043E\u0432\u043A\u0438: {{ product.pack }}\n <tui-icon\n *ngIf=\"product.ignoreMinCountCheck\"\n icon=\"@tui.package\"\n [tuiHint]=\"minCountHint\"\n [tuiHintShowDelay]=\"100\"\n tuiHintDirection=\"top\"\n class=\"text-body-xl text-tui-text-01 opacity-90\"\n />\n <ng-template #minCountHint>\n \u0414\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0437\u0430\u043A\u0430\u0437 <br />\n \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u044C\u043D\u043E\u0433\u043E <br />\n \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430\n </ng-template>\n </div>\n </sc-noindex-wrapper>\n\n <sc-cost-with-discount [product]=\"product\" />\n\n <sc-noindex-wrapper>\n <sc-price-warehouse-stock [product]=\"product\" />\n </sc-noindex-wrapper>\n </div>\n </div>\n\n <sc-noindex-wrapper>\n <div class=\"flex w-40 shrink-0 flex-col justify-between\">\n <div class=\"flex justify-end\">\n <tui-avatar\n *ngIf=\"product.isPreviouslyOrdered\"\n src=\"@tui.history\"\n size=\"s\"\n [style.background]=\"'none'\"\n [style.color]=\"'var(--tui-text-action)'\"\n />\n <sc-favorite-button\n *ngIf=\"authStatus$ | async\"\n (clickEvent)=\"clickFavoriteEvent.emit()\"\n [showLoader]=\"favoriteShowLoader()\"\n [isFavorite]=\"product.isFavorite\"\n [disabled]=\"!!product.primaryCategory?.isFavorite\"\n />\n </div>\n <div class=\"flex gap-2\">\n <button\n *ngIf=\"!showQuantityControl\"\n tuiButton\n (click)=\"clickAddToCartEvent.emit(product)\"\n [loading]=\"showLoader()\"\n size=\"s\"\n iconStart=\"@tui.shopping-cart\"\n class=\"grow !font-extrabold\"\n >\n \u0412 \u043A\u043E\u0440\u0437\u0438\u043D\u0443\n </button>\n <sc-input-quantity\n #inputQuantity\n [tuiAutoFocus]=\"autoFocuseQuantityInput()\"\n *ngIf=\"showQuantityControl\"\n [formControl]=\"quantityControl\"\n size=\"m\"\n [step]=\"unitsHelper.productMultiplicity(product)\"\n [ignoreStepValidators]=\"product.ignoreMinCountCheck\"\n [showLoader]=\"showLoader()\"\n (clickClearEvent)=\"clickClearEvent.emit(orderItem)\"\n (keydown.enter)=\"inputQuantity.nativeFocusableElement?.blur()\"\n class=\"w-full\"\n />\n <tui-avatar\n *ngIf=\"orderItem && !showQuantityControl\"\n src=\"@tui.check\"\n size=\"s\"\n [style.background]=\"'var(--tui-status-warning-pale)'\"\n [style.color]=\"'var(--tui-background-accent-1)'\"\n />\n </div>\n </div>\n </sc-noindex-wrapper>\n</div>\n\n<ng-template #skeleton>\n <div class=\"tui-skeleton flex h-[8.25rem] w-full overflow-hidden rounded-xl\"></div>\n</ng-template>\n", styles: [":host tui-badge{--t-padding: .25rem !important}:host .name{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4}:host .card-wrapper{font-size:.8125rem;line-height:1.25rem;font-weight:500}:host .card-wrapper .name,:host .card-wrapper .cost{font-size:.9375rem;line-height:1.5rem;font-weight:800}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2$2.AsyncPipe, name: "async" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiIcon, selector: "tui-icon", inputs: ["icon", "background"] }, { kind: "ngmodule", type: TuiTextfieldControllerModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.TuiHintDirective, selector: "[tuiHint]:not(ng-container):not(ng-template)", inputs: ["tuiHintContext", "tuiHintAppearance", "tuiHint"], outputs: ["tuiHintVisible"] }, { kind: "directive", type: TuiLink, selector: "a[tuiLink], button[tuiLink]", inputs: ["pseudo"] }, { kind: "directive", type: TuiHighlight, selector: "[tuiHighlight]", inputs: ["tuiHighlight", "tuiHighlightColor"] }, { kind: "directive", type: TuiAutoFocus, selector: "[tuiAutoFocus]", inputs: ["tuiAutoFocus"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "component", type: TuiAvatar, selector: "tui-avatar,button[tuiAvatar],a[tuiAvatar]", inputs: ["size", "round", "src"] }, { kind: "component", type: ScHoverImageCarouselComponent, selector: "sc-hover-image-carousel", inputs: ["images", "isShowActions", "productName"] }, { kind: "component", type: CostWithDiscountComponent, selector: "sc-cost-with-discount", inputs: ["product", "size"] }, { kind: "component", type: ScPriceWarehouseStockComponent, selector: "sc-price-warehouse-stock", inputs: ["classList", "product", "withStockHint", "fromMain"] }, { kind: "component", type: ScFavoriteButtonComponent, selector: "sc-favorite-button", inputs: ["isFavorite", "showLoader", "disabled"], outputs: ["clickEvent"] }, { kind: "component", type: ScInputQuantityComponent, selector: "sc-input-quantity", inputs: ["step", "showLoader", "showCross", "ignoreStepValidators", "appearance", "isDisabled", "size"], outputs: ["clickClearEvent"] }, { kind: "component", type: ScNoindexWrapperComponent, selector: "sc-noindex-wrapper" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5329
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.14", type: ScPriceCardInlineComponent, isStandalone: true, selector: "sc-price-card-inline", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null } }, providers: [SEARCH_TERM_PROVIDERS], usesInheritance: true, ngImport: i0, template: "<div\n *ngIf=\"product; else skeleton\"\n class=\"card-wrapper relative flex w-full gap-4 rounded-xl p-1 hover:bg-tui-background-neutral-1\"\n>\n <sc-hover-image-carousel\n (click)=\"clickCardEvent.emit()\"\n [images]=\"!isMobile ? getCardImagePreviewList(product) : [getCardImagePreview()]\"\n [isShowActions]=\"false\"\n class=\"size-24 shrink-0 cursor-pointer self-center\"\n />\n <div class=\"flex grow flex-col gap-1\">\n <sc-noindex-wrapper>\n <div\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B: {{ product.code }}\n </div>\n </sc-noindex-wrapper>\n\n <div class=\"flex flex-col gap-1\">\n <a\n tuiLink\n [attr.href]=\"href ?? null\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n (click)=\"$event.preventDefault(); clickCardEvent.emit()\"\n class=\"!text-body-m-bold\"\n >\n {{ product.name }}\n </a>\n\n <sc-noindex-wrapper>\n <span\n *ngIf=\"product.supplierSku\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044F: {{ product.supplierSku }}\n </span>\n\n <div\n *ngIf=\"product?.pack\"\n class=\"flex items-center gap-1 text-tui-text-02\"\n >\n \u041D\u043E\u0440\u043C\u0430 \u0443\u043F\u0430\u043A\u043E\u0432\u043A\u0438: {{ product.pack }}\n <tui-icon\n *ngIf=\"product.ignoreMinCountCheck\"\n icon=\"@tui.package\"\n [tuiHint]=\"minCountHint\"\n [tuiHintShowDelay]=\"100\"\n tuiHintDirection=\"top\"\n class=\"text-body-xl text-tui-text-01 opacity-90\"\n />\n <ng-template #minCountHint>\n \u0414\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0437\u0430\u043A\u0430\u0437 <br />\n \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u044C\u043D\u043E\u0433\u043E <br />\n \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430\n </ng-template>\n </div>\n </sc-noindex-wrapper>\n\n <sc-cost-with-discount [product]=\"product\" />\n\n <sc-noindex-wrapper>\n <sc-price-warehouse-stock [product]=\"product\" />\n </sc-noindex-wrapper>\n </div>\n </div>\n\n <sc-noindex-wrapper>\n <div class=\"flex w-40 shrink-0 flex-col justify-between\">\n <div class=\"flex justify-end\">\n <tui-avatar\n *ngIf=\"product.isPreviouslyOrdered\"\n src=\"@tui.history\"\n size=\"s\"\n [style.background]=\"'none'\"\n [style.color]=\"'var(--tui-text-action)'\"\n />\n <sc-favorite-button\n *ngIf=\"authStatus$ | async\"\n (clickEvent)=\"clickFavoriteEvent.emit()\"\n [showLoader]=\"favoriteShowLoader()\"\n [isFavorite]=\"product.isFavorite\"\n [disabled]=\"!!product.primaryCategory?.isFavorite\"\n />\n </div>\n <div class=\"flex gap-2\">\n <button\n *ngIf=\"!showQuantityControl\"\n tuiButton\n (click)=\"clickAddToCartEvent.emit(product)\"\n [loading]=\"showLoader()\"\n size=\"s\"\n iconStart=\"@tui.shopping-cart\"\n class=\"grow !font-extrabold\"\n >\n \u0412 \u043A\u043E\u0440\u0437\u0438\u043D\u0443\n </button>\n <sc-input-quantity\n #inputQuantity\n [tuiAutoFocus]=\"autoFocuseQuantityInput()\"\n *ngIf=\"showQuantityControl\"\n [formControl]=\"quantityControl\"\n size=\"m\"\n [step]=\"ScUnitsHelper.getProductMultiplicity(product)\"\n [ignoreStepValidators]=\"product.ignoreMinCountCheck\"\n [showLoader]=\"showLoader()\"\n (clickClearEvent)=\"clickClearEvent.emit(orderItem)\"\n (keydown.enter)=\"inputQuantity.nativeFocusableElement?.blur()\"\n class=\"w-full\"\n />\n <tui-avatar\n *ngIf=\"orderItem && !showQuantityControl\"\n src=\"@tui.check\"\n size=\"s\"\n [style.background]=\"'var(--tui-status-warning-pale)'\"\n [style.color]=\"'var(--tui-background-accent-1)'\"\n />\n </div>\n </div>\n </sc-noindex-wrapper>\n</div>\n\n<ng-template #skeleton>\n <div class=\"tui-skeleton flex h-[8.25rem] w-full overflow-hidden rounded-xl\"></div>\n</ng-template>\n", styles: [":host tui-badge{--t-padding: .25rem !important}:host .name{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4}:host .card-wrapper{font-size:.8125rem;line-height:1.25rem;font-weight:500}:host .card-wrapper .name,:host .card-wrapper .cost{font-size:.9375rem;line-height:1.5rem;font-weight:800}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2$2.AsyncPipe, name: "async" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiIcon, selector: "tui-icon", inputs: ["icon", "background"] }, { kind: "ngmodule", type: TuiTextfieldControllerModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.TuiHintDirective, selector: "[tuiHint]:not(ng-container):not(ng-template)", inputs: ["tuiHintContext", "tuiHintAppearance", "tuiHint"], outputs: ["tuiHintVisible"] }, { kind: "directive", type: TuiLink, selector: "a[tuiLink], button[tuiLink]", inputs: ["pseudo"] }, { kind: "directive", type: TuiHighlight, selector: "[tuiHighlight]", inputs: ["tuiHighlight", "tuiHighlightColor"] }, { kind: "directive", type: TuiAutoFocus, selector: "[tuiAutoFocus]", inputs: ["tuiAutoFocus"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "component", type: TuiAvatar, selector: "tui-avatar,button[tuiAvatar],a[tuiAvatar]", inputs: ["size", "round", "src"] }, { kind: "component", type: ScHoverImageCarouselComponent, selector: "sc-hover-image-carousel", inputs: ["images", "isShowActions", "productName"] }, { kind: "component", type: CostWithDiscountComponent, selector: "sc-cost-with-discount", inputs: ["product", "size"] }, { kind: "component", type: ScPriceWarehouseStockComponent, selector: "sc-price-warehouse-stock", inputs: ["classList", "product", "withStockHint", "fromMain"] }, { kind: "component", type: ScFavoriteButtonComponent, selector: "sc-favorite-button", inputs: ["isFavorite", "showLoader", "disabled"], outputs: ["clickEvent"] }, { kind: "component", type: ScInputQuantityComponent, selector: "sc-input-quantity", inputs: ["step", "showLoader", "showCross", "ignoreStepValidators", "appearance", "isDisabled", "size"], outputs: ["clickClearEvent"] }, { kind: "component", type: ScNoindexWrapperComponent, selector: "sc-noindex-wrapper" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5277
5330
  }
5278
5331
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScPriceCardInlineComponent, decorators: [{
5279
5332
  type: Component,
@@ -5297,7 +5350,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
5297
5350
  ScFavoriteButtonComponent,
5298
5351
  ScInputQuantityComponent,
5299
5352
  ScNoindexWrapperComponent,
5300
- ], template: "<div\n *ngIf=\"product; else skeleton\"\n class=\"card-wrapper relative flex w-full gap-4 rounded-xl p-1 hover:bg-tui-background-neutral-1\"\n>\n <sc-hover-image-carousel\n (click)=\"clickCardEvent.emit()\"\n [images]=\"!isMobile ? getCardImagePreviewList(product) : [getCardImagePreview()]\"\n [isShowActions]=\"false\"\n class=\"size-24 shrink-0 cursor-pointer self-center\"\n />\n <div class=\"flex grow flex-col gap-1\">\n <sc-noindex-wrapper>\n <div\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B: {{ product.code }}\n </div>\n </sc-noindex-wrapper>\n\n <div class=\"flex flex-col gap-1\">\n <a\n tuiLink\n [attr.href]=\"href ?? null\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n (click)=\"$event.preventDefault(); clickCardEvent.emit()\"\n class=\"!text-body-m-bold\"\n >\n {{ product.name }}\n </a>\n\n <sc-noindex-wrapper>\n <span\n *ngIf=\"product.supplierSku\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044F: {{ product.supplierSku }}\n </span>\n\n <div\n *ngIf=\"product?.pack\"\n class=\"flex items-center gap-1 text-tui-text-02\"\n >\n \u041D\u043E\u0440\u043C\u0430 \u0443\u043F\u0430\u043A\u043E\u0432\u043A\u0438: {{ product.pack }}\n <tui-icon\n *ngIf=\"product.ignoreMinCountCheck\"\n icon=\"@tui.package\"\n [tuiHint]=\"minCountHint\"\n [tuiHintShowDelay]=\"100\"\n tuiHintDirection=\"top\"\n class=\"text-body-xl text-tui-text-01 opacity-90\"\n />\n <ng-template #minCountHint>\n \u0414\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0437\u0430\u043A\u0430\u0437 <br />\n \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u044C\u043D\u043E\u0433\u043E <br />\n \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430\n </ng-template>\n </div>\n </sc-noindex-wrapper>\n\n <sc-cost-with-discount [product]=\"product\" />\n\n <sc-noindex-wrapper>\n <sc-price-warehouse-stock [product]=\"product\" />\n </sc-noindex-wrapper>\n </div>\n </div>\n\n <sc-noindex-wrapper>\n <div class=\"flex w-40 shrink-0 flex-col justify-between\">\n <div class=\"flex justify-end\">\n <tui-avatar\n *ngIf=\"product.isPreviouslyOrdered\"\n src=\"@tui.history\"\n size=\"s\"\n [style.background]=\"'none'\"\n [style.color]=\"'var(--tui-text-action)'\"\n />\n <sc-favorite-button\n *ngIf=\"authStatus$ | async\"\n (clickEvent)=\"clickFavoriteEvent.emit()\"\n [showLoader]=\"favoriteShowLoader()\"\n [isFavorite]=\"product.isFavorite\"\n [disabled]=\"!!product.primaryCategory?.isFavorite\"\n />\n </div>\n <div class=\"flex gap-2\">\n <button\n *ngIf=\"!showQuantityControl\"\n tuiButton\n (click)=\"clickAddToCartEvent.emit(product)\"\n [loading]=\"showLoader()\"\n size=\"s\"\n iconStart=\"@tui.shopping-cart\"\n class=\"grow !font-extrabold\"\n >\n \u0412 \u043A\u043E\u0440\u0437\u0438\u043D\u0443\n </button>\n <sc-input-quantity\n #inputQuantity\n [tuiAutoFocus]=\"autoFocuseQuantityInput()\"\n *ngIf=\"showQuantityControl\"\n [formControl]=\"quantityControl\"\n size=\"m\"\n [step]=\"unitsHelper.productMultiplicity(product)\"\n [ignoreStepValidators]=\"product.ignoreMinCountCheck\"\n [showLoader]=\"showLoader()\"\n (clickClearEvent)=\"clickClearEvent.emit(orderItem)\"\n (keydown.enter)=\"inputQuantity.nativeFocusableElement?.blur()\"\n class=\"w-full\"\n />\n <tui-avatar\n *ngIf=\"orderItem && !showQuantityControl\"\n src=\"@tui.check\"\n size=\"s\"\n [style.background]=\"'var(--tui-status-warning-pale)'\"\n [style.color]=\"'var(--tui-background-accent-1)'\"\n />\n </div>\n </div>\n </sc-noindex-wrapper>\n</div>\n\n<ng-template #skeleton>\n <div class=\"tui-skeleton flex h-[8.25rem] w-full overflow-hidden rounded-xl\"></div>\n</ng-template>\n", styles: [":host tui-badge{--t-padding: .25rem !important}:host .name{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4}:host .card-wrapper{font-size:.8125rem;line-height:1.25rem;font-weight:500}:host .card-wrapper .name,:host .card-wrapper .cost{font-size:.9375rem;line-height:1.5rem;font-weight:800}\n"] }]
5353
+ ], template: "<div\n *ngIf=\"product; else skeleton\"\n class=\"card-wrapper relative flex w-full gap-4 rounded-xl p-1 hover:bg-tui-background-neutral-1\"\n>\n <sc-hover-image-carousel\n (click)=\"clickCardEvent.emit()\"\n [images]=\"!isMobile ? getCardImagePreviewList(product) : [getCardImagePreview()]\"\n [isShowActions]=\"false\"\n class=\"size-24 shrink-0 cursor-pointer self-center\"\n />\n <div class=\"flex grow flex-col gap-1\">\n <sc-noindex-wrapper>\n <div\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B: {{ product.code }}\n </div>\n </sc-noindex-wrapper>\n\n <div class=\"flex flex-col gap-1\">\n <a\n tuiLink\n [attr.href]=\"href ?? null\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n (click)=\"$event.preventDefault(); clickCardEvent.emit()\"\n class=\"!text-body-m-bold\"\n >\n {{ product.name }}\n </a>\n\n <sc-noindex-wrapper>\n <span\n *ngIf=\"product.supplierSku\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044F: {{ product.supplierSku }}\n </span>\n\n <div\n *ngIf=\"product?.pack\"\n class=\"flex items-center gap-1 text-tui-text-02\"\n >\n \u041D\u043E\u0440\u043C\u0430 \u0443\u043F\u0430\u043A\u043E\u0432\u043A\u0438: {{ product.pack }}\n <tui-icon\n *ngIf=\"product.ignoreMinCountCheck\"\n icon=\"@tui.package\"\n [tuiHint]=\"minCountHint\"\n [tuiHintShowDelay]=\"100\"\n tuiHintDirection=\"top\"\n class=\"text-body-xl text-tui-text-01 opacity-90\"\n />\n <ng-template #minCountHint>\n \u0414\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0437\u0430\u043A\u0430\u0437 <br />\n \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u044C\u043D\u043E\u0433\u043E <br />\n \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430\n </ng-template>\n </div>\n </sc-noindex-wrapper>\n\n <sc-cost-with-discount [product]=\"product\" />\n\n <sc-noindex-wrapper>\n <sc-price-warehouse-stock [product]=\"product\" />\n </sc-noindex-wrapper>\n </div>\n </div>\n\n <sc-noindex-wrapper>\n <div class=\"flex w-40 shrink-0 flex-col justify-between\">\n <div class=\"flex justify-end\">\n <tui-avatar\n *ngIf=\"product.isPreviouslyOrdered\"\n src=\"@tui.history\"\n size=\"s\"\n [style.background]=\"'none'\"\n [style.color]=\"'var(--tui-text-action)'\"\n />\n <sc-favorite-button\n *ngIf=\"authStatus$ | async\"\n (clickEvent)=\"clickFavoriteEvent.emit()\"\n [showLoader]=\"favoriteShowLoader()\"\n [isFavorite]=\"product.isFavorite\"\n [disabled]=\"!!product.primaryCategory?.isFavorite\"\n />\n </div>\n <div class=\"flex gap-2\">\n <button\n *ngIf=\"!showQuantityControl\"\n tuiButton\n (click)=\"clickAddToCartEvent.emit(product)\"\n [loading]=\"showLoader()\"\n size=\"s\"\n iconStart=\"@tui.shopping-cart\"\n class=\"grow !font-extrabold\"\n >\n \u0412 \u043A\u043E\u0440\u0437\u0438\u043D\u0443\n </button>\n <sc-input-quantity\n #inputQuantity\n [tuiAutoFocus]=\"autoFocuseQuantityInput()\"\n *ngIf=\"showQuantityControl\"\n [formControl]=\"quantityControl\"\n size=\"m\"\n [step]=\"ScUnitsHelper.getProductMultiplicity(product)\"\n [ignoreStepValidators]=\"product.ignoreMinCountCheck\"\n [showLoader]=\"showLoader()\"\n (clickClearEvent)=\"clickClearEvent.emit(orderItem)\"\n (keydown.enter)=\"inputQuantity.nativeFocusableElement?.blur()\"\n class=\"w-full\"\n />\n <tui-avatar\n *ngIf=\"orderItem && !showQuantityControl\"\n src=\"@tui.check\"\n size=\"s\"\n [style.background]=\"'var(--tui-status-warning-pale)'\"\n [style.color]=\"'var(--tui-background-accent-1)'\"\n />\n </div>\n </div>\n </sc-noindex-wrapper>\n</div>\n\n<ng-template #skeleton>\n <div class=\"tui-skeleton flex h-[8.25rem] w-full overflow-hidden rounded-xl\"></div>\n</ng-template>\n", styles: [":host tui-badge{--t-padding: .25rem !important}:host .name{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4}:host .card-wrapper{font-size:.8125rem;line-height:1.25rem;font-weight:500}:host .card-wrapper .name,:host .card-wrapper .cost{font-size:.9375rem;line-height:1.5rem;font-weight:800}\n"] }]
5301
5354
  }] });
5302
5355
 
5303
5356
  /**
@@ -5600,6 +5653,60 @@ const SC_CATALOG_PRODUCTS_FILTERS = new InjectionToken('SC_CATALOG_PRODUCTS_FILT
5600
5653
  */
5601
5654
  const SC_CATALOG_SHOW_PRODUCTS_RECURSIVELY = new InjectionToken('SC_CATALOG_SHOW_PRODUCTS_RECURSIVELY');
5602
5655
 
5656
+ /**
5657
+ * Контейнер сворачивания для длинного списка вариантов фильтра.
5658
+ *
5659
+ * Когда число элементов превышает порог: свёрнут — fade с обрезкой, развёрнут — scrollbar.
5660
+ * Иначе рендерит контент без обёртки и кнопки переключения.
5661
+ *
5662
+ * Контент проецируется как `<ng-template>` — это сохраняет инжектор `ControlContainer`
5663
+ * родителя для `formControlName`/`formGroupName` внутри проецируемого фрагмента.
5664
+ */
5665
+ class ScCatalogFilterCollapsibleComponent {
5666
+ constructor() {
5667
+ /**
5668
+ * Число элементов содержимого, по которому решается необходимость сворачивания.
5669
+ */
5670
+ this.itemsCount = input.required();
5671
+ /**
5672
+ * Показывать ли кнопку сброса значений группы.
5673
+ */
5674
+ this.showReset = input(false);
5675
+ /**
5676
+ * Событие нажатия на кнопку сброса группы.
5677
+ */
5678
+ this.resetGroup = output();
5679
+ /**
5680
+ * Проецируемое содержимое (объявляется в шаблоне родителя как `<ng-template>`).
5681
+ */
5682
+ this.contentTpl = contentChild.required(TemplateRef);
5683
+ /**
5684
+ * Развёрнут ли список.
5685
+ */
5686
+ this.isExpanded = signal(false);
5687
+ /**
5688
+ * Нужно ли сворачивание для текущего числа элементов.
5689
+ */
5690
+ this.isCollapsible = computed(() => this.itemsCount() > ScCatalogFilterCollapsibleComponent.COLLAPSE_THRESHOLD);
5691
+ }
5692
+ /**
5693
+ * Порог числа вариантов, после которого включается сворачивание с {@link TuiFade}.
5694
+ */
5695
+ static { this.COLLAPSE_THRESHOLD = 5; }
5696
+ /**
5697
+ * Переключает развёрнутость списка.
5698
+ */
5699
+ toggle() {
5700
+ this.isExpanded.update((value) => !value);
5701
+ }
5702
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScCatalogFilterCollapsibleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5703
+ 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 }); }
5704
+ }
5705
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScCatalogFilterCollapsibleComponent, decorators: [{
5706
+ type: Component,
5707
+ 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"] }]
5708
+ }] });
5709
+
5603
5710
  /* eslint-disable class-methods-use-this */
5604
5711
  /**
5605
5712
  * Компонент вывода фильтров каталога.
@@ -5610,9 +5717,9 @@ class ScCatalogFiltersComponent {
5610
5717
  */
5611
5718
  constructor() {
5612
5719
  /**
5613
- * Состояние открытия accordion.
5720
+ * Подписки синхронизации контролов формы (range slider, single-select checkbox).
5614
5721
  */
5615
- this.isOpenAccordion = input(false);
5722
+ this.formSyncs = new Subscription();
5616
5723
  /**
5617
5724
  * Сервис для работы с фильтрами каталога.
5618
5725
  */
@@ -5630,16 +5737,33 @@ class ScCatalogFiltersComponent {
5630
5737
  */
5631
5738
  this.isRecursively = inject(SC_CATALOG_SHOW_PRODUCTS_RECURSIVELY);
5632
5739
  /**
5633
- * {@link Observable} фильтров категории.
5740
+ * Показывать ли кнопку «Показать результаты».
5634
5741
  */
5635
- 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) => {
5636
- this.updateFormControls(filters);
5637
- }), share()));
5742
+ this.showResultsButton = input(false);
5743
+ /**
5744
+ * Событие нажатия на кнопку сброса всех фильтров.
5745
+ */
5746
+ this.resetFilters = output();
5747
+ /**
5748
+ * Событие нажатия на кнопку показа результатов.
5749
+ */
5750
+ this.showResults = output();
5638
5751
  /**
5639
5752
  * FormGroup для фильтров.
5640
5753
  */
5641
5754
  this.form = new FormGroup({});
5642
- this.form.valueChanges.pipe(takeUntilDestroyed()).subscribe((filters) => {
5755
+ /**
5756
+ * {@link Observable} фильтров категории.
5757
+ */
5758
+ 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
5759
+ .filter((item) => item.type !== 'range' || item.min !== item.max)
5760
+ .map((item) => (item.type === 'checkbox' ? { ...item, values: [...item.values].sort((a, b) => a.label.localeCompare(b.label)) } : item))), tap((filters) => {
5761
+ this.updateFormControls(filters);
5762
+ }), share()));
5763
+ inject(DestroyRef).onDestroy(() => {
5764
+ this.formSyncs.unsubscribe();
5765
+ });
5766
+ this.form.valueChanges.pipe(debounceTime(0), takeUntilDestroyed()).subscribe((filters) => {
5643
5767
  this.catalogProductsFilters$.next(this.buildPropertyFilters(filters));
5644
5768
  });
5645
5769
  }
@@ -5649,17 +5773,28 @@ class ScCatalogFiltersComponent {
5649
5773
  * @param filters Массив фильтров для создания контролов.
5650
5774
  */
5651
5775
  updateFormControls(filters) {
5776
+ this.formSyncs.unsubscribe();
5777
+ this.formSyncs = new Subscription();
5652
5778
  Object.keys(this.form.controls).forEach((key) => {
5653
5779
  this.form.removeControl(key, { emitEvent: false });
5654
5780
  });
5655
5781
  filters.forEach((item) => {
5656
5782
  switch (item.type) {
5657
- case 'checkbox':
5658
- this.form.addControl(item.id, this.createCheckboxFormControl(item), { emitEvent: false });
5783
+ case 'checkbox': {
5784
+ const checkboxControl = this.createCheckboxFormControl(item);
5785
+ this.form.addControl(item.id, checkboxControl, { emitEvent: false });
5786
+ // Single-select для !isMultiple: при выборе одного остальные снимаются.
5787
+ if (!item.isMultiple && item.values.length > 1) {
5788
+ this.formSyncs.add(this.syncSingleSelectCheckbox(checkboxControl));
5789
+ }
5659
5790
  break;
5660
- case 'range':
5661
- this.form.addControl(item.id, this.createRangeFormControl(item), { emitEvent: false });
5791
+ }
5792
+ case 'range': {
5793
+ const rangeControl = this.createRangeFormControl(item);
5794
+ this.form.addControl(item.id, rangeControl, { emitEvent: false });
5795
+ this.formSyncs.add(this.syncRangeFromToAndSlider(rangeControl));
5662
5796
  break;
5797
+ }
5663
5798
  case 'toggle':
5664
5799
  this.form.addControl(item.id, this.createToggleFormControl(item), { emitEvent: false });
5665
5800
  break;
@@ -5683,7 +5818,7 @@ class ScCatalogFiltersComponent {
5683
5818
  }
5684
5819
  switch (filterItem.type) {
5685
5820
  case 'checkbox':
5686
- this.processCheckboxFilter(result, filterItem.id, controlValue);
5821
+ this.processCheckboxFilter(result, filterItem, controlValue);
5687
5822
  break;
5688
5823
  case 'range':
5689
5824
  this.processRangeFilter(result, filterItem.id, controlValue);
@@ -5698,31 +5833,107 @@ class ScCatalogFiltersComponent {
5698
5833
  return result;
5699
5834
  }
5700
5835
  /**
5701
- * Создает контрол формы для фильтра типа checkbox.
5836
+ * Создаёт FormGroup для checkbox: на каждый {@code value.id} — булевый контрол.
5702
5837
  *
5703
- * Если `isMultiple === false` возвращает {@link FormControl} строкового идентификатора (логика radio),
5704
- * иначе {@link FormGroup} независимых булевых контролов по идентификаторам значений.
5838
+ * Единый формат и для одного, и для множества значений: шаблон рендерит их одинаково.
5839
+ * Различие в API-выводе для одиночного значения (boolean вместо массива) обрабатывается в {@link processCheckboxFilter}.
5705
5840
  *
5706
5841
  * @param checkboxFilter Фильтр типа checkbox.
5707
5842
  */
5708
5843
  createCheckboxFormControl(checkboxFilter) {
5709
- if (!checkboxFilter.isMultiple) {
5710
- return new FormControl(null);
5711
- }
5844
+ const isSelected = (id) => checkboxFilter.selectedValues?.includes(id) ?? false;
5712
5845
  const controls = {};
5713
5846
  checkboxFilter.values.forEach((value) => {
5714
- controls[value.id] = new FormControl(false, { nonNullable: true });
5847
+ controls[value.id] = new FormControl(isSelected(value.id), { nonNullable: true });
5715
5848
  });
5716
5849
  return new FormGroup(controls);
5717
5850
  }
5718
5851
  /**
5719
- * Создает FormControl для range.
5852
+ * Создаёт {@link FormGroup} для range: {@code from}, {@code to}, {@code slider} (кортеж для {@link TuiRange}).
5720
5853
  *
5721
5854
  * @param rangeFilter Фильтр типа range.
5722
5855
  */
5723
5856
  createRangeFormControl(rangeFilter) {
5724
- // TODO: Добавить updateOn: 'blur' после исправления бага в taiga-ui.
5725
- return new FormControl([Number(rangeFilter.selectedMin ?? rangeFilter.min), Number(rangeFilter.selectedMax ?? rangeFilter.max)], { nonNullable: true });
5857
+ const fromValue = Number(rangeFilter.selectedMin ?? rangeFilter.min);
5858
+ const toValue = Number(rangeFilter.selectedMax ?? rangeFilter.max);
5859
+ return new FormGroup({
5860
+ from: new FormControl(fromValue, { nonNullable: true }),
5861
+ to: new FormControl(toValue, { nonNullable: true }),
5862
+ slider: new FormControl([fromValue, toValue], { nonNullable: true }),
5863
+ });
5864
+ }
5865
+ /**
5866
+ * Реализует single-select поведение для FormGroup с булевыми контролами:
5867
+ * при появлении нового true остальные контролы группы сбрасываются в false.
5868
+ *
5869
+ * Сохраняет последнее «стабильное» состояние и сравнивает следующее значение с ним —
5870
+ * новый true (отсутствовал в prev) считается выбранным, остальные сбрасываются через setValue.
5871
+ *
5872
+ * @param group FormGroup checkbox-фильтра (id → boolean).
5873
+ */
5874
+ syncSingleSelectCheckbox(group) {
5875
+ let previousState = group.getRawValue();
5876
+ return group.valueChanges.subscribe((value) => {
5877
+ const current = value;
5878
+ const newlyChecked = Object.entries(current).find(([id, isChecked]) => {
5879
+ // eslint-disable-next-line security/detect-object-injection
5880
+ return isChecked && !previousState[id];
5881
+ })?.[0];
5882
+ if (!newlyChecked) {
5883
+ previousState = { ...current };
5884
+ return;
5885
+ }
5886
+ const next = {};
5887
+ Object.keys(group.controls).forEach((id) => {
5888
+ // eslint-disable-next-line security/detect-object-injection
5889
+ next[id] = id === newlyChecked;
5890
+ });
5891
+ previousState = next;
5892
+ group.setValue(next);
5893
+ });
5894
+ }
5895
+ /**
5896
+ * Связывает поля «от»/«до» с контролом слайдера.
5897
+ *
5898
+ * @param group FormGroup range-фильтра.
5899
+ */
5900
+ syncRangeFromToAndSlider(group) {
5901
+ const from = group.get('from');
5902
+ const to = group.get('to');
5903
+ const slider = group.get('slider');
5904
+ if (!from || !to || !slider) {
5905
+ return new Subscription();
5906
+ }
5907
+ const sub = new Subscription();
5908
+ // Инпуты → слайдер; если «от» > «до», поднимаем «до» до «от».
5909
+ const applySliderFromInputs = () => {
5910
+ const low = Number(from.value);
5911
+ let high = Number(to.value);
5912
+ if (low > high) {
5913
+ high = low;
5914
+ to.setValue(high, { emitEvent: false });
5915
+ }
5916
+ const currentPair = slider.value;
5917
+ if (currentPair[0] !== low || currentPair[1] !== high) {
5918
+ slider.setValue([low, high], { emitEvent: false });
5919
+ slider.markAsDirty();
5920
+ }
5921
+ };
5922
+ sub.add(merge(from.valueChanges, to.valueChanges).subscribe(applySliderFromInputs));
5923
+ sub.add(slider.valueChanges.subscribe((value) => {
5924
+ const [low, high] = value;
5925
+ if (from.value !== low) {
5926
+ from.setValue(low, { emitEvent: false });
5927
+ from.markAsDirty();
5928
+ }
5929
+ if (to.value !== high) {
5930
+ to.setValue(high, { emitEvent: false });
5931
+ to.markAsDirty();
5932
+ }
5933
+ }));
5934
+ // Совпасть с полями при первом показе (уже совпадает при создании, но на всякий случай).
5935
+ applySliderFromInputs();
5936
+ return sub;
5726
5937
  }
5727
5938
  /**
5728
5939
  * Создает FormControl для toggle.
@@ -5733,45 +5944,36 @@ class ScCatalogFiltersComponent {
5733
5944
  return new FormControl(toggleFilter.selectedValue ?? false, { nonNullable: true });
5734
5945
  }
5735
5946
  /**
5736
- * Обрабатывает checkbox фильтр.
5947
+ * Обрабатывает checkbox: FormGroup → string[] выбранных id; для единственного значения — boolean (как toggle).
5737
5948
  *
5738
5949
  * @param result Объект результата для заполнения.
5739
- * @param filterId Идентификатор фильтра.
5740
- * @param controlValue Значение контрола формы.
5950
+ * @param checkboxFilter Метафильтр checkbox.
5951
+ * @param controlValue Значение контрола формы (запись id → boolean).
5741
5952
  */
5742
- processCheckboxFilter(result, filterId, controlValue) {
5743
- // Для isMultiple === false: FormControl<string | null> -> string[] из одного выбранного ID.
5744
- if (typeof controlValue === 'string') {
5745
- if (controlValue) {
5746
- // eslint-disable-next-line security/detect-object-injection, no-param-reassign
5747
- result[filterId] = [controlValue];
5748
- }
5749
- return;
5750
- }
5751
- // Для checkbox: FormGroup с FormControl<boolean> -> string[] (массив ID выбранных значений).
5953
+ processCheckboxFilter(result, checkboxFilter, controlValue) {
5752
5954
  const selectedIds = Object.entries(controlValue)
5753
5955
  .filter(([, isSelected]) => isSelected)
5754
5956
  .map(([id]) => id);
5755
- if (selectedIds.length > 0) {
5756
- // eslint-disable-next-line security/detect-object-injection, no-param-reassign
5757
- result[filterId] = selectedIds;
5957
+ if (selectedIds.length === 0) {
5958
+ return;
5758
5959
  }
5960
+ // eslint-disable-next-line security/detect-object-injection, no-param-reassign
5961
+ result[checkboxFilter.id] = selectedIds;
5759
5962
  }
5760
5963
  /**
5761
5964
  * Обрабатывает range фильтр.
5762
5965
  *
5763
5966
  * @param result Объект результата для заполнения.
5764
5967
  * @param filterId Идентификатор фильтра.
5765
- * @param controlValue Значение контрола формы.
5766
- * @param controlValue.0 Начальное значение диапазона.
5767
- * @param controlValue.1 Конечное значение диапазона.
5968
+ * @param range Значение контрола формы (объект с границами).
5969
+ * @param range.from Начальное значение диапазона.
5970
+ * @param range.to Конечное значение диапазона.
5768
5971
  */
5769
- processRangeFilter(result, filterId, [from, to]) {
5770
- // Для range: FormControl<[number, number]> -> { from?: string; to?: string; }
5972
+ processRangeFilter(result, filterId, range) {
5771
5973
  // eslint-disable-next-line security/detect-object-injection, no-param-reassign
5772
5974
  result[filterId] = {
5773
- from: String(from),
5774
- to: String(to),
5975
+ from: String(range.from),
5976
+ to: String(range.to),
5775
5977
  };
5776
5978
  }
5777
5979
  /**
@@ -5782,18 +5984,111 @@ class ScCatalogFiltersComponent {
5782
5984
  * @param controlValue Значение контрола формы.
5783
5985
  */
5784
5986
  processToggleFilter(result, filterId, controlValue) {
5785
- // Для toggle: FormControl<boolean> -> boolean
5786
5987
  if (controlValue) {
5787
5988
  // eslint-disable-next-line security/detect-object-injection, no-param-reassign
5788
5989
  result[filterId] = controlValue;
5789
5990
  }
5790
5991
  }
5992
+ /**
5993
+ * Сбрасывает поле «от» диапазона к минимальному значению фильтра.
5994
+ *
5995
+ * @param filterId Идентификатор фильтра.
5996
+ * @param min Минимальное значение диапазона.
5997
+ */
5998
+ resetRangeFrom(filterId, min) {
5999
+ this.form.get(filterId)?.get('from')?.reset(+min);
6000
+ }
6001
+ /**
6002
+ * Сбрасывает поле «до» диапазона к максимальному значению фильтра.
6003
+ *
6004
+ * @param filterId Идентификатор фильтра.
6005
+ * @param max Максимальное значение диапазона.
6006
+ */
6007
+ resetRangeTo(filterId, max) {
6008
+ this.form.get(filterId)?.get('to')?.reset(+max);
6009
+ }
6010
+ /**
6011
+ * Сбрасывает все чекбоксы группы в `false`.
6012
+ *
6013
+ * @param filterId Идентификатор фильтра (ключ FormGroup в форме).
6014
+ */
6015
+ resetCheckboxGroup(filterId) {
6016
+ const group = this.form.get(filterId);
6017
+ if (!group) {
6018
+ return;
6019
+ }
6020
+ const resetValue = {};
6021
+ Object.keys(group.controls).forEach((id) => {
6022
+ // eslint-disable-next-line security/detect-object-injection
6023
+ resetValue[id] = false;
6024
+ });
6025
+ group.reset(resetValue);
6026
+ }
6027
+ /**
6028
+ * Сбрасывает все фильтры и оповещает родителя о нажатии кнопки сброса.
6029
+ */
6030
+ onResetFiltersClick() {
6031
+ this.resetAllFilters();
6032
+ this.resetFilters.emit();
6033
+ }
6034
+ /**
6035
+ * Оповещает родителя о нажатии кнопки показа результатов.
6036
+ */
6037
+ onShowResultsClick() {
6038
+ this.showResults.emit();
6039
+ }
6040
+ /**
6041
+ * Сбрасывает все фильтры к исходным значениям.
6042
+ */
6043
+ resetAllFilters() {
6044
+ this.filters()?.forEach((filterItem) => {
6045
+ const control = this.form.get(filterItem.id);
6046
+ if (!control) {
6047
+ return;
6048
+ }
6049
+ switch (filterItem.type) {
6050
+ case 'checkbox': {
6051
+ const group = control;
6052
+ const resetValue = {};
6053
+ Object.keys(group.controls).forEach((id) => {
6054
+ // eslint-disable-next-line security/detect-object-injection
6055
+ resetValue[id] = false;
6056
+ });
6057
+ group.reset(resetValue);
6058
+ break;
6059
+ }
6060
+ case 'toggle':
6061
+ control.reset(false);
6062
+ break;
6063
+ case 'range': {
6064
+ const group = control;
6065
+ const min = +filterItem.min;
6066
+ const max = +filterItem.max;
6067
+ group.reset({ from: min, to: max, slider: [min, max] });
6068
+ break;
6069
+ }
6070
+ default:
6071
+ break;
6072
+ }
6073
+ });
6074
+ }
5791
6075
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScCatalogFiltersComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5792
- 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 }); }
6076
+ 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 }); }
5793
6077
  }
5794
6078
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScCatalogFiltersComponent, decorators: [{
5795
6079
  type: Component,
5796
- 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"] }]
6080
+ args: [{ standalone: true, selector: 'sc-catalog-filters', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
6081
+ ReactiveFormsModule,
6082
+ TuiTextfield,
6083
+ ScSelectOnFocusinDirective,
6084
+ ScCatalogFilterCollapsibleComponent,
6085
+ TuiLabel,
6086
+ TuiNumberFormat,
6087
+ TuiCheckbox,
6088
+ TuiInputNumber,
6089
+ TuiRange,
6090
+ TuiButton,
6091
+ ], 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"] }]
5797
6092
  }], ctorParameters: () => [] });
5798
6093
 
5799
6094
  /* eslint-disable @typescript-eslint/unbound-method */
@@ -6674,7 +6969,7 @@ class ScSandwichM2Component {
6674
6969
  stringify: signal((x) => x.name),
6675
6970
  identityMatcher: signal((a, b) => a.id === b.id),
6676
6971
  }),
6677
- ], ngImport: i0, template: "@if (!orderItem() && settings()?.allowShowTable) {\n <div class=\"mb-5 flex justify-center\">\n <button\n tuiButton\n appearance=\"secondary\"\n (click)=\"toggleShowEvent.emit()\"\n type=\"button\"\n iconStart=\"@tui.layout-list\"\n >\n \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0432 \u0432\u0438\u0434\u0435 \u0441\u043F\u0438\u0441\u043A\u0430\n </button>\n </div>\n}\n<div class=\"\">\n @let products = products$ | async;\n @let productValue = product.value;\n\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit()\"\n ScNextInputFocus\n class=\"flex flex-col gap-2\"\n >\n <label\n tuiLabel\n class=\"grow\"\n >\n \u0422\u043E\u0432\u0430\u0440\n <tui-textfield\n tuiChevron\n [tuiTextfieldCleaner]=\"false\"\n >\n <input\n tuiChevron\n tuiSelect\n [formControl]=\"product\"\n placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043C\u0430\u0442\u0435\u0440\u0438\u0430\u043B\"\n />\n\n <tui-data-list-wrapper\n *tuiTextfieldDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n <tui-error\n [formControl]=\"product\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n @if (productValue && productValue.costRub !== undefined) {\n <div class=\"-mt-1 text-sm text-tui-text-secondary\">\n <span class=\"font-bold\">{{ productValue.code }}</span>\n \u2014\n {{ productValue.costRub.toLocaleString() }} {{ productValue.currency.symbol }}/\u043C\u00B2\n </div>\n }\n\n @if (productValue) {\n <div class=\"mt-4 flex flex-col gap-1.5\">\n <div class=\"w-full font-bold\">\u0420\u0430\u0437\u043C\u0435\u0440\u044B \u0438\u0437\u0434\u0435\u043B\u0438\u0439</div>\n <div class=\"flex flex-col gap-1 text-sm text-tui-text-secondary\">\n @let wt = widthRangeText();\n @let lt = lengthRangeText();\n @if (wt) {\n <div>\u0428\u0438\u0440\u0438\u043D\u0430 {{ wt }}.</div>\n }\n @if (lt) {\n <div>\u0414\u043B\u0438\u043D\u0430 {{ lt }}.</div>\n }\n </div>\n </div>\n }\n\n <div class=\"flex flex-col gap-3\">\n <div\n formArrayName=\"items\"\n class=\"flex flex-col gap-3\"\n >\n @for (item of items.controls; track item) {\n @if ($index > 0) {\n <hr class=\"border-sc-grey h-px\" />\n }\n @let itemIndex = $index;\n <div\n class=\"relative flex flex-col gap-1\"\n [formGroupName]=\"itemIndex\"\n >\n @if (isItemLocked(itemIndex)) {\n <div class=\"pointer-events-none absolute right-3 bottom-0 z-10 flex size-8 items-center justify-center\">\n <tui-icon\n icon=\"@tui.check\"\n class=\"text-tui-status-positive\"\n />\n </div>\n }\n <tui-loader [showLoader]=\"isItemLoading(itemIndex)\">\n <div\n [class.opacity-70]=\"isItemLocked(itemIndex)\"\n class=\"flex min-w-0 items-start gap-2\"\n >\n <div class=\"flex min-w-0 flex-1 flex-col gap-3\">\n <div class=\"flex flex-col gap-3 lg:!flex-row lg:!items-start lg:!gap-6\">\n <!-- \u0413\u0440\u0443\u043F\u043F\u0430 1: \u0448\u0438\u0440\u0438\u043D\u0430 + \u0434\u043B\u0438\u043D\u0430 -->\n <div class=\"grid grid-cols-1 gap-2 sm:grid-cols-2 lg:!flex-[2]\">\n <label tuiLabel>\n \u0428\u0438\u0440\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"width\"\n [min]=\"settings()?.minWidth ?? 0\"\n [max]=\"product.value?.properties?.width ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u0428\u0438\u0440\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n <tui-error\n formControlName=\"width\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u0414\u043B\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"length\"\n [min]=\"settings()?.minLength ?? 0\"\n [max]=\"product.value?.properties?.length ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u0414\u043B\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n <tui-error\n formControlName=\"length\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n\n <!-- \u0413\u0440\u0443\u043F\u043F\u0430 2: \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E + \u043C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430 (\u043D\u0430 lg 1fr | 2fr) -->\n <div class=\"grid grid-cols-1 gap-2 sm:grid-cols-2 lg:!grid-cols-[1fr_2fr] lg:!flex-[3]\">\n <label tuiLabel>\n <span class=\"whitespace-nowrap\">\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E, \u0448\u0442</span>\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n tuiInputNumber\n formControlName=\"count\"\n [min]=\"1\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"count\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\n <tui-textfield>\n <input\n tuiTextfield\n formControlName=\"marker\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"marker\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n </div>\n\n @let rowVal = item.getRawValue();\n\n @if (rowVal.width > 0 && rowVal.length > 0) {\n <div class=\"mt-1 flex flex-col gap-y-1 text-sm lg:!flex-row lg:!gap-6\">\n @if (pieceAreaM2(rowVal) > 0) {\n <div class=\"lg:!flex-[2]\">\n \u041F\u043B\u043E\u0449\u0430\u0434\u044C (S) =\n <span class=\"font-bold\">{{ pieceAreaM2(rowVal) | number: '1.0-4' }} \u043C\u00B2</span>\n </div>\n }\n @if (productValue && rowCost(rowVal) > 0) {\n <div class=\"lg:!flex-[3]\">\n \u0418\u0442\u043E\u0433\u043E:\n <span class=\"font-bold\">{{ rowCost(rowVal).toLocaleString() }} {{ productValue.currency.symbol }}</span>\n </div>\n }\n </div>\n }\n </div>\n\n @if (!isEditingExistingItem()) {\n <button\n tuiIconButton\n title=\"\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\"\n (click)=\"removeItem(itemIndex)\"\n [disabled]=\"items.length <= 1 || !product.value || isItemLoading(itemIndex)\"\n size=\"m\"\n type=\"button\"\n iconStart=\"@tui.trash-2\"\n appearance=\"secondary\"\n class=\"mt-6 shrink-0 lg:!ml-4\"\n [style.flex]=\"'0 0 auto'\"\n ></button>\n }\n </div>\n </tui-loader>\n </div>\n }\n </div>\n\n @if (productValue) {\n <hr class=\"border-sc-grey h-px\" />\n <div class=\"flex flex-wrap items-end gap-4 pt-2\">\n @if (!isEditingExistingItem()) {\n <button\n tuiButton\n appearance=\"secondary\"\n [disabled]=\"!product.value || items.invalid\"\n (click)=\"addItem()\"\n type=\"button\"\n class=\"self-start\"\n iconStart=\"@tui.plus\"\n >\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\n </button>\n }\n\n <div class=\"ml-auto min-w-0 gap-1 text-right\">\n @if (totalAreaM2() > 0) {\n <div>\n \u041E\u0431\u0449\u0430\u044F \u043F\u043B\u043E\u0449\u0430\u0434\u044C:\n <span class=\"font-bold\">{{ totalAreaM2() | number: '1.0-4' }} \u043C\u00B2</span>\n </div>\n }\n @if (productValue.costRub && totalCost() > 0) {\n <div>\n \u0418\u0442\u043E\u0433\u043E:\n <span class=\"whitespace-nowrap text-xl font-bold\"> {{ totalCost().toLocaleString() }} {{ productValue.currency.symbol }} </span>\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n <tui-error [error]=\"[] | tuiFieldError | async\" />\n\n <button\n type=\"submit\"\n [disabled]=\"form.invalid || isSubmitLoading() || hasNoPendingItems()\"\n [loading]=\"isSubmitLoading()\"\n tuiButton\n class=\"self-start\"\n iconStart=\"@tui.check\"\n >\n {{ !orderItem() ? '\u0412 \u043A\u043E\u0440\u0437\u0438\u043D\u0443' : '\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C' }}\n </button>\n </form>\n</div>\n", styles: [":host{display:block;width:100%;max-width:36rem}.row-summary{color:var(--tui-text-secondary);font-size:.75rem}\n"], dependencies: [{ kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["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: i1$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: ScNextInputFocusModule }, { kind: "directive", type: ScNextInputFocusDirective, selector: "form[ScNextInputFocus]" }, { kind: "directive", type: TuiLabel, selector: "label[tuiLabel]" }, { kind: "component", type: TuiDataListWrapperComponent, selector: "tui-data-list-wrapper:not([labels]), tui-data-list-wrapper:not([labels])[new]", inputs: ["items", "disabledItemHandler", "emptyContent", "size", "itemContent"], outputs: ["itemClick"] }, { kind: "component", type: TuiError, selector: "tui-error", inputs: ["error"] }, { kind: "component", type: i1$2.TuiTextfieldComponent, selector: "tui-textfield:not([multi])" }, { kind: "directive", type: i1$2.TuiTextfieldDirective, selector: "input[tuiTextfield]:not([tuiInputCard]):not([tuiInputExpire]):not([tuiInputCVC])" }, { kind: "directive", type: i1$2.TuiTextfieldOptionsDirective, selector: "[tuiTextfieldAppearance],[tuiTextfieldSize],[tuiTextfieldCleaner]", inputs: ["tuiTextfieldAppearance", "tuiTextfieldSize", "tuiTextfieldCleaner"] }, { kind: "directive", type: i1$2.TuiTextfieldDropdownDirective, selector: "ng-template[tuiTextfieldDropdown]" }, { kind: "directive", type: TuiChevron, selector: "[tuiChevron]", inputs: ["tuiChevron"] }, { kind: "directive", type: i2$1.TuiSelectDirective, selector: "input[tuiSelect]" }, { kind: "directive", type: i2$1.TuiInputNumberDirective, selector: "input[tuiInputNumber]", inputs: ["min", "max", "prefix", "postfix"] }, { kind: "directive", type: TuiNumberFormat, selector: "[tuiNumberFormat]", inputs: ["tuiNumberFormat"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DecimalPipe, name: "number" }, { kind: "pipe", type: TuiFieldErrorPipe, name: "tuiFieldError" }, { kind: "component", type: i5$2.TuiSliderComponent, selector: "input[type=range][tuiSlider]", inputs: ["size", "segments"] }, { kind: "directive", type: i2$1.TuiInputSliderDirective, selector: "input[tuiInputSlider]" }, { 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: TuiLoader, selector: "tui-loader", inputs: ["size", "inheritColor", "overlay", "textContent", "showLoader"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "component", type: TuiIcon, selector: "tui-icon", inputs: ["icon", "background"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6972
+ ], ngImport: i0, template: "@if (!orderItem() && settings()?.allowShowTable) {\n <div class=\"mb-5 flex justify-center\">\n <button\n tuiButton\n appearance=\"secondary\"\n (click)=\"toggleShowEvent.emit()\"\n type=\"button\"\n iconStart=\"@tui.layout-list\"\n >\n \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0432 \u0432\u0438\u0434\u0435 \u0441\u043F\u0438\u0441\u043A\u0430\n </button>\n </div>\n}\n<div class=\"\">\n @let products = products$ | async;\n @let productValue = product.value;\n\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit()\"\n ScNextInputFocus\n class=\"flex flex-col gap-2\"\n >\n <label\n tuiLabel\n class=\"grow\"\n >\n \u0422\u043E\u0432\u0430\u0440\n <tui-textfield\n tuiChevron\n [tuiTextfieldCleaner]=\"false\"\n >\n <input\n tuiChevron\n tuiSelect\n [formControl]=\"product\"\n placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043C\u0430\u0442\u0435\u0440\u0438\u0430\u043B\"\n />\n\n <tui-data-list-wrapper\n *tuiTextfieldDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n <tui-error\n [formControl]=\"product\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n @if (productValue && productValue.costRub !== undefined) {\n <div class=\"-mt-1 text-sm text-tui-text-secondary\">\n <span class=\"font-bold\">{{ productValue.code }}</span>\n \u2014\n {{ productValue.costRub.toLocaleString() }} {{ productValue.currency.symbol }}/\u043C\u00B2\n </div>\n }\n\n @if (productValue) {\n <div class=\"mt-4 mb-3 flex flex-col gap-1.5\">\n <div class=\"w-full font-bold\">\u0420\u0430\u0437\u043C\u0435\u0440\u044B \u0438\u0437\u0434\u0435\u043B\u0438\u0439</div>\n <div class=\"flex flex-col gap-1 text-sm text-tui-text-secondary\">\n @let wt = widthRangeText();\n @let lt = lengthRangeText();\n @if (wt) {\n <div>\u0428\u0438\u0440\u0438\u043D\u0430 {{ wt }}.</div>\n }\n @if (lt) {\n <div>\u0414\u043B\u0438\u043D\u0430 {{ lt }}.</div>\n }\n </div>\n </div>\n }\n\n <div class=\"flex flex-col gap-3\">\n <div\n formArrayName=\"items\"\n class=\"flex flex-col gap-3\"\n >\n @for (item of items.controls; track item) {\n @if ($index > 0) {\n <hr class=\"border-sc-grey h-px\" />\n }\n @let itemIndex = $index;\n <div\n class=\"relative flex flex-col gap-1\"\n [formGroupName]=\"itemIndex\"\n >\n @if (isItemLocked(itemIndex)) {\n <div class=\"pointer-events-none absolute right-3 bottom-0 z-10 flex size-8 items-center justify-center\">\n <tui-icon\n icon=\"@tui.check\"\n class=\"text-tui-status-positive\"\n />\n </div>\n }\n <tui-loader [showLoader]=\"isItemLoading(itemIndex)\">\n <div\n [class.opacity-70]=\"isItemLocked(itemIndex)\"\n class=\"flex min-w-0 items-start gap-2\"\n >\n <div class=\"flex min-w-0 flex-1 flex-col gap-3\">\n <div class=\"flex flex-col gap-3 lg:!flex-row lg:!items-start lg:!gap-6\">\n <!-- \u0413\u0440\u0443\u043F\u043F\u0430 1: \u0448\u0438\u0440\u0438\u043D\u0430 + \u0434\u043B\u0438\u043D\u0430 -->\n <div class=\"grid grid-cols-1 gap-2 sm:grid-cols-2 lg:!flex-[2]\">\n <label tuiLabel>\n \u0428\u0438\u0440\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"width\"\n [min]=\"settings()?.minWidth ?? 0\"\n [max]=\"product.value?.properties?.width ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n [tuiAutoFocus]=\"!$first\"\n placeholder=\"\u0428\u0438\u0440\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n <tui-error\n formControlName=\"width\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u0414\u043B\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"length\"\n [min]=\"settings()?.minLength ?? 0\"\n [max]=\"product.value?.properties?.length ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u0414\u043B\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n <tui-error\n formControlName=\"length\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n\n <!-- \u0413\u0440\u0443\u043F\u043F\u0430 2: \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E + \u043C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430 (\u043D\u0430 lg 1fr | 2fr) -->\n <div class=\"grid grid-cols-1 gap-2 sm:grid-cols-2 lg:!grid-cols-[1fr_2fr] lg:!flex-[3]\">\n <label tuiLabel>\n <span class=\"whitespace-nowrap\">\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E, \u0448\u0442</span>\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n tuiInputNumber\n formControlName=\"count\"\n [min]=\"1\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"count\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\n <tui-textfield>\n <input\n tuiTextfield\n formControlName=\"marker\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"marker\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n </div>\n\n @let rowVal = item.getRawValue();\n\n @if (rowVal.width > 0 && rowVal.length > 0) {\n <div class=\"mt-1 flex flex-col gap-y-1 text-sm lg:!flex-row lg:!gap-6\">\n @if (pieceAreaM2(rowVal) > 0) {\n <div class=\"lg:!flex-[2]\">\n \u041F\u043B\u043E\u0449\u0430\u0434\u044C (S) =\n <span class=\"font-bold\">{{ pieceAreaM2(rowVal) | number: '1.0-4' }} \u043C\u00B2</span>\n </div>\n }\n @if (productValue && rowCost(rowVal) > 0) {\n <div class=\"lg:!flex-[3]\">\n \u0418\u0442\u043E\u0433\u043E:\n <span class=\"font-bold\">{{ rowCost(rowVal).toLocaleString() }} {{ productValue.currency.symbol }}</span>\n </div>\n }\n </div>\n }\n </div>\n\n @if (!isEditingExistingItem()) {\n <button\n tuiIconButton\n title=\"\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\"\n (click)=\"removeItem(itemIndex)\"\n [disabled]=\"items.length <= 1 || !product.value || isItemLoading(itemIndex)\"\n size=\"m\"\n type=\"button\"\n iconStart=\"@tui.trash-2\"\n appearance=\"secondary\"\n class=\"mt-6 shrink-0 lg:!ml-4\"\n [style.flex]=\"'0 0 auto'\"\n ></button>\n }\n </div>\n </tui-loader>\n </div>\n }\n </div>\n\n @if (productValue) {\n <hr class=\"border-sc-grey h-px\" />\n <div class=\"min-w-0 gap-1 pt-2 text-right\">\n @if (totalAreaM2() > 0) {\n <div>\n \u041E\u0431\u0449\u0430\u044F \u043F\u043B\u043E\u0449\u0430\u0434\u044C:\n <span class=\"font-bold\">{{ totalAreaM2() | number: '1.0-4' }} \u043C\u00B2</span>\n </div>\n }\n @if (productValue.costRub && totalCost() > 0) {\n <div>\n \u0418\u0442\u043E\u0433\u043E:\n <span class=\"whitespace-nowrap text-xl font-bold\"> {{ totalCost().toLocaleString() }} {{ productValue.currency.symbol }} </span>\n </div>\n }\n </div>\n }\n </div>\n\n <tui-error [error]=\"[] | tuiFieldError | async\" />\n\n <div class=\"flex flex-wrap items-center gap-3\">\n @if (productValue && !isEditingExistingItem()) {\n <button\n tuiButton\n appearance=\"secondary\"\n [disabled]=\"!product.value || items.invalid\"\n (click)=\"addItem()\"\n type=\"button\"\n iconStart=\"@tui.plus\"\n >\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\n </button>\n }\n <button\n type=\"submit\"\n [disabled]=\"form.invalid || isSubmitLoading() || hasNoPendingItems()\"\n [loading]=\"isSubmitLoading()\"\n tuiButton\n class=\"ml-auto\"\n iconStart=\"@tui.check\"\n >\n {{ !orderItem() ? '\u0412 \u043A\u043E\u0440\u0437\u0438\u043D\u0443' : '\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C' }}\n </button>\n </div>\n </form>\n</div>\n", styles: [":host{display:block;width:100%;max-width:36rem}.row-summary{color:var(--tui-text-secondary);font-size:.75rem}\n"], dependencies: [{ kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["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: i1$1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: ScNextInputFocusModule }, { kind: "directive", type: ScNextInputFocusDirective, selector: "form[ScNextInputFocus]" }, { kind: "directive", type: TuiLabel, selector: "label[tuiLabel]" }, { kind: "component", type: TuiDataListWrapperComponent, selector: "tui-data-list-wrapper:not([labels]), tui-data-list-wrapper:not([labels])[new]", inputs: ["items", "disabledItemHandler", "emptyContent", "size", "itemContent"], outputs: ["itemClick"] }, { kind: "component", type: TuiError, selector: "tui-error", inputs: ["error"] }, { kind: "component", type: i1$2.TuiTextfieldComponent, selector: "tui-textfield:not([multi])" }, { kind: "directive", type: i1$2.TuiTextfieldDirective, selector: "input[tuiTextfield]:not([tuiInputCard]):not([tuiInputExpire]):not([tuiInputCVC])" }, { kind: "directive", type: i1$2.TuiTextfieldOptionsDirective, selector: "[tuiTextfieldAppearance],[tuiTextfieldSize],[tuiTextfieldCleaner]", inputs: ["tuiTextfieldAppearance", "tuiTextfieldSize", "tuiTextfieldCleaner"] }, { kind: "directive", type: i1$2.TuiTextfieldDropdownDirective, selector: "ng-template[tuiTextfieldDropdown]" }, { kind: "directive", type: TuiChevron, selector: "[tuiChevron]", inputs: ["tuiChevron"] }, { kind: "directive", type: i2$1.TuiSelectDirective, selector: "input[tuiSelect]" }, { kind: "directive", type: i2$1.TuiInputNumberDirective, selector: "input[tuiInputNumber]", inputs: ["min", "max", "prefix", "postfix"] }, { kind: "directive", type: TuiNumberFormat, selector: "[tuiNumberFormat]", inputs: ["tuiNumberFormat"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DecimalPipe, name: "number" }, { kind: "pipe", type: TuiFieldErrorPipe, name: "tuiFieldError" }, { kind: "component", type: i5$2.TuiSliderComponent, selector: "input[type=range][tuiSlider]", inputs: ["size", "segments"] }, { kind: "directive", type: i2$1.TuiInputSliderDirective, selector: "input[tuiInputSlider]" }, { 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: TuiLoader, selector: "tui-loader", inputs: ["size", "inheritColor", "overlay", "textContent", "showLoader"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "component", type: TuiIcon, selector: "tui-icon", inputs: ["icon", "background"] }, { kind: "directive", type: TuiAutoFocus, selector: "[tuiAutoFocus]", inputs: ["tuiAutoFocus"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6678
6973
  }
6679
6974
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScSandwichM2Component, decorators: [{
6680
6975
  type: Component,
@@ -6699,6 +6994,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
6699
6994
  TuiLoader,
6700
6995
  TuiButtonLoading,
6701
6996
  TuiIcon,
6997
+ TuiAutoFocus,
6702
6998
  ], providers: [
6703
6999
  tuiNumberFormatProvider({ precision: 0 }),
6704
7000
  tuiInputNumberOptionsProvider({
@@ -6708,7 +7004,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
6708
7004
  stringify: signal((x) => x.name),
6709
7005
  identityMatcher: signal((a, b) => a.id === b.id),
6710
7006
  }),
6711
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (!orderItem() && settings()?.allowShowTable) {\n <div class=\"mb-5 flex justify-center\">\n <button\n tuiButton\n appearance=\"secondary\"\n (click)=\"toggleShowEvent.emit()\"\n type=\"button\"\n iconStart=\"@tui.layout-list\"\n >\n \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0432 \u0432\u0438\u0434\u0435 \u0441\u043F\u0438\u0441\u043A\u0430\n </button>\n </div>\n}\n<div class=\"\">\n @let products = products$ | async;\n @let productValue = product.value;\n\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit()\"\n ScNextInputFocus\n class=\"flex flex-col gap-2\"\n >\n <label\n tuiLabel\n class=\"grow\"\n >\n \u0422\u043E\u0432\u0430\u0440\n <tui-textfield\n tuiChevron\n [tuiTextfieldCleaner]=\"false\"\n >\n <input\n tuiChevron\n tuiSelect\n [formControl]=\"product\"\n placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043C\u0430\u0442\u0435\u0440\u0438\u0430\u043B\"\n />\n\n <tui-data-list-wrapper\n *tuiTextfieldDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n <tui-error\n [formControl]=\"product\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n @if (productValue && productValue.costRub !== undefined) {\n <div class=\"-mt-1 text-sm text-tui-text-secondary\">\n <span class=\"font-bold\">{{ productValue.code }}</span>\n \u2014\n {{ productValue.costRub.toLocaleString() }} {{ productValue.currency.symbol }}/\u043C\u00B2\n </div>\n }\n\n @if (productValue) {\n <div class=\"mt-4 flex flex-col gap-1.5\">\n <div class=\"w-full font-bold\">\u0420\u0430\u0437\u043C\u0435\u0440\u044B \u0438\u0437\u0434\u0435\u043B\u0438\u0439</div>\n <div class=\"flex flex-col gap-1 text-sm text-tui-text-secondary\">\n @let wt = widthRangeText();\n @let lt = lengthRangeText();\n @if (wt) {\n <div>\u0428\u0438\u0440\u0438\u043D\u0430 {{ wt }}.</div>\n }\n @if (lt) {\n <div>\u0414\u043B\u0438\u043D\u0430 {{ lt }}.</div>\n }\n </div>\n </div>\n }\n\n <div class=\"flex flex-col gap-3\">\n <div\n formArrayName=\"items\"\n class=\"flex flex-col gap-3\"\n >\n @for (item of items.controls; track item) {\n @if ($index > 0) {\n <hr class=\"border-sc-grey h-px\" />\n }\n @let itemIndex = $index;\n <div\n class=\"relative flex flex-col gap-1\"\n [formGroupName]=\"itemIndex\"\n >\n @if (isItemLocked(itemIndex)) {\n <div class=\"pointer-events-none absolute right-3 bottom-0 z-10 flex size-8 items-center justify-center\">\n <tui-icon\n icon=\"@tui.check\"\n class=\"text-tui-status-positive\"\n />\n </div>\n }\n <tui-loader [showLoader]=\"isItemLoading(itemIndex)\">\n <div\n [class.opacity-70]=\"isItemLocked(itemIndex)\"\n class=\"flex min-w-0 items-start gap-2\"\n >\n <div class=\"flex min-w-0 flex-1 flex-col gap-3\">\n <div class=\"flex flex-col gap-3 lg:!flex-row lg:!items-start lg:!gap-6\">\n <!-- \u0413\u0440\u0443\u043F\u043F\u0430 1: \u0448\u0438\u0440\u0438\u043D\u0430 + \u0434\u043B\u0438\u043D\u0430 -->\n <div class=\"grid grid-cols-1 gap-2 sm:grid-cols-2 lg:!flex-[2]\">\n <label tuiLabel>\n \u0428\u0438\u0440\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"width\"\n [min]=\"settings()?.minWidth ?? 0\"\n [max]=\"product.value?.properties?.width ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u0428\u0438\u0440\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n <tui-error\n formControlName=\"width\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u0414\u043B\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"length\"\n [min]=\"settings()?.minLength ?? 0\"\n [max]=\"product.value?.properties?.length ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u0414\u043B\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n <tui-error\n formControlName=\"length\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n\n <!-- \u0413\u0440\u0443\u043F\u043F\u0430 2: \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E + \u043C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430 (\u043D\u0430 lg 1fr | 2fr) -->\n <div class=\"grid grid-cols-1 gap-2 sm:grid-cols-2 lg:!grid-cols-[1fr_2fr] lg:!flex-[3]\">\n <label tuiLabel>\n <span class=\"whitespace-nowrap\">\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E, \u0448\u0442</span>\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n tuiInputNumber\n formControlName=\"count\"\n [min]=\"1\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"count\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\n <tui-textfield>\n <input\n tuiTextfield\n formControlName=\"marker\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"marker\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n </div>\n\n @let rowVal = item.getRawValue();\n\n @if (rowVal.width > 0 && rowVal.length > 0) {\n <div class=\"mt-1 flex flex-col gap-y-1 text-sm lg:!flex-row lg:!gap-6\">\n @if (pieceAreaM2(rowVal) > 0) {\n <div class=\"lg:!flex-[2]\">\n \u041F\u043B\u043E\u0449\u0430\u0434\u044C (S) =\n <span class=\"font-bold\">{{ pieceAreaM2(rowVal) | number: '1.0-4' }} \u043C\u00B2</span>\n </div>\n }\n @if (productValue && rowCost(rowVal) > 0) {\n <div class=\"lg:!flex-[3]\">\n \u0418\u0442\u043E\u0433\u043E:\n <span class=\"font-bold\">{{ rowCost(rowVal).toLocaleString() }} {{ productValue.currency.symbol }}</span>\n </div>\n }\n </div>\n }\n </div>\n\n @if (!isEditingExistingItem()) {\n <button\n tuiIconButton\n title=\"\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\"\n (click)=\"removeItem(itemIndex)\"\n [disabled]=\"items.length <= 1 || !product.value || isItemLoading(itemIndex)\"\n size=\"m\"\n type=\"button\"\n iconStart=\"@tui.trash-2\"\n appearance=\"secondary\"\n class=\"mt-6 shrink-0 lg:!ml-4\"\n [style.flex]=\"'0 0 auto'\"\n ></button>\n }\n </div>\n </tui-loader>\n </div>\n }\n </div>\n\n @if (productValue) {\n <hr class=\"border-sc-grey h-px\" />\n <div class=\"flex flex-wrap items-end gap-4 pt-2\">\n @if (!isEditingExistingItem()) {\n <button\n tuiButton\n appearance=\"secondary\"\n [disabled]=\"!product.value || items.invalid\"\n (click)=\"addItem()\"\n type=\"button\"\n class=\"self-start\"\n iconStart=\"@tui.plus\"\n >\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\n </button>\n }\n\n <div class=\"ml-auto min-w-0 gap-1 text-right\">\n @if (totalAreaM2() > 0) {\n <div>\n \u041E\u0431\u0449\u0430\u044F \u043F\u043B\u043E\u0449\u0430\u0434\u044C:\n <span class=\"font-bold\">{{ totalAreaM2() | number: '1.0-4' }} \u043C\u00B2</span>\n </div>\n }\n @if (productValue.costRub && totalCost() > 0) {\n <div>\n \u0418\u0442\u043E\u0433\u043E:\n <span class=\"whitespace-nowrap text-xl font-bold\"> {{ totalCost().toLocaleString() }} {{ productValue.currency.symbol }} </span>\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n <tui-error [error]=\"[] | tuiFieldError | async\" />\n\n <button\n type=\"submit\"\n [disabled]=\"form.invalid || isSubmitLoading() || hasNoPendingItems()\"\n [loading]=\"isSubmitLoading()\"\n tuiButton\n class=\"self-start\"\n iconStart=\"@tui.check\"\n >\n {{ !orderItem() ? '\u0412 \u043A\u043E\u0440\u0437\u0438\u043D\u0443' : '\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C' }}\n </button>\n </form>\n</div>\n", styles: [":host{display:block;width:100%;max-width:36rem}.row-summary{color:var(--tui-text-secondary);font-size:.75rem}\n"] }]
7007
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (!orderItem() && settings()?.allowShowTable) {\n <div class=\"mb-5 flex justify-center\">\n <button\n tuiButton\n appearance=\"secondary\"\n (click)=\"toggleShowEvent.emit()\"\n type=\"button\"\n iconStart=\"@tui.layout-list\"\n >\n \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0432 \u0432\u0438\u0434\u0435 \u0441\u043F\u0438\u0441\u043A\u0430\n </button>\n </div>\n}\n<div class=\"\">\n @let products = products$ | async;\n @let productValue = product.value;\n\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit()\"\n ScNextInputFocus\n class=\"flex flex-col gap-2\"\n >\n <label\n tuiLabel\n class=\"grow\"\n >\n \u0422\u043E\u0432\u0430\u0440\n <tui-textfield\n tuiChevron\n [tuiTextfieldCleaner]=\"false\"\n >\n <input\n tuiChevron\n tuiSelect\n [formControl]=\"product\"\n placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043C\u0430\u0442\u0435\u0440\u0438\u0430\u043B\"\n />\n\n <tui-data-list-wrapper\n *tuiTextfieldDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n <tui-error\n [formControl]=\"product\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n @if (productValue && productValue.costRub !== undefined) {\n <div class=\"-mt-1 text-sm text-tui-text-secondary\">\n <span class=\"font-bold\">{{ productValue.code }}</span>\n \u2014\n {{ productValue.costRub.toLocaleString() }} {{ productValue.currency.symbol }}/\u043C\u00B2\n </div>\n }\n\n @if (productValue) {\n <div class=\"mt-4 mb-3 flex flex-col gap-1.5\">\n <div class=\"w-full font-bold\">\u0420\u0430\u0437\u043C\u0435\u0440\u044B \u0438\u0437\u0434\u0435\u043B\u0438\u0439</div>\n <div class=\"flex flex-col gap-1 text-sm text-tui-text-secondary\">\n @let wt = widthRangeText();\n @let lt = lengthRangeText();\n @if (wt) {\n <div>\u0428\u0438\u0440\u0438\u043D\u0430 {{ wt }}.</div>\n }\n @if (lt) {\n <div>\u0414\u043B\u0438\u043D\u0430 {{ lt }}.</div>\n }\n </div>\n </div>\n }\n\n <div class=\"flex flex-col gap-3\">\n <div\n formArrayName=\"items\"\n class=\"flex flex-col gap-3\"\n >\n @for (item of items.controls; track item) {\n @if ($index > 0) {\n <hr class=\"border-sc-grey h-px\" />\n }\n @let itemIndex = $index;\n <div\n class=\"relative flex flex-col gap-1\"\n [formGroupName]=\"itemIndex\"\n >\n @if (isItemLocked(itemIndex)) {\n <div class=\"pointer-events-none absolute right-3 bottom-0 z-10 flex size-8 items-center justify-center\">\n <tui-icon\n icon=\"@tui.check\"\n class=\"text-tui-status-positive\"\n />\n </div>\n }\n <tui-loader [showLoader]=\"isItemLoading(itemIndex)\">\n <div\n [class.opacity-70]=\"isItemLocked(itemIndex)\"\n class=\"flex min-w-0 items-start gap-2\"\n >\n <div class=\"flex min-w-0 flex-1 flex-col gap-3\">\n <div class=\"flex flex-col gap-3 lg:!flex-row lg:!items-start lg:!gap-6\">\n <!-- \u0413\u0440\u0443\u043F\u043F\u0430 1: \u0448\u0438\u0440\u0438\u043D\u0430 + \u0434\u043B\u0438\u043D\u0430 -->\n <div class=\"grid grid-cols-1 gap-2 sm:grid-cols-2 lg:!flex-[2]\">\n <label tuiLabel>\n \u0428\u0438\u0440\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"width\"\n [min]=\"settings()?.minWidth ?? 0\"\n [max]=\"product.value?.properties?.width ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n [tuiAutoFocus]=\"!$first\"\n placeholder=\"\u0428\u0438\u0440\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n <tui-error\n formControlName=\"width\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u0414\u043B\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"length\"\n [min]=\"settings()?.minLength ?? 0\"\n [max]=\"product.value?.properties?.length ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u0414\u043B\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n <tui-error\n formControlName=\"length\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n\n <!-- \u0413\u0440\u0443\u043F\u043F\u0430 2: \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E + \u043C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430 (\u043D\u0430 lg 1fr | 2fr) -->\n <div class=\"grid grid-cols-1 gap-2 sm:grid-cols-2 lg:!grid-cols-[1fr_2fr] lg:!flex-[3]\">\n <label tuiLabel>\n <span class=\"whitespace-nowrap\">\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E, \u0448\u0442</span>\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n tuiInputNumber\n formControlName=\"count\"\n [min]=\"1\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"count\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\n <tui-textfield>\n <input\n tuiTextfield\n formControlName=\"marker\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"marker\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n </div>\n\n @let rowVal = item.getRawValue();\n\n @if (rowVal.width > 0 && rowVal.length > 0) {\n <div class=\"mt-1 flex flex-col gap-y-1 text-sm lg:!flex-row lg:!gap-6\">\n @if (pieceAreaM2(rowVal) > 0) {\n <div class=\"lg:!flex-[2]\">\n \u041F\u043B\u043E\u0449\u0430\u0434\u044C (S) =\n <span class=\"font-bold\">{{ pieceAreaM2(rowVal) | number: '1.0-4' }} \u043C\u00B2</span>\n </div>\n }\n @if (productValue && rowCost(rowVal) > 0) {\n <div class=\"lg:!flex-[3]\">\n \u0418\u0442\u043E\u0433\u043E:\n <span class=\"font-bold\">{{ rowCost(rowVal).toLocaleString() }} {{ productValue.currency.symbol }}</span>\n </div>\n }\n </div>\n }\n </div>\n\n @if (!isEditingExistingItem()) {\n <button\n tuiIconButton\n title=\"\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\"\n (click)=\"removeItem(itemIndex)\"\n [disabled]=\"items.length <= 1 || !product.value || isItemLoading(itemIndex)\"\n size=\"m\"\n type=\"button\"\n iconStart=\"@tui.trash-2\"\n appearance=\"secondary\"\n class=\"mt-6 shrink-0 lg:!ml-4\"\n [style.flex]=\"'0 0 auto'\"\n ></button>\n }\n </div>\n </tui-loader>\n </div>\n }\n </div>\n\n @if (productValue) {\n <hr class=\"border-sc-grey h-px\" />\n <div class=\"min-w-0 gap-1 pt-2 text-right\">\n @if (totalAreaM2() > 0) {\n <div>\n \u041E\u0431\u0449\u0430\u044F \u043F\u043B\u043E\u0449\u0430\u0434\u044C:\n <span class=\"font-bold\">{{ totalAreaM2() | number: '1.0-4' }} \u043C\u00B2</span>\n </div>\n }\n @if (productValue.costRub && totalCost() > 0) {\n <div>\n \u0418\u0442\u043E\u0433\u043E:\n <span class=\"whitespace-nowrap text-xl font-bold\"> {{ totalCost().toLocaleString() }} {{ productValue.currency.symbol }} </span>\n </div>\n }\n </div>\n }\n </div>\n\n <tui-error [error]=\"[] | tuiFieldError | async\" />\n\n <div class=\"flex flex-wrap items-center gap-3\">\n @if (productValue && !isEditingExistingItem()) {\n <button\n tuiButton\n appearance=\"secondary\"\n [disabled]=\"!product.value || items.invalid\"\n (click)=\"addItem()\"\n type=\"button\"\n iconStart=\"@tui.plus\"\n >\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\n </button>\n }\n <button\n type=\"submit\"\n [disabled]=\"form.invalid || isSubmitLoading() || hasNoPendingItems()\"\n [loading]=\"isSubmitLoading()\"\n tuiButton\n class=\"ml-auto\"\n iconStart=\"@tui.check\"\n >\n {{ !orderItem() ? '\u0412 \u043A\u043E\u0440\u0437\u0438\u043D\u0443' : '\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C' }}\n </button>\n </div>\n </form>\n</div>\n", styles: [":host{display:block;width:100%;max-width:36rem}.row-summary{color:var(--tui-text-secondary);font-size:.75rem}\n"] }]
6712
7008
  }], propDecorators: { orderId: [{
6713
7009
  type: Input
6714
7010
  }] } });
@@ -7187,12 +7483,16 @@ class ScResourcePreviewComponent {
7187
7483
  * @param videoElement HTML элемент видео.
7188
7484
  */
7189
7485
  onCanPlay(videoElement) {
7486
+ if (this.playAttempt) {
7487
+ clearInterval(this.playAttempt);
7488
+ }
7190
7489
  this.playAttempt = setInterval(() => {
7191
7490
  videoElement
7192
7491
  .play()
7193
7492
  .then(() => {
7194
7493
  if (this.playAttempt) {
7195
7494
  clearInterval(this.playAttempt);
7495
+ this.playAttempt = undefined;
7196
7496
  }
7197
7497
  })
7198
7498
  // eslint-disable-next-line lodash/prefer-noop
@@ -7206,6 +7506,7 @@ class ScResourcePreviewComponent {
7206
7506
  // Исправляет ошибку фонового воспроизведения после закрытия диалога.
7207
7507
  if (this.playAttempt) {
7208
7508
  clearInterval(this.playAttempt);
7509
+ this.playAttempt = undefined;
7209
7510
  }
7210
7511
  }
7211
7512
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScResourcePreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
@@ -8002,7 +8303,7 @@ class ScOrderItemComponent extends AbstractScPriceCard {
8002
8303
  appearance: signal('textfield'),
8003
8304
  }),
8004
8305
  tuiHintOptionsProvider({ direction: 'top', showDelay: 100, hideDelay: 100 }),
8005
- ], usesInheritance: true, ngImport: i0, template: "@if (product && orderItem) {\n <div class=\"@container relative flex w-full gap-4 rounded-xl p-1 text-body-s hover:bg-tui-background-neutral-1\">\n <sc-noindex-wrapper>\n @let isDisabled = product.isHidden || product.isNull;\n <sc-hover-image-carousel\n (click)=\"isDisabled ? null : clickCardEvent.emit()\"\n [images]=\"!isMobile ? getCardImagePreviewList(product) : [getCardImagePreview()]\"\n [isShowActions]=\"false\"\n class=\"aspect-square w-24 shrink-0 cursor-pointer self-start\"\n />\n <div class=\"flex w-full flex-col gap-y-1 gap-x-4 @5xl:flex-row @5xl:items-center @5xl:gap-5\">\n <div class=\"flex min-w-0 flex-1 flex-col gap-1\">\n <div\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B: {{ product.code }}\n </div>\n <div class=\"flex flex-col gap-1\">\n <a\n tuiLink\n [attr.href]=\"href ?? null\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n (click)=\"$event.preventDefault(); clickCardEvent.emit()\"\n [class.disabled]=\"isDisabled\"\n class=\"!text-body-m-bold\"\n >\n {{ product.name }}\n </a>\n @if (product.supplierSku) {\n <span class=\"text-tui-text-02\"> \u0410\u0440\u0442\u0438\u043A\u0443\u043B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044F: {{ product.supplierSku }} </span>\n }\n @if (product.pack) {\n <div class=\"flex items-center gap-1 text-tui-text-02\">\n \u041D\u043E\u0440\u043C\u0430 \u0443\u043F\u0430\u043A\u043E\u0432\u043A\u0438: {{ product.pack }}\n @if (product.ignoreMinCountCheck) {\n <tui-icon\n icon=\"@tui.package\"\n [tuiHint]=\"minCountHint\"\n [tuiHintShowDelay]=\"100\"\n tuiHintDirection=\"top\"\n class=\"text-body-xl text-tui-text-01 opacity-90\"\n />\n <ng-template #minCountHint>\n \u0414\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0437\u0430\u043A\u0430\u0437 <br />\n \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u044C\u043D\u043E\u0433\u043E <br />\n \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430\n </ng-template>\n }\n </div>\n }\n\n <sc-cost-with-discount\n scPrint=\"cost\"\n [product]=\"product\"\n />\n </div>\n @if (orderItem.specificationImgUrl) {\n <a\n tuiLink\n (click)=\"showSpecification(specificationPreview)\"\n [class.disabled]=\"isDisabled\"\n >\n \u0421\u043F\u0435\u0446\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F\n </a>\n }\n <ng-template\n #specificationPreview\n let-preview\n >\n <tui-preview\n [rotatable]=\"false\"\n [zoomable]=\"false\"\n >\n <img\n *polymorpheusOutlet=\"orderItem.specificationImgUrl as src\"\n alt=\"preview\"\n [src]=\"orderItem.specificationImgUrl\"\n />\n <button\n iconStart=\"@tui.x\"\n title=\"Close\"\n tuiIconButton\n tuiPreviewAction\n type=\"button\"\n (click)=\"preview.complete()\"\n ></button>\n </tui-preview>\n </ng-template>\n </div>\n <div class=\"grid grid-cols-1 @lg:grid-cols-3 gap-2 @2xl:gap-4 @2xl:grid-rows-1\">\n <div class=\"grid grid-cols-1 items-center @lg:gap-2 @2xl:grid-cols-2 @lg:col-span-2\">\n <!-- \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (isShowEditControls() && showQuantityControl) {\n <!-- \u041F\u043E\u043B\u0435 \u0432\u0432\u043E\u0434\u0430 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0442\u043E\u0432\u0430\u0440\u0430. -->\n <sc-input-quantity\n #inputQuantity\n [tuiAutoFocus]=\"autoFocuseQuantityInput()\"\n [formControl]=\"quantityControl\"\n size=\"m\"\n [showCross]=\"false\"\n [isDisabled]=\"isDisabled\"\n [step]=\"unitsHelper.productMultiplicity(product)\"\n [ignoreStepValidators]=\"product.ignoreMinCountCheck\"\n [showLoader]=\"showLoader()\"\n (clickClearEvent)=\"clickClearEvent.emit(orderItem)\"\n (keydown.enter)=\"inputQuantity.nativeFocusableElement?.blur()\"\n class=\"w-32 shrink-0\"\n />\n } @else {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n >\n <div class=\"!text-body-m text-start\">\n \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E:\n <strong> {{ orderItem.quantity }} \u0448\u0442.</strong>\n </div>\n </button>\n }\n\n @let showAdditionalInfo = orderItem.configurator || orderItem.height || orderItem.length || orderItem.width || orderItem.marker;\n @if (showAdditionalInfo) {\n <div class=\"flex items-center gap-2 @lg:gap-3 max-w-min\">\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (isShowEditControls()) {\n <button\n tuiIconButton\n iconStart=\"@tui.settings\"\n [disabled]=\"isDisabled\"\n [loading]=\"showLoader()\"\n (click)=\"clickSettings.emit()\"\n size=\"s\"\n [appearance]=\"isConfiguratorHintVisible() ? 'primary' : 'secondary'\"\n class=\"shrink-0\"\n ></button>\n }\n\n <!-- \u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044F \u043E \u0442\u043E\u0432\u0430\u0440\u0435. -->\n <div\n class=\"flex flex-col gap-x-1 text-tui-base-07\"\n [class.text-body-m]=\"!isShowEditControls()\"\n >\n @if (orderItem.marker) {\n <p>\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430: {{ orderItem.marker }}</p>\n }\n @if (orderItem.width) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0448\u0438\u0440\u0438\u043D\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0428\u0438\u0440\u0438\u043D\u0430: <span class=\"text-body-s-bold\">{{ orderItem.width }} \u043C.</span>\n </button>\n }\n @if (orderItem.height) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0432\u044B\u0441\u043E\u0442\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0412\u044B\u0441\u043E\u0442\u0430: <span class=\"text-body-s-bold\">{{ orderItem.height }} \u043C.</span>\n </button>\n } @else if (orderItem.length) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0434\u043B\u0438\u043D\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0414\u043B\u0438\u043D\u0430: <span class=\"text-body-s-bold\">{{ orderItem.length }} \u043C.</span>\n </button>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- \u0421\u0443\u043C\u043C\u0430 \u0442\u043E\u0432\u0430\u0440\u0430 \u0438 \u0441\u043A\u043B\u0430\u0434\u0441\u043A\u043E\u0435 \u043D\u0430\u043B\u0438\u0447\u0438\u0435. -->\n <div\n scPrint=\"cost\"\n class=\"flex min-w-[11rem] flex-col @lg:justify-end @2xl:!justify-center text-body-m\"\n >\n <p class=\"whitespace-nowrap\">\n \u0421\u0443\u043C\u043C\u0430:\n <strong> {{ orderItem.costRub | tuiFormatNumber: { precision: 2, decimalSeparator: '.', rounding: 'ceil' } | async }} {{ 'RUB' | tuiCurrency }}</strong>\n </p>\n <sc-price-warehouse-stock\n scPrint=\"defaultNoPrint\"\n [product]=\"product\"\n />\n </div>\n </div>\n </div>\n </sc-noindex-wrapper>\n </div>\n} @else {\n <div class=\"tui-skeleton flex h-[8.25rem] w-full overflow-hidden rounded-xl\"></div>\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i2$2.AsyncPipe, name: "async" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiIcon, selector: "tui-icon", inputs: ["icon", "background"] }, { kind: "ngmodule", type: TuiTextfieldControllerModule }, { kind: "directive", type: i2$3.PolymorpheusOutlet, selector: "[polymorpheusOutlet]", inputs: ["polymorpheusOutlet", "polymorpheusOutletContext"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.TuiHintDirective, selector: "[tuiHint]:not(ng-container):not(ng-template)", inputs: ["tuiHintContext", "tuiHintAppearance", "tuiHint"], outputs: ["tuiHintVisible"] }, { kind: "directive", type: TuiLink, selector: "a[tuiLink], button[tuiLink]", inputs: ["pseudo"] }, { kind: "directive", type: TuiHighlight, selector: "[tuiHighlight]", inputs: ["tuiHighlight", "tuiHighlightColor"] }, { kind: "directive", type: TuiAutoFocus, selector: "[tuiAutoFocus]", inputs: ["tuiAutoFocus"] }, { kind: "component", type: ScHoverImageCarouselComponent, selector: "sc-hover-image-carousel", inputs: ["images", "isShowActions", "productName"] }, { kind: "component", type: CostWithDiscountComponent, selector: "sc-cost-with-discount", inputs: ["product", "size"] }, { kind: "component", type: ScPriceWarehouseStockComponent, selector: "sc-price-warehouse-stock", inputs: ["classList", "product", "withStockHint", "fromMain"] }, { kind: "component", type: ScInputQuantityComponent, selector: "sc-input-quantity", inputs: ["step", "showLoader", "showCross", "ignoreStepValidators", "appearance", "isDisabled", "size"], outputs: ["clickClearEvent"] }, { kind: "pipe", type: TuiCurrencyPipe, name: "tuiCurrency" }, { kind: "pipe", type: TuiFormatNumberPipe, name: "tuiFormatNumber" }, { kind: "component", type: i2$1.TuiPreviewComponent, selector: "tui-preview", inputs: ["zoomable", "rotatable", "initialScale"] }, { kind: "directive", type: i2$1.TuiPreviewAction, selector: "[tuiPreviewAction]" }, { kind: "component", type: ScNoindexWrapperComponent, selector: "sc-noindex-wrapper" }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "directive", type: ScPrintDirective, selector: "[scPrint]", inputs: ["scPrint"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8306
+ ], usesInheritance: true, ngImport: i0, template: "@if (product && orderItem) {\n <div class=\"@container relative flex w-full gap-4 rounded-xl p-1 text-body-s hover:bg-tui-background-neutral-1\">\n <sc-noindex-wrapper>\n @let isDisabled = product.isHidden || product.isNull;\n <sc-hover-image-carousel\n (click)=\"isDisabled ? null : clickCardEvent.emit()\"\n [images]=\"!isMobile ? getCardImagePreviewList(product) : [getCardImagePreview()]\"\n [isShowActions]=\"false\"\n class=\"aspect-square w-24 shrink-0 cursor-pointer self-start\"\n />\n <div class=\"flex w-full flex-col gap-y-1 gap-x-4 @5xl:flex-row @5xl:items-center @5xl:gap-5\">\n <div class=\"flex min-w-0 flex-1 flex-col gap-1\">\n <div\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B: {{ product.code }}\n </div>\n <div class=\"flex flex-col gap-1\">\n <a\n tuiLink\n [attr.href]=\"href ?? null\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n (click)=\"$event.preventDefault(); clickCardEvent.emit()\"\n [class.disabled]=\"isDisabled\"\n class=\"!text-body-m-bold\"\n >\n {{ product.name }}\n </a>\n @if (product.supplierSku) {\n <span class=\"text-tui-text-02\"> \u0410\u0440\u0442\u0438\u043A\u0443\u043B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044F: {{ product.supplierSku }} </span>\n }\n @if (product.pack) {\n <div class=\"flex items-center gap-1 text-tui-text-02\">\n \u041D\u043E\u0440\u043C\u0430 \u0443\u043F\u0430\u043A\u043E\u0432\u043A\u0438: {{ product.pack }}\n @if (product.ignoreMinCountCheck) {\n <tui-icon\n icon=\"@tui.package\"\n [tuiHint]=\"minCountHint\"\n [tuiHintShowDelay]=\"100\"\n tuiHintDirection=\"top\"\n class=\"text-body-xl text-tui-text-01 opacity-90\"\n />\n <ng-template #minCountHint>\n \u0414\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0437\u0430\u043A\u0430\u0437 <br />\n \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u044C\u043D\u043E\u0433\u043E <br />\n \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430\n </ng-template>\n }\n </div>\n }\n\n <sc-cost-with-discount\n scPrint=\"cost\"\n [product]=\"product\"\n />\n </div>\n @if (orderItem.specificationImgUrl) {\n <a\n tuiLink\n (click)=\"showSpecification(specificationPreview)\"\n [class.disabled]=\"isDisabled\"\n >\n \u0421\u043F\u0435\u0446\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F\n </a>\n }\n <ng-template\n #specificationPreview\n let-preview\n >\n <tui-preview\n [rotatable]=\"false\"\n [zoomable]=\"false\"\n >\n <img\n *polymorpheusOutlet=\"orderItem.specificationImgUrl as src\"\n alt=\"preview\"\n [src]=\"orderItem.specificationImgUrl\"\n />\n <button\n iconStart=\"@tui.x\"\n title=\"Close\"\n tuiIconButton\n tuiPreviewAction\n type=\"button\"\n (click)=\"preview.complete()\"\n ></button>\n </tui-preview>\n </ng-template>\n </div>\n <div class=\"grid grid-cols-1 @lg:grid-cols-3 gap-2 @2xl:gap-4 @2xl:grid-rows-1\">\n <div class=\"grid grid-cols-1 items-center @lg:gap-2 @2xl:grid-cols-2 @lg:col-span-2\">\n <!-- \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (isShowEditControls() && showQuantityControl) {\n <!-- \u041F\u043E\u043B\u0435 \u0432\u0432\u043E\u0434\u0430 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0442\u043E\u0432\u0430\u0440\u0430. -->\n <sc-input-quantity\n #inputQuantity\n [tuiAutoFocus]=\"autoFocuseQuantityInput()\"\n [formControl]=\"quantityControl\"\n size=\"m\"\n [showCross]=\"false\"\n [isDisabled]=\"isDisabled\"\n [step]=\"ScUnitsHelper.getProductMultiplicity(product)\"\n [ignoreStepValidators]=\"product.ignoreMinCountCheck\"\n [showLoader]=\"showLoader()\"\n (clickClearEvent)=\"clickClearEvent.emit(orderItem)\"\n (keydown.enter)=\"inputQuantity.nativeFocusableElement?.blur()\"\n class=\"w-32 shrink-0\"\n />\n } @else {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n >\n <div class=\"!text-body-m text-start\">\n \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E:\n <strong> {{ orderItem.quantity }} \u0448\u0442.</strong>\n </div>\n </button>\n }\n\n @let showAdditionalInfo = orderItem.configurator || orderItem.height || orderItem.length || orderItem.width || orderItem.marker;\n @if (showAdditionalInfo) {\n <div class=\"flex items-center gap-2 @lg:gap-3 max-w-min\">\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (isShowEditControls()) {\n <button\n tuiIconButton\n iconStart=\"@tui.settings\"\n [disabled]=\"isDisabled\"\n [loading]=\"showLoader()\"\n (click)=\"clickSettings.emit()\"\n size=\"s\"\n [appearance]=\"isConfiguratorHintVisible() ? 'primary' : 'secondary'\"\n class=\"shrink-0\"\n ></button>\n }\n\n <!-- \u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044F \u043E \u0442\u043E\u0432\u0430\u0440\u0435. -->\n <div\n class=\"flex flex-col gap-x-1 text-tui-base-07\"\n [class.text-body-m]=\"!isShowEditControls()\"\n >\n @if (orderItem.marker) {\n <p>\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430: {{ orderItem.marker }}</p>\n }\n @if (orderItem.width) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0448\u0438\u0440\u0438\u043D\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0428\u0438\u0440\u0438\u043D\u0430: <span class=\"text-body-s-bold\">{{ orderItem.width }} \u043C.</span>\n </button>\n }\n @if (orderItem.height) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0432\u044B\u0441\u043E\u0442\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0412\u044B\u0441\u043E\u0442\u0430: <span class=\"text-body-s-bold\">{{ orderItem.height }} \u043C.</span>\n </button>\n } @else if (orderItem.length) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0434\u043B\u0438\u043D\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0414\u043B\u0438\u043D\u0430: <span class=\"text-body-s-bold\">{{ orderItem.length }} \u043C.</span>\n </button>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- \u0421\u0443\u043C\u043C\u0430 \u0442\u043E\u0432\u0430\u0440\u0430 \u0438 \u0441\u043A\u043B\u0430\u0434\u0441\u043A\u043E\u0435 \u043D\u0430\u043B\u0438\u0447\u0438\u0435. -->\n <div\n scPrint=\"cost\"\n class=\"flex min-w-[11rem] flex-col @lg:justify-end @2xl:!justify-center text-body-m\"\n >\n <p class=\"whitespace-nowrap\">\n \u0421\u0443\u043C\u043C\u0430:\n <strong> {{ orderItem.costRub | tuiFormatNumber: { precision: 2, decimalSeparator: '.', rounding: 'ceil' } | async }} {{ 'RUB' | tuiCurrency }}</strong>\n </p>\n <sc-price-warehouse-stock\n scPrint=\"defaultNoPrint\"\n [product]=\"product\"\n />\n </div>\n </div>\n </div>\n </sc-noindex-wrapper>\n </div>\n} @else {\n <div class=\"tui-skeleton flex h-[8.25rem] w-full overflow-hidden rounded-xl\"></div>\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i2$2.AsyncPipe, name: "async" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiIcon, selector: "tui-icon", inputs: ["icon", "background"] }, { kind: "ngmodule", type: TuiTextfieldControllerModule }, { kind: "directive", type: i2$3.PolymorpheusOutlet, selector: "[polymorpheusOutlet]", inputs: ["polymorpheusOutlet", "polymorpheusOutletContext"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.TuiHintDirective, selector: "[tuiHint]:not(ng-container):not(ng-template)", inputs: ["tuiHintContext", "tuiHintAppearance", "tuiHint"], outputs: ["tuiHintVisible"] }, { kind: "directive", type: TuiLink, selector: "a[tuiLink], button[tuiLink]", inputs: ["pseudo"] }, { kind: "directive", type: TuiHighlight, selector: "[tuiHighlight]", inputs: ["tuiHighlight", "tuiHighlightColor"] }, { kind: "directive", type: TuiAutoFocus, selector: "[tuiAutoFocus]", inputs: ["tuiAutoFocus"] }, { kind: "component", type: ScHoverImageCarouselComponent, selector: "sc-hover-image-carousel", inputs: ["images", "isShowActions", "productName"] }, { kind: "component", type: CostWithDiscountComponent, selector: "sc-cost-with-discount", inputs: ["product", "size"] }, { kind: "component", type: ScPriceWarehouseStockComponent, selector: "sc-price-warehouse-stock", inputs: ["classList", "product", "withStockHint", "fromMain"] }, { kind: "component", type: ScInputQuantityComponent, selector: "sc-input-quantity", inputs: ["step", "showLoader", "showCross", "ignoreStepValidators", "appearance", "isDisabled", "size"], outputs: ["clickClearEvent"] }, { kind: "pipe", type: TuiCurrencyPipe, name: "tuiCurrency" }, { kind: "pipe", type: TuiFormatNumberPipe, name: "tuiFormatNumber" }, { kind: "component", type: i2$1.TuiPreviewComponent, selector: "tui-preview", inputs: ["zoomable", "rotatable", "initialScale"] }, { kind: "directive", type: i2$1.TuiPreviewAction, selector: "[tuiPreviewAction]" }, { kind: "component", type: ScNoindexWrapperComponent, selector: "sc-noindex-wrapper" }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "directive", type: ScPrintDirective, selector: "[scPrint]", inputs: ["scPrint"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8006
8307
  }
8007
8308
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScOrderItemComponent, decorators: [{
8008
8309
  type: Component,
@@ -8039,7 +8340,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
8039
8340
  appearance: signal('textfield'),
8040
8341
  }),
8041
8342
  tuiHintOptionsProvider({ direction: 'top', showDelay: 100, hideDelay: 100 }),
8042
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (product && orderItem) {\n <div class=\"@container relative flex w-full gap-4 rounded-xl p-1 text-body-s hover:bg-tui-background-neutral-1\">\n <sc-noindex-wrapper>\n @let isDisabled = product.isHidden || product.isNull;\n <sc-hover-image-carousel\n (click)=\"isDisabled ? null : clickCardEvent.emit()\"\n [images]=\"!isMobile ? getCardImagePreviewList(product) : [getCardImagePreview()]\"\n [isShowActions]=\"false\"\n class=\"aspect-square w-24 shrink-0 cursor-pointer self-start\"\n />\n <div class=\"flex w-full flex-col gap-y-1 gap-x-4 @5xl:flex-row @5xl:items-center @5xl:gap-5\">\n <div class=\"flex min-w-0 flex-1 flex-col gap-1\">\n <div\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B: {{ product.code }}\n </div>\n <div class=\"flex flex-col gap-1\">\n <a\n tuiLink\n [attr.href]=\"href ?? null\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n (click)=\"$event.preventDefault(); clickCardEvent.emit()\"\n [class.disabled]=\"isDisabled\"\n class=\"!text-body-m-bold\"\n >\n {{ product.name }}\n </a>\n @if (product.supplierSku) {\n <span class=\"text-tui-text-02\"> \u0410\u0440\u0442\u0438\u043A\u0443\u043B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044F: {{ product.supplierSku }} </span>\n }\n @if (product.pack) {\n <div class=\"flex items-center gap-1 text-tui-text-02\">\n \u041D\u043E\u0440\u043C\u0430 \u0443\u043F\u0430\u043A\u043E\u0432\u043A\u0438: {{ product.pack }}\n @if (product.ignoreMinCountCheck) {\n <tui-icon\n icon=\"@tui.package\"\n [tuiHint]=\"minCountHint\"\n [tuiHintShowDelay]=\"100\"\n tuiHintDirection=\"top\"\n class=\"text-body-xl text-tui-text-01 opacity-90\"\n />\n <ng-template #minCountHint>\n \u0414\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0437\u0430\u043A\u0430\u0437 <br />\n \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u044C\u043D\u043E\u0433\u043E <br />\n \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430\n </ng-template>\n }\n </div>\n }\n\n <sc-cost-with-discount\n scPrint=\"cost\"\n [product]=\"product\"\n />\n </div>\n @if (orderItem.specificationImgUrl) {\n <a\n tuiLink\n (click)=\"showSpecification(specificationPreview)\"\n [class.disabled]=\"isDisabled\"\n >\n \u0421\u043F\u0435\u0446\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F\n </a>\n }\n <ng-template\n #specificationPreview\n let-preview\n >\n <tui-preview\n [rotatable]=\"false\"\n [zoomable]=\"false\"\n >\n <img\n *polymorpheusOutlet=\"orderItem.specificationImgUrl as src\"\n alt=\"preview\"\n [src]=\"orderItem.specificationImgUrl\"\n />\n <button\n iconStart=\"@tui.x\"\n title=\"Close\"\n tuiIconButton\n tuiPreviewAction\n type=\"button\"\n (click)=\"preview.complete()\"\n ></button>\n </tui-preview>\n </ng-template>\n </div>\n <div class=\"grid grid-cols-1 @lg:grid-cols-3 gap-2 @2xl:gap-4 @2xl:grid-rows-1\">\n <div class=\"grid grid-cols-1 items-center @lg:gap-2 @2xl:grid-cols-2 @lg:col-span-2\">\n <!-- \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (isShowEditControls() && showQuantityControl) {\n <!-- \u041F\u043E\u043B\u0435 \u0432\u0432\u043E\u0434\u0430 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0442\u043E\u0432\u0430\u0440\u0430. -->\n <sc-input-quantity\n #inputQuantity\n [tuiAutoFocus]=\"autoFocuseQuantityInput()\"\n [formControl]=\"quantityControl\"\n size=\"m\"\n [showCross]=\"false\"\n [isDisabled]=\"isDisabled\"\n [step]=\"unitsHelper.productMultiplicity(product)\"\n [ignoreStepValidators]=\"product.ignoreMinCountCheck\"\n [showLoader]=\"showLoader()\"\n (clickClearEvent)=\"clickClearEvent.emit(orderItem)\"\n (keydown.enter)=\"inputQuantity.nativeFocusableElement?.blur()\"\n class=\"w-32 shrink-0\"\n />\n } @else {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n >\n <div class=\"!text-body-m text-start\">\n \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E:\n <strong> {{ orderItem.quantity }} \u0448\u0442.</strong>\n </div>\n </button>\n }\n\n @let showAdditionalInfo = orderItem.configurator || orderItem.height || orderItem.length || orderItem.width || orderItem.marker;\n @if (showAdditionalInfo) {\n <div class=\"flex items-center gap-2 @lg:gap-3 max-w-min\">\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (isShowEditControls()) {\n <button\n tuiIconButton\n iconStart=\"@tui.settings\"\n [disabled]=\"isDisabled\"\n [loading]=\"showLoader()\"\n (click)=\"clickSettings.emit()\"\n size=\"s\"\n [appearance]=\"isConfiguratorHintVisible() ? 'primary' : 'secondary'\"\n class=\"shrink-0\"\n ></button>\n }\n\n <!-- \u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044F \u043E \u0442\u043E\u0432\u0430\u0440\u0435. -->\n <div\n class=\"flex flex-col gap-x-1 text-tui-base-07\"\n [class.text-body-m]=\"!isShowEditControls()\"\n >\n @if (orderItem.marker) {\n <p>\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430: {{ orderItem.marker }}</p>\n }\n @if (orderItem.width) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0448\u0438\u0440\u0438\u043D\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0428\u0438\u0440\u0438\u043D\u0430: <span class=\"text-body-s-bold\">{{ orderItem.width }} \u043C.</span>\n </button>\n }\n @if (orderItem.height) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0432\u044B\u0441\u043E\u0442\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0412\u044B\u0441\u043E\u0442\u0430: <span class=\"text-body-s-bold\">{{ orderItem.height }} \u043C.</span>\n </button>\n } @else if (orderItem.length) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0434\u043B\u0438\u043D\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0414\u043B\u0438\u043D\u0430: <span class=\"text-body-s-bold\">{{ orderItem.length }} \u043C.</span>\n </button>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- \u0421\u0443\u043C\u043C\u0430 \u0442\u043E\u0432\u0430\u0440\u0430 \u0438 \u0441\u043A\u043B\u0430\u0434\u0441\u043A\u043E\u0435 \u043D\u0430\u043B\u0438\u0447\u0438\u0435. -->\n <div\n scPrint=\"cost\"\n class=\"flex min-w-[11rem] flex-col @lg:justify-end @2xl:!justify-center text-body-m\"\n >\n <p class=\"whitespace-nowrap\">\n \u0421\u0443\u043C\u043C\u0430:\n <strong> {{ orderItem.costRub | tuiFormatNumber: { precision: 2, decimalSeparator: '.', rounding: 'ceil' } | async }} {{ 'RUB' | tuiCurrency }}</strong>\n </p>\n <sc-price-warehouse-stock\n scPrint=\"defaultNoPrint\"\n [product]=\"product\"\n />\n </div>\n </div>\n </div>\n </sc-noindex-wrapper>\n </div>\n} @else {\n <div class=\"tui-skeleton flex h-[8.25rem] w-full overflow-hidden rounded-xl\"></div>\n}\n" }]
8343
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (product && orderItem) {\n <div class=\"@container relative flex w-full gap-4 rounded-xl p-1 text-body-s hover:bg-tui-background-neutral-1\">\n <sc-noindex-wrapper>\n @let isDisabled = product.isHidden || product.isNull;\n <sc-hover-image-carousel\n (click)=\"isDisabled ? null : clickCardEvent.emit()\"\n [images]=\"!isMobile ? getCardImagePreviewList(product) : [getCardImagePreview()]\"\n [isShowActions]=\"false\"\n class=\"aspect-square w-24 shrink-0 cursor-pointer self-start\"\n />\n <div class=\"flex w-full flex-col gap-y-1 gap-x-4 @5xl:flex-row @5xl:items-center @5xl:gap-5\">\n <div class=\"flex min-w-0 flex-1 flex-col gap-1\">\n <div\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n class=\"text-tui-text-02\"\n >\n \u0410\u0440\u0442\u0438\u043A\u0443\u043B: {{ product.code }}\n </div>\n <div class=\"flex flex-col gap-1\">\n <a\n tuiLink\n [attr.href]=\"href ?? null\"\n [tuiHighlight]=\"(search$ | async) ?? ''\"\n (click)=\"$event.preventDefault(); clickCardEvent.emit()\"\n [class.disabled]=\"isDisabled\"\n class=\"!text-body-m-bold\"\n >\n {{ product.name }}\n </a>\n @if (product.supplierSku) {\n <span class=\"text-tui-text-02\"> \u0410\u0440\u0442\u0438\u043A\u0443\u043B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u0438\u0442\u0435\u043B\u044F: {{ product.supplierSku }} </span>\n }\n @if (product.pack) {\n <div class=\"flex items-center gap-1 text-tui-text-02\">\n \u041D\u043E\u0440\u043C\u0430 \u0443\u043F\u0430\u043A\u043E\u0432\u043A\u0438: {{ product.pack }}\n @if (product.ignoreMinCountCheck) {\n <tui-icon\n icon=\"@tui.package\"\n [tuiHint]=\"minCountHint\"\n [tuiHintShowDelay]=\"100\"\n tuiHintDirection=\"top\"\n class=\"text-body-xl text-tui-text-01 opacity-90\"\n />\n <ng-template #minCountHint>\n \u0414\u043E\u0441\u0442\u0443\u043F\u0435\u043D \u0437\u0430\u043A\u0430\u0437 <br />\n \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u044C\u043D\u043E\u0433\u043E <br />\n \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430\n </ng-template>\n }\n </div>\n }\n\n <sc-cost-with-discount\n scPrint=\"cost\"\n [product]=\"product\"\n />\n </div>\n @if (orderItem.specificationImgUrl) {\n <a\n tuiLink\n (click)=\"showSpecification(specificationPreview)\"\n [class.disabled]=\"isDisabled\"\n >\n \u0421\u043F\u0435\u0446\u0438\u0444\u0438\u043A\u0430\u0446\u0438\u044F\n </a>\n }\n <ng-template\n #specificationPreview\n let-preview\n >\n <tui-preview\n [rotatable]=\"false\"\n [zoomable]=\"false\"\n >\n <img\n *polymorpheusOutlet=\"orderItem.specificationImgUrl as src\"\n alt=\"preview\"\n [src]=\"orderItem.specificationImgUrl\"\n />\n <button\n iconStart=\"@tui.x\"\n title=\"Close\"\n tuiIconButton\n tuiPreviewAction\n type=\"button\"\n (click)=\"preview.complete()\"\n ></button>\n </tui-preview>\n </ng-template>\n </div>\n <div class=\"grid grid-cols-1 @lg:grid-cols-3 gap-2 @2xl:gap-4 @2xl:grid-rows-1\">\n <div class=\"grid grid-cols-1 items-center @lg:gap-2 @2xl:grid-cols-2 @lg:col-span-2\">\n <!-- \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (isShowEditControls() && showQuantityControl) {\n <!-- \u041F\u043E\u043B\u0435 \u0432\u0432\u043E\u0434\u0430 \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0442\u043E\u0432\u0430\u0440\u0430. -->\n <sc-input-quantity\n #inputQuantity\n [tuiAutoFocus]=\"autoFocuseQuantityInput()\"\n [formControl]=\"quantityControl\"\n size=\"m\"\n [showCross]=\"false\"\n [isDisabled]=\"isDisabled\"\n [step]=\"ScUnitsHelper.getProductMultiplicity(product)\"\n [ignoreStepValidators]=\"product.ignoreMinCountCheck\"\n [showLoader]=\"showLoader()\"\n (clickClearEvent)=\"clickClearEvent.emit(orderItem)\"\n (keydown.enter)=\"inputQuantity.nativeFocusableElement?.blur()\"\n class=\"w-32 shrink-0\"\n />\n } @else {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n >\n <div class=\"!text-body-m text-start\">\n \u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E:\n <strong> {{ orderItem.quantity }} \u0448\u0442.</strong>\n </div>\n </button>\n }\n\n @let showAdditionalInfo = orderItem.configurator || orderItem.height || orderItem.length || orderItem.width || orderItem.marker;\n @if (showAdditionalInfo) {\n <div class=\"flex items-center gap-2 @lg:gap-3 max-w-min\">\n <!-- \u041A\u043D\u043E\u043F\u043A\u0430 \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0442\u043E\u0432\u0430\u0440\u0430. -->\n @if (isShowEditControls()) {\n <button\n tuiIconButton\n iconStart=\"@tui.settings\"\n [disabled]=\"isDisabled\"\n [loading]=\"showLoader()\"\n (click)=\"clickSettings.emit()\"\n size=\"s\"\n [appearance]=\"isConfiguratorHintVisible() ? 'primary' : 'secondary'\"\n class=\"shrink-0\"\n ></button>\n }\n\n <!-- \u0414\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044F \u043E \u0442\u043E\u0432\u0430\u0440\u0435. -->\n <div\n class=\"flex flex-col gap-x-1 text-tui-base-07\"\n [class.text-body-m]=\"!isShowEditControls()\"\n >\n @if (orderItem.marker) {\n <p>\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430: {{ orderItem.marker }}</p>\n }\n @if (orderItem.width) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0448\u0438\u0440\u0438\u043D\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0428\u0438\u0440\u0438\u043D\u0430: <span class=\"text-body-s-bold\">{{ orderItem.width }} \u043C.</span>\n </button>\n }\n @if (orderItem.height) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0432\u044B\u0441\u043E\u0442\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0412\u044B\u0441\u043E\u0442\u0430: <span class=\"text-body-s-bold\">{{ orderItem.height }} \u043C.</span>\n </button>\n } @else if (orderItem.length) {\n <button\n [appearance]=\"isShowEditControls() ? 'action-grayscale' : ''\"\n tuiTheme=\"light\"\n tuiHint=\"\u0414\u043B\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0434\u043B\u0438\u043D\u044B \u0432\u043E\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435\u0441\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0442\u043E\u0440\u043E\u043C\"\n (tuiHintVisible)=\"configuratorHintVisible($event)\"\n tuiLink\n [style.text-decoration-line]=\"isShowEditControls() ? 'underline' : 'none'\"\n [class.pointer-events-none]=\"!isShowEditControls()\"\n class=\"text-body-s self-start whitespace-nowrap\"\n >\n \u0414\u043B\u0438\u043D\u0430: <span class=\"text-body-s-bold\">{{ orderItem.length }} \u043C.</span>\n </button>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- \u0421\u0443\u043C\u043C\u0430 \u0442\u043E\u0432\u0430\u0440\u0430 \u0438 \u0441\u043A\u043B\u0430\u0434\u0441\u043A\u043E\u0435 \u043D\u0430\u043B\u0438\u0447\u0438\u0435. -->\n <div\n scPrint=\"cost\"\n class=\"flex min-w-[11rem] flex-col @lg:justify-end @2xl:!justify-center text-body-m\"\n >\n <p class=\"whitespace-nowrap\">\n \u0421\u0443\u043C\u043C\u0430:\n <strong> {{ orderItem.costRub | tuiFormatNumber: { precision: 2, decimalSeparator: '.', rounding: 'ceil' } | async }} {{ 'RUB' | tuiCurrency }}</strong>\n </p>\n <sc-price-warehouse-stock\n scPrint=\"defaultNoPrint\"\n [product]=\"product\"\n />\n </div>\n </div>\n </div>\n </sc-noindex-wrapper>\n </div>\n} @else {\n <div class=\"tui-skeleton flex h-[8.25rem] w-full overflow-hidden rounded-xl\"></div>\n}\n" }]
8043
8344
  }] });
8044
8345
 
8045
8346
  /* eslint-disable no-param-reassign */
@@ -8209,11 +8510,10 @@ class ScOrderItemsListComponent {
8209
8510
  */
8210
8511
  openSettingsDialog(item) {
8211
8512
  const isConfigurator = Boolean(item.configurator);
8212
- const { isLinear } = item.product.unit;
8213
8513
  if (isConfigurator) {
8214
8514
  this.scDialogService.openConfiguratorDialog(item.product, item, this.orderOptions?.orderId());
8215
8515
  }
8216
- else if (isLinear) {
8516
+ else if (ScUnitsHelper.productIsMeasurable(item.product)) {
8217
8517
  this.scDialogService.openAddOrEditingCartItemDialog(item.product, item, this.orderOptions?.orderId(), true);
8218
8518
  }
8219
8519
  }
@@ -9901,5 +10201,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
9901
10201
  * Generated bundle index. Do not edit.
9902
10202
  */
9903
10203
 
9904
- 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 };
10204
+ 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, cleanupRecaptchaArtifacts, phoneValidator, scAtLeastOneRequiredValidator, scBicValidator, scClientUiIconsName, scCorrespondentAccountValidator, scGetCurrentRoute, scPasswordConfirmMatchingValidator, stepValidator, tuiDateValueTransformerDefaultProvider };
9905
10205
  //# sourceMappingURL=snabcentr-client-ui.mjs.map