@snabcentr/client-ui 3.32.3 → 3.33.0

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 (35) hide show
  1. package/banner/sc-banner.module.d.ts +2 -1
  2. 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 -1
  3. package/cart/index.d.ts +1 -1
  4. package/cart/{sc-car-add-products-from-csv-dialog/sc-car-add-products-from-csv-dialog.component.d.ts → sc-cart-add-products-from-csv-dialog/sc-cart-add-products-from-csv-dialog.component.d.ts} +3 -3
  5. package/catalog/category-card/sc-category-card.component.d.ts +0 -6
  6. package/catalog/hover-image-carousel/{hover-image-carousel.component.d.ts → sc-hover-image-carousel.component.d.ts} +16 -7
  7. package/catalog/index.d.ts +1 -0
  8. package/catalog/sc-catalog.module.d.ts +3 -2
  9. package/directives/abstract-price-card/abstract-sc-price-card.directive.d.ts +4 -4
  10. package/esm2022/banner/sc-banner.component.mjs +3 -3
  11. package/esm2022/banner/sc-banner.module.mjs +4 -3
  12. package/esm2022/cart/add-or-editing-cart-item-dialog/add-or-editing-cart-item-form/sc-add-or-editing-cart-item-form.component.mjs +6 -6
  13. package/esm2022/cart/cart-item/sc-cart-item.component.mjs +4 -4
  14. package/esm2022/cart/index.mjs +2 -2
  15. package/esm2022/cart/sc-cart-add-products-from-csv-dialog/sc-cart-add-products-from-csv-dialog.component.mjs +110 -0
  16. package/esm2022/catalog/category-card/sc-category-card.component.mjs +4 -11
  17. package/esm2022/catalog/hover-image-carousel/sc-hover-image-carousel.component.mjs +76 -0
  18. package/esm2022/catalog/index.mjs +2 -1
  19. package/esm2022/catalog/price-card/sc-price-card.component.mjs +2 -2
  20. package/esm2022/catalog/price-card-inline/sc-price-card-inline.component.mjs +4 -4
  21. package/esm2022/catalog/sc-catalog.module.mjs +8 -5
  22. package/esm2022/directives/abstract-price-card/abstract-sc-price-card.directive.mjs +5 -6
  23. package/esm2022/news/news-card/sc-news-card.component.mjs +4 -8
  24. package/esm2022/news/sc-news.module.mjs +4 -3
  25. package/esm2022/order/order-item-mobile/sc-order-item-mobile.component.mjs +12 -20
  26. package/fesm2022/snabcentr-client-ui.mjs +67 -86
  27. package/fesm2022/snabcentr-client-ui.mjs.map +1 -1
  28. package/news/news-card/sc-news-card.component.d.ts +1 -5
  29. package/news/sc-news.module.d.ts +2 -1
  30. package/order/order-item-mobile/sc-order-item-mobile.component.d.ts +8 -14
  31. package/package.json +2 -2
  32. package/release_notes.tmp +5 -9
  33. package/styles/tailwind/tailwind.scss +0 -4
  34. package/esm2022/cart/sc-car-add-products-from-csv-dialog/sc-car-add-products-from-csv-dialog.component.mjs +0 -110
  35. package/esm2022/catalog/hover-image-carousel/hover-image-carousel.component.mjs +0 -76
@@ -1,5 +1,5 @@
1
1
  import { InputSignal } from '@angular/core';
2
- import { ScImageHelper, ScNewsTile } from '@snabcentr/client-core';
2
+ import { ScNewsTile } from '@snabcentr/client-core';
3
3
  import * as i0 from "@angular/core";
4
4
  /**
5
5
  * Компонент карточки новости.
@@ -17,10 +17,6 @@ export declare class ScNewsCardComponent {
17
17
  * Признак того, что этот компонент отображается на мобильном устройстве.
18
18
  */
19
19
  readonly isMobile: boolean;
20
- /**
21
- * Класс с вспомогательными методами для работы с изображениями.
22
- */
23
- protected readonly imageHelper: ScImageHelper;
24
20
  static ɵfac: i0.ɵɵFactoryDeclaration<ScNewsCardComponent, never>;
25
21
  static ɵcmp: i0.ɵɵComponentDeclaration<ScNewsCardComponent, "sc-news-card", never, { "news": { "alias": "news"; "required": true; "isSignal": true; }; "href": { "alias": "href"; "required": true; "isSignal": true; }; }, {}, never, never, false, never>;
26
22
  }
@@ -5,11 +5,12 @@ import * as i3 from "@angular/common";
5
5
  import * as i4 from "@angular/router";
6
6
  import * as i5 from "../share-button/sc-share-button.module";
7
7
  import * as i6 from "../pipes/sc-format-date";
8
+ import * as i7 from "@snabcentr/client-core";
8
9
  /**
9
10
  * Модуль работы с новостями.
10
11
  */
11
12
  export declare class ScNewsModule {
12
13
  static ɵfac: i0.ɵɵFactoryDeclaration<ScNewsModule, never>;
13
- static ɵmod: i0.ɵɵNgModuleDeclaration<ScNewsModule, [typeof i1.ScNewsCardComponent, typeof i2.ScNewsCardSkeletonComponent], [typeof i3.CommonModule, typeof i4.RouterModule, typeof i5.ScShareButtonModule, typeof i6.ScFormatDatePipe], [typeof i1.ScNewsCardComponent, typeof i2.ScNewsCardSkeletonComponent]>;
14
+ static ɵmod: i0.ɵɵNgModuleDeclaration<ScNewsModule, [typeof i1.ScNewsCardComponent, typeof i2.ScNewsCardSkeletonComponent], [typeof i3.CommonModule, typeof i4.RouterModule, typeof i5.ScShareButtonModule, typeof i6.ScFormatDatePipe, typeof i7.ScMediaImageTransformerPipe], [typeof i1.ScNewsCardComponent, typeof i2.ScNewsCardSkeletonComponent]>;
14
15
  static ɵinj: i0.ɵɵInjectorDeclaration<ScNewsModule>;
15
16
  }
@@ -1,5 +1,5 @@
1
- import { EventEmitter } from '@angular/core';
2
- import { ScCartItem, ScProduct } from '@snabcentr/client-core';
1
+ import { EventEmitter, InputSignal, Signal } from '@angular/core';
2
+ import { ScCartItem, ScIImage } from '@snabcentr/client-core';
3
3
  import { TuiPreviewDialogService } from '@taiga-ui/kit';
4
4
  import { AbstractScPriceCard } from '../../directives';
5
5
  import * as i0 from "@angular/core";
@@ -15,31 +15,25 @@ export declare class ScOrderItemMobileComponent extends AbstractScPriceCard {
15
15
  /**
16
16
  * Элемент заказа.
17
17
  */
18
- orderItem?: ScCartItem;
18
+ readonly orderItem: InputSignal<ScCartItem>;
19
19
  /**
20
20
  * Событие нажатия на дополнительные действия.
21
21
  */
22
22
  clickActionsEvent: EventEmitter<void>;
23
+ /**
24
+ * Изображение товара в заказе.
25
+ */
26
+ readonly cartImage: Signal<ScIImage>;
23
27
  /**
24
28
  * Инициирует экземпляр класса {@link ScOrderItemMobileComponent}.
25
29
  *
26
30
  * @param previewDialogService Сервис диалогового окна предварительного просмотра.
27
31
  */
28
32
  constructor(previewDialogService: TuiPreviewDialogService);
29
- /**
30
- * Продукт элемента заказа.
31
- */
32
- get product(): ScProduct | undefined;
33
33
  /**
34
34
  * Отобразить спецификацию.
35
35
  */
36
36
  showSpecification(): void;
37
- /**
38
- * Возвращает ссылку на изображение карточки товара.
39
- *
40
- * @param product Позиция товара/услуги.
41
- */
42
- getCardImage(product: ScProduct): string;
43
37
  static ɵfac: i0.ɵɵFactoryDeclaration<ScOrderItemMobileComponent, never>;
44
- static ɵcmp: i0.ɵɵComponentDeclaration<ScOrderItemMobileComponent, "sc-order-item-mobile", never, { "orderItem": { "alias": "orderItem"; "required": false; }; }, { "clickActionsEvent": "clickActionsEvent"; }, never, never, false, never>;
38
+ static ɵcmp: i0.ɵɵComponentDeclaration<ScOrderItemMobileComponent, "sc-order-item-mobile", never, { "orderItem": { "alias": "orderItem"; "required": true; "isSignal": true; }; }, { "clickActionsEvent": "clickActionsEvent"; }, never, never, false, never>;
45
39
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snabcentr/client-ui",
3
- "version": "3.32.3",
3
+ "version": "3.33.0",
4
4
  "author": "Snabcentr Ltd.",
5
5
  "repository": "https://gitlab.snabcentr.met/web/angular/snabcentr-client-ui-lib",
6
6
  "license": "Commercial",
@@ -15,7 +15,7 @@
15
15
  "@maskito/core": "^3.2.0",
16
16
  "@ng-web-apis/intersection-observer": "^4.11.1",
17
17
  "@ng-web-apis/common": "^4.11.1",
18
- "@snabcentr/client-core": "^2.52.2",
18
+ "@snabcentr/client-core": "^2.54.0",
19
19
  "@taiga-ui/addon-charts": "^4.41.0",
20
20
  "@taiga-ui/addon-commerce": "^4.41.0",
21
21
  "@taiga-ui/cdk": "^4.41.0",
package/release_notes.tmp CHANGED
@@ -1,14 +1,10 @@
1
- ## 3.32.3 (2025-06-26)
1
+ ## 3.33.0 (2025-07-03)
2
2
 
3
- ### fixed (1 change)
4
-
5
- - [#11858: Исправлена ошибка на форме добавления товара в корзину](web_soft/libs/angular/snabcentr-client-ui-lib@847c2a675ffd9e8b80d47dc6927ff6e1dbe2f3c5) ([merge request](web_soft/libs/angular/snabcentr-client-ui-lib!292))
3
+ ### added (1 change)
6
4
 
7
- ### removed (1 change)
5
+ - [#11909: Добавлена поддержка WebP изображений в компонентах товаров, новостей, баннеров и категорий](web_soft/libs/angular/snabcentr-client-ui-lib@973979a00de3a2b1509dee5343ebc97abdc1220c) ([merge request](web_soft/libs/angular/snabcentr-client-ui-lib!295))
8
6
 
9
- - [#11863: Удалена дата установки цены в плитках товаров.](web_soft/libs/angular/snabcentr-client-ui-lib@2620bdff21d10af7f54d7a93f307fcb3bc0408b7) ([merge request](web_soft/libs/angular/snabcentr-client-ui-lib!291))
10
-
11
- ### changed (1 change)
7
+ ### fixed (1 change)
12
8
 
13
- - [#11836: Доработаны формулировки alt-текстов изображений в компонентах....](web_soft/libs/angular/snabcentr-client-ui-lib@cddb9a86e0e2cc8a336d1088889e0424b86d530b) ([merge request](web_soft/libs/angular/snabcentr-client-ui-lib!290))
9
+ - [#11775: Исправлена ошибка добавления измеряемого товара в корзину.](web_soft/libs/angular/snabcentr-client-ui-lib@2e94b690a62736a481c061745ead0eebb6cacc2d) ([merge request](web_soft/libs/angular/snabcentr-client-ui-lib!294))
14
10
 
@@ -1323,10 +1323,6 @@ video {
1323
1323
  --tw-gradient-to: var(--tui-background-base) var(--tw-gradient-to-position);
1324
1324
  }
1325
1325
 
1326
- .bg-\[length\:100\%_100\%\] {
1327
- background-size: 100% 100%;
1328
- }
1329
-
1330
1326
  .bg-cover {
1331
1327
  background-size: cover;
1332
1328
  }
@@ -1,110 +0,0 @@
1
- import { NgIf } from '@angular/common';
2
- import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
3
- import { toSignal } from '@angular/core/rxjs-interop';
4
- import { FormControl, ReactiveFormsModule } from '@angular/forms';
5
- import { WA_WINDOW } from '@ng-web-apis/common';
6
- import { ScCartService, ScUploadedFile } from '@snabcentr/client-core';
7
- import { tuiIsPresent } from '@taiga-ui/cdk';
8
- import { TuiButton, TuiLink, TuiLoader } from '@taiga-ui/core';
9
- import { TuiButtonLoading, TuiFiles } from '@taiga-ui/kit';
10
- import { POLYMORPHEUS_CONTEXT } from '@taiga-ui/polymorpheus';
11
- import { filter, map, Observable, share, startWith, Subject, switchMap, tap } from 'rxjs';
12
- import * as i0 from "@angular/core";
13
- import * as i1 from "@taiga-ui/kit";
14
- import * as i2 from "@angular/forms";
15
- /**
16
- * Компонент диалога для добавления товаров в корзину из CSV файла.
17
- */
18
- export class ScCarAddProductsFromCsvDialogComponent {
19
- constructor() {
20
- /**
21
- * Контекст диалогового окна, в котором открыт компонент.
22
- */
23
- this.context = inject(POLYMORPHEUS_CONTEXT);
24
- /**
25
- * Сервис для работы с корзиной.
26
- */
27
- this.cartService = inject(ScCartService);
28
- /**
29
- * Объект окна.
30
- */
31
- this.window = inject(WA_WINDOW);
32
- /**
33
- * {@link Subject} события скачивания цен каталога.
34
- */
35
- this.onDownloadClick = new Subject();
36
- /**
37
- * {@link Observable} запроса на скачивание цен каталога.
38
- */
39
- this.downloadRequest$ = this.onDownloadClick.pipe(switchMap(() => this.cartService.getCartCsvExample$().pipe(tap((blob) => {
40
- this.downloadExampleFile(blob);
41
- }), startWith(null))), share(),
42
- // eslint-disable-next-line unicorn/no-useless-undefined
43
- startWith(undefined));
44
- /**
45
- * Признак того, что запрос выполняется.
46
- */
47
- this.isDownloadLoading = toSignal(this.downloadRequest$.pipe(map((value) => value === null)), {
48
- initialValue: false,
49
- });
50
- /**
51
- * {@link Subject} события отправки формы.
52
- */
53
- this.onSubmit$ = new Subject();
54
- /**
55
- * {@link Observable} запроса на добавление товаров из CSV файла.
56
- */
57
- this.submitRequest$ = this.onSubmit$.pipe(map(() => this.control.value), filter(tuiIsPresent), switchMap((file) => new Observable((observer) => {
58
- const reader = new FileReader();
59
- reader.addEventListener('load', () => {
60
- observer.next(new ScUploadedFile(file.name, reader.result));
61
- });
62
- reader.addEventListener('error', (e) => {
63
- observer.error(e);
64
- });
65
- reader.readAsDataURL(file);
66
- return () => {
67
- reader.abort();
68
- };
69
- })), switchMap((file) => this.cartService.addProductsFromCsv$(file).pipe(tap(() => {
70
- this.context.$implicit.complete();
71
- }), startWith(null))));
72
- /**
73
- * Признак того, что запрос на добавление товаров выполняется.
74
- */
75
- this.isSubmitLoading = toSignal(this.submitRequest$.pipe(map((value) => value === null)), {
76
- initialValue: false,
77
- });
78
- /**
79
- * Поле для загрузки файла.
80
- */
81
- this.control = new FormControl(null);
82
- }
83
- /**
84
- * Метод для удаления загруженного файла.
85
- */
86
- removeFile() {
87
- this.control.setValue(null);
88
- }
89
- /**
90
- * Метод для скачивания примера файла.
91
- *
92
- * @param blob Бинарный объект.
93
- */
94
- downloadExampleFile(blob) {
95
- const url = this.window.URL.createObjectURL(blob);
96
- // используем ссылку и download, чтобы указать название файла.
97
- const a = this.window.document.createElement('a');
98
- a.href = url;
99
- a.download = 'Пример файла добавления товаров в корзину.csv';
100
- a.click();
101
- this.window.URL.revokeObjectURL(url);
102
- }
103
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ScCarAddProductsFromCsvDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
104
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ScCarAddProductsFromCsvDialogComponent, isStandalone: true, selector: "sc-car-add-products-from-csv-dialog", ngImport: i0, template: "<div class=\"flex flex-col items-center gap-8\">\n <tui-loader\n [overlay]=\"true\"\n [showLoader]=\"isDownloadLoading()\"\n size=\"s\"\n class=\"mt-8\"\n >\n <button\n tuiLink\n [pseudo]=\"true\"\n type=\"button\"\n (click)=\"onDownloadClick.next()\"\n >\n \u041F\u0440\u0438\u043C\u0435\u0440 .csv \u0444\u0430\u0439\u043B\u0430\n </button>\n </tui-loader>\n\n <div class=\"flex w-full flex-col gap-1\">\n <label\n tuiInputFiles\n class=\"w-full\"\n >\n <input\n accept=\"text/csv\"\n tuiInputFiles\n [formControl]=\"control\"\n />\n </label>\n\n <tui-files class=\"tui-space_top-1\">\n <tui-file\n *ngIf=\"control.value as file\"\n [file]=\"file\"\n (remove)=\"removeFile()\"\n />\n </tui-files>\n </div>\n <div class=\"flex gap-2\">\n <button\n tuiButton\n [disabled]=\"!control.value\"\n [loading]=\"isSubmitLoading()\"\n iconStart=\"@tui.sc.send\"\n class=\"self-center\"\n (click)=\"onSubmit$.next()\"\n >\n \u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C\n </button>\n <button\n tuiButton\n (click)=\"context.$implicit.complete()\"\n type=\"button\"\n appearance=\"secondary\"\n >\n \u041E\u0442\u043C\u0435\u043D\u0430\n </button>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: TuiLink, selector: "a[tuiLink], button[tuiLink]", inputs: ["pseudo"] }, { kind: "component", type: TuiLoader, selector: "tui-loader", inputs: ["size", "inheritColor", "overlay", "textContent", "showLoader"] }, { kind: "component", type: i1.TuiFile, selector: "tui-file,a[tuiFile],button[tuiFile]", inputs: ["file", "state", "size", "showDelete", "showSize", "leftContent"], outputs: ["remove"] }, { kind: "component", type: i1.TuiInputFiles, selector: "label[tuiInputFiles]" }, { kind: "component", type: i1.TuiFilesComponent, selector: "tui-files", inputs: ["max", "expanded"], outputs: ["expandedChange"] }, { kind: "directive", type: i1.TuiInputFilesDirective, selector: "input[tuiInputFiles]", outputs: ["reject"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.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: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
105
- }
106
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ScCarAddProductsFromCsvDialogComponent, decorators: [{
107
- type: Component,
108
- args: [{ standalone: true, selector: 'sc-car-add-products-from-csv-dialog', imports: [TuiLink, TuiLoader, TuiFiles, ReactiveFormsModule, NgIf, TuiButton, TuiButtonLoading], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"flex flex-col items-center gap-8\">\n <tui-loader\n [overlay]=\"true\"\n [showLoader]=\"isDownloadLoading()\"\n size=\"s\"\n class=\"mt-8\"\n >\n <button\n tuiLink\n [pseudo]=\"true\"\n type=\"button\"\n (click)=\"onDownloadClick.next()\"\n >\n \u041F\u0440\u0438\u043C\u0435\u0440 .csv \u0444\u0430\u0439\u043B\u0430\n </button>\n </tui-loader>\n\n <div class=\"flex w-full flex-col gap-1\">\n <label\n tuiInputFiles\n class=\"w-full\"\n >\n <input\n accept=\"text/csv\"\n tuiInputFiles\n [formControl]=\"control\"\n />\n </label>\n\n <tui-files class=\"tui-space_top-1\">\n <tui-file\n *ngIf=\"control.value as file\"\n [file]=\"file\"\n (remove)=\"removeFile()\"\n />\n </tui-files>\n </div>\n <div class=\"flex gap-2\">\n <button\n tuiButton\n [disabled]=\"!control.value\"\n [loading]=\"isSubmitLoading()\"\n iconStart=\"@tui.sc.send\"\n class=\"self-center\"\n (click)=\"onSubmit$.next()\"\n >\n \u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C\n </button>\n <button\n tuiButton\n (click)=\"context.$implicit.complete()\"\n type=\"button\"\n appearance=\"secondary\"\n >\n \u041E\u0442\u043C\u0435\u043D\u0430\n </button>\n </div>\n</div>\n" }]
109
- }] });
110
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2MtY2FyLWFkZC1wcm9kdWN0cy1mcm9tLWNzdi1kaWFsb2cuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY2xpZW50LXVpL2NhcnQvc2MtY2FyLWFkZC1wcm9kdWN0cy1mcm9tLWNzdi1kaWFsb2cvc2MtY2FyLWFkZC1wcm9kdWN0cy1mcm9tLWNzdi1kaWFsb2cuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY2xpZW50LXVpL2NhcnQvc2MtY2FyLWFkZC1wcm9kdWN0cy1mcm9tLWNzdi1kaWFsb2cvc2MtY2FyLWFkZC1wcm9kdWN0cy1mcm9tLWNzdi1kaWFsb2cuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3ZDLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFVLE1BQU0sZUFBZSxDQUFDO0FBQ25GLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN0RCxPQUFPLEVBQUUsV0FBVyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDbEUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxhQUFhLEVBQUUsY0FBYyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDdkUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM3QyxPQUFPLEVBQUUsU0FBUyxFQUFvQixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDakYsT0FBTyxFQUFFLGdCQUFnQixFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsTUFBTSxF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QUFFLElBQUksRUFBRSxTQUFTLEVBQUUsZ0JBQWdCLENBQUMsbUJBQzlFLHVCQUF1QixDQUFDLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBOZ0lmIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIGluamVjdCwgU2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyB0b1NpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcbmltcG9ydCB7IEZvcm1Db250cm9sLCBSZWFjdGl2ZUZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgV0FfV0lORE9XIH0gZnJvbSAnQG5nLXdlYi1hcGlzL2NvbW1vbic7XG5pbXBvcnQgeyBTY0NhcnRTZXJ2aWNlLCBTY1VwbG9hZGVkRmlsZSB9IGZyb20gJ0BzbmFiY2VudHIvY2xpZW50LWNvcmUnO1xuaW1wb3J0IHsgdHVpSXNQcmVzZW50IH0gZnJvbSAnQHRhaWdhLXVpL2Nkayc7XG5pbXBvcnQgeyBUdWlCdXR0b24sIFR1aURpYWxvZ0NvbnRleHQsIFR1aUxpbmssIFR1aUxvYWRlciB9IGZyb20gJ0B0YWlnYS11aS9jb3JlJztcbmltcG9ydCB7IFR1aUJ1dHRvbkxvYWRpbmcsIFR1aUZpbGVzIH0gZnJvbSAnQHRhaWdhLXVpL2tpdCc7XG5pbXBvcnQgeyBQT0xZTU9SUEhFVVNfQ09OVEVYVCB9IGZyb20gJ0B0YWlnYS11aS9wb2x5bW9ycGhldXMnO1xuaW1wb3J0IHsgZmlsdGVyLCBtYXAsIE9ic2VydmFibGUsIHNoYXJlLCBzdGFydFdpdGgsIFN1YmplY3QsIHN3aXRjaE1hcCwgdGFwIH0gZnJvbSAncnhqcyc7XG5cbi8qKlxuICog0JrQvtC80L/QvtC90LXQvdGCINC00LjQsNC70L7Qs9CwINC00LvRjyDQtNC+0LHQsNCy0LvQtdC90LjRjyDRgtC+0LLQsNGA0L7QsiDQsiDQutC+0YDQt9C40L3RgyDQuNC3IENTViDRhNCw0LnQu9CwLlxuICovXG5AQ29tcG9uZW50KHtcbiAgICBzdGFuZGFsb25lOiB0cnVlLFxuICAgIHNlbGVjdG9yOiAnc2MtY2FyLWFkZC1wcm9kdWN0cy1mcm9tLWNzdi1kaWFsb2cnLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9zYy1jYXItYWRkLXByb2R1Y3RzLWZyb20tY3N2LWRpYWxvZy5jb21wb25lbnQuaHRtbCcsXG4gICAgaW1wb3J0czogW1R1aUxpbmssIFR1aUxvYWRlciwgVHVpRmlsZXMsIFJlYWN0aXZlRm9ybXNNb2R1bGUsIE5nSWYsIFR1aUJ1dHRvbiwgVHVpQnV0dG9uTG9hZGluZ10sXG4gICAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIFNjQ2FyQWRkUHJvZHVjdHNGcm9tQ3N2RGlhbG9nQ29tcG9uZW50IHtcbiAgICAvKipcbiAgICAgKiDQmtC+0L3RgtC10LrRgdGCINC00LjQsNC70L7Qs9C+0LLQvtCz0L4g0L7QutC90LAsINCyINC60L7RgtC+0YDQvtC8INC+0YLQutGA0YvRgiDQutC+0LzQv9C+0L3QtdC90YIuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGNvbnRleHQ6IFR1aURpYWxvZ0NvbnRleHQgPSBpbmplY3Q8VHVpRGlhbG9nQ29udGV4dD4oUE9MWU1PUlBIRVVTX0NPTlRFWFQpO1xuXG4gICAgLyoqXG4gICAgICog0KHQtdGA0LLQuNGBINC00LvRjyDRgNCw0LHQvtGC0Ysg0YEg0LrQvtGA0LfQuNC90L7QuS5cbiAgICAgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IGNhcnRTZXJ2aWNlOiBTY0NhcnRTZXJ2aWNlID0gaW5qZWN0KFNjQ2FydFNlcnZpY2UpO1xuXG4gICAgLyoqXG4gICAgICog0J7QsdGK0LXQutGCINC+0LrQvdCwLlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgd2luZG93OiBXaW5kb3cgJiB0eXBlb2YgZ2xvYmFsVGhpcyA9IGluamVjdDxXaW5kb3cgJiB0eXBlb2YgZ2xvYmFsVGhpcz4oV0FfV0lORE9XKTtcblxuICAgIC8qKlxuICAgICAqIHtAbGluayBTdWJqZWN0fSDRgdC+0LHRi9GC0LjRjyDRgdC60LDRh9C40LLQsNC90LjRjyDRhtC10L0g0LrQsNGC0LDQu9C+0LPQsC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgb25Eb3dubG9hZENsaWNrOiBTdWJqZWN0PHZvaWQ+ID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAgIC8qKlxuICAgICAqIHtAbGluayBPYnNlcnZhYmxlfSDQt9Cw0L/RgNC+0YHQsCDQvdCwINGB0LrQsNGH0LjQstCw0L3QuNC1INGG0LXQvSDQutCw0YLQsNC70L7Qs9CwLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZWFkb25seSBkb3dubG9hZFJlcXVlc3QkID0gdGhpcy5vbkRvd25sb2FkQ2xpY2sucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKCgpID0+XG4gICAgICAgICAgICB0aGlzLmNhcnRTZXJ2aWNlLmdldENhcnRDc3ZFeGFtcGxlJCgpLnBpcGUoXG4gICAgICAgICAgICAgICAgdGFwKChibG9iOiBCbG9iKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZG93bmxvYWRFeGFtcGxlRmlsZShibG9iKTtcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICBzdGFydFdpdGgobnVsbClcbiAgICAgICAgICAgIClcbiAgICAgICAgKSxcbiAgICAgICAgc2hhcmUoKSxcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHVuaWNvcm4vbm8tdXNlbGVzcy11bmRlZmluZWRcbiAgICAgICAgc3RhcnRXaXRoKHVuZGVmaW5lZClcbiAgICApO1xuXG4gICAgLyoqXG4gICAgICog0J/RgNC40LfQvdCw0Log0YLQvtCz0L4sINGH0YLQviDQt9Cw0L/RgNC+0YEg0LLRi9C/0L7Qu9C90Y/QtdGC0YHRjy5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgaXNEb3dubG9hZExvYWRpbmc6IFNpZ25hbDxib29sZWFuPiA9IHRvU2lnbmFsKHRoaXMuZG93bmxvYWRSZXF1ZXN0JC5waXBlKG1hcCgodmFsdWUpID0+IHZhbHVlID09PSBudWxsKSksIHtcbiAgICAgICAgaW5pdGlhbFZhbHVlOiBmYWxzZSxcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIHtAbGluayBTdWJqZWN0fSDRgdC+0LHRi9GC0LjRjyDQvtGC0L/RgNCw0LLQutC4INGE0L7RgNC80YsuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IG9uU3VibWl0JDogU3ViamVjdDx2b2lkPiA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgICAvKipcbiAgICAgKiB7QGxpbmsgT2JzZXJ2YWJsZX0g0LfQsNC/0YDQvtGB0LAg0L3QsCDQtNC+0LHQsNCy0LvQtdC90LjQtSDRgtC+0LLQsNGA0L7QsiDQuNC3IENTViDRhNCw0LnQu9CwLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZWFkb25seSBzdWJtaXRSZXF1ZXN0JCA9IHRoaXMub25TdWJtaXQkLnBpcGUoXG4gICAgICAgIG1hcCgoKSA9PiB0aGlzLmNvbnRyb2wudmFsdWUpLFxuICAgICAgICBmaWx0ZXIodHVpSXNQcmVzZW50KSxcbiAgICAgICAgc3dpdGNoTWFwKFxuICAgICAgICAgICAgKGZpbGU6IEZpbGUpID0+XG4gICAgICAgICAgICAgICAgbmV3IE9ic2VydmFibGU8U2NVcGxvYWRlZEZpbGU+KChvYnNlcnZlcikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xuXG4gICAgICAgICAgICAgICAgICAgIHJlYWRlci5hZGRFdmVudExpc3RlbmVyKCdsb2FkJywgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dChuZXcgU2NVcGxvYWRlZEZpbGUoZmlsZS5uYW1lLCByZWFkZXIucmVzdWx0IGFzIHN0cmluZykpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICByZWFkZXIuYWRkRXZlbnRMaXN0ZW5lcignZXJyb3InLCAoZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuZXJyb3IoZSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKGZpbGUpO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWFkZXIuYWJvcnQoKTtcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICApLFxuICAgICAgICBzd2l0Y2hNYXAoKGZpbGUpID0+XG4gICAgICAgICAgICB0aGlzLmNhcnRTZXJ2aWNlLmFkZFByb2R1Y3RzRnJvbUNzdiQoZmlsZSkucGlwZShcbiAgICAgICAgICAgICAgICB0YXAoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRleHQuJGltcGxpY2l0LmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgc3RhcnRXaXRoKG51bGwpXG4gICAgICAgICAgICApXG4gICAgICAgIClcbiAgICApO1xuXG4gICAgLyoqXG4gICAgICog0J/RgNC40LfQvdCw0Log0YLQvtCz0L4sINGH0YLQviDQt9Cw0L/RgNC+0YEg0L3QsCDQtNC+0LHQsNCy0LvQtdC90LjQtSDRgtC+0LLQsNGA0L7QsiDQstGL0L/QvtC70L3Rj9C10YLRgdGPLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZWFkb25seSBpc1N1Ym1pdExvYWRpbmc6IFNpZ25hbDxib29sZWFuPiA9IHRvU2lnbmFsKHRoaXMuc3VibWl0UmVxdWVzdCQucGlwZShtYXAoKHZhbHVlKSA9PiB2YWx1ZSA9PT0gbnVsbCkpLCB7XG4gICAgICAgIGluaXRpYWxWYWx1ZTogZmFsc2UsXG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiDQn9C+0LvQtSDQtNC70Y8g0LfQsNCz0YDRg9C30LrQuCDRhNCw0LnQu9CwLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZWFkb25seSBjb250cm9sOiBGb3JtQ29udHJvbDxGaWxlIHwgbnVsbD4gPSBuZXcgRm9ybUNvbnRyb2w8RmlsZSB8IG51bGw+KG51bGwpO1xuXG4gICAgLyoqXG4gICAgICog0JzQtdGC0L7QtCDQtNC70Y8g0YPQtNCw0LvQtdC90LjRjyDQt9Cw0LPRgNGD0LbQtdC90L3QvtCz0L4g0YTQsNC50LvQsC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVtb3ZlRmlsZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jb250cm9sLnNldFZhbHVlKG51bGwpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCc0LXRgtC+0LQg0LTQu9GPINGB0LrQsNGH0LjQstCw0L3QuNGPINC/0YDQuNC80LXRgNCwINGE0LDQudC70LAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gYmxvYiDQkdC40L3QsNGA0L3Ri9C5INC+0LHRitC10LrRgi5cbiAgICAgKi9cbiAgICBwcml2YXRlIGRvd25sb2FkRXhhbXBsZUZpbGUoYmxvYjogQmxvYik6IHZvaWQge1xuICAgICAgICBjb25zdCB1cmwgPSB0aGlzLndpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKGJsb2IpO1xuICAgICAgICAvLyDQuNGB0L/QvtC70YzQt9GD0LXQvCDRgdGB0YvQu9C60YMg0LggZG93bmxvYWQsINGH0YLQvtCx0Ysg0YPQutCw0LfQsNGC0Ywg0L3QsNC30LLQsNC90LjQtSDRhNCw0LnQu9CwLlxuICAgICAgICBjb25zdCBhID0gdGhpcy53aW5kb3cuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuXG4gICAgICAgIGEuaHJlZiA9IHVybDtcbiAgICAgICAgYS5kb3dubG9hZCA9ICfQn9GA0LjQvNC10YAg0YTQsNC50LvQsCDQtNC+0LHQsNCy0LvQtdC90LjRjyDRgtC+0LLQsNGA0L7QsiDQsiDQutC+0YDQt9C40L3Rgy5jc3YnO1xuICAgICAgICBhLmNsaWNrKCk7XG4gICAgICAgIHRoaXMud2luZG93LlVSTC5yZXZva2VPYmplY3RVUkwodXJsKTtcbiAgICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwiZmxleCBmbGV4LWNvbCBpdGVtcy1jZW50ZXIgZ2FwLThcIj5cbiAgICA8dHVpLWxvYWRlclxuICAgICAgICBbb3ZlcmxheV09XCJ0cnVlXCJcbiAgICAgICAgW3Nob3dMb2FkZXJdPVwiaXNEb3dubG9hZExvYWRpbmcoKVwiXG4gICAgICAgIHNpemU9XCJzXCJcbiAgICAgICAgY2xhc3M9XCJtdC04XCJcbiAgICA+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIHR1aUxpbmtcbiAgICAgICAgICAgIFtwc2V1ZG9dPVwidHJ1ZVwiXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIChjbGljayk9XCJvbkRvd25sb2FkQ2xpY2submV4dCgpXCJcbiAgICAgICAgPlxuICAgICAgICAgICAg0J/RgNC40LzQtdGAIC5jc3Yg0YTQsNC50LvQsFxuICAgICAgICA8L2J1dHRvbj5cbiAgICA8L3R1aS1sb2FkZXI+XG5cbiAgICA8ZGl2IGNsYXNzPVwiZmxleCB3LWZ1bGwgZmxleC1jb2wgZ2FwLTFcIj5cbiAgICAgICAgPGxhYmVsXG4gICAgICAgICAgICB0dWlJbnB1dEZpbGVzXG4gICAgICAgICAgICBjbGFzcz1cInctZnVsbFwiXG4gICAgICAgID5cbiAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgIGFjY2VwdD1cInRleHQvY3N2XCJcbiAgICAgICAgICAgICAgICB0dWlJbnB1dEZpbGVzXG4gICAgICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cImNvbnRyb2xcIlxuICAgICAgICAgICAgLz5cbiAgICAgICAgPC9sYWJlbD5cblxuICAgICAgICA8dHVpLWZpbGVzIGNsYXNzPVwidHVpLXNwYWNlX3RvcC0xXCI+XG4gICAgICAgICAgICA8dHVpLWZpbGVcbiAgICAgICAgICAgICAgICAqbmdJZj1cImNvbnRyb2wudmFsdWUgYXMgZmlsZVwiXG4gICAgICAgICAgICAgICAgW2ZpbGVdPVwiZmlsZVwiXG4gICAgICAgICAgICAgICAgKHJlbW92ZSk9XCJyZW1vdmVGaWxlKClcIlxuICAgICAgICAgICAgLz5cbiAgICAgICAgPC90dWktZmlsZXM+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImZsZXggZ2FwLTJcIj5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgdHVpQnV0dG9uXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiIWNvbnRyb2wudmFsdWVcIlxuICAgICAgICAgICAgW2xvYWRpbmddPVwiaXNTdWJtaXRMb2FkaW5nKClcIlxuICAgICAgICAgICAgaWNvblN0YXJ0PVwiQHR1aS5zYy5zZW5kXCJcbiAgICAgICAgICAgIGNsYXNzPVwic2VsZi1jZW50ZXJcIlxuICAgICAgICAgICAgKGNsaWNrKT1cIm9uU3VibWl0JC5uZXh0KClcIlxuICAgICAgICA+XG4gICAgICAgICAgICDQl9Cw0LPRgNGD0LfQuNGC0YxcbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIHR1aUJ1dHRvblxuICAgICAgICAgICAgKGNsaWNrKT1cImNvbnRleHQuJGltcGxpY2l0LmNvbXBsZXRlKClcIlxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICBhcHBlYXJhbmNlPVwic2Vjb25kYXJ5XCJcbiAgICAgICAgPlxuICAgICAgICAgICAg0J7RgtC80LXQvdCwXG4gICAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuPC9kaXY+XG4iXX0=
@@ -1,76 +0,0 @@
1
- import { ChangeDetectionStrategy, Component, HostListener, Input, signal } from '@angular/core';
2
- import { TuiHovered, TuiRepeatTimes } from '@taiga-ui/cdk';
3
- import { TuiButton } from '@taiga-ui/core';
4
- import * as i0 from "@angular/core";
5
- /**
6
- * Компонент просмотра изображений через событие наведения.
7
- */
8
- export class HoverImageCarouselComponent {
9
- constructor() {
10
- /**
11
- * Массив изображений.
12
- */
13
- this.images = [];
14
- /**
15
- * Признак что необходимо отобразить элементы управления.
16
- */
17
- this.isShowActions = true;
18
- /**
19
- * {@link WritableSignal} для отслеживания текущего индекса изображения.
20
- */
21
- this.currentIndex = signal(0);
22
- }
23
- /**
24
- * Обработчик события `mousemove.silent`.
25
- *
26
- * @param offsetX Отступ курсора мыши по оси X от края {@link HTMLElement}.
27
- * @param target Объект {@link HTMLElement} в котором лежат изображения
28
- */
29
- onHover(offsetX, target) {
30
- if (this.images.length <= 1 || offsetX < 0) {
31
- return;
32
- }
33
- // new Event().preventDefault
34
- const elementWidth = target.offsetWidth;
35
- const hoverPercentage = offsetX / elementWidth;
36
- const newIndex = Math.floor(hoverPercentage * this.images.length);
37
- this.currentIndex.set(newIndex);
38
- }
39
- /**
40
- * Обработчик события `mouseleave.silent`.
41
- */
42
- onLeave() {
43
- if (this.images.length <= 1) {
44
- return;
45
- }
46
- this.currentIndex.set(0);
47
- }
48
- /**
49
- * Обработчик события наведения указателя мыши на точку.
50
- *
51
- * @param hovered Признак что указатель мыши наведен на точку.
52
- * @param index Индекс изображения, который соответствует точке.
53
- */
54
- onDotHovered(hovered, index) {
55
- if (hovered) {
56
- this.currentIndex.set(index);
57
- }
58
- }
59
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HoverImageCarouselComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
60
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: HoverImageCarouselComponent, isStandalone: true, selector: "sc-hover-image-carousel", inputs: { images: "images", isShowActions: "isShowActions" }, host: { listeners: { "mousemove.silent": "onHover($event.offsetX,$event.target)", "mouseleave.silent": "onLeave()" } }, ngImport: i0, template: "<div\n class=\"overflow-hidden rounded-xl\"\n [class.mb-2]=\"images.length <= 1 && isShowActions\"\n [style.aspect-ratio]=\"'20/19'\"\n>\n <img\n [src]=\"images[currentIndex()]\"\n class=\"size-full rounded-xl object-contain\"\n />\n</div>\n\n@if (images.length > 1 && isShowActions) {\n <div\n (mousemove.silent)=\"$event.stopPropagation()\"\n class=\"flex justify-center\"\n >\n <button\n *tuiRepeatTimes=\"let indexItem of images.length\"\n #element\n tuiButton\n type=\"button\"\n class=\"button button_small\"\n [appearance]=\"indexItem === currentIndex() ? 'primary' : 'secondary'\"\n (tuiHoveredChange)=\"onDotHovered($event, indexItem)\"\n ></button>\n </div>\n}\n", styles: [".button{flex-shrink:0}.button:first-child{margin-inline-start:0}.button:last-child{margin-inline-end:0}.button_small{inline-size:.5rem;block-size:.5rem;font-size:0;padding:0;margin:0}.button_small:not(:first-child){margin-left:.5rem}\n"], dependencies: [{ kind: "directive", type: TuiRepeatTimes, selector: "[tuiRepeatTimes][tuiRepeatTimesOf]", inputs: ["tuiRepeatTimesOf"] }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { kind: "directive", type: TuiHovered, selector: "[tuiHoveredChange]", outputs: ["tuiHoveredChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
61
- }
62
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HoverImageCarouselComponent, decorators: [{
63
- type: Component,
64
- args: [{ standalone: true, selector: 'sc-hover-image-carousel', imports: [TuiRepeatTimes, TuiButton, TuiHovered], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"overflow-hidden rounded-xl\"\n [class.mb-2]=\"images.length <= 1 && isShowActions\"\n [style.aspect-ratio]=\"'20/19'\"\n>\n <img\n [src]=\"images[currentIndex()]\"\n class=\"size-full rounded-xl object-contain\"\n />\n</div>\n\n@if (images.length > 1 && isShowActions) {\n <div\n (mousemove.silent)=\"$event.stopPropagation()\"\n class=\"flex justify-center\"\n >\n <button\n *tuiRepeatTimes=\"let indexItem of images.length\"\n #element\n tuiButton\n type=\"button\"\n class=\"button button_small\"\n [appearance]=\"indexItem === currentIndex() ? 'primary' : 'secondary'\"\n (tuiHoveredChange)=\"onDotHovered($event, indexItem)\"\n ></button>\n </div>\n}\n", styles: [".button{flex-shrink:0}.button:first-child{margin-inline-start:0}.button:last-child{margin-inline-end:0}.button_small{inline-size:.5rem;block-size:.5rem;font-size:0;padding:0;margin:0}.button_small:not(:first-child){margin-left:.5rem}\n"] }]
65
- }], propDecorators: { images: [{
66
- type: Input
67
- }], isShowActions: [{
68
- type: Input
69
- }], onHover: [{
70
- type: HostListener,
71
- args: ['mousemove.silent', ['$event.offsetX', '$event.target']]
72
- }], onLeave: [{
73
- type: HostListener,
74
- args: ['mouseleave.silent']
75
- }] } });
76
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG92ZXItaW1hZ2UtY2Fyb3VzZWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY2xpZW50LXVpL2NhdGFsb2cvaG92ZXItaW1hZ2UtY2Fyb3VzZWwvaG92ZXItaW1hZ2UtY2Fyb3VzZWwuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY2xpZW50LXVpL2NhdGFsb2cvaG92ZXItaW1hZ2UtY2Fyb3VzZWwvaG92ZXItaW1hZ2UtY2Fyb3VzZWwuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBa0IsTUFBTSxlQUFlLENBQUM7QUFDaEgsT0FBTyxFQUFFLFVBQVUsRUFBRSxjQUFjLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0QsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDOztBQUUzQzs7R0FFRztBQVNILE1BQU0sT0FBTywyQkFBMkI7SUFSeEM7UUFTSTs7V0FFRztRQUVJLFdBQU0sR0FBYSxFQUFFLENBQUM7UUFFN0I7O1dBRUc7UUFFSSxrQkFBYSxHQUFZLElBQUksQ0FBQztRQUVyQzs7V0FFRztRQUNJLGlCQUFZLEdBQTJCLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztLQTJDM0Q7SUF6Q0c7Ozs7O09BS0c7SUFFSyxPQUFPLENBQUMsT0FBZSxFQUFFLE1BQW1CO1FBQ2hELElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLElBQUksQ0FBQyxJQUFJLE9BQU8sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN6QyxPQUFPO1FBQ1gsQ0FBQztRQUNELDZCQUE2QjtRQUM3QixNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDO1FBQ3hDLE1BQU0sZUFBZSxHQUFHLE9BQU8sR0FBRyxZQUFZLENBQUM7UUFDL0MsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNsRSxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRUQ7O09BRUc7SUFFSyxPQUFPO1FBQ1gsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUMxQixPQUFPO1FBQ1gsQ0FBQztRQUVELElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzdCLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNPLFlBQVksQ0FBQyxPQUFnQixFQUFFLEtBQWE7UUFDbEQsSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUNWLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pDLENBQUM7SUFDTCxDQUFDOytHQTFEUSwyQkFBMkI7bUdBQTNCLDJCQUEyQix5UUNmeEMsaXpCQTJCQSxxU0RqQmMsY0FBYyw2R0FBRSxTQUFTLG9JQUFFLFVBQVU7OzRGQUt0QywyQkFBMkI7a0JBUnZDLFNBQVM7aUNBQ00sSUFBSSxZQUNOLHlCQUF5QixXQUMxQixDQUFDLGNBQWMsRUFBRSxTQUFTLEVBQUUsVUFBVSxDQUFDLG1CQUcvQix1QkFBdUIsQ0FBQyxNQUFNOzhCQU94QyxNQUFNO3NCQURaLEtBQUs7Z0JBT0MsYUFBYTtzQkFEbkIsS0FBSztnQkFlRSxPQUFPO3NCQURkLFlBQVk7dUJBQUMsa0JBQWtCLEVBQUUsQ0FBQyxnQkFBZ0IsRUFBRSxlQUFlLENBQUM7Z0JBZ0I3RCxPQUFPO3NCQURkLFlBQVk7dUJBQUMsbUJBQW1CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgSG9zdExpc3RlbmVyLCBJbnB1dCwgc2lnbmFsLCBXcml0YWJsZVNpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgVHVpSG92ZXJlZCwgVHVpUmVwZWF0VGltZXMgfSBmcm9tICdAdGFpZ2EtdWkvY2RrJztcbmltcG9ydCB7IFR1aUJ1dHRvbiB9IGZyb20gJ0B0YWlnYS11aS9jb3JlJztcblxuLyoqXG4gKiDQmtC+0LzQv9C+0L3QtdC90YIg0L/RgNC+0YHQvNC+0YLRgNCwINC40LfQvtCx0YDQsNC20LXQvdC40Lkg0YfQtdGA0LXQtyDRgdC+0LHRi9GC0LjQtSDQvdCw0LLQtdC00LXQvdC40Y8uXG4gKi9cbkBDb21wb25lbnQoe1xuICAgIHN0YW5kYWxvbmU6IHRydWUsXG4gICAgc2VsZWN0b3I6ICdzYy1ob3Zlci1pbWFnZS1jYXJvdXNlbCcsXG4gICAgaW1wb3J0czogW1R1aVJlcGVhdFRpbWVzLCBUdWlCdXR0b24sIFR1aUhvdmVyZWRdLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9ob3Zlci1pbWFnZS1jYXJvdXNlbC5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmw6ICcuL2hvdmVyLWltYWdlLWNhcm91c2VsLmNvbXBvbmVudC5zY3NzJyxcbiAgICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgSG92ZXJJbWFnZUNhcm91c2VsQ29tcG9uZW50IHtcbiAgICAvKipcbiAgICAgKiDQnNCw0YHRgdC40LIg0LjQt9C+0LHRgNCw0LbQtdC90LjQuS5cbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBpbWFnZXM6IHN0cmluZ1tdID0gW107XG5cbiAgICAvKipcbiAgICAgKiDQn9GA0LjQt9C90LDQuiDRh9GC0L4g0L3QtdC+0LHRhdC+0LTQuNC80L4g0L7RgtC+0LHRgNCw0LfQuNGC0Ywg0Y3Qu9C10LzQtdC90YLRiyDRg9C/0YDQsNCy0LvQtdC90LjRjy5cbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIHB1YmxpYyBpc1Nob3dBY3Rpb25zOiBib29sZWFuID0gdHJ1ZTtcblxuICAgIC8qKlxuICAgICAqIHtAbGluayBXcml0YWJsZVNpZ25hbH0g0LTQu9GPINC+0YLRgdC70LXQttC40LLQsNC90LjRjyDRgtC10LrRg9GJ0LXQs9C+INC40L3QtNC10LrRgdCwINC40LfQvtCx0YDQsNC20LXQvdC40Y8uXG4gICAgICovXG4gICAgcHVibGljIGN1cnJlbnRJbmRleDogV3JpdGFibGVTaWduYWw8bnVtYmVyPiA9IHNpZ25hbCgwKTtcblxuICAgIC8qKlxuICAgICAqINCe0LHRgNCw0LHQvtGC0YfQuNC6INGB0L7QsdGL0YLQuNGPIGBtb3VzZW1vdmUuc2lsZW50YC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBvZmZzZXRYINCe0YLRgdGC0YPQvyDQutGD0YDRgdC+0YDQsCDQvNGL0YjQuCDQv9C+INC+0YHQuCBYINC+0YIg0LrRgNCw0Y8ge0BsaW5rIEhUTUxFbGVtZW50fS5cbiAgICAgKiBAcGFyYW0gdGFyZ2V0INCe0LHRitC10LrRgiB7QGxpbmsgSFRNTEVsZW1lbnR9INCyINC60L7RgtC+0YDQvtC8INC70LXQttCw0YIg0LjQt9C+0LHRgNCw0LbQtdC90LjRj1xuICAgICAqL1xuICAgIEBIb3N0TGlzdGVuZXIoJ21vdXNlbW92ZS5zaWxlbnQnLCBbJyRldmVudC5vZmZzZXRYJywgJyRldmVudC50YXJnZXQnXSlcbiAgICBwcml2YXRlIG9uSG92ZXIob2Zmc2V0WDogbnVtYmVyLCB0YXJnZXQ6IEhUTUxFbGVtZW50KTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLmltYWdlcy5sZW5ndGggPD0gMSB8fCBvZmZzZXRYIDwgMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIG5ldyBFdmVudCgpLnByZXZlbnREZWZhdWx0XG4gICAgICAgIGNvbnN0IGVsZW1lbnRXaWR0aCA9IHRhcmdldC5vZmZzZXRXaWR0aDtcbiAgICAgICAgY29uc3QgaG92ZXJQZXJjZW50YWdlID0gb2Zmc2V0WCAvIGVsZW1lbnRXaWR0aDtcbiAgICAgICAgY29uc3QgbmV3SW5kZXggPSBNYXRoLmZsb29yKGhvdmVyUGVyY2VudGFnZSAqIHRoaXMuaW1hZ2VzLmxlbmd0aCk7XG4gICAgICAgIHRoaXMuY3VycmVudEluZGV4LnNldChuZXdJbmRleCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0J7QsdGA0LDQsdC+0YLRh9C40Log0YHQvtCx0YvRgtC40Y8gYG1vdXNlbGVhdmUuc2lsZW50YC5cbiAgICAgKi9cbiAgICBASG9zdExpc3RlbmVyKCdtb3VzZWxlYXZlLnNpbGVudCcpXG4gICAgcHJpdmF0ZSBvbkxlYXZlKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5pbWFnZXMubGVuZ3RoIDw9IDEpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY3VycmVudEluZGV4LnNldCgwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQntCx0YDQsNCx0L7RgtGH0LjQuiDRgdC+0LHRi9GC0LjRjyDQvdCw0LLQtdC00LXQvdC40Y8g0YPQutCw0LfQsNGC0LXQu9GPINC80YvRiNC4INC90LAg0YLQvtGH0LrRgy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBob3ZlcmVkINCf0YDQuNC30L3QsNC6INGH0YLQviDRg9C60LDQt9Cw0YLQtdC70Ywg0LzRi9GI0Lgg0L3QsNCy0LXQtNC10L0g0L3QsCDRgtC+0YfQutGDLlxuICAgICAqIEBwYXJhbSBpbmRleCDQmNC90LTQtdC60YEg0LjQt9C+0LHRgNCw0LbQtdC90LjRjywg0LrQvtGC0L7RgNGL0Lkg0YHQvtC+0YLQstC10YLRgdGC0LLRg9C10YIg0YLQvtGH0LrQtS5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgb25Eb3RIb3ZlcmVkKGhvdmVyZWQ6IGJvb2xlYW4sIGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgaWYgKGhvdmVyZWQpIHtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudEluZGV4LnNldChpbmRleCk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCI8ZGl2XG4gICAgY2xhc3M9XCJvdmVyZmxvdy1oaWRkZW4gcm91bmRlZC14bFwiXG4gICAgW2NsYXNzLm1iLTJdPVwiaW1hZ2VzLmxlbmd0aCA8PSAxICYmIGlzU2hvd0FjdGlvbnNcIlxuICAgIFtzdHlsZS5hc3BlY3QtcmF0aW9dPVwiJzIwLzE5J1wiXG4+XG4gICAgPGltZ1xuICAgICAgICBbc3JjXT1cImltYWdlc1tjdXJyZW50SW5kZXgoKV1cIlxuICAgICAgICBjbGFzcz1cInNpemUtZnVsbCByb3VuZGVkLXhsIG9iamVjdC1jb250YWluXCJcbiAgICAvPlxuPC9kaXY+XG5cbkBpZiAoaW1hZ2VzLmxlbmd0aCA+IDEgJiYgaXNTaG93QWN0aW9ucykge1xuICAgIDxkaXZcbiAgICAgICAgKG1vdXNlbW92ZS5zaWxlbnQpPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCJcbiAgICAgICAgY2xhc3M9XCJmbGV4IGp1c3RpZnktY2VudGVyXCJcbiAgICA+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICp0dWlSZXBlYXRUaW1lcz1cImxldCBpbmRleEl0ZW0gb2YgaW1hZ2VzLmxlbmd0aFwiXG4gICAgICAgICAgICAjZWxlbWVudFxuICAgICAgICAgICAgdHVpQnV0dG9uXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIGNsYXNzPVwiYnV0dG9uIGJ1dHRvbl9zbWFsbFwiXG4gICAgICAgICAgICBbYXBwZWFyYW5jZV09XCJpbmRleEl0ZW0gPT09IGN1cnJlbnRJbmRleCgpID8gJ3ByaW1hcnknIDogJ3NlY29uZGFyeSdcIlxuICAgICAgICAgICAgKHR1aUhvdmVyZWRDaGFuZ2UpPVwib25Eb3RIb3ZlcmVkKCRldmVudCwgaW5kZXhJdGVtKVwiXG4gICAgICAgID48L2J1dHRvbj5cbiAgICA8L2Rpdj5cbn1cbiJdfQ==