@liquidcommercedev/rmn-sdk 1.4.6-beta.2 → 1.4.6-beta.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (26) hide show
  1. package/dist/index.cjs +611 -504
  2. package/dist/index.esm.js +611 -505
  3. package/dist/types/enums.d.ts +1 -0
  4. package/dist/types/index.umd.d.ts +2 -2
  5. package/dist/types/modules/element/component/carousel/carousel.component.d.ts +3 -58
  6. package/dist/types/modules/element/component/carousel/carousel.interface.d.ts +31 -0
  7. package/dist/types/modules/element/component/carousel/carousel.style.d.ts +2 -1
  8. package/dist/types/modules/element/component/carousel/index.d.ts +1 -0
  9. package/dist/types/modules/element/component/spot/index.d.ts +2 -0
  10. package/dist/types/modules/element/component/spot/spot.component.d.ts +3 -0
  11. package/dist/types/modules/element/component/spot/spot.interface.d.ts +10 -0
  12. package/dist/types/modules/element/element.constant.d.ts +2 -1
  13. package/dist/types/modules/element/element.interface.d.ts +21 -15
  14. package/dist/types/modules/element/{spot.element.service.d.ts → element.service.d.ts} +15 -3
  15. package/dist/types/modules/element/index.d.ts +1 -1
  16. package/dist/types/modules/element/template/helper.d.ts +1 -0
  17. package/dist/types/modules/element/template/template.service.d.ts +1 -1
  18. package/dist/types/modules/event/helpers/resize.service.d.ts +1 -1
  19. package/dist/types/modules/selection/selection.interface.d.ts +2 -2
  20. package/dist/types/modules/selection/selection.type.d.ts +3 -2
  21. package/dist/types/rmn-client.d.ts +36 -14
  22. package/dist/types/static.constant.d.ts +3 -0
  23. package/dist/types/types.d.ts +4 -4
  24. package/package.json +2 -2
  25. package/umd/liquidcommerce-rmn-sdk.min.js +1 -1
  26. package/dist/types/modules/element/spot.element.d.ts +0 -2
package/dist/index.esm.js CHANGED
@@ -42,6 +42,7 @@ var RMN_SPOT_TYPE;
42
42
  var RMN_FILTER_PROPERTIES;
43
43
  (function (RMN_FILTER_PROPERTIES) {
44
44
  RMN_FILTER_PROPERTIES["KEYWORDS"] = "keywords";
45
+ RMN_FILTER_PROPERTIES["PAGE_LOCATION"] = "pageLocation";
45
46
  RMN_FILTER_PROPERTIES["PARENTCO"] = "parentCo";
46
47
  RMN_FILTER_PROPERTIES["BRAND"] = "brand";
47
48
  RMN_FILTER_PROPERTIES["CATEGORY"] = "category";
@@ -15148,7 +15149,8 @@ class AuthService extends BaseApi {
15148
15149
  }
15149
15150
  }
15150
15151
 
15151
- const ELEMENT_TAG = 'spot-element';
15152
+ const SPOT_ELEMENT_TAG = 'spot-element';
15153
+ const CAROUSEL_ELEMENT_TAG = 'spot-carousel-element';
15152
15154
  const GFONT_PRECONNECT = `
15153
15155
  <link rel="preconnect" href="https://fonts.googleapis.com">
15154
15156
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
@@ -15161,7 +15163,7 @@ const GFONT_CORMORANT = `
15161
15163
  `;
15162
15164
 
15163
15165
  class ResizeObserverService {
15164
- constructor({ element, maxSize, minScale = 0.275 }) {
15166
+ constructor({ element, maxSize, minScale }) {
15165
15167
  this.element = element;
15166
15168
  if (!element.parentElement) {
15167
15169
  throw new Error('RmnSdk: Spot element must have a parent container.');
@@ -15228,6 +15230,431 @@ class ResizeObserverService {
15228
15230
  }
15229
15231
  }
15230
15232
 
15233
+ const CAROUSEL_COMPONENT_STYLE = ({ width, height, fluid }) => `
15234
+ :host {
15235
+ position: relative;
15236
+ display: inline-block;
15237
+ margin: 0;
15238
+ overflow: hidden;
15239
+ width: ${fluid ? '100%' : `${width}px`};
15240
+ height: ${fluid ? '100%' : `${height}px`};
15241
+ }
15242
+
15243
+ .slides {
15244
+ position: relative;
15245
+ height: 100%;
15246
+ width: 100%;
15247
+ }
15248
+
15249
+ .slide {
15250
+ display: none;
15251
+
15252
+ justify-content: center;
15253
+ align-items: center;
15254
+ height: 100%;
15255
+ width: 100%;
15256
+ }
15257
+
15258
+ .slide.active {
15259
+ display: flex;
15260
+ }
15261
+
15262
+ .dots {
15263
+ position: absolute;
15264
+ display: flex;
15265
+ align-items: center;
15266
+ gap: 8px;
15267
+ }
15268
+
15269
+ .dots .dot {
15270
+ width: 12px;
15271
+ height: 12px;
15272
+ border-radius: 50%;
15273
+ cursor: pointer;
15274
+ transition: all 0.3s ease;
15275
+ }
15276
+
15277
+ .dots.top-left,
15278
+ .dots.bottom-left {
15279
+ left: 10px;
15280
+ }
15281
+
15282
+ .dots.top-center,
15283
+ .dots.bottom-center {
15284
+ left: 50%;
15285
+ transform: translateX(-50%);
15286
+ }
15287
+
15288
+ .dots.top-right,
15289
+ .dots.bottom-right {
15290
+ right: 10px;
15291
+ }
15292
+
15293
+ .dots.top-left,
15294
+ .dots.top-center,
15295
+ .dots.top-right {
15296
+ top: 10px;
15297
+ }
15298
+
15299
+ .dots.bottom-left,
15300
+ .dots.bottom-center,
15301
+ .dots.bottom-right {
15302
+ bottom: 10px;
15303
+ }
15304
+
15305
+ .dots.middle-left {
15306
+ left: 10px;
15307
+ top: 50%;
15308
+ transform: translateY(-50%);
15309
+ flex-direction: column;
15310
+ }
15311
+
15312
+ .dots.middle-right {
15313
+ right: 10px;
15314
+ top: 50%;
15315
+ transform: translateY(-50%);
15316
+ flex-direction: column;
15317
+ }
15318
+
15319
+ .buttons button {
15320
+ background-color: #00000080;
15321
+ color: #fff;
15322
+ border: none;
15323
+ padding: 10px;
15324
+ cursor: pointer;
15325
+ transition: background-color 0.3s ease;
15326
+ }
15327
+
15328
+ .buttons button:hover {
15329
+ background-color: #000000b3;
15330
+ }
15331
+
15332
+ .buttons.buttons-separate button {
15333
+ position: absolute;
15334
+ top: 50%;
15335
+ transform: translateY(-50%);
15336
+ }
15337
+
15338
+ .buttons.buttons-separate .prev-button {
15339
+ left: 10px;
15340
+ }
15341
+
15342
+ .buttons.buttons-separate .next-button {
15343
+ right: 10px;
15344
+ }
15345
+
15346
+ .buttons.buttons-together {
15347
+ position: absolute;
15348
+ display: flex;
15349
+ gap: 10px;
15350
+ }
15351
+
15352
+ .buttons.buttons-together.top-left,
15353
+ .buttons.buttons-together.bottom-left {
15354
+ left: 10px;
15355
+ }
15356
+
15357
+ .buttons.buttons-together.top-center,
15358
+ .buttons.buttons-together.bottom-center {
15359
+ left: 50%;
15360
+ transform: translateX(-50%);
15361
+ }
15362
+
15363
+ .buttons.buttons-together.top-right,
15364
+ .buttons.buttons-together.bottom-right {
15365
+ right: 10px;
15366
+ }
15367
+
15368
+ .buttons.buttons-together.top-left,
15369
+ .buttons.buttons-together.top-center,
15370
+ .buttons.buttons-together.top-right {
15371
+ top: 10px;
15372
+ }
15373
+
15374
+ .buttons.buttons-together.bottom-left,
15375
+ .buttons.buttons-together.bottom-center,
15376
+ .buttons.buttons-together.bottom-right {
15377
+ bottom: 10px;
15378
+ }
15379
+
15380
+ .buttons.buttons-together.middle-left,
15381
+ .buttons.buttons-together.middle-right {
15382
+ top: 50%;
15383
+ transform: translateY(-50%);
15384
+ flex-direction: column;
15385
+ }
15386
+
15387
+ .buttons.buttons-together.middle-left {
15388
+ left: 10px;
15389
+ }
15390
+
15391
+ .buttons.buttons-together.middle-right {
15392
+ right: 10px;
15393
+ }
15394
+
15395
+ @media (max-width: 768px) {
15396
+ .buttons button {
15397
+ padding: 8px 12px;
15398
+ font-size: 14px;
15399
+ }
15400
+
15401
+ .dots .dot {
15402
+ width: 8px;
15403
+ height: 8px;
15404
+ }
15405
+ }
15406
+ `;
15407
+
15408
+ let CarouselElement;
15409
+ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined') {
15410
+ class CustomCarouselElement extends HTMLElement {
15411
+ constructor() {
15412
+ super();
15413
+ this.currentSlide = 0;
15414
+ this.dotElements = [];
15415
+ this.prevButton = null;
15416
+ this.nextButton = null;
15417
+ this.autoplayInterval = null;
15418
+ this.useDots = false;
15419
+ this.useButtons = false;
15420
+ this.attachShadow({ mode: 'open' });
15421
+ }
15422
+ connectedCallback() {
15423
+ this.initializeOptions();
15424
+ this.setupResizeObserver();
15425
+ this.render();
15426
+ this.setupCarousel();
15427
+ }
15428
+ disconnectedCallback() {
15429
+ var _a;
15430
+ this.stopAutoplay();
15431
+ (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
15432
+ }
15433
+ initializeOptions() {
15434
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
15435
+ this.useDots = ((_a = this.data) === null || _a === void 0 ? void 0 : _a.useDots) === true || typeof ((_b = this.data) === null || _b === void 0 ? void 0 : _b.useDots) === 'object';
15436
+ this.useButtons = ((_c = this.data) === null || _c === void 0 ? void 0 : _c.useButtons) === true || typeof ((_d = this.data) === null || _d === void 0 ? void 0 : _d.useButtons) === 'object';
15437
+ this.autoplay = (_f = (_e = this.data) === null || _e === void 0 ? void 0 : _e.autoplay) !== null && _f !== void 0 ? _f : true;
15438
+ this.interval = (_h = (_g = this.data) === null || _g === void 0 ? void 0 : _g.interval) !== null && _h !== void 0 ? _h : CustomCarouselElement.defaultInterval;
15439
+ this.dotsOptions = {
15440
+ position: 'bottom-center',
15441
+ color: '#d9d9d9',
15442
+ activeColor: '#b5914a',
15443
+ ...(typeof ((_j = this.data) === null || _j === void 0 ? void 0 : _j.useDots) === 'object' ? this.data.useDots : {}),
15444
+ };
15445
+ this.buttonsOptions = {
15446
+ together: false,
15447
+ position: 'middle-sides',
15448
+ textColor: '#000000',
15449
+ backgroundColor: '#ffffff',
15450
+ borderRadius: '50%',
15451
+ prev: 'Prev',
15452
+ next: 'Next',
15453
+ ...(typeof ((_k = this.data) === null || _k === void 0 ? void 0 : _k.useButtons) === 'object' ? this.data.useButtons : {}),
15454
+ };
15455
+ this.validateOptions();
15456
+ }
15457
+ setupResizeObserver() {
15458
+ if (this.data) {
15459
+ this.resizeObserver = new ResizeObserverService({
15460
+ element: this,
15461
+ maxSize: {
15462
+ width: this.data.width,
15463
+ height: this.data.height,
15464
+ },
15465
+ minScale: this.data.minScale,
15466
+ });
15467
+ this.addEventListener('spotSizeChanged', this.handleCarouselSizeChanged.bind(this));
15468
+ }
15469
+ }
15470
+ handleCarouselSizeChanged(event) {
15471
+ console.info('Carousel Size Changed', event);
15472
+ }
15473
+ render() {
15474
+ var _a;
15475
+ if (!this.shadowRoot)
15476
+ return;
15477
+ const style = document.createElement('style');
15478
+ style.textContent = CAROUSEL_COMPONENT_STYLE(this.data);
15479
+ this.shadowRoot.appendChild(style);
15480
+ const slides = this.renderSlides();
15481
+ this.shadowRoot.appendChild(slides);
15482
+ this.slidesContainer = (_a = this.shadowRoot.querySelector('.slides')) !== null && _a !== void 0 ? _a : undefined;
15483
+ if (this.useDots) {
15484
+ const dots = this.renderDots();
15485
+ if (dots)
15486
+ this.shadowRoot.appendChild(dots);
15487
+ }
15488
+ if (this.useButtons) {
15489
+ const buttons = this.renderButtons();
15490
+ if (buttons)
15491
+ this.shadowRoot.appendChild(buttons);
15492
+ }
15493
+ }
15494
+ setupCarousel() {
15495
+ this.setupDots();
15496
+ this.setupButtons();
15497
+ if (this.autoplay) {
15498
+ this.startAutoplay();
15499
+ }
15500
+ this.updateCarousel();
15501
+ }
15502
+ renderSlides() {
15503
+ const slidesContainer = document.createElement('div');
15504
+ slidesContainer.className = 'slides';
15505
+ this.slides.forEach((slide, index) => {
15506
+ const slideElement = document.createElement('div');
15507
+ slideElement.className = `slide ${index === this.currentSlide ? 'active' : ''}`;
15508
+ if (slide instanceof HTMLElement) {
15509
+ slideElement.appendChild(slide);
15510
+ }
15511
+ slidesContainer.appendChild(slideElement);
15512
+ });
15513
+ return slidesContainer;
15514
+ }
15515
+ renderDots() {
15516
+ const dotsContainer = document.createElement('div');
15517
+ dotsContainer.className = `dots ${this.dotsOptions.position}`;
15518
+ this.slides.forEach((_, index) => {
15519
+ const dot = document.createElement('span');
15520
+ dot.className = `dot ${index === this.currentSlide ? 'active' : ''}`;
15521
+ dot.style.backgroundColor = this.dotsOptions.color;
15522
+ dotsContainer.appendChild(dot);
15523
+ });
15524
+ return dotsContainer;
15525
+ }
15526
+ renderButtons() {
15527
+ const buttonsContainer = document.createElement('div');
15528
+ const buttonsClass = this.buttonsOptions.together
15529
+ ? `buttons-together ${this.buttonsOptions.position}`
15530
+ : 'buttons-separate';
15531
+ buttonsContainer.className = `buttons ${buttonsClass}`;
15532
+ this.prevButton = this.createButton('prev-button', this.buttonsOptions.prev);
15533
+ this.nextButton = this.createButton('next-button', this.buttonsOptions.next);
15534
+ buttonsContainer.appendChild(this.prevButton);
15535
+ buttonsContainer.appendChild(this.nextButton);
15536
+ return buttonsContainer;
15537
+ }
15538
+ createButton(className, text) {
15539
+ const button = document.createElement('button');
15540
+ button.className = className;
15541
+ button.textContent = text;
15542
+ button.style.color = this.buttonsOptions.textColor;
15543
+ button.style.backgroundColor = this.buttonsOptions.backgroundColor;
15544
+ button.style.borderRadius = this.buttonsOptions.borderRadius;
15545
+ return button;
15546
+ }
15547
+ setupDots() {
15548
+ if (!this.shadowRoot || !this.useDots)
15549
+ return;
15550
+ this.dotElements = Array.from(this.shadowRoot.querySelectorAll('.dot'));
15551
+ this.dotElements.forEach((dot, index) => {
15552
+ dot.addEventListener('click', () => {
15553
+ this.goToSlide(index);
15554
+ this.resetAutoplay();
15555
+ });
15556
+ });
15557
+ }
15558
+ setupButtons() {
15559
+ var _a, _b;
15560
+ if (!this.useButtons)
15561
+ return;
15562
+ (_a = this.prevButton) === null || _a === void 0 ? void 0 : _a.addEventListener('click', () => {
15563
+ this.prevSlide();
15564
+ this.resetAutoplay();
15565
+ });
15566
+ (_b = this.nextButton) === null || _b === void 0 ? void 0 : _b.addEventListener('click', () => {
15567
+ this.nextSlide();
15568
+ this.resetAutoplay();
15569
+ });
15570
+ }
15571
+ nextSlide() {
15572
+ this.goToSlide((this.currentSlide + 1) % this.slides.length);
15573
+ }
15574
+ prevSlide() {
15575
+ this.goToSlide((this.currentSlide - 1 + this.slides.length) % this.slides.length);
15576
+ }
15577
+ goToSlide(index) {
15578
+ this.currentSlide = index;
15579
+ this.updateCarousel();
15580
+ }
15581
+ updateCarousel() {
15582
+ if (!this.slidesContainer)
15583
+ return;
15584
+ const slides = Array.from(this.slidesContainer.children);
15585
+ slides.forEach((slide, index) => {
15586
+ slide.classList.toggle('active', index === this.currentSlide);
15587
+ });
15588
+ this.updateDots();
15589
+ }
15590
+ updateDots() {
15591
+ if (!this.useDots)
15592
+ return;
15593
+ this.dotElements.forEach((dot, index) => {
15594
+ const isActive = index === this.currentSlide;
15595
+ dot.classList.toggle('active', isActive);
15596
+ dot.style.backgroundColor = isActive
15597
+ ? this.dotsOptions.activeColor
15598
+ : this.dotsOptions.color;
15599
+ });
15600
+ }
15601
+ startAutoplay() {
15602
+ this.autoplayInterval = window.setInterval(() => this.nextSlide(), this.interval);
15603
+ }
15604
+ stopAutoplay() {
15605
+ if (this.autoplayInterval !== null) {
15606
+ window.clearInterval(this.autoplayInterval);
15607
+ this.autoplayInterval = null;
15608
+ }
15609
+ }
15610
+ resetAutoplay() {
15611
+ if (this.autoplay) {
15612
+ this.stopAutoplay();
15613
+ this.startAutoplay();
15614
+ }
15615
+ }
15616
+ validateOptions() {
15617
+ this.validatePosition(this.dotsOptions.position, 'dotsPosition', 'bottom-center');
15618
+ this.validateButtonsPosition();
15619
+ }
15620
+ validatePosition(position, optionName, defaultValue) {
15621
+ if (!CustomCarouselElement.validPositions.includes(position)) {
15622
+ console.warn(`Invalid ${optionName}: ${position}. Defaulting to '${defaultValue}'.`);
15623
+ if (optionName === 'dotsPosition') {
15624
+ this.dotsOptions.position = defaultValue;
15625
+ }
15626
+ else if (optionName === 'buttonsPosition') {
15627
+ this.buttonsOptions.position = defaultValue;
15628
+ }
15629
+ }
15630
+ }
15631
+ validateButtonsPosition() {
15632
+ if (this.useButtons) {
15633
+ if (this.buttonsOptions.together) {
15634
+ this.validatePosition(this.buttonsOptions.position, 'buttonsPosition', 'bottom-center');
15635
+ }
15636
+ else if (this.buttonsOptions.position !== 'middle-sides') {
15637
+ console.warn(`Invalid buttonsPosition: ${this.buttonsOptions.position}. When buttons are not together, only 'middle-sides' is allowed. Defaulting to 'middle-sides'.`);
15638
+ this.buttonsOptions.position = 'middle-sides';
15639
+ }
15640
+ }
15641
+ }
15642
+ }
15643
+ CustomCarouselElement.defaultInterval = 5000;
15644
+ CustomCarouselElement.validPositions = [
15645
+ 'top-left',
15646
+ 'top-center',
15647
+ 'top-right',
15648
+ 'bottom-left',
15649
+ 'bottom-center',
15650
+ 'bottom-right',
15651
+ 'middle-left',
15652
+ 'middle-right',
15653
+ 'middle-sides',
15654
+ ];
15655
+ CarouselElement = CustomCarouselElement;
15656
+ }
15657
+
15231
15658
  let SpotElement;
15232
15659
  if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined') {
15233
15660
  class CustomSpotElement extends HTMLElement {
@@ -15267,6 +15694,7 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
15267
15694
  * #########################################################
15268
15695
  */
15269
15696
  handleSpotSizeChanged(event) {
15697
+ console.info('Spot Size Changed', event);
15270
15698
  // Adjust text elements font size based on the scale factor
15271
15699
  this.adjustFontSize(event.detail.scale);
15272
15700
  }
@@ -15309,8 +15737,8 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
15309
15737
  const scaleFactor = 1 + (baseFactor - 1) * dampening;
15310
15738
  // Step 3: Define the allowed range for the scale factor
15311
15739
  // This ensures that the font size never changes too drastically
15312
- const minScale = 0.9; // Font will never be smaller than 90% of original
15313
- const maxScale = 1.1; // Font will never be larger than 110% of original
15740
+ const minScale = 0.5; // Font will never be smaller than 90% of original
15741
+ const maxScale = 1.5; // Font will never be larger than 110% of original
15314
15742
  // Step 4: Clamp the scale factor to the defined range
15315
15743
  // Math.min ensures the value doesn't exceed maxScale
15316
15744
  // Math.max ensures the value isn't less than minScale
@@ -15324,15 +15752,9 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
15324
15752
  if (!this.shadowRoot || !this.data || !this.content)
15325
15753
  return;
15326
15754
  const style = this.getTemplateStyle(this.data.width, this.data.height);
15327
- const spot = document.createElement('div');
15328
- spot.className = 'spot';
15329
- if (typeof this.content === 'string') {
15330
- spot.innerHTML = this.content;
15331
- }
15332
15755
  if (this.content instanceof HTMLElement) {
15333
- spot.replaceChildren(this.content);
15756
+ this.shadowRoot.replaceChildren(style, this.content);
15334
15757
  }
15335
- this.shadowRoot.replaceChildren(style, spot);
15336
15758
  }
15337
15759
  getTemplateStyle(width, height) {
15338
15760
  const style = document.createElement('style');
@@ -15345,12 +15767,6 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
15345
15767
  width: ${this.data.fluid ? '100%' : `${width}px`};
15346
15768
  height: ${this.data.fluid ? '100%' : `${height}px`};
15347
15769
  }
15348
-
15349
- :host .spot {
15350
- width: 100%;
15351
- height: 100%;
15352
- display: block;
15353
- }
15354
15770
  `;
15355
15771
  return style;
15356
15772
  }
@@ -15367,24 +15783,43 @@ class ElementService {
15367
15783
  *
15368
15784
  * This method is only available in browser environments.
15369
15785
  *
15370
- * @param {ICreateFinalElementParams} params - The parameters to create the final element.
15786
+ * @param {ICreateSpotElementParams} params - The parameters to create the final element.
15371
15787
  *
15372
15788
  * @return {HTMLElement | null} - The html element or null if the browser environment is not available.
15373
15789
  */
15374
- createFinalElement({ content, config }) {
15790
+ createSpotElement({ content, config }) {
15375
15791
  var _a;
15376
15792
  if (!this.ensureBrowserEnvironmentAndDefineElement()) {
15377
15793
  return null;
15378
15794
  }
15379
- const element = document.createElement(ELEMENT_TAG);
15380
- element.data = {
15381
- width: config.width,
15382
- height: config.height,
15383
- minScale: config === null || config === void 0 ? void 0 : config.minScale,
15795
+ const spot = document.createElement(SPOT_ELEMENT_TAG);
15796
+ spot.data = {
15384
15797
  fluid: (_a = config === null || config === void 0 ? void 0 : config.fluid) !== null && _a !== void 0 ? _a : false,
15798
+ ...config,
15385
15799
  };
15386
- element.content = content;
15387
- return element;
15800
+ spot.content = content;
15801
+ return spot;
15802
+ }
15803
+ /**
15804
+ * Creates the carousel html element based on the provided slides and configs using shadow dom.
15805
+ *
15806
+ * This method is only available in browser environments.
15807
+ *
15808
+ * @param {ICreateCarouselElementParams} params - The parameters to create the final element.
15809
+ *
15810
+ * @return {HTMLElement | null} - The html element or null if the browser environment is not available.
15811
+ */
15812
+ createCarouselElement({ slides, config, }) {
15813
+ if (!this.ensureBrowserEnvironmentAndDefineElement()) {
15814
+ return null;
15815
+ }
15816
+ const carousel = document.createElement(CAROUSEL_ELEMENT_TAG);
15817
+ carousel.data = {
15818
+ fluid: false,
15819
+ ...config,
15820
+ };
15821
+ carousel.slides = slides;
15822
+ return carousel;
15388
15823
  }
15389
15824
  /**
15390
15825
  * Overrides the spot colors with the provided colors.
@@ -15414,428 +15849,35 @@ class ElementService {
15414
15849
  console.warn('LiquidCommerce Rmn Sdk: Methods which create elements are only available in browser environments.');
15415
15850
  return false;
15416
15851
  }
15417
- if (!window.customElements.get(ELEMENT_TAG)) {
15418
- window.customElements.define(ELEMENT_TAG, SpotElement);
15852
+ if (!window.customElements.get(SPOT_ELEMENT_TAG)) {
15853
+ window.customElements.define(SPOT_ELEMENT_TAG, SpotElement);
15854
+ }
15855
+ if (!window.customElements.get(CAROUSEL_ELEMENT_TAG)) {
15856
+ window.customElements.define(CAROUSEL_ELEMENT_TAG, CarouselElement);
15419
15857
  }
15420
15858
  return true;
15421
15859
  }
15422
15860
  }
15423
15861
 
15424
- const CAROUSEL_COMPONENT_STYLE = `
15425
- :host {
15426
- position: relative;
15427
- display: inline-block;
15428
- margin: 0;
15429
- overflow: hidden;
15430
- height: 100%;
15431
- width: 100%;
15432
- }
15433
-
15434
- .carousel-slides {
15435
- position: relative;
15436
- height: 100%;
15437
- width: 100%;
15438
- }
15439
-
15440
- .carousel-slide {
15441
- display: none;
15442
-
15443
- justify-content: center;
15444
- align-items: center;
15445
- height: 100%;
15446
- width: 100%;
15447
- }
15448
-
15449
- .carousel-slide.active {
15450
- display: flex;
15451
- }
15452
-
15453
- .carousel-dots {
15454
- position: absolute;
15455
- display: flex;
15456
- align-items: center;
15457
- gap: 8px;
15458
- }
15459
-
15460
- .carousel-dots .dot {
15461
- width: 12px;
15462
- height: 12px;
15463
- border-radius: 50%;
15464
- cursor: pointer;
15465
- transition: all 0.3s ease;
15466
- }
15467
-
15468
- .carousel-dots.top-left,
15469
- .carousel-dots.bottom-left {
15470
- left: 10px;
15471
- }
15472
-
15473
- .carousel-dots.top-center,
15474
- .carousel-dots.bottom-center {
15475
- left: 50%;
15476
- transform: translateX(-50%);
15477
- }
15478
-
15479
- .carousel-dots.top-right,
15480
- .carousel-dots.bottom-right {
15481
- right: 10px;
15482
- }
15483
-
15484
- .carousel-dots.top-left,
15485
- .carousel-dots.top-center,
15486
- .carousel-dots.top-right {
15487
- top: 10px;
15488
- }
15489
-
15490
- .carousel-dots.bottom-left,
15491
- .carousel-dots.bottom-center,
15492
- .carousel-dots.bottom-right {
15493
- bottom: 10px;
15494
- }
15495
-
15496
- .carousel-dots.middle-left {
15497
- left: 10px;
15498
- top: 50%;
15499
- transform: translateY(-50%);
15500
- flex-direction: column;
15501
- }
15502
-
15503
- .carousel-dots.middle-right {
15504
- right: 10px;
15505
- top: 50%;
15506
- transform: translateY(-50%);
15507
- flex-direction: column;
15508
- }
15509
-
15510
- .carousel-buttons button {
15511
- background-color: #00000080;
15512
- color: #fff;
15513
- border: none;
15514
- padding: 10px;
15515
- cursor: pointer;
15516
- transition: background-color 0.3s ease;
15517
- }
15518
-
15519
- .carousel-buttons button:hover {
15520
- background-color: #000000b3;
15521
- }
15522
-
15523
- .carousel-buttons.buttons-separate button {
15524
- position: absolute;
15525
- top: 50%;
15526
- transform: translateY(-50%);
15527
- }
15528
-
15529
- .carousel-buttons.buttons-separate .prev-button {
15530
- left: 10px;
15531
- }
15532
-
15533
- .carousel-buttons.buttons-separate .next-button {
15534
- right: 10px;
15535
- }
15536
-
15537
- .carousel-buttons.buttons-together {
15538
- position: absolute;
15539
- display: flex;
15540
- gap: 10px;
15541
- }
15542
-
15543
- .carousel-buttons.buttons-together.top-left,
15544
- .carousel-buttons.buttons-together.bottom-left {
15545
- left: 10px;
15546
- }
15547
-
15548
- .carousel-buttons.buttons-together.top-center,
15549
- .carousel-buttons.buttons-together.bottom-center {
15550
- left: 50%;
15551
- transform: translateX(-50%);
15552
- }
15553
-
15554
- .carousel-buttons.buttons-together.top-right,
15555
- .carousel-buttons.buttons-together.bottom-right {
15556
- right: 10px;
15557
- }
15558
-
15559
- .carousel-buttons.buttons-together.top-left,
15560
- .carousel-buttons.buttons-together.top-center,
15561
- .carousel-buttons.buttons-together.top-right {
15562
- top: 10px;
15563
- }
15564
-
15565
- .carousel-buttons.buttons-together.bottom-left,
15566
- .carousel-buttons.buttons-together.bottom-center,
15567
- .carousel-buttons.buttons-together.bottom-right {
15568
- bottom: 10px;
15569
- }
15570
-
15571
- .carousel-buttons.buttons-together.middle-left,
15572
- .carousel-buttons.buttons-together.middle-right {
15573
- top: 50%;
15574
- transform: translateY(-50%);
15575
- flex-direction: column;
15576
- }
15577
-
15578
- .carousel-buttons.buttons-together.middle-left {
15579
- left: 10px;
15580
- }
15581
-
15582
- .carousel-buttons.buttons-together.middle-right {
15583
- right: 10px;
15584
- }
15585
-
15586
- @media (max-width: 768px) {
15587
- .carousel-buttons button {
15588
- padding: 8px 12px;
15589
- font-size: 14px;
15590
- }
15591
-
15592
- .carousel-dots .dot {
15593
- width: 8px;
15594
- height: 8px;
15595
- }
15596
- }
15597
- `;
15598
-
15599
- class CarouselComponent {
15600
- constructor(slides, options = {}) {
15601
- var _a, _b;
15602
- this.currentSlide = 0;
15603
- this.dotElements = [];
15604
- this.prevButton = null;
15605
- this.nextButton = null;
15606
- this.autoplayInterval = null;
15607
- this.slides = slides;
15608
- this.autoplay = (_a = options.autoplay) !== null && _a !== void 0 ? _a : true;
15609
- this.interval = (_b = options.interval) !== null && _b !== void 0 ? _b : 10000;
15610
- this.dotsOptions = this.initializeDotOptions(options.useDots);
15611
- this.buttonsOptions = this.initializeButtonOptions(options.useButtons);
15612
- this.validateOptions();
15613
- this.carousel = document.createElement('div');
15614
- this.carousel.className = 'carousel';
15615
- this.shadowRoot = this.carousel.attachShadow({ mode: 'open' });
15616
- this.render();
15617
- this.slidesContainer = this.shadowRoot.querySelector('.carousel-slides');
15618
- this.setupCarousel();
15619
- }
15620
- // Public method to get the carousel element
15621
- getElement() {
15622
- return this.carousel;
15623
- }
15624
- // Main setup methods
15625
- render() {
15626
- const style = document.createElement('style');
15627
- style.textContent = CAROUSEL_COMPONENT_STYLE;
15628
- this.shadowRoot.appendChild(style);
15629
- this.shadowRoot.appendChild(this.renderSlides());
15630
- if (this.dotsOptions) {
15631
- const dots = this.renderDots();
15632
- if (dots)
15633
- this.shadowRoot.appendChild(dots);
15634
- }
15635
- if (this.buttonsOptions) {
15636
- const buttons = this.renderButtons();
15637
- if (buttons)
15638
- this.shadowRoot.appendChild(buttons);
15639
- }
15640
- }
15641
- setupCarousel() {
15642
- this.setupDots();
15643
- this.setupButtons();
15644
- if (this.autoplay) {
15645
- this.startAutoplay();
15646
- }
15647
- this.updateCarousel();
15648
- }
15649
- // Rendering methods
15650
- renderSlides() {
15651
- const slidesContainer = document.createElement('div');
15652
- slidesContainer.className = 'carousel-slides';
15653
- this.slides.forEach((slide, index) => {
15654
- const slideElement = document.createElement('div');
15655
- slideElement.className = `carousel-slide ${index === this.currentSlide ? 'active' : ''}`;
15656
- if (typeof slide === 'string') {
15657
- slideElement.innerHTML = slide;
15658
- }
15659
- else if (slide instanceof HTMLElement) {
15660
- slideElement.appendChild(slide);
15661
- }
15662
- slidesContainer.appendChild(slideElement);
15663
- });
15664
- return slidesContainer;
15665
- }
15666
- renderDots() {
15667
- if (!this.dotsOptions)
15668
- return null;
15669
- const dotsContainer = document.createElement('div');
15670
- dotsContainer.className = `carousel-dots ${this.dotsOptions.position}`;
15671
- this.slides.forEach((_, index) => {
15672
- if (!this.dotsOptions)
15673
- return;
15674
- const dot = document.createElement('span');
15675
- dot.className = `dot ${index === this.currentSlide ? 'active' : ''}`;
15676
- dot.style.backgroundColor = this.dotsOptions.color;
15677
- dotsContainer.appendChild(dot);
15678
- });
15679
- return dotsContainer;
15680
- }
15681
- renderButtons() {
15682
- if (!this.buttonsOptions)
15683
- return null;
15684
- const buttonsContainer = document.createElement('div');
15685
- const buttonsClass = this.buttonsOptions.together
15686
- ? `buttons-together ${this.buttonsOptions.position}`
15687
- : 'buttons-separate';
15688
- buttonsContainer.className = `carousel-buttons ${buttonsClass}`;
15689
- this.prevButton = document.createElement('button');
15690
- this.prevButton.className = 'prev-button';
15691
- this.prevButton.textContent = this.buttonsOptions.prev;
15692
- this.prevButton.style.color = this.buttonsOptions.textColor;
15693
- this.prevButton.style.backgroundColor = this.buttonsOptions.backgroundColor;
15694
- this.prevButton.style.borderRadius = this.buttonsOptions.borderRadius;
15695
- buttonsContainer.appendChild(this.prevButton);
15696
- this.nextButton = document.createElement('button');
15697
- this.nextButton.className = 'next-button';
15698
- this.nextButton.textContent = this.buttonsOptions.next;
15699
- this.nextButton.style.color = this.buttonsOptions.textColor;
15700
- this.nextButton.style.backgroundColor = this.buttonsOptions.backgroundColor;
15701
- this.nextButton.style.borderRadius = this.buttonsOptions.borderRadius;
15702
- buttonsContainer.appendChild(this.nextButton);
15703
- return buttonsContainer;
15704
- }
15705
- // Setup methods
15706
- setupDots() {
15707
- if (this.dotsOptions) {
15708
- this.dotElements = Array.from(this.shadowRoot.querySelectorAll('.dot'));
15709
- this.dotElements.forEach((dot, index) => {
15710
- dot.addEventListener('click', () => {
15711
- this.goToSlide(index);
15712
- this.resetAutoplay();
15713
- });
15714
- });
15715
- }
15716
- }
15717
- setupButtons() {
15718
- var _a, _b;
15719
- if (this.buttonsOptions) {
15720
- (_a = this.prevButton) === null || _a === void 0 ? void 0 : _a.addEventListener('click', () => {
15721
- this.prevSlide();
15722
- this.resetAutoplay();
15723
- });
15724
- (_b = this.nextButton) === null || _b === void 0 ? void 0 : _b.addEventListener('click', () => {
15725
- this.nextSlide();
15726
- this.resetAutoplay();
15727
- });
15728
- }
15729
- }
15730
- // Navigation methods
15731
- nextSlide() {
15732
- this.goToSlide((this.currentSlide + 1) % this.slides.length);
15733
- }
15734
- prevSlide() {
15735
- this.goToSlide((this.currentSlide - 1 + this.slides.length) % this.slides.length);
15736
- }
15737
- goToSlide(index) {
15738
- this.currentSlide = index;
15739
- this.updateCarousel();
15740
- }
15741
- // Update methods
15742
- updateCarousel() {
15743
- const slides = Array.from(this.slidesContainer.children);
15744
- slides.forEach((slide, index) => {
15745
- if (index === this.currentSlide) {
15746
- slide.classList.add('active');
15747
- }
15748
- else {
15749
- slide.classList.remove('active');
15750
- }
15751
- });
15752
- this.updateDots();
15753
- }
15754
- updateDots() {
15755
- this.dotElements.forEach((dot, index) => {
15756
- const isActive = index === this.currentSlide;
15757
- dot.classList.toggle('active', isActive);
15758
- if (!this.dotsOptions)
15759
- return;
15760
- dot.style.backgroundColor = isActive ? this.dotsOptions.activeColor : this.dotsOptions.color;
15761
- });
15762
- }
15763
- // Autoplay methods
15764
- startAutoplay() {
15765
- this.autoplayInterval = window.setInterval(() => this.nextSlide(), this.interval);
15766
- }
15767
- stopAutoplay() {
15768
- if (this.autoplayInterval !== null) {
15769
- window.clearInterval(this.autoplayInterval);
15770
- this.autoplayInterval = null;
15771
- }
15772
- }
15773
- resetAutoplay() {
15774
- if (this.autoplay) {
15775
- this.stopAutoplay();
15776
- this.startAutoplay();
15777
- }
15778
- }
15779
- // Initialization and validation methods
15780
- initializeDotOptions(useDots) {
15781
- var _a, _b, _c;
15782
- return !useDots
15783
- ? false
15784
- : {
15785
- position: (_a = useDots === null || useDots === void 0 ? void 0 : useDots.position) !== null && _a !== void 0 ? _a : 'bottom-center',
15786
- color: (_b = useDots === null || useDots === void 0 ? void 0 : useDots.color) !== null && _b !== void 0 ? _b : '#d9d9d9',
15787
- activeColor: (_c = useDots === null || useDots === void 0 ? void 0 : useDots.activeColor) !== null && _c !== void 0 ? _c : '#b5914a',
15788
- };
15789
- }
15790
- initializeButtonOptions(useButtons) {
15791
- var _a, _b, _c, _d, _e, _f, _g;
15792
- return !useButtons
15793
- ? false
15794
- : {
15795
- position: (_a = useButtons === null || useButtons === void 0 ? void 0 : useButtons.position) !== null && _a !== void 0 ? _a : 'middle-sides',
15796
- together: (_b = useButtons === null || useButtons === void 0 ? void 0 : useButtons.together) !== null && _b !== void 0 ? _b : false,
15797
- textColor: (_c = useButtons === null || useButtons === void 0 ? void 0 : useButtons.textColor) !== null && _c !== void 0 ? _c : '#000000',
15798
- backgroundColor: (_d = useButtons === null || useButtons === void 0 ? void 0 : useButtons.backgroundColor) !== null && _d !== void 0 ? _d : '#ffffff',
15799
- borderRadius: (_e = useButtons === null || useButtons === void 0 ? void 0 : useButtons.borderRadius) !== null && _e !== void 0 ? _e : '50%',
15800
- prev: (_f = useButtons === null || useButtons === void 0 ? void 0 : useButtons.prev) !== null && _f !== void 0 ? _f : 'Prev',
15801
- next: (_g = useButtons === null || useButtons === void 0 ? void 0 : useButtons.next) !== null && _g !== void 0 ? _g : 'Next',
15802
- };
15803
- }
15804
- validateOptions() {
15805
- const validPositions = [
15806
- 'top-left',
15807
- 'top-center',
15808
- 'top-right',
15809
- 'bottom-left',
15810
- 'bottom-center',
15811
- 'bottom-right',
15812
- 'middle-left',
15813
- 'middle-right',
15814
- 'middle-sides',
15815
- ];
15816
- this.validateDotsPosition(validPositions);
15817
- this.validateButtonsPosition(validPositions);
15818
- }
15819
- validateDotsPosition(validPositions) {
15820
- if (this.dotsOptions && !validPositions.includes(this.dotsOptions.position)) {
15821
- console.warn(`Invalid dotsPosition: ${this.dotsOptions.position}. Defaulting to 'bottom-center'.`);
15822
- this.dotsOptions.position = 'bottom-center';
15823
- }
15824
- }
15825
- validateButtonsPosition(validPositions) {
15826
- if (this.buttonsOptions) {
15827
- if (this.buttonsOptions.together) {
15828
- if (!validPositions.includes(this.buttonsOptions.position)) {
15829
- console.warn(`Invalid buttonsPosition: ${this.buttonsOptions.position}. Defaulting to 'bottom-center'.`);
15830
- this.buttonsOptions.position = 'bottom-center';
15831
- }
15832
- }
15833
- else if (this.buttonsOptions.position !== 'middle-sides') {
15834
- console.warn(`Invalid buttonsPosition: ${this.buttonsOptions.position}. When buttons are not together, only 'middle-sides' is allowed. Defaulting to 'middle-sides'.`);
15835
- this.buttonsOptions.position = 'middle-sides';
15836
- }
15837
- }
15862
+ function linearGradientColorStop(overlay, fallback) {
15863
+ if (!overlay || overlay.length === 0) {
15864
+ return fallback;
15838
15865
  }
15866
+ return overlay.map(({ color, colorStop }) => `${color} ${colorStop}`).join(', ');
15867
+ }
15868
+ function spotHtmlStringToElement(htmlString) {
15869
+ const spot = document.createElement('div');
15870
+ spot.className = 'spot';
15871
+ spot.innerHTML = htmlString;
15872
+ Object.assign(spot.style, {
15873
+ position: 'relative',
15874
+ display: 'block',
15875
+ width: '100%',
15876
+ height: '100%',
15877
+ margin: '0',
15878
+ padding: '0',
15879
+ });
15880
+ return spot;
15839
15881
  }
15840
15882
 
15841
15883
  const STYLES$i = ({ primaryImage, secondaryImage }) => `
@@ -16688,13 +16730,6 @@ function rbCollectionBannerWithoutTextBlockTemplate(spot, config) {
16688
16730
  `;
16689
16731
  }
16690
16732
 
16691
- function linearGradientColorStop(overlay, fallback) {
16692
- if (!overlay || overlay.length === 0) {
16693
- return fallback;
16694
- }
16695
- return overlay.map(({ color, colorStop }) => `${color} ${colorStop}`).join(', ');
16696
- }
16697
-
16698
16733
  const STYLES$6 = ({ textColor = '#ffffff', ctaTextColor = textColor, ctaBorderColor = ctaTextColor, primaryImage, mobilePrimaryImage = primaryImage, }, { prefix, overlay }) => {
16699
16734
  const linearGradient = linearGradientColorStop(overlay || [], 'rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 40%');
16700
16735
  return `
@@ -17289,7 +17324,9 @@ function rbLargeCategoryImageToutTemplate(spot, config) {
17289
17324
  `;
17290
17325
  }
17291
17326
 
17292
- const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = primaryImage }, { prefix }) => `
17327
+ const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = primaryImage }, { prefix, overlay }) => {
17328
+ const linearGradient = linearGradientColorStop(overlay || [], 'rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 30%');
17329
+ return `
17293
17330
  <style>
17294
17331
  :host {
17295
17332
  min-width: 320px;
@@ -17305,10 +17342,9 @@ const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = pr
17305
17342
  border-radius: 5px;
17306
17343
  overflow: hidden;
17307
17344
  cursor: pointer;
17308
- background-image: url("${mobilePrimaryImage}");
17345
+ background-image: linear-gradient(to top, ${linearGradient}), url("${mobilePrimaryImage}");
17309
17346
  background-size: cover;
17310
17347
  background-position: center;
17311
- background-blend-mode: overlay;
17312
17348
  background-repeat: no-repeat;
17313
17349
  }
17314
17350
 
@@ -17329,7 +17365,7 @@ const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = pr
17329
17365
 
17330
17366
  @media (min-width: 640px) {
17331
17367
  .${prefix}__content {
17332
- background-image: url("${primaryImage}");
17368
+ background-image: linear-gradient(to top, ${linearGradient}), url("${primaryImage}");
17333
17369
  }
17334
17370
  }
17335
17371
 
@@ -17352,6 +17388,7 @@ const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = pr
17352
17388
  }
17353
17389
  </style>
17354
17390
  `;
17391
+ };
17355
17392
  function rbNavigationBannerTemplate(spot, config) {
17356
17393
  const { prefix = '' } = config;
17357
17394
  return `
@@ -17507,7 +17544,7 @@ function rbSmallDiscoverToutTemplate(spot, config) {
17507
17544
  *
17508
17545
  * @return {string} - The spot html string.
17509
17546
  */
17510
- const GET_SPOT_TEMPLATE_HTML_STRING = (spot, config) => {
17547
+ const SPOT_TEMPLATE_HTML_ELEMENT = (spot, config) => {
17511
17548
  const templates = {
17512
17549
  // Reserve Bar Spot Templates
17513
17550
  [RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE]: {
@@ -17566,15 +17603,16 @@ const GET_SPOT_TEMPLATE_HTML_STRING = (spot, config) => {
17566
17603
  };
17567
17604
  const spotVariants = templates[spot.spot];
17568
17605
  if (!spotVariants) {
17569
- return '';
17606
+ return null;
17570
17607
  }
17571
17608
  const variantTemplate = spotVariants[spot.variant];
17572
17609
  if (!variantTemplate) {
17573
- return '';
17610
+ return null;
17574
17611
  }
17575
17612
  // Generate a random prefix to avoid conflicts with other elements.
17576
17613
  const prefix = 's' + Math.random().toString(36).substring(6);
17577
- return variantTemplate(spot, { ...config, prefix });
17614
+ const spotHtmlString = variantTemplate(spot, { ...config, prefix });
17615
+ return spotHtmlStringToElement(spotHtmlString);
17578
17616
  };
17579
17617
 
17580
17618
  const SELECTION_API_PATH = '/spots/selection';
@@ -17617,37 +17655,32 @@ class LiquidCommerceRmnClient {
17617
17655
  *
17618
17656
  * To create a spot html element, use the RmnCreateSpotElement function.
17619
17657
  *
17620
- * @param {ISpotSelectionParams} data - Spots selection parameters.
17658
+ * @param {ISpotSelectionParams} params - Spots selection parameters.
17621
17659
  *
17622
17660
  * @return {Promise<ISpots>} - The spots response object.
17623
17661
  */
17624
- async spotSelection(data) {
17625
- return this.selectionService.spotSelection(data);
17662
+ async spotSelection(params) {
17663
+ return this.selectionService.spotSelection(params);
17626
17664
  }
17627
17665
  /**
17628
17666
  * Injects the spot elements into their provided placement.
17629
17667
  *
17630
- * @param {IInjectSpotElement[]} data - The spot elements data.
17631
- * @param {IInjectSpotsConfig} config - The configuration object.
17668
+ * @param {IInjectSpotElementParams} params - Parameters for injecting spot elements.
17632
17669
  *
17633
17670
  * @return {Promise<void>} - A promise that resolves when the spot elements are injected.
17634
17671
  */
17635
- async injectSpotElement(data, config) {
17636
- if (!data.length) {
17637
- console.warn('RmnSdk: Failed to request spot selection. No spot elements provided.');
17672
+ async injectSpotElement(params) {
17673
+ var _a;
17674
+ const { inject, config } = params;
17675
+ if (!inject.length) {
17676
+ console.warn('RmnSdk: Failed to inject spot element. Please provide at least one spot element to inject.');
17638
17677
  return;
17639
17678
  }
17640
- const spotSelectionRequest = data.map((item) => {
17641
- var _a;
17642
- return ({
17643
- spot: item.spotType,
17644
- count: (_a = item === null || item === void 0 ? void 0 : item.count) !== null && _a !== void 0 ? _a : 1,
17645
- });
17646
- });
17647
- const response = await this.spotSelection({ spots: spotSelectionRequest });
17648
- const normalizedData = this.normalizeDataSpotType(data);
17649
- for (const item of normalizedData) {
17650
- const spots = response[item.spotType];
17679
+ this.preventDuplicateSpotPlacementIds(inject);
17680
+ const response = await this.spotSelectionRequest(params);
17681
+ for (const item of inject) {
17682
+ const itemConfig = (_a = item.config) !== null && _a !== void 0 ? _a : config;
17683
+ const spots = response[item.placementId];
17651
17684
  if (!(spots === null || spots === void 0 ? void 0 : spots.length)) {
17652
17685
  console.warn(`RmnSdk: Failed to inject spot element. No spots found for type "${item.spotType}".`);
17653
17686
  continue;
@@ -17659,32 +17692,73 @@ class LiquidCommerceRmnClient {
17659
17692
  continue;
17660
17693
  }
17661
17694
  if (spots.length === 1) {
17662
- this.injectOneSpotElement(item, placement, spots[0], config);
17695
+ this.injectOneSpotElement(item, placement, spots[0], itemConfig);
17663
17696
  }
17664
17697
  if (spots.length > 1) {
17665
- this.injectCarouselSpotElement(placement, spots, config);
17698
+ this.injectCarouselSpotElement(placement, spots, itemConfig);
17666
17699
  }
17667
17700
  }
17668
17701
  }
17702
+ /**
17703
+ * Makes a selection request on our server based on the provided data.
17704
+ *
17705
+ * @param {IInjectSpotElementParams} params - Parameters for injecting spot elements.
17706
+ *
17707
+ * @return {Promise<ISpots>} - The spots response object.
17708
+ */
17709
+ async spotSelectionRequest(params) {
17710
+ const { inject, filter, config } = params;
17711
+ const request = {
17712
+ url: config === null || config === void 0 ? void 0 : config.url,
17713
+ filter,
17714
+ spots: inject.map((item) => ({
17715
+ placementId: item.placementId,
17716
+ spot: item.spotType,
17717
+ count: item === null || item === void 0 ? void 0 : item.count,
17718
+ ...item === null || item === void 0 ? void 0 : item.filter,
17719
+ })),
17720
+ };
17721
+ return this.spotSelection(request);
17722
+ }
17669
17723
  /**
17670
17724
  * Injects a carousel element with the provided spots into the placement.
17671
17725
  *
17672
17726
  * @param {HTMLElement} placement - The placement element.
17673
17727
  * @param {ISpot[]} spots - The spot data.
17674
- * @param {IInjectSpotsConfig} config - The configuration object.
17728
+ * @param {IInjectSpotElementConfig} config - The configuration object.
17675
17729
  *
17676
17730
  * @return {void}
17677
17731
  */
17678
17732
  injectCarouselSpotElement(placement, spots, config) {
17733
+ var _a;
17679
17734
  const carouselSlides = [];
17680
17735
  for (const spotItem of spots) {
17681
17736
  const spot = this.elementService.overrideSpotColors(spotItem, config === null || config === void 0 ? void 0 : config.colors);
17682
- const content = GET_SPOT_TEMPLATE_HTML_STRING(spot, { overlay: config === null || config === void 0 ? void 0 : config.overlay });
17737
+ const content = SPOT_TEMPLATE_HTML_ELEMENT(spot, { overlay: config === null || config === void 0 ? void 0 : config.overlay });
17738
+ if (!content) {
17739
+ console.warn(`RmnSdk: Failed to inject carousel spot element. Could not create element for type "${spot.spot}".`);
17740
+ return;
17741
+ }
17683
17742
  carouselSlides.push(content);
17684
17743
  }
17685
- const carousel = new CarouselComponent(carouselSlides, config === null || config === void 0 ? void 0 : config.carousel);
17686
- const carouselElement = carousel.getElement();
17687
- placement.appendChild(carouselElement);
17744
+ const { maxWidth, maxHeight } = spots.reduce((max, spot) => ({
17745
+ maxWidth: Math.max(max.maxWidth, spot.width),
17746
+ maxHeight: Math.max(max.maxHeight, spot.height),
17747
+ }), { maxWidth: 0, maxHeight: 0 });
17748
+ const carouselElement = this.elementService.createCarouselElement({
17749
+ slides: carouselSlides,
17750
+ config: {
17751
+ width: maxWidth,
17752
+ height: maxHeight,
17753
+ minScale: (_a = config === null || config === void 0 ? void 0 : config.minScale) !== null && _a !== void 0 ? _a : 0.25, // Scale down to 25% of the original size
17754
+ ...config === null || config === void 0 ? void 0 : config.carousel,
17755
+ },
17756
+ });
17757
+ if (!carouselElement) {
17758
+ console.warn(`RmnSdk: Failed to inject spot carousel element. Could not create spot carousel element.`);
17759
+ return;
17760
+ }
17761
+ placement.replaceChildren(carouselElement);
17688
17762
  }
17689
17763
  /**
17690
17764
  * Injects a single spot element into the provided placement.
@@ -17692,48 +17766,49 @@ class LiquidCommerceRmnClient {
17692
17766
  * @param {IInjectSpotElement} injectItem - The inject item data.
17693
17767
  * @param {HTMLElement} placement - The placement element.
17694
17768
  * @param {ISpot} spot - The spot data.
17695
- * @param {IInjectSpotsConfig} config - The configuration object.
17769
+ * @param {IInjectSpotElementConfig} config - The configuration object.
17696
17770
  *
17697
17771
  * @return {void}
17698
17772
  */
17699
17773
  injectOneSpotElement(injectItem, placement, spot, config) {
17774
+ var _a;
17700
17775
  const spotData = this.elementService.overrideSpotColors(spot, config === null || config === void 0 ? void 0 : config.colors);
17701
- const content = GET_SPOT_TEMPLATE_HTML_STRING(spotData, { overlay: config === null || config === void 0 ? void 0 : config.overlay });
17702
- const spotElement = this.elementService.createFinalElement({
17776
+ const content = SPOT_TEMPLATE_HTML_ELEMENT(spotData, { overlay: config === null || config === void 0 ? void 0 : config.overlay });
17777
+ if (!content) {
17778
+ console.warn(`RmnSdk: Failed to inject spot element. Could not create element for type "${injectItem.spotType}".`);
17779
+ return;
17780
+ }
17781
+ const spotElement = this.elementService.createSpotElement({
17703
17782
  content,
17704
17783
  config: {
17705
- fluid: true,
17706
17784
  width: spot.width,
17707
17785
  height: spot.height,
17708
- minScale: config === null || config === void 0 ? void 0 : config.minScale,
17786
+ minScale: (_a = config === null || config === void 0 ? void 0 : config.minScale) !== null && _a !== void 0 ? _a : 0.25, // Scale down to 25% of the original size
17709
17787
  },
17710
17788
  });
17711
17789
  if (!spotElement) {
17712
17790
  console.warn(`RmnSdk: Failed to inject spot element. Could not create element for type "${injectItem.spotType}".`);
17713
17791
  return;
17714
17792
  }
17715
- placement.appendChild(spotElement);
17793
+ placement.replaceChildren(spotElement);
17716
17794
  }
17717
17795
  /**
17718
- * Normalizes the spot type data by adding a number suffix to the spot type.
17796
+ * Prevents duplicate placement ids in the inject data.
17797
+ *
17798
+ * @param {IInjectSpotElement[]} inject - The inject data.
17719
17799
  *
17720
- * @param {IInjectSpotElement[]} spots - The spot type data.
17800
+ * @throws {Error} - If a duplicate placement id is found.
17721
17801
  *
17722
- * @return {IInjectSpotElement[]} - The normalized spot type data.
17802
+ * @return {void}
17723
17803
  */
17724
- normalizeDataSpotType(spots) {
17725
- const spotTypeCounts = {};
17726
- return spots.map((spot) => {
17727
- const { spotType } = spot;
17728
- spotTypeCounts[spotType] = (spotTypeCounts[spotType] || 0) + 1;
17729
- if (spotTypeCounts[spotType] === 1) {
17730
- return spot;
17804
+ preventDuplicateSpotPlacementIds(inject) {
17805
+ const placementIds = new Set();
17806
+ for (const item of inject) {
17807
+ if (placementIds.has(item.placementId)) {
17808
+ throw new Error(`RmnSdk: Duplicate placement id (${item.placementId}) found. Please provide a unique placement id for each spot element.`);
17731
17809
  }
17732
- return {
17733
- ...spot,
17734
- spotType: `${spotType}${spotTypeCounts[spotType]}`,
17735
- };
17736
- });
17810
+ placementIds.add(item.placementId);
17811
+ }
17737
17812
  }
17738
17813
  }
17739
17814
  /**
@@ -17749,5 +17824,36 @@ async function RmnClient(apiKey, config) {
17749
17824
  const credentials = await authService.initialize();
17750
17825
  return new LiquidCommerceRmnClient(credentials);
17751
17826
  }
17827
+ /**
17828
+ * Creates the spot html element based on the provided data using shadow dom.
17829
+ *
17830
+ * This method is useful when you are initializing the client in a non-browser environment.
17831
+ * When you request a spot selection, you will receive the spot data in server-side and return them to the client.
17832
+ * Then you can use this function to create the spot html element based on the provided data without the need of the RmnClient instance.
17833
+ *
17834
+ * @param {ISpot} spot - The spot data.
17835
+ * @param {IRmnCreateSpotElementConfig} config - The configuration object.
17836
+ *
17837
+ * @return {HTMLElement | null} - The spot html element or null if the browser environment is not available.
17838
+ */
17839
+ function RmnCreateSpotElement(spot, config) {
17840
+ var _a;
17841
+ const elementService = ElementService.getInstance();
17842
+ const spotData = elementService.overrideSpotColors(spot, config === null || config === void 0 ? void 0 : config.colors);
17843
+ const content = SPOT_TEMPLATE_HTML_ELEMENT(spotData, { overlay: config === null || config === void 0 ? void 0 : config.overlay });
17844
+ if (!content) {
17845
+ console.warn(`RmnSdk: Failed to create spot element for type "${spotData.spot}".`);
17846
+ return null;
17847
+ }
17848
+ return elementService.createSpotElement({
17849
+ content,
17850
+ config: {
17851
+ fluid: true,
17852
+ width: spot.width,
17853
+ height: spot.height,
17854
+ minScale: (_a = config === null || config === void 0 ? void 0 : config.minScale) !== null && _a !== void 0 ? _a : 0.25, // Scale down to 25% of the original size
17855
+ },
17856
+ });
17857
+ }
17752
17858
 
17753
- export { LiquidCommerceRmnClient, RMN_ENV, RMN_FILTER_PROPERTIES, RMN_SPOT_EVENT, RMN_SPOT_TYPE, RmnClient };
17859
+ export { LiquidCommerceRmnClient, RMN_ENV, RMN_FILTER_PROPERTIES, RMN_SPOT_EVENT, RMN_SPOT_TYPE, RmnClient, RmnCreateSpotElement };