@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.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;