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

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