@colijnit/product 257.1.12 → 257.1.13

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.
@@ -14,6 +14,9 @@ export declare class ImageCarouselComponent implements OnDestroy {
14
14
  private _changeDetector;
15
15
  private _domSanitizer;
16
16
  carousel: ElementRef;
17
+ isPopupOpen: boolean;
18
+ selectedImage?: ImageViewModel;
19
+ onEsc(): void;
17
20
  showRefresh: boolean;
18
21
  set images(value: (CoDocument | string)[]);
19
22
  get images(): (CoDocument | string)[];
@@ -36,8 +39,10 @@ export declare class ImageCarouselComponent implements OnDestroy {
36
39
  handleThumbClick(index: number): void;
37
40
  onForceRenderImage(): void;
38
41
  handleShowImage(imageViewModel: ImageViewModel): void;
42
+ closePopup(): void;
39
43
  private _filterValidImages;
40
44
  private _loadAndRescaleImages;
41
45
  private _resizeAndSanitizeSource;
46
+ private _detectPreferredMime;
42
47
  private _scrollCarouselToIndex;
43
48
  }
@@ -6,11 +6,13 @@ import { ProductEventService } from '../../service/product-event.service';
6
6
  import { ArticleFullObject } from '@colijnit/articleapi/build/model/article-full-object';
7
7
  import { ProductSettingsService } from '../../service/product-settings.service';
8
8
  import { ExternalSource } from '@colijnit/articleapi/build/model/external-source.bo';
9
+ import { ProductConnectorAdapterService } from '../../service/product-connector-adapter.service';
9
10
  export declare class ProductAddtocartComponent implements OnInit, OnDestroy {
10
11
  iconCache: IconCacheService;
11
12
  private _ioneControllerService;
12
13
  private _appEventService;
13
14
  private _settingsService;
15
+ private _productConnectorAdapterService;
14
16
  readonly icon: typeof IconEnum;
15
17
  addToCartButton: ElementRef;
16
18
  article: ArticleFullObject;
@@ -29,10 +31,12 @@ export declare class ProductAddtocartComponent implements OnInit, OnDestroy {
29
31
  showRelatedPopup: EventEmitter<boolean>;
30
32
  showQuoteButton: boolean;
31
33
  private _quantity;
32
- constructor(iconCache: IconCacheService, _ioneControllerService: ProductConnectorService, _appEventService: ProductEventService, _settingsService: ProductSettingsService);
34
+ constructor(iconCache: IconCacheService, _ioneControllerService: ProductConnectorService, _appEventService: ProductEventService, _settingsService: ProductSettingsService, _productConnectorAdapterService: ProductConnectorAdapterService);
33
35
  ngOnInit(): void;
34
36
  ngOnDestroy(): void;
35
37
  handleAddToCartClick(quantity: number): Promise<void>;
36
38
  handleAddToQuoteClick(quantity: number): Promise<void>;
39
+ private _handleGeneratedArticleDirectly;
40
+ private _getGeneratedArtDirectly;
37
41
  private _getJSONFromArticleObject;
38
42
  }
@@ -50,6 +50,7 @@ export declare class ProductPageComponent implements OnInit, OnDestroy, AfterVie
50
50
  private _currentView;
51
51
  private _subs;
52
52
  private _settings;
53
+ private _pageLoadedSubscription;
53
54
  constructor(_ione: ProductConnectorService, _renderer: Renderer2, _changeDetector: ChangeDetectorRef, iconCache: IconCacheService, settingsService: ProductSettingsService, appEventService: ProductEventService);
54
55
  ngOnInit(): void;
55
56
  ngAfterViewInit(): void;
@@ -29,6 +29,7 @@ export declare class ProductConnectorAdapterService implements OnDestroy {
29
29
  getDeliveryDate2(goodId: number): Promise<DeliveryPrognosis>;
30
30
  getJsonConfiguredArticles(configuratorStatistics?: ConfiguratorStatisticsEnvironment): Promise<string>;
31
31
  getJsonArticleFlatTree(goodId: number, goodType: string, quantity: number, externalSource?: boolean, showLoader?: boolean, instanceId?: any, configuratorStatistics?: ConfiguratorStatisticsEnvironment): Promise<string>;
32
+ getGeneratedArtDirectly(goodId: number, showLoader: boolean): Promise<number>;
32
33
  getGoodIdFromArticleNr(sku: string): Promise<number>;
33
34
  getArticleFullObject(goodId: number, showLoader?: boolean): Promise<ArticleFullObject>;
34
35
  getSuperArticle(id: string, branch?: string): Promise<SuperArticle>;
@@ -13,6 +13,7 @@ export declare class ProductConnectorService implements OnDestroy {
13
13
  private _settingsService;
14
14
  get shouldShowLoader(): boolean;
15
15
  controllerInitialized: BehaviorSubject<boolean>;
16
+ articleLoaded: BehaviorSubject<boolean>;
16
17
  private _shouldShowLoader;
17
18
  private _initializing;
18
19
  private _initialized;
@@ -33,6 +34,7 @@ export declare class ProductConnectorService implements OnDestroy {
33
34
  getDeliveryDate2(goodId: number): Promise<DeliveryPrognosis>;
34
35
  getSuperArticle(id: string): Promise<SuperArticle>;
35
36
  getJsonArticleFlatTree(goodId: number, goodType: string, quantity: number, externalSource?: boolean, showLoader?: boolean, configuratorStatistics?: ConfiguratorStatisticsEnvironment): Promise<string>;
37
+ getGeneratedArtDirectly(goodId: number, showLoader?: boolean): Promise<number>;
36
38
  addWebSessionTransactionLine(transactionUuid: string, sku: string, quantity: number): Promise<string>;
37
39
  onShowLoaderChange(showLoader: boolean): void;
38
40
  }
@@ -31,8 +31,8 @@
31
31
  function Version() {
32
32
  this.name = "@colijnit/product";
33
33
  this.description = "Product detail page project for iOne";
34
- this.symVer = "257.1.12";
35
- this.publishDate = "9-7-2025 14:29:11";
34
+ this.symVer = "257.1.13";
35
+ this.publishDate = "22-8-2025 16:12:09";
36
36
  }
37
37
  return Version;
38
38
  }());
@@ -748,6 +748,17 @@
748
748
  });
749
749
  });
750
750
  };
751
+ ProductConnectorAdapterService.prototype.getGeneratedArtDirectly = function (goodId, showLoader) {
752
+ return __awaiter(this, void 0, void 0, function () {
753
+ var _this = this;
754
+ return __generator(this, function (_a) {
755
+ return [2 /*return*/, this.articleConnector.getGeneratedArtDirectly(goodId, showLoader).catch(function (messages) {
756
+ _this._eventService.errorMessage.next(messages);
757
+ return null;
758
+ })];
759
+ });
760
+ });
761
+ };
751
762
  ProductConnectorAdapterService.prototype.getGoodIdFromArticleNr = function (sku) {
752
763
  return __awaiter(this, void 0, void 0, function () {
753
764
  var response;
@@ -1195,6 +1206,7 @@
1195
1206
  this._adapterService = _adapterService;
1196
1207
  this._settingsService = _settingsService;
1197
1208
  this.controllerInitialized = new rxjs.BehaviorSubject(false);
1209
+ this.articleLoaded = new rxjs.BehaviorSubject(false);
1198
1210
  this._initializing = false;
1199
1211
  this._initialized = false;
1200
1212
  this.connectorOptions = new options.Options();
@@ -1302,6 +1314,10 @@
1302
1314
  if (showLoader === void 0) { showLoader = true; }
1303
1315
  return this._adapterService.getJsonArticleFlatTree(goodId, goodType, quantity, externalSource, showLoader, this._instanceId, configuratorStatistics);
1304
1316
  };
1317
+ ProductConnectorService.prototype.getGeneratedArtDirectly = function (goodId, showLoader) {
1318
+ if (showLoader === void 0) { showLoader = true; }
1319
+ return this._adapterService.getGeneratedArtDirectly(goodId, showLoader);
1320
+ };
1305
1321
  ProductConnectorService.prototype.addWebSessionTransactionLine = function (transactionUuid, sku, quantity) {
1306
1322
  return __awaiter(this, void 0, void 0, function () {
1307
1323
  return __generator(this, function (_a) {
@@ -1658,9 +1674,19 @@
1658
1674
  if (_this.selections.nativeElement) {
1659
1675
  _this.selections.nativeElement.forceRenderImage();
1660
1676
  }
1661
- }), this.settingsService.settingsLoaded.subscribe(function (loaded) { return _this._handleSettingsLoaded(loaded); }), this._ione.controllerInitialized.subscribe(function (initialized) {
1662
- _this.settingsLoaded = initialized;
1663
- }), this.appEventService.onAnswersAvailable.subscribe(function (answers) {
1677
+ }), this.settingsService.settingsLoaded.subscribe(function (loaded) { return _this._handleSettingsLoaded(loaded); }), this._pageLoadedSubscription = rxjs.combineLatest([
1678
+ this._ione.controllerInitialized,
1679
+ this._ione.articleLoaded
1680
+ ]).subscribe(function (_a) {
1681
+ var _b = __read(_a, 2), initialized = _b[0], articleLoaded = _b[1];
1682
+ if (initialized && articleLoaded) {
1683
+ _this.settingsLoaded = initialized;
1684
+ }
1685
+ }),
1686
+ // this._ione.controllerInitialized.subscribe((initialized: boolean) => {
1687
+ // this.settingsLoaded = initialized;
1688
+ // }),
1689
+ this.appEventService.onAnswersAvailable.subscribe(function (answers) {
1664
1690
  if (answers && _this.configurable) {
1665
1691
  _this.showAddToCart = false;
1666
1692
  }
@@ -1756,6 +1782,7 @@
1756
1782
  if (this._initializedSub) {
1757
1783
  this._initializedSub.unsubscribe();
1758
1784
  }
1785
+ this._pageLoadedSubscription.unsubscribe();
1759
1786
  this.configurator = undefined;
1760
1787
  this.selections = undefined;
1761
1788
  this.fullscreenbutton = undefined;
@@ -1791,7 +1818,8 @@
1791
1818
  this._ione.getFullArticle(this._sku).then(function (article) {
1792
1819
  _this.article = article;
1793
1820
  if (_this.article) {
1794
- _this.configurable = _this.article.goodType === 'B';
1821
+ _this.configurable = _this.article.goodType === 'B' && (_this.article.isConfigurable || _this.article.isConfigurable === undefined);
1822
+ // this.configurable = this.article.goodType === 'B';
1795
1823
  if (_this.configurable) {
1796
1824
  _this.showAddToCart = false;
1797
1825
  _this.currentView = SelectorType.TwoD;
@@ -1808,6 +1836,7 @@
1808
1836
  });
1809
1837
  _this._changeDetector.detectChanges();
1810
1838
  }
1839
+ _this._ione.articleLoaded.next(true);
1811
1840
  });
1812
1841
  }
1813
1842
  return [2 /*return*/];
@@ -1829,37 +1858,37 @@
1829
1858
  ProductPageComponent.decorators = [
1830
1859
  { type: i0.Component, args: [{
1831
1860
  selector: 'app-product-page',
1832
- template: "<ng-container *ngIf=\"settingsLoaded\">\r\n <div class=\"page-wrapper\">\r\n <div class=\"page-wrapper-content\">\r\n <div class=\"page-wrapper-left\">\r\n <div class=\"product-image-container\">\r\n <div class=\"product-page-block-selector-type\">\r\n <app-product-selector-type class=\"default-padding\"\r\n [(currentType)]=\"currentView\"\r\n [show2D]=\"configurable\"\r\n [show3D]=\"threeD\"\r\n ></app-product-selector-type>\r\n </div>\r\n <div class=\"product-page-block-image default-padding\" [class.full]=\"fullScreen\">\r\n <app-image-carousel [@toggleVisibilityByState]=\"show2D ? 'show' : 'hide'\" [images]=\"article?.images\" [showRefresh]=\"configurable && threeD\"></app-image-carousel>\r\n <ng-container *ngIf=\"settingsLoaded\">\r\n <threed-configurator #configurator class=\"threed-configurator\"\r\n [class.configurator-full-screen]=\"fullScreen\"\r\n [@toggleVisibilityByState]=\"show3D ? 'show' : 'hide'\"\r\n [@toggleFullScreen]=\"fullScreen ? 'fullscreen' : 'halfscreen'\"\r\n ></threed-configurator>\r\n </ng-container>\r\n <co-icon #fullscreenbutton class=\"fullscreen-button\" *ngIf=\"show3D\"\r\n [@toggleTopLeft]=\"fullScreen ? 'fullscreen' : 'halfscreen'\"\r\n [iconData]=\"iconCache.getIcon(fullScreenIcon)\"\r\n (click)=\"showFullScreen()\"></co-icon>\r\n <co-icon class=\"threed-watermark\" *ngIf=\"show3D && fullScreen\"\r\n [iconData]=\"iconCache.getIcon(icon.Logo)\"></co-icon>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"page-wrapper-right\">\r\n <div class=\"product-page-block-description\">\r\n <app-product-description class=\"default-padding\" [article]=\"article\"></app-product-description>\r\n </div>\r\n <div class=\"product-page-block-additional\">\r\n <div class=\"product-page-block-additional-description\">\r\n <app-product-additional-description class=\"default-padding\" [article]=\"article\"></app-product-additional-description>\r\n </div>\r\n <div class=\"product-page-block-price\" [class.full]=\"configuring\">\r\n <app-product-price class=\"s-padding\" *ngIf=\"!configuring\"\r\n [pricing]=\"article?.pricing\"\r\n [configurable]=\"configurable\"\r\n ></app-product-price>\r\n <ng-container *ngIf=\"settingsLoaded\">\r\n <threed-selections #selections class=\"threed-selections\" [class.show-selections]=\"configuring\" [@toggleFullScreenRight]=\"fullScreen ? 'fullscreen' : 'halfscreen'\"\r\n [class.default-padding]=\"!fullScreen\"\r\n [class.show-full-screen]=\"fullScreen\"\r\n [class.mini-scrollbar]=\"fullScreen\"\r\n [sku]=\"sku\"\r\n [settings]=\"settings\"\r\n (onUserActionFromThreeD)=\"configuring = true\"\r\n (instanceSet)=\"setInstance($event)\"\r\n (onImageReceived)=\"appEventService.onImageReceived.next($event)\"\r\n (onRenderStarted)=\"appEventService.onRenderStarted.next()\"\r\n (onDraftRenderImageReceived)=\"appEventService.onDraftRenderImageReceived.next($event)\"\r\n (onArticleReceived)=\"appEventService.onArticleReceived.next($event.detail)\"\r\n (onSelectionsReceived)=\"appEventService.onSelectionsReceived.next($event.detail)\"\r\n (onArticleInfoReceived)=\"appEventService.onArticleInfoReceived.next($event.detail)\"\r\n (onAnswersAvailable)=\"appEventService.onAnswersAvailable.next($event.detail)\"\r\n ></threed-selections>\r\n </ng-container>\r\n </div>\r\n <div class=\"product-page-block-addtocart no-padding product-action-buttons\" *ngIf=\"!configuring\" [@toggleTopRight]=\"fullScreen ? 'fullscreen' : 'halfscreen'\">\r\n <app-product-addtocart\r\n [configurable]=\"configurable\"\r\n [createFrozenArticle]=\"createFrozenArticle\"\r\n [configuring]=\"configuring\"\r\n [showAddToCart]=\"showAddToCart\"\r\n [article]=\"article\"\r\n [externalSource]=\"externalSource\"\r\n [isReturn]=\"isReturn\"\r\n (startConfiguration)=\"handleStartConfiguration()\"\r\n (showRelatedPopup)=\"handlePopUpChange($event)\"\r\n ></app-product-addtocart>\r\n </div>\r\n <div class=\"addtocart-reserved product-action-buttons\" *ngIf=\"configuring\" [class.full-screen]=\"fullScreen\">\r\n <app-product-addtocart class=\"default-padding\"\r\n [configurable]=\"false\"\r\n [fullscreen]=\"fullScreen\"\r\n [showAddToCart]=\"showAddToCart\"\r\n [configuring]=\"configuring\"\r\n [article]=\"article\"\r\n [externalSource]=\"externalSource\"\r\n [isReturn]=\"isReturn\"\r\n (startConfiguration)=\"handleStartConfiguration()\"\r\n ></app-product-addtocart>\r\n </div>\r\n <div class=\"product-page-block-variants\">\r\n <app-product-related class=\"no-padding\" *ngIf=\"article?.relatedArticles && article?.relatedArticles.length > 0\"\r\n [externalSource]=\"externalSource\"\r\n [articles]=\"article?.relatedArticles\" [refType]=\"64\" [label]=\"'VARIANTS' | localize\"></app-product-related>\r\n </div>\r\n <div class=\"product-page-block-stock\">\r\n <app-product-stock class=\"no-padding\" [goodId]=\"article?.goodId\" (openStockEvent)=\"openStock()\"></app-product-stock>\r\n </div>\r\n <div class=\"product-page-block-delivery\">\r\n <app-product-delivery class=\"no-padding\" [stockAndDelivery]=\"stockAndDelivery\"></app-product-delivery>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"page-wrapper-content\">\r\n <div class=\"page-wrapper-left\">\r\n <app-product-info-tabs class=\"no-padding\" [article]=\"article\"></app-product-info-tabs>\r\n </div>\r\n <div class=\"page-wrapper-right\">\r\n <div class=\"product-page-block-related s-padding\">\r\n <app-product-related\r\n *ngIf=\"article?.relatedArticles && article?.relatedArticles.length > 0\"\r\n [externalSource]=\"externalSource\"\r\n [articles]=\"article?.relatedArticles\"\r\n [refType]=\"1\"\r\n [label]=\"'RELATED_PRODUCTS' | localize\">\r\n </app-product-related>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"page-wrapper-content no-top-margin\">\r\n <div class=\"page-wrapper-full\">\r\n <div class=\"product-page-block-alternatives s-padding\">\r\n <app-product-related\r\n *ngIf=\"article?.relatedArticles && article?.relatedArticles.length > 0\"\r\n [externalSource]=\"externalSource\"\r\n [articles]=\"article?.relatedArticles\"\r\n [refType]=\"4\"\r\n [isSmallModus]=\"false\"\r\n [label]=\"'ALTERNATIVE_PRODUCTS' | localize\">\r\n </app-product-related>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n\r\n <div *ngIf=\"showRelatedProductsPopup\">\r\n <co-product-dialog\r\n [mainArticle]=\"article\"\r\n [articles]=\"article?.relatedArticles\"\r\n [refType]=\"1\"\r\n (closeRelatedPopup)=\"handlePopUpChange($event)\"\r\n >\r\n </co-product-dialog>\r\n\r\n<!-- <app-product-related class=\"no-padding\" *ngIf=\"article?.relatedArticles && article?.relatedArticles.length > 0\"-->\r\n<!-- [articles]=\"article?.relatedArticles\" [refType]=\"64\" [label]=\"'VARIANTS' | localize\"></app-product-related>-->\r\n </div>\r\n\r\n\r\n </div>\r\n</ng-container>\r\n",
1861
+ template: "<ng-container *ngIf=\"settingsLoaded\">\r\n <div class=\"page-wrapper\">\r\n <div class=\"page-wrapper-content\">\r\n <div class=\"page-wrapper-left\">\r\n <div class=\"product-image-container\">\r\n <div class=\"product-page-block-selector-type\">\r\n <app-product-selector-type class=\"default-padding\"\r\n [(currentType)]=\"currentView\"\r\n [show2D]=\"configurable\"\r\n [show3D]=\"threeD\"\r\n ></app-product-selector-type>\r\n </div>\r\n <div class=\"product-page-block-image default-padding\" [class.full]=\"fullScreen\">\r\n <app-image-carousel [@toggleVisibilityByState]=\"show2D ? 'show' : 'hide'\" [images]=\"article?.images\" [showRefresh]=\"configurable && threeD\"></app-image-carousel>\r\n <ng-container *ngIf=\"settingsLoaded && this.configurable\">\r\n <threed-configurator #configurator class=\"threed-configurator\"\r\n [class.configurator-full-screen]=\"fullScreen\"\r\n [@toggleVisibilityByState]=\"show3D ? 'show' : 'hide'\"\r\n [@toggleFullScreen]=\"fullScreen ? 'fullscreen' : 'halfscreen'\"\r\n ></threed-configurator>\r\n </ng-container>\r\n <co-icon #fullscreenbutton class=\"fullscreen-button\" *ngIf=\"show3D\"\r\n [@toggleTopLeft]=\"fullScreen ? 'fullscreen' : 'halfscreen'\"\r\n [iconData]=\"iconCache.getIcon(fullScreenIcon)\"\r\n (click)=\"showFullScreen()\"></co-icon>\r\n <co-icon class=\"threed-watermark\" *ngIf=\"show3D && fullScreen\"\r\n [iconData]=\"iconCache.getIcon(icon.Logo)\"></co-icon>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"page-wrapper-right\">\r\n <div class=\"product-page-block-description\">\r\n <app-product-description class=\"default-padding\" [article]=\"article\"></app-product-description>\r\n </div>\r\n <div class=\"product-page-block-additional\">\r\n <div class=\"product-page-block-additional-description\">\r\n <app-product-additional-description class=\"default-padding\" [article]=\"article\"></app-product-additional-description>\r\n </div>\r\n <div class=\"product-page-block-price\" [class.full]=\"configuring\">\r\n <app-product-price class=\"s-padding\" *ngIf=\"!configuring\"\r\n [pricing]=\"article?.pricing\"\r\n [configurable]=\"configurable\"\r\n ></app-product-price>\r\n <ng-container *ngIf=\"settingsLoaded\">\r\n <threed-selections #selections class=\"threed-selections\" [class.show-selections]=\"configuring\" [@toggleFullScreenRight]=\"fullScreen ? 'fullscreen' : 'halfscreen'\"\r\n [class.default-padding]=\"!fullScreen\"\r\n [class.show-full-screen]=\"fullScreen\"\r\n [class.mini-scrollbar]=\"fullScreen\"\r\n [sku]=\"sku\"\r\n [settings]=\"settings\"\r\n (onUserActionFromThreeD)=\"configuring = true\"\r\n (instanceSet)=\"setInstance($event)\"\r\n (onImageReceived)=\"appEventService.onImageReceived.next($event)\"\r\n (onRenderStarted)=\"appEventService.onRenderStarted.next()\"\r\n (onDraftRenderImageReceived)=\"appEventService.onDraftRenderImageReceived.next($event)\"\r\n (onArticleReceived)=\"appEventService.onArticleReceived.next($event.detail)\"\r\n (onSelectionsReceived)=\"appEventService.onSelectionsReceived.next($event.detail)\"\r\n (onArticleInfoReceived)=\"appEventService.onArticleInfoReceived.next($event.detail)\"\r\n (onAnswersAvailable)=\"appEventService.onAnswersAvailable.next($event.detail)\"\r\n ></threed-selections>\r\n </ng-container>\r\n </div>\r\n <div class=\"product-page-block-addtocart no-padding product-action-buttons\" *ngIf=\"!configuring\" [@toggleTopRight]=\"fullScreen ? 'fullscreen' : 'halfscreen'\">\r\n <app-product-addtocart\r\n [configurable]=\"configurable\"\r\n [createFrozenArticle]=\"createFrozenArticle\"\r\n [configuring]=\"configuring\"\r\n [showAddToCart]=\"showAddToCart\"\r\n [article]=\"article\"\r\n [externalSource]=\"externalSource\"\r\n [isReturn]=\"isReturn\"\r\n (startConfiguration)=\"handleStartConfiguration()\"\r\n (showRelatedPopup)=\"handlePopUpChange($event)\"\r\n ></app-product-addtocart>\r\n </div>\r\n <div class=\"addtocart-reserved product-action-buttons\" *ngIf=\"configuring\" [class.full-screen]=\"fullScreen\">\r\n <app-product-addtocart class=\"default-padding\"\r\n [configurable]=\"false\"\r\n [fullscreen]=\"fullScreen\"\r\n [showAddToCart]=\"showAddToCart\"\r\n [configuring]=\"configuring\"\r\n [article]=\"article\"\r\n [externalSource]=\"externalSource\"\r\n [isReturn]=\"isReturn\"\r\n (startConfiguration)=\"handleStartConfiguration()\"\r\n ></app-product-addtocart>\r\n </div>\r\n <div class=\"product-page-block-variants\">\r\n <app-product-related class=\"no-padding\" *ngIf=\"article?.relatedArticles && article?.relatedArticles.length > 0\"\r\n [externalSource]=\"externalSource\"\r\n [articles]=\"article?.relatedArticles\" [refType]=\"64\" [label]=\"'VARIANTS' | localize\"></app-product-related>\r\n </div>\r\n <div class=\"product-page-block-stock\">\r\n <app-product-stock class=\"no-padding\" [goodId]=\"article?.goodId\" (openStockEvent)=\"openStock()\"></app-product-stock>\r\n </div>\r\n <div class=\"product-page-block-delivery\">\r\n <app-product-delivery class=\"no-padding\" [stockAndDelivery]=\"stockAndDelivery\"></app-product-delivery>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"page-wrapper-content\">\r\n <div class=\"page-wrapper-left\" *ngIf=\"article\">\r\n <app-product-info-tabs class=\"no-padding\" [article]=\"article\"></app-product-info-tabs>\r\n </div>\r\n <div class=\"page-wrapper-right\">\r\n <div class=\"product-page-block-related s-padding\">\r\n <app-product-related\r\n *ngIf=\"article?.relatedArticles && article?.relatedArticles.length > 0\"\r\n [externalSource]=\"externalSource\"\r\n [articles]=\"article?.relatedArticles\"\r\n [refType]=\"1\"\r\n [label]=\"'RELATED_PRODUCTS' | localize\">\r\n </app-product-related>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"page-wrapper-content no-top-margin\">\r\n <div class=\"page-wrapper-full\">\r\n <div class=\"product-page-block-alternatives s-padding\">\r\n <app-product-related\r\n *ngIf=\"article?.relatedArticles && article?.relatedArticles.length > 0\"\r\n [externalSource]=\"externalSource\"\r\n [articles]=\"article?.relatedArticles\"\r\n [refType]=\"4\"\r\n [isSmallModus]=\"false\"\r\n [label]=\"'ALTERNATIVE_PRODUCTS' | localize\">\r\n </app-product-related>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n\r\n <div *ngIf=\"showRelatedProductsPopup\">\r\n <co-product-dialog\r\n [mainArticle]=\"article\"\r\n [articles]=\"article?.relatedArticles\"\r\n [refType]=\"1\"\r\n (closeRelatedPopup)=\"handlePopUpChange($event)\"\r\n >\r\n </co-product-dialog>\r\n\r\n<!-- <app-product-related class=\"no-padding\" *ngIf=\"article?.relatedArticles && article?.relatedArticles.length > 0\"-->\r\n<!-- [articles]=\"article?.relatedArticles\" [refType]=\"64\" [label]=\"'VARIANTS' | localize\"></app-product-related>-->\r\n </div>\r\n\r\n\r\n </div>\r\n</ng-container>\r\n",
1833
1862
  animations: [
1834
1863
  animations.trigger('toggleFullScreen', [
1835
1864
  animations.state('fullscreen', animations.style({ 'position': 'fixed', 'top': '0', 'left': '0', 'width': '100%', 'height': '100%' })),
1836
1865
  animations.state('halfscreen', animations.style({ 'position': '*', 'top': '*', 'left': '*', 'width': '*', 'height': '*' })),
1837
- animations.transition('halfscreen <=> fullscreen', animations.animate('200ms ease-in-out')),
1866
+ animations.transition('halfscreen <=> fullscreen', animations.animate('200ms ease-in-out'))
1838
1867
  ]),
1839
1868
  animations.trigger('toggleTopLeft', [
1840
1869
  animations.state('fullscreen', animations.style({ 'position': 'fixed', 'top': '0', 'left': '0' })),
1841
1870
  animations.state('halfscreen', animations.style({ 'position': 'absolute', 'top': '*', 'left': '*' })),
1842
- animations.transition('halfscreen <=> fullscreen', animations.animate('200ms ease-in-out')),
1871
+ animations.transition('halfscreen <=> fullscreen', animations.animate('200ms ease-in-out'))
1843
1872
  ]),
1844
1873
  animations.trigger('toggleTopRight', [
1845
1874
  animations.state('fullscreen', animations.style({ 'position': 'fixed', 'top': '0', 'right': '0' })),
1846
1875
  animations.state('halfscreen', animations.style({ 'position': '*', 'top': '*', 'right': '*' })),
1847
- animations.transition('halfscreen <=> fullscreen', animations.animate('200ms ease-in-out')),
1876
+ animations.transition('halfscreen <=> fullscreen', animations.animate('200ms ease-in-out'))
1848
1877
  ]),
1849
1878
  animations.trigger('toggleFullScreenRight', [
1850
1879
  animations.state('fullscreen', animations.style({ 'position': 'fixed', 'width': '400px', 'top': '0', 'right': '0' })),
1851
1880
  animations.state('halfscreen', animations.style({ 'position': '*', 'width': '*', 'top': '*', 'right': '*' })),
1852
- animations.transition('halfscreen <=> fullscreen', animations.animate('200ms ease-in-out')),
1881
+ animations.transition('halfscreen <=> fullscreen', animations.animate('200ms ease-in-out'))
1853
1882
  ]),
1854
1883
  animations.trigger('toggleVisibilityByState', [
1855
1884
  animations.state('hide', animations.style({ 'opacity': '0', 'display': 'none' })),
1856
1885
  animations.state('show', animations.style({ 'display': 'block', 'opacity': '1' })),
1857
- animations.transition('hide <=> show', animations.animate('200ms 100ms ease-in-out')),
1886
+ animations.transition('hide <=> show', animations.animate('200ms 100ms ease-in-out'))
1858
1887
  ]),
1859
1888
  animations.trigger('toggleVisibility', [
1860
1889
  animations.state('void', animations.style({ 'opacity': '0' })),
1861
1890
  animations.state('*', animations.style({ 'opacity': '1' })),
1862
- animations.transition('void => *', animations.animate('200ms ease-in-out')),
1891
+ animations.transition('void => *', animations.animate('200ms ease-in-out'))
1863
1892
  ])
1864
1893
  ],
1865
1894
  styles: [".page-wrapper{font-family:iOneMontserrat;font-size:12px;display:flex;flex-direction:column;max-width:1400px;padding:0 15px;margin:0 auto}.page-wrapper-content{display:flex;flex-direction:row;margin:40px 0}.page-wrapper-content:first-child{margin-top:0}.page-wrapper-content.no-top-margin{margin-top:0}.page-wrapper-left{display:flex;width:55%;flex-direction:column}.page-wrapper-right{display:flex;width:45%;flex-direction:column}.page-wrapper-full{display:flex;width:100%;flex-direction:column}.page-wrapper-66{display:flex;width:60%;flex-direction:column}.page-wrapper-33{display:flex;width:40%;flex-direction:column}.threed-selections{display:none}.threed-selections.show-selections{display:block}.threed-selections ::ng-deep .rp-lite-selector .rp-answers-slideout ::ng-deep co-slideout{width:480px;z-index:3}.threed-selections ::ng-deep .co-summary-line{cursor:pointer}.product-action-buttons{position:relative}.product-action-buttons.full-screen{z-index:10}.product-image-container{grid-column:1/7;grid-row:1/6;position:relative}.product-page-block-selector-type{width:auto;position:absolute;top:10px;right:10px;z-index:2}.product-page-block-image{box-sizing:border-box;width:100%;z-index:1;position:relative}.product-page-block-image .threed-configurator{border:1px solid #efefef}.product-page-block-image .threed-configurator .layer .viewer canvas{height:100%;width:100%}.product-page-block-image .threed-configurator ::ng-deep .rp-element-toolbar{top:30px}.product-page-block-image app-image-carousel.show-animated,.product-page-block-image threed-configurator.show-animated{opacity:1;z-index:0;transition:all .2s ease-in-out}.product-page-block-image .fullscreen-button{cursor:pointer;height:50px;width:50px;position:absolute;left:30px;z-index:100;top:30px}.product-page-block-image.full{grid-column:1/11;grid-row:2/span 10;z-index:3}.product-page-block-description{grid-column:7/12;grid-row:1/1}.product-page-block-additional{width:100%}.product-page-block-additional-description{width:100%}.product-page-block-price{grid-column:1/3;grid-row:2/2;align-self:center}.product-page-block-price.full{grid-column:1/5}.product-page-block-addtocart{grid-column:3/5;grid-row:2/2;align-self:center;padding-top:30px!important}.product-page-block-addtocart ::ng-deep co-number-picker ::ng-deep co-button{cursor:pointer}.product-page-block-addtocart ::ng-deep co-number-picker ::ng-deep co-button:hover div.rippler{background:#f6f5f4}.product-page-block-addtocart ::ng-deep co-number-picker ::ng-deep co-button ::ng-deep co-icon{position:relative;z-index:2}.product-page-block-addtocart ::ng-deep co-button.cart-button{cursor:pointer}.product-page-block-addtocart ::ng-deep co-button.cart-button:hover{background:#74B77F}.addtocart-reserved{grid-column:1/3;grid-row:3/3}.product-page-block-stock{grid-column:1/3;grid-row:4/4}.product-page-block-delivery{grid-column:3/5;grid-row:4/4}::ng-deep co-scroll-container{overflow:hidden;position:relative}::ng-deep co-scroll-container .content-wrapper{padding:0}::ng-deep co-scroll-container .scroll-layer{left:0;top:0}::ng-deep co-scroll-container .scroll-layer .scroller{width:34px;height:34px;border-radius:36px;background:#fff;cursor:pointer;box-shadow:0 0 5px #0003}::ng-deep co-scroll-container .scroll-layer .scroller:hover{background:#f6f5f4}::ng-deep co-scroll-container .scroll-layer .scroller.left-scroll{left:5px}::ng-deep co-scroll-container .scroll-layer .scroller.left-scroll:before{border-width:0 3px 3px 0;padding:4px;margin-left:13px;margin-top:11px}::ng-deep co-scroll-container .scroll-layer .scroller.right-scroll{right:5px}::ng-deep co-scroll-container .scroll-layer .scroller.right-scroll:after{border-width:0 3px 3px 0;padding:4px;margin-left:9px;margin-top:11px}.product-page-block-variants{margin:20px 0 0}.product-page-block-variants ::ng-deep app-product-related>div{display:flex;grid-gap:15px;gap:15px;align-items:center;border-top:1px solid #f6f5f4;padding:5px 0 7px 15px}.product-page-block-variants ::ng-deep app-product-related>div ::ng-deep app-header h3{font-size:14px}.product-page-block-variants ::ng-deep app-product-related>div ::ng-deep co-scroll-container{width:320px;max-width:100%;padding:0 16px}.product-page-block-variants ::ng-deep app-product-related>div ::ng-deep co-scroll-container .scroller{width:26px;height:26px}.product-page-block-variants ::ng-deep app-product-related>div ::ng-deep co-scroll-container .scroller.left-scroll{left:5px}.product-page-block-variants ::ng-deep app-product-related>div ::ng-deep co-scroll-container .scroller.left-scroll:before{border-width:0 2px 2px 0;margin-left:9px;margin-top:9px}.product-page-block-variants ::ng-deep app-product-related>div ::ng-deep co-scroll-container .scroller.right-scroll{right:5px}.product-page-block-variants ::ng-deep app-product-related>div ::ng-deep co-scroll-container .scroller.right-scroll:after{border-width:0 2px 2px 0;margin-left:6px;margin-top:9px}.product-page-block-variants ::ng-deep co-tile.small{min-width:50px!important;max-width:50px!important;border:1px solid #f6f5f4;margin:0 10px 0 0;border-radius:4px}.product-page-block-variants ::ng-deep co-tile.small:hover{border-color:#22313c}.product-page-block-variants ::ng-deep co-tile.small .tile-wrapper{padding:0}.product-page-block-variants ::ng-deep co-tile.small .tile-wrapper .tile-top{display:none}.product-page-block-variants ::ng-deep co-tile.small .tile-wrapper .image{height:40px!important;padding:5px;margin-bottom:10px}.product-page-block-variants ::ng-deep co-tile.small .tile-wrapper .image .no-image-wrapper .no-image{width:40px;height:40px}.product-page-block-variants ::ng-deep co-tile.small .tile-wrapper .image .no-image-wrapper span{display:none!important}.product-page-block-variants ::ng-deep co-tile.small .tile-wrapper .tile-bottom{display:none}.product-page-block-variants ::ng-deep co-tile.small .tile-extra-bottom{display:none}.product-page-block-alternatives ::ng-deep .article-wrapper{margin:0 20px 0 0}.product-page-block-alternatives ::ng-deep .article-wrapper:last-child{margin:0}.product-page-block-alternatives ::ng-deep co-tile{cursor:pointer;transition:all .14s ease-out;border:1px solid transparent;border-bottom-color:#f6f5f4;padding:15px 10px 0;width:319px;max-width:none;min-width:0;box-sizing:border-box}.product-page-block-alternatives ::ng-deep co-tile:hover{box-shadow:none;border-color:#f6f5f4}.product-page-block-alternatives ::ng-deep co-tile:hover .tile-wrapper div.image co-image{transform:scale(1.05)}.product-page-block-alternatives ::ng-deep co-tile:hover .tile-wrapper .tile-bottom{margin:0}.product-page-block-alternatives ::ng-deep co-tile:hover .tile-extra-bottom .main .description{text-decoration:underline}.product-page-block-alternatives ::ng-deep co-tile .tile-wrapper{padding:0;position:relative;outline:none;overflow:hidden}.product-page-block-alternatives ::ng-deep co-tile .tile-wrapper .tile-top{position:absolute;left:0;top:0;width:100%}.product-page-block-alternatives ::ng-deep co-tile .tile-wrapper div.image{position:relative;padding:1px;display:flex;align-items:center;justify-content:center;overflow:hidden;max-width:250px;margin:0 auto 10px;height:auto}.product-page-block-alternatives ::ng-deep co-tile .tile-wrapper div.image:after{content:\"\";padding:100% 0 0;float:left;width:100%}.product-page-block-alternatives ::ng-deep co-tile .tile-wrapper div.image co-image{position:absolute;left:0;top:0;overflow:hidden;width:100%;height:100%;-o-object-fit:contain;object-fit:contain;z-index:-1;transition:all .2s ease}.product-page-block-alternatives ::ng-deep co-tile .tile-wrapper div.image .no-image-wrapper{position:absolute;display:flex;left:50%;top:50%;margin:-48px 0 0 -54px;flex-direction:column;align-items:center;opacity:.25}.product-page-block-alternatives ::ng-deep co-tile .tile-wrapper .tile-bottom{transition:all .2s ease;height:auto}.product-page-block-alternatives ::ng-deep co-tile .tile-wrapper .tile-bottom ::ng-deep co-button{margin:0 0 5px!important;width:36px;height:36px;border:1px solid #22313C;cursor:pointer;border-radius:4px;padding:0!important;font-size:0}.product-page-block-alternatives ::ng-deep co-tile .tile-wrapper .tile-bottom ::ng-deep co-button co-icon{width:32px;height:32px;margin:0 2px}.product-page-block-alternatives ::ng-deep co-tile .tile-extra-bottom{outline:none;padding:15px 0;background:transparent!important;min-height:60px}.product-page-block-alternatives ::ng-deep co-tile .tile-extra-bottom .main{padding:0 10px}.product-page-block-alternatives ::ng-deep co-tile .tile-extra-bottom .main .description{font-size:15px;font-weight:bold;margin:0 0 2px}.product-page-block-alternatives ::ng-deep co-tile .tile-extra-bottom .main .price{font-size:16px;margin:15px 0 0;font-weight:bold;color:#2b60a7}.product-page-block-additional-information{grid-column:1/6;grid-row:4/4}.product-page-block-properties{grid-column:7/10;grid-row:3/3}.product-page-block-related-articles{grid-column:2/6;grid-row:4/4}.product-page-block-alternative-articles{grid-column:6/10;grid-row:4/4}.product-page-block-documents{grid-column:2/6;grid-row:5/5}.product-page-block-symbols{grid-column:6/10;grid-row:5/5}@media screen and (max-width: 950px){.default-padding{padding-top:20px;padding-bottom:20px}.m-padding{padding-top:15px;padding-bottom:15px}.s-padding{padding-top:5px;padding-bottom:5px}.page-wrapper{max-width:650px}.page-wrapper .page-wrapper-content{flex-direction:column;margin:30px 0}.page-wrapper .page-wrapper-content .page-wrapper-left{width:100%}.page-wrapper .page-wrapper-content .page-wrapper-right{width:100%}.product-page-block-alternatives ::ng-deep co-tile{width:284px!important}}@media screen and (max-width: 650px){[class*=-padding]{padding-left:0!important;padding-right:0!important}.product-page-block-addtocart ::ng-deep co-number-picker co-button{height:38px!important}.product-page-block-addtocart ::ng-deep co-number-picker co-input-text{height:38px!important;width:36px!important}.product-page-block-addtocart ::ng-deep co-button.cart-button{height:40px;font-size:13px}}\n"]
@@ -2010,6 +2039,7 @@
2010
2039
  this._appEventService = _appEventService;
2011
2040
  this._changeDetector = _changeDetector;
2012
2041
  this._domSanitizer = _domSanitizer;
2042
+ this.isPopupOpen = false;
2013
2043
  this.showRefresh = false;
2014
2044
  this.resizing = false;
2015
2045
  this.imageViewModels = [];
@@ -2039,6 +2069,12 @@
2039
2069
  _this._changeDetector.detectChanges();
2040
2070
  }));
2041
2071
  }
2072
+ // Close on ESC
2073
+ ImageCarouselComponent.prototype.onEsc = function () {
2074
+ if (this.isPopupOpen) {
2075
+ this.closePopup();
2076
+ }
2077
+ };
2042
2078
  Object.defineProperty(ImageCarouselComponent.prototype, "images", {
2043
2079
  get: function () {
2044
2080
  return this._images;
@@ -2094,15 +2130,16 @@
2094
2130
  };
2095
2131
  ImageCarouselComponent.prototype.handleShowImage = function (imageViewModel) {
2096
2132
  if (imageViewModel && imageViewModel.originalSource) {
2097
- var popupWindow = window.open('', 'Image zoom', 'width=600,height=400');
2098
- // Set the content of the popup window
2099
- popupWindow.document.write('<html><head><title>Image zoom</title></head><body>');
2100
- popupWindow.document.write("<img src=" + imageViewModel.originalSource + " alt=\"Image\" style=\"width:100%; height:auto;\">");
2101
- popupWindow.document.write('</body></html>');
2102
- // Close the document to render the popup window
2103
- popupWindow.document.close();
2133
+ this.selectedImage = imageViewModel;
2134
+ this.isPopupOpen = true;
2135
+ this._changeDetector.markForCheck();
2104
2136
  }
2105
2137
  };
2138
+ ImageCarouselComponent.prototype.closePopup = function () {
2139
+ this.isPopupOpen = false;
2140
+ this.selectedImage = undefined;
2141
+ this._changeDetector.markForCheck();
2142
+ };
2106
2143
  ImageCarouselComponent.prototype._filterValidImages = function (value) {
2107
2144
  if (!value) {
2108
2145
  return [];
@@ -2147,39 +2184,54 @@
2147
2184
  ImageCarouselComponent.prototype._resizeAndSanitizeSource = function (source, imageViewModel) {
2148
2185
  var _this = this;
2149
2186
  var resizeCanvas = document.createElement('canvas');
2150
- var resizeCanvasContext = resizeCanvas.getContext('2d');
2151
- var resizeImage = document.createElement('img');
2152
- resizeImage.crossOrigin = 'anonymous';
2153
- resizeImage.onload = function () { return __awaiter(_this, void 0, void 0, function () {
2154
- var originalWidth, originalHeight, aspectRatio, newWidth, newHeight, imageWidth, resizedSource;
2155
- return __generator(this, function (_a) {
2156
- resizeCanvasContext.imageSmoothingEnabled = true;
2157
- resizeCanvasContext.imageSmoothingQuality = 'high';
2158
- originalWidth = resizeImage.width;
2159
- originalHeight = resizeImage.height;
2160
- aspectRatio = originalWidth / originalHeight;
2161
- newWidth = this._resizeCanvasHeight;
2162
- newHeight = this._resizeCanvasHeight;
2163
- if (originalWidth > originalHeight) {
2164
- newHeight = this._resizeCanvasHeight / aspectRatio;
2165
- }
2166
- else {
2167
- newWidth = this._resizeCanvasHeight * aspectRatio;
2168
- }
2169
- // Set the canvas size to the new width and height
2170
- resizeCanvas.width = newWidth;
2171
- resizeCanvas.height = newHeight;
2172
- imageWidth = this._resizeCanvasHeight * (resizeImage.height / resizeImage.width);
2173
- resizeCanvasContext.drawImage(resizeImage, 0, 0, newWidth, newHeight);
2174
- resizedSource = resizeCanvas.toDataURL('image/jpeg');
2175
- imageViewModel.source = this._domSanitizer.bypassSecurityTrustUrl(resizedSource);
2176
- imageViewModel.originalSource = source;
2177
- this._changeDetector.detectChanges();
2178
- return [2 /*return*/];
2179
- });
2180
- }); };
2181
- // @ts-ignore
2182
- resizeImage.src = source;
2187
+ var ctx = resizeCanvas.getContext('2d');
2188
+ var img = document.createElement('img');
2189
+ img.crossOrigin = 'anonymous';
2190
+ img.onload = function () {
2191
+ ctx.imageSmoothingEnabled = true;
2192
+ ctx.imageSmoothingQuality = 'high';
2193
+ var ow = img.width;
2194
+ var oh = img.height;
2195
+ var aspect = ow / oh;
2196
+ var newW = _this._resizeCanvasHeight;
2197
+ var newH = _this._resizeCanvasHeight;
2198
+ if (ow > oh) {
2199
+ newH = _this._resizeCanvasHeight / aspect;
2200
+ }
2201
+ else {
2202
+ newW = _this._resizeCanvasHeight * aspect;
2203
+ }
2204
+ resizeCanvas.width = Math.round(newW);
2205
+ resizeCanvas.height = Math.round(newH);
2206
+ // Ensure transparent background before drawing
2207
+ ctx.clearRect(0, 0, resizeCanvas.width, resizeCanvas.height);
2208
+ ctx.drawImage(img, 0, 0, resizeCanvas.width, resizeCanvas.height);
2209
+ var mime = _this._detectPreferredMime(source);
2210
+ var resizedSource = mime === 'image/jpeg'
2211
+ ? resizeCanvas.toDataURL('image/jpeg', 0.92) // only if original was JPEG
2212
+ : resizeCanvas.toDataURL(mime); // PNG/WebP keep alpha
2213
+ imageViewModel.source = _this._domSanitizer.bypassSecurityTrustUrl(resizedSource);
2214
+ imageViewModel.originalSource = source;
2215
+ _this._changeDetector.detectChanges();
2216
+ };
2217
+ img.src = source;
2218
+ };
2219
+ ImageCarouselComponent.prototype._detectPreferredMime = function (source) {
2220
+ // Data URI check
2221
+ var m = source.match(/^data:(image\/[a-zA-Z+.-]+);base64,/);
2222
+ if (m) {
2223
+ var t = m[1].toLowerCase();
2224
+ if (t === 'image/png' || t === 'image/webp' || t === 'image/jpeg')
2225
+ return t;
2226
+ }
2227
+ var lower = source.toLowerCase();
2228
+ if (lower.endsWith('.png'))
2229
+ return 'image/png';
2230
+ if (lower.endsWith('.webp'))
2231
+ return 'image/webp';
2232
+ if (lower.endsWith('.jpg') || lower.endsWith('.jpeg'))
2233
+ return 'image/jpeg';
2234
+ return 'image/png';
2183
2235
  };
2184
2236
  ImageCarouselComponent.prototype._scrollCarouselToIndex = function () {
2185
2237
  if (this.currentIndex > -1 && this.currentIndex <= this.images.length) {
@@ -2198,9 +2250,9 @@
2198
2250
  ImageCarouselComponent.decorators = [
2199
2251
  { type: i0.Component, args: [{
2200
2252
  selector: 'app-image-carousel',
2201
- template: "\n <div id=\"product_page_carousel\">\n <div id=\"product_page_carousel_items\">\n <co-loader [isShown]=\"true\" *ngIf=\"showLoader\"></co-loader>\n <div #carousel class=\"inner-carousel\">\n <!-- This has been taken out of the for loop to prevent flashing images when updating. -->\n <div *ngIf=\"imageViewModels[0]\" class=\"carousel-item\" [id]=\"'slide-0'\" [class.active]=\"isCurrentIndex(0)\" (click)=\"handleShowImage(imageViewModels[0])\">\n <img [src]=\"imageViewModels[0].source\">\n </div>\n <div *ngFor=\"let imageViewModel of imageViewModels.slice(1); let index = index\" class=\"carousel-item\"\n [id]=\"'slide-' + (index + 1)\" [class.active]=\"isCurrentIndex((index + 1))\" (click)=\"handleShowImage(imageViewModel)\">\n <img [src]=\"imageViewModel.source\">\n </div>\n <div class=\"carousel-scroller-layer\" *ngIf=\"imageViewModels && imageViewModels.length > 1\">\n <div class=\"carousel-item-scroller prev\" (click)=\"gotoPrevSlide()\" *ngIf=\"currentIndex > 0\"></div>\n <div class=\"carousel-item-scroller next\" (click)=\"gotoNextSlide()\" *ngIf=\"currentIndex < images.length - 1\"></div>\n </div>\n </div>\n <!--\n <co-icon class=\"selector-type-icon refresh-button\" [iconData]=\"iconCache.getIcon(icons.Refresh)\" (click)=\"onForceRenderImage()\" [class.loading]=\"showLoader\" *ngIf=\"showRefresh\"></co-icon>\n -->\n </div>\n\n <div id=\"product_page_carousel_thumbs\">\n <co-scroll-container class=\"scroll-container\" *ngIf=\"imageViewModels && imageViewModels.length > 1\">\n <div *ngFor=\"let imageViewModel of imageViewModels; let index = index\" class=\"carousel-thumb\"\n [class.active]=\"index === currentIndex\">\n <img [src]=\"imageViewModel.source\" (click)=\"handleThumbClick(index)\"/>\n </div>\n </co-scroll-container>\n </div>\n </div>\n ",
2253
+ template: "\n <div id=\"product_page_carousel\">\n <div id=\"product_page_carousel_items\">\n <co-loader [isShown]=\"true\" *ngIf=\"showLoader\"></co-loader>\n <div #carousel class=\"inner-carousel\">\n <!-- This has been taken out of the for loop to prevent flashing images when updating. -->\n <div *ngIf=\"imageViewModels[0]\" class=\"carousel-item\" [id]=\"'slide-0'\" [class.active]=\"isCurrentIndex(0)\" (click)=\"handleShowImage(imageViewModels[0])\">\n <img [src]=\"imageViewModels[0].source\">\n </div>\n <div *ngFor=\"let imageViewModel of imageViewModels.slice(1); let index = index\" class=\"carousel-item\"\n [id]=\"'slide-' + (index + 1)\" [class.active]=\"isCurrentIndex((index + 1))\" (click)=\"handleShowImage(imageViewModel)\">\n <img [src]=\"imageViewModel.source\">\n </div>\n <div class=\"carousel-scroller-layer\" *ngIf=\"imageViewModels && imageViewModels.length > 1\">\n <div class=\"carousel-item-scroller prev\" (click)=\"gotoPrevSlide()\" *ngIf=\"currentIndex > 0\"></div>\n <div class=\"carousel-item-scroller next\" (click)=\"gotoNextSlide()\" *ngIf=\"currentIndex < images.length - 1\"></div>\n </div>\n </div>\n <!--\n <co-icon class=\"selector-type-icon refresh-button\" [iconData]=\"iconCache.getIcon(icons.Refresh)\" (click)=\"onForceRenderImage()\" [class.loading]=\"showLoader\" *ngIf=\"showRefresh\"></co-icon>\n -->\n </div>\n\n <div id=\"product_page_carousel_thumbs\">\n <co-scroll-container class=\"scroll-container\" *ngIf=\"imageViewModels && imageViewModels.length > 1\">\n <div *ngFor=\"let imageViewModel of imageViewModels; let index = index\" class=\"carousel-thumb\"\n [class.active]=\"index === currentIndex\">\n <img [src]=\"imageViewModel.source\" (click)=\"handleThumbClick(index)\"/>\n </div>\n </co-scroll-container>\n </div>\n </div>\n <!-- Modal (real popup) -->\n <div\n class=\"image-modal\"\n *ngIf=\"isPopupOpen\"\n (click)=\"closePopup()\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Image preview\"\n >\n <div class=\"image-modal__content\" (click)=\"$event.stopPropagation()\">\n <button\n class=\"image-modal__close\"\n type=\"button\"\n aria-label=\"Close\"\n (click)=\"closePopup()\"\n >\n \u00D7\n </button>\n\n <img [src]=\"selectedImage?.originalSource\" alt=\"Image preview\" />\n </div>\n </div>\n ",
2202
2254
  changeDetection: i0.ChangeDetectionStrategy.OnPush,
2203
- styles: [":host{max-height:540px;height:100%;position:relative}:host:not(.resizing) .inner-carousel{scroll-behavior:smooth;-webkit-overflow-scrolling:touch;scroll-snap-type:x mandatory}#product_page_carousel{position:relative}#product_page_carousel .refresh-button{position:absolute;bottom:10px;right:10px;background:#fff}#product_page_carousel .refresh-button.loading{animation:spin 1s linear infinite}#product_page_carousel .refresh-button:hover{box-shadow:none;background:#74B77F;transition:all .2s ease-in-out}#product_page_carousel .refresh-button:hover ::ng-deep svg path{fill:#fff!important}#product_page_carousel #product_page_carousel_items{position:relative;margin-bottom:10px}#product_page_carousel #product_page_carousel_items ::ng-deep co-loader{position:absolute}#product_page_carousel .inner-carousel{display:flex;flex-direction:row;align-items:center;overflow:hidden;max-height:500px;border:1px solid #efefef}#product_page_carousel .carousel-item{max-height:500px;width:100%;display:flex;cursor:zoom-in;flex-shrink:0;flex-grow:0}#product_page_carousel .carousel-item img{width:100%;height:auto;-o-object-fit:contain;object-fit:contain}#product_page_carousel .carousel-scroller-layer{height:100%;width:100%;position:absolute;pointer-events:none;top:0;left:0}#product_page_carousel #product_page_carousel_thumbs{display:flex;justify-content:flex-start;height:80px;margin-left:auto;margin-right:auto}#product_page_carousel #product_page_carousel_thumbs ::ng-deep co-scroll-container{padding:0 22px}#product_page_carousel #product_page_carousel_thumbs ::ng-deep co-scroll-container .content-wrapper{padding:0}#product_page_carousel #product_page_carousel_thumbs .carousel-thumb{opacity:1;cursor:pointer;transition:all .2s ease;padding:4px;border:1px solid #f6f5f4}#product_page_carousel #product_page_carousel_thumbs .carousel-thumb.active,#product_page_carousel #product_page_carousel_thumbs .carousel-thumb:hover{border-color:#22313c}#product_page_carousel #product_page_carousel_thumbs .carousel-thumb:not(:last-child){margin-right:10px}#product_page_carousel #product_page_carousel_thumbs .carousel-thumb img{height:68px}@media screen and (max-width: 650px){#product_page_carousel_thumbs{height:57px!important}#product_page_carousel_thumbs .carousel-thumb img{height:50px!important}}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"]
2255
+ styles: [":host{max-height:540px;height:100%;position:relative}:host:not(.resizing) .inner-carousel{scroll-behavior:smooth;-webkit-overflow-scrolling:touch;scroll-snap-type:x mandatory}#product_page_carousel{position:relative}#product_page_carousel .refresh-button{position:absolute;bottom:10px;right:10px;background:#fff}#product_page_carousel .refresh-button.loading{animation:spin 1s linear infinite}#product_page_carousel .refresh-button:hover{box-shadow:none;background:#74B77F;transition:all .2s ease-in-out}#product_page_carousel .refresh-button:hover ::ng-deep svg path{fill:#fff!important}#product_page_carousel #product_page_carousel_items{position:relative;margin-bottom:10px}#product_page_carousel #product_page_carousel_items ::ng-deep co-loader{position:absolute}#product_page_carousel .inner-carousel{display:flex;flex-direction:row;align-items:center;overflow:hidden;max-height:500px;border:1px solid #efefef}#product_page_carousel .carousel-item{max-height:500px;width:100%;display:flex;cursor:zoom-in;flex-shrink:0;flex-grow:0}#product_page_carousel .carousel-item img{width:100%;height:auto;-o-object-fit:contain;object-fit:contain}#product_page_carousel .carousel-scroller-layer{height:100%;width:100%;position:absolute;pointer-events:none;top:0;left:0}#product_page_carousel #product_page_carousel_thumbs{display:flex;justify-content:flex-start;height:80px;margin-left:auto;margin-right:auto}#product_page_carousel #product_page_carousel_thumbs ::ng-deep co-scroll-container{padding:0 22px}#product_page_carousel #product_page_carousel_thumbs ::ng-deep co-scroll-container .content-wrapper{padding:0}#product_page_carousel #product_page_carousel_thumbs .carousel-thumb{opacity:1;cursor:pointer;transition:all .2s ease;padding:4px;border:1px solid #f6f5f4}#product_page_carousel #product_page_carousel_thumbs .carousel-thumb.active,#product_page_carousel #product_page_carousel_thumbs .carousel-thumb:hover{border-color:#22313c}#product_page_carousel #product_page_carousel_thumbs .carousel-thumb:not(:last-child){margin-right:10px}#product_page_carousel #product_page_carousel_thumbs .carousel-thumb img{height:68px}.image-modal{position:fixed;inset:0;background:rgba(0,0,0,.8);display:flex;align-items:center;justify-content:center;z-index:1000}.image-modal__content{position:relative;max-width:90vw;max-height:90vh}.image-modal__content img{max-width:90vw;max-height:90vh;-o-object-fit:contain;object-fit:contain;display:block}.image-modal__close{position:fixed;top:15px;right:30px;background:transparent;border:none;color:#fff;font-size:60px;line-height:1;cursor:pointer}@media screen and (max-width: 650px){#product_page_carousel_thumbs{height:57px!important}#product_page_carousel_thumbs .carousel-thumb img{height:50px!important}}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"]
2204
2256
  },] }
2205
2257
  ];
2206
2258
  ImageCarouselComponent.ctorParameters = function () { return [
@@ -2211,6 +2263,7 @@
2211
2263
  ]; };
2212
2264
  ImageCarouselComponent.propDecorators = {
2213
2265
  carousel: [{ type: i0.ViewChild, args: ['carousel', { read: i0.ElementRef },] }],
2266
+ onEsc: [{ type: i0.HostListener, args: ['document:keydown.escape',] }],
2214
2267
  showRefresh: [{ type: i0.Input }],
2215
2268
  images: [{ type: i0.Input }],
2216
2269
  handleWindowResize: [{ type: i0.HostListener, args: ['window:resize',] }],
@@ -2468,11 +2521,12 @@
2468
2521
  ];
2469
2522
 
2470
2523
  var ProductAddtocartComponent = /** @class */ (function () {
2471
- function ProductAddtocartComponent(iconCache, _ioneControllerService, _appEventService, _settingsService) {
2524
+ function ProductAddtocartComponent(iconCache, _ioneControllerService, _appEventService, _settingsService, _productConnectorAdapterService) {
2472
2525
  this.iconCache = iconCache;
2473
2526
  this._ioneControllerService = _ioneControllerService;
2474
2527
  this._appEventService = _appEventService;
2475
2528
  this._settingsService = _settingsService;
2529
+ this._productConnectorAdapterService = _productConnectorAdapterService;
2476
2530
  this.icon = IconEnum;
2477
2531
  this.createFrozenArticle = true;
2478
2532
  this.configurable = false;
@@ -2518,36 +2572,50 @@
2518
2572
  return __generator(this, function (_a) {
2519
2573
  switch (_a.label) {
2520
2574
  case 0:
2521
- if (!this.createFrozenArticle) return [3 /*break*/, 7];
2522
- if (!(this.article.goodType === 'B')) return [3 /*break*/, 2];
2575
+ if (!this.createFrozenArticle) return [3 /*break*/, 10];
2576
+ if (!(this.article.goodType === 'B')) return [3 /*break*/, 5];
2577
+ if (!this.article.isConfigurable) return [3 /*break*/, 2];
2523
2578
  return [4 /*yield*/, this._getJSONFromArticleObject({ article: this.article, quantity: quantity })];
2524
2579
  case 1:
2525
2580
  article = _a.sent();
2526
2581
  if (article) {
2527
2582
  this._appEventService.onAddToCart.next({ article: article, quantity: quantity });
2528
2583
  }
2529
- return [3 /*break*/, 6];
2530
- case 2:
2584
+ return [3 /*break*/, 4];
2585
+ case 2: return [4 /*yield*/, this._handleGeneratedArticleDirectly(quantity)];
2586
+ case 3:
2587
+ _a.sent();
2588
+ _a.label = 4;
2589
+ case 4: return [3 /*break*/, 9];
2590
+ case 5:
2531
2591
  article = void 0;
2532
- if (!!!this.externalSource) return [3 /*break*/, 4];
2592
+ if (!!!this.externalSource) return [3 /*break*/, 7];
2533
2593
  return [4 /*yield*/, this._getJSONFromArticleObject({ article: this.article, quantity: quantity })];
2534
- case 3:
2594
+ case 6:
2535
2595
  article = _a.sent();
2536
- return [3 /*break*/, 5];
2537
- case 4:
2596
+ return [3 /*break*/, 8];
2597
+ case 7:
2538
2598
  article = this._ioneControllerService.convertArticleFullObjectToArticleExtended(this.article);
2539
- _a.label = 5;
2540
- case 5:
2599
+ _a.label = 8;
2600
+ case 8:
2541
2601
  if (article) {
2542
2602
  this._appEventService.onAddToCart.next({ article: article, quantity: quantity });
2543
2603
  }
2544
- _a.label = 6;
2545
- case 6: return [3 /*break*/, 8];
2546
- case 7:
2604
+ _a.label = 9;
2605
+ case 9: return [3 /*break*/, 14];
2606
+ case 10:
2607
+ if (!(this.article.goodType === 'B')) return [3 /*break*/, 13];
2608
+ if (!!this.article.isConfigurable) return [3 /*break*/, 12];
2609
+ return [4 /*yield*/, this._handleGeneratedArticleDirectly(quantity)];
2610
+ case 11:
2611
+ _a.sent();
2612
+ _a.label = 12;
2613
+ case 12: return [3 /*break*/, 14];
2614
+ case 13:
2547
2615
  article = this._ioneControllerService.convertArticleFullObjectToArticleExtended(this.article);
2548
2616
  this._appEventService.onAddToCart.next({ article: article, quantity: quantity });
2549
- _a.label = 8;
2550
- case 8: return [2 /*return*/];
2617
+ _a.label = 14;
2618
+ case 14: return [2 /*return*/];
2551
2619
  }
2552
2620
  });
2553
2621
  });
@@ -2567,6 +2635,36 @@
2567
2635
  });
2568
2636
  });
2569
2637
  };
2638
+ ProductAddtocartComponent.prototype._handleGeneratedArticleDirectly = function (quantity) {
2639
+ return __awaiter(this, void 0, void 0, function () {
2640
+ var generatedGoodId, articleFull, article;
2641
+ return __generator(this, function (_a) {
2642
+ switch (_a.label) {
2643
+ case 0: return [4 /*yield*/, this._getGeneratedArtDirectly(this.article.goodId)];
2644
+ case 1:
2645
+ generatedGoodId = _a.sent();
2646
+ if (!generatedGoodId) return [3 /*break*/, 3];
2647
+ return [4 /*yield*/, this._productConnectorAdapterService.getArticleFullObject(generatedGoodId, true)];
2648
+ case 2:
2649
+ articleFull = _a.sent();
2650
+ article = this._ioneControllerService.convertArticleFullObjectToArticleExtended(articleFull);
2651
+ this._appEventService.onAddToCart.next({ article: article, quantity: quantity });
2652
+ _a.label = 3;
2653
+ case 3: return [2 /*return*/];
2654
+ }
2655
+ });
2656
+ });
2657
+ };
2658
+ ProductAddtocartComponent.prototype._getGeneratedArtDirectly = function (goodId) {
2659
+ return __awaiter(this, void 0, void 0, function () {
2660
+ return __generator(this, function (_a) {
2661
+ switch (_a.label) {
2662
+ case 0: return [4 /*yield*/, this._ioneControllerService.getGeneratedArtDirectly(goodId, true)];
2663
+ case 1: return [2 /*return*/, _a.sent()];
2664
+ }
2665
+ });
2666
+ });
2667
+ };
2570
2668
  ProductAddtocartComponent.prototype._getJSONFromArticleObject = function (article) {
2571
2669
  return __awaiter(this, void 0, void 0, function () {
2572
2670
  var configuratorStatistics;
@@ -2599,7 +2697,8 @@
2599
2697
  { type: IconCacheService },
2600
2698
  { type: ProductConnectorService },
2601
2699
  { type: ProductEventService },
2602
- { type: ProductSettingsService }
2700
+ { type: ProductSettingsService },
2701
+ { type: ProductConnectorAdapterService }
2603
2702
  ]; };
2604
2703
  ProductAddtocartComponent.propDecorators = {
2605
2704
  addToCartButton: [{ type: i0.ViewChild, args: ['addtocartbutton', { read: i0.ElementRef },] }],
@@ -3000,7 +3099,7 @@
3000
3099
  this.updateHeight(tabIndex);
3001
3100
  };
3002
3101
  ProductInfoTabsComponent.prototype.updateHeight = function (tabIndex) {
3003
- if (this.tabContent.nativeElement.children.length > 0) {
3102
+ if (this.tabContent && this.tabContent.nativeElement.children.length > 0) {
3004
3103
  if (this.tabContent.nativeElement.children[tabIndex] !== undefined) {
3005
3104
  this.activeTabHeight = this.tabContent.nativeElement.children[tabIndex].offsetHeight;
3006
3105
  }