@liquidcommercedev/rmn-sdk 1.4.6-beta.1 → 1.4.6-beta.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. package/dist/index.cjs +1360 -645
  2. package/dist/index.esm.js +1360 -645
  3. package/dist/types/enums.d.ts +57 -1
  4. package/dist/types/modules/element/component/carousel/carousel.component.d.ts +3 -0
  5. package/dist/types/modules/element/component/carousel/carousel.interface.d.ts +31 -0
  6. package/dist/types/modules/element/component/carousel/carousel.style.d.ts +2 -0
  7. package/dist/types/modules/element/component/carousel/index.d.ts +3 -0
  8. package/dist/types/modules/element/component/spot/index.d.ts +2 -0
  9. package/dist/types/modules/element/component/spot/spot.component.d.ts +3 -0
  10. package/dist/types/modules/element/component/spot/spot.interface.d.ts +10 -0
  11. package/dist/types/modules/{spot/html/constants/html.constant.d.ts → element/element.constant.d.ts} +2 -5
  12. package/dist/types/modules/element/element.interface.d.ts +41 -0
  13. package/dist/types/modules/element/element.service.d.ts +40 -0
  14. package/dist/types/modules/element/index.d.ts +3 -0
  15. package/dist/types/modules/element/template/helper.d.ts +3 -0
  16. package/dist/types/modules/element/template/index.d.ts +1 -0
  17. package/dist/types/modules/element/template/reservebar/collection-banner-without-text-block.template.d.ts +3 -0
  18. package/dist/types/modules/element/template/reservebar/homepage-hero-full-image.template.d.ts +3 -0
  19. package/dist/types/modules/element/template/reservebar/homepage-hero-three-tile.template.d.ts +3 -0
  20. package/dist/types/modules/element/template/reservebar/homepage-hero-two-tile.template.d.ts +3 -0
  21. package/dist/types/modules/element/template/reservebar/large-category-image-tout.template.d.ts +3 -0
  22. package/dist/types/modules/element/template/reservebar/navigation-banner.template.d.ts +3 -0
  23. package/dist/types/modules/element/template/reservebar/small-category-image-tout.template.d.ts +3 -0
  24. package/dist/types/modules/element/template/reservebar/small-discover-tout.template.d.ts +3 -0
  25. package/dist/types/modules/element/template/template.service.d.ts +10 -0
  26. package/dist/types/modules/element/template/template.type.d.ts +11 -0
  27. package/dist/types/modules/event/event.constant.d.ts +1 -0
  28. package/dist/types/modules/event/event.interface.d.ts +5 -0
  29. package/dist/types/modules/event/event.service.d.ts +5 -0
  30. package/dist/types/modules/event/helpers/index.d.ts +2 -0
  31. package/dist/types/modules/event/helpers/intersection.service.d.ts +8 -0
  32. package/dist/types/modules/event/helpers/resize.service.d.ts +30 -0
  33. package/dist/types/modules/event/index.d.ts +3 -0
  34. package/dist/types/modules/selection/index.d.ts +4 -0
  35. package/dist/types/modules/selection/selection.constant.d.ts +1 -0
  36. package/dist/types/modules/{spot/spot.interface.d.ts → selection/selection.interface.d.ts} +4 -11
  37. package/dist/types/modules/selection/selection.service.d.ts +16 -0
  38. package/dist/types/modules/{spot/spot.type.d.ts → selection/selection.type.d.ts} +1 -1
  39. package/dist/types/rmn-client.d.ts +41 -19
  40. package/dist/types/static.constant.d.ts +3 -0
  41. package/dist/types/types.d.ts +7 -5
  42. package/package.json +2 -2
  43. package/umd/liquidcommerce-rmn-sdk.min.js +1 -1
  44. package/dist/types/modules/spot/html/constants/index.d.ts +0 -1
  45. package/dist/types/modules/spot/html/index.d.ts +0 -1
  46. package/dist/types/modules/spot/html/spot.element.service.d.ts +0 -7
  47. package/dist/types/modules/spot/html/templates/index.d.ts +0 -1
  48. package/dist/types/modules/spot/html/templates/reservebar/collection-banner-without-text-block.template.d.ts +0 -2
  49. package/dist/types/modules/spot/html/templates/reservebar/homepage-hero-full-image.template.d.ts +0 -2
  50. package/dist/types/modules/spot/html/templates/reservebar/homepage-hero-three-tile.template.d.ts +0 -2
  51. package/dist/types/modules/spot/html/templates/reservebar/homepage-hero-two-tile.template.d.ts +0 -2
  52. package/dist/types/modules/spot/html/templates/reservebar/large-category-image-tout.template.d.ts +0 -2
  53. package/dist/types/modules/spot/html/templates/reservebar/navigation-banner.template.d.ts +0 -2
  54. package/dist/types/modules/spot/html/templates/reservebar/small-category-image-tout.template.d.ts +0 -2
  55. package/dist/types/modules/spot/html/templates/reservebar/small-discover-tout.template.d.ts +0 -2
  56. package/dist/types/modules/spot/html/templates/spot.template.d.ts +0 -21
  57. package/dist/types/modules/spot/index.d.ts +0 -6
  58. package/dist/types/modules/spot/spot.constant.d.ts +0 -4
  59. package/dist/types/modules/spot/spot.enum.d.ts +0 -57
  60. package/dist/types/modules/spot/spot.html.service.d.ts +0 -22
  61. package/dist/types/modules/spot/spot.selection.service.d.ts +0 -15
  62. /package/dist/types/modules/{spot/html/templates → element/template}/iab/billboard/billboard-v1.template.d.ts +0 -0
  63. /package/dist/types/modules/{spot/html/templates → element/template}/iab/billboard/billboard-v2.template.d.ts +0 -0
  64. /package/dist/types/modules/{spot/html/templates → element/template}/iab/billboard/billboard-v3.template.d.ts +0 -0
  65. /package/dist/types/modules/{spot/html/templates → element/template}/iab/billboard/index.d.ts +0 -0
  66. /package/dist/types/modules/{spot/html/templates → element/template}/iab/in-text/in-text-v1.template.d.ts +0 -0
  67. /package/dist/types/modules/{spot/html/templates → element/template}/iab/in-text/index.d.ts +0 -0
  68. /package/dist/types/modules/{spot/html/templates → element/template}/iab/index.d.ts +0 -0
  69. /package/dist/types/modules/{spot/html/templates → element/template}/iab/large-leaderboard/index.d.ts +0 -0
  70. /package/dist/types/modules/{spot/html/templates → element/template}/iab/large-leaderboard/large-leaderboard-v1.template.d.ts +0 -0
  71. /package/dist/types/modules/{spot/html/templates → element/template}/iab/large-leaderboard/large-leaderboard-v2.template.d.ts +0 -0
  72. /package/dist/types/modules/{spot/html/templates → element/template}/iab/large-rectangle/index.d.ts +0 -0
  73. /package/dist/types/modules/{spot/html/templates → element/template}/iab/large-rectangle/large-rectangle-v1.template.d.ts +0 -0
  74. /package/dist/types/modules/{spot/html/templates → element/template}/iab/square/index.d.ts +0 -0
  75. /package/dist/types/modules/{spot/html/templates → element/template}/iab/square/square-v1.template.d.ts +0 -0
  76. /package/dist/types/modules/{spot/html/templates → element/template}/iab/square/square-v2.template.d.ts +0 -0
  77. /package/dist/types/modules/{spot/html/templates → element/template}/iab/vertical-rectangle/index.d.ts +0 -0
  78. /package/dist/types/modules/{spot/html/templates → element/template}/iab/vertical-rectangle/vertical-rectangle-v1.template.d.ts +0 -0
  79. /package/dist/types/modules/{spot/html/templates → element/template}/iab/wide-skyscraper/index.d.ts +0 -0
  80. /package/dist/types/modules/{spot/html/templates → element/template}/iab/wide-skyscraper/wide-skyscraper-v1.template.d.ts +0 -0
  81. /package/dist/types/modules/{spot/html/templates → element/template}/reservebar/index.d.ts +0 -0
package/dist/index.esm.js CHANGED
@@ -60,7 +60,6 @@ var RMN_SPOT_EVENT;
60
60
  RMN_SPOT_EVENT["ADD_TO_WISHLIST"] = "ADD_TO_WISHLIST";
61
61
  RMN_SPOT_EVENT["BUY_NOW"] = "BUY_NOW";
62
62
  })(RMN_SPOT_EVENT || (RMN_SPOT_EVENT = {}));
63
-
64
63
  var RMN_ENV;
65
64
  (function (RMN_ENV) {
66
65
  RMN_ENV["LOCAL"] = "local";
@@ -14997,7 +14996,7 @@ class BaseApi extends BaseApiAbstract {
14997
14996
  */
14998
14997
  async post(path, data, configOverrides) {
14999
14998
  let requestData = data;
15000
- if (this.authInfo.env !== RMN_ENV.DEVELOPMENT) {
14999
+ if (this.authInfo.env !== RMN_ENV.LOCAL) {
15001
15000
  const timestamp = new Date().getTime();
15002
15001
  configOverrides = {
15003
15002
  ...configOverrides,
@@ -15150,9 +15149,7 @@ class AuthService extends BaseApi {
15150
15149
  }
15151
15150
 
15152
15151
  const SPOT_ELEMENT_TAG = 'spot-element';
15153
- const SPOT_ELEMENT_SLOT_NAME = `${SPOT_ELEMENT_TAG}-custom-content`;
15154
- const SPOTS_SELECTION_API_PATH = '/spots/selection';
15155
-
15152
+ const CAROUSEL_ELEMENT_TAG = 'spot-carousel-element';
15156
15153
  const GFONT_PRECONNECT = `
15157
15154
  <link rel="preconnect" href="https://fonts.googleapis.com">
15158
15155
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
@@ -15163,42 +15160,724 @@ const GFONT_SOURCE_SANS_3 = `
15163
15160
  const GFONT_CORMORANT = `
15164
15161
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Cormorant:ital,wght@0,300..700;1,300..700&family=Source+Sans+3:ital,wght@0,200..900;1,200..900&display=swap">
15165
15162
  `;
15166
- const SPOT_ELEMENT_TEMPLATE = (width, height, hasCustomContent) => {
15167
- const style = document.createElement('style');
15168
- style.textContent = `
15169
- :host {
15170
- display: block;
15171
- position: relative;
15172
- container-type: inline-size;
15173
- overflow: hidden;
15163
+
15164
+ class ResizeObserverService {
15165
+ constructor({ element, maxSize, minScale }) {
15166
+ this.element = element;
15167
+ if (!element.parentElement) {
15168
+ throw new Error('RmnSdk: Spot element must have a parent container.');
15169
+ }
15170
+ this.container = element.parentElement;
15171
+ this.setDimensions(maxSize, minScale);
15172
+ this.resizeObserver = new ResizeObserver(() => this.updateElementSize());
15173
+ this.resizeObserver.observe(this.container);
15174
+ // Initial size update
15175
+ this.updateElementSize();
15176
+ }
15177
+ setDimensions(maxSize, minScale) {
15178
+ if (minScale <= 0 || minScale > 1) {
15179
+ throw new Error('RmnSdk: Invalid minScale value');
15180
+ }
15181
+ const minSize = {
15182
+ width: maxSize.width * minScale,
15183
+ height: maxSize.height * minScale,
15184
+ };
15185
+ if (maxSize.width <= 0 || maxSize.height <= 0 || minSize.width <= 0 || minSize.height <= 0) {
15186
+ throw new Error('RmnSdk: Invalid dimensions');
15187
+ }
15188
+ if (minSize.width > maxSize.width || minSize.height > maxSize.height) {
15189
+ throw new Error('RmnSdk: Minimum size cannot be greater than maximum size');
15190
+ }
15191
+ this.maxSize = maxSize;
15192
+ this.minSize = minSize;
15193
+ this.aspectRatio = this.maxSize.width / this.maxSize.height;
15194
+ }
15195
+ updateElementSize() {
15196
+ const { clientWidth: containerWidth, clientHeight: containerHeight } = this.container;
15197
+ let newWidth;
15198
+ let newHeight;
15199
+ // First, try to fit the maximum width
15200
+ newWidth = Math.min(containerWidth, this.maxSize.width);
15201
+ newHeight = newWidth / this.aspectRatio;
15202
+ // If the height exceeds the container, adjust based on height
15203
+ if (newHeight > containerHeight) {
15204
+ newHeight = containerHeight;
15205
+ newWidth = newHeight * this.aspectRatio;
15206
+ }
15207
+ // Ensure we're not going below minimum dimensions
15208
+ newWidth = Math.max(newWidth, this.minSize.width);
15209
+ newHeight = Math.max(newHeight, this.minSize.height);
15210
+ this.element.style.width = `${newWidth}px`;
15211
+ this.element.style.height = `${newHeight}px`;
15212
+ // Calculate the scale percentage
15213
+ const scaleWidth = newWidth / this.maxSize.width;
15214
+ const scaleHeight = newHeight / this.maxSize.height;
15215
+ const scale = Math.min(scaleWidth, scaleHeight);
15216
+ // Dispatch a custom event
15217
+ this.element.dispatchEvent(new CustomEvent('spotSizeChanged', {
15218
+ detail: {
15219
+ width: this.maxSize.width,
15220
+ height: this.maxSize.height,
15221
+ newWidth,
15222
+ newHeight,
15223
+ scale,
15224
+ },
15225
+ }));
15174
15226
  }
15175
- :host([fluid="true"]) {
15176
- width: 100%;
15177
- height: 100%;
15227
+ disconnect() {
15228
+ this.resizeObserver.disconnect();
15178
15229
  }
15179
- :host([fluid="false"]) {
15180
- width: ${width}px;
15181
- height: ${height}px;
15230
+ }
15231
+
15232
+ const CAROUSEL_COMPONENT_STYLE = ({ width, height, fluid }) => `
15233
+ :host {
15234
+ position: relative;
15235
+ display: inline-block;
15236
+ margin: 0;
15237
+ overflow: hidden;
15238
+ width: ${fluid ? '100%' : `${width}px`};
15239
+ height: ${fluid ? '100%' : `${height}px`};
15182
15240
  }
15183
- `;
15184
- const wrapper = document.createElement('div');
15185
- wrapper.className = 'wrapper';
15186
- const slot = document.createElement('slot');
15187
- slot.name = SPOT_ELEMENT_SLOT_NAME;
15188
- if (!hasCustomContent) {
15189
- style.textContent += `
15190
- :host .wrapper {
15191
- position: absolute;
15192
- top: 0;
15193
- left: 0;
15241
+
15242
+ .slides {
15243
+ position: relative;
15244
+ height: 100%;
15194
15245
  width: 100%;
15246
+ }
15247
+
15248
+ .slide {
15249
+ display: none;
15250
+
15251
+ justify-content: center;
15252
+ align-items: center;
15195
15253
  height: 100%;
15196
- overflow: hidden;
15197
- }
15198
- `;
15254
+ width: 100%;
15199
15255
  }
15200
- return { style, wrapper, slot };
15201
- };
15256
+
15257
+ .slide.active {
15258
+ display: flex;
15259
+ }
15260
+
15261
+ .dots {
15262
+ position: absolute;
15263
+ display: flex;
15264
+ align-items: center;
15265
+ gap: 8px;
15266
+ }
15267
+
15268
+ .dots .dot {
15269
+ width: 12px;
15270
+ height: 12px;
15271
+ border-radius: 50%;
15272
+ cursor: pointer;
15273
+ transition: all 0.3s ease;
15274
+ }
15275
+
15276
+ .dots.top-left,
15277
+ .dots.bottom-left {
15278
+ left: 10px;
15279
+ }
15280
+
15281
+ .dots.top-center,
15282
+ .dots.bottom-center {
15283
+ left: 50%;
15284
+ transform: translateX(-50%);
15285
+ }
15286
+
15287
+ .dots.top-right,
15288
+ .dots.bottom-right {
15289
+ right: 10px;
15290
+ }
15291
+
15292
+ .dots.top-left,
15293
+ .dots.top-center,
15294
+ .dots.top-right {
15295
+ top: 10px;
15296
+ }
15297
+
15298
+ .dots.bottom-left,
15299
+ .dots.bottom-center,
15300
+ .dots.bottom-right {
15301
+ bottom: 10px;
15302
+ }
15303
+
15304
+ .dots.middle-left {
15305
+ left: 10px;
15306
+ top: 50%;
15307
+ transform: translateY(-50%);
15308
+ flex-direction: column;
15309
+ }
15310
+
15311
+ .dots.middle-right {
15312
+ right: 10px;
15313
+ top: 50%;
15314
+ transform: translateY(-50%);
15315
+ flex-direction: column;
15316
+ }
15317
+
15318
+ .buttons button {
15319
+ background-color: #00000080;
15320
+ color: #fff;
15321
+ border: none;
15322
+ padding: 10px;
15323
+ cursor: pointer;
15324
+ transition: background-color 0.3s ease;
15325
+ }
15326
+
15327
+ .buttons button:hover {
15328
+ background-color: #000000b3;
15329
+ }
15330
+
15331
+ .buttons.buttons-separate button {
15332
+ position: absolute;
15333
+ top: 50%;
15334
+ transform: translateY(-50%);
15335
+ }
15336
+
15337
+ .buttons.buttons-separate .prev-button {
15338
+ left: 10px;
15339
+ }
15340
+
15341
+ .buttons.buttons-separate .next-button {
15342
+ right: 10px;
15343
+ }
15344
+
15345
+ .buttons.buttons-together {
15346
+ position: absolute;
15347
+ display: flex;
15348
+ gap: 10px;
15349
+ }
15350
+
15351
+ .buttons.buttons-together.top-left,
15352
+ .buttons.buttons-together.bottom-left {
15353
+ left: 10px;
15354
+ }
15355
+
15356
+ .buttons.buttons-together.top-center,
15357
+ .buttons.buttons-together.bottom-center {
15358
+ left: 50%;
15359
+ transform: translateX(-50%);
15360
+ }
15361
+
15362
+ .buttons.buttons-together.top-right,
15363
+ .buttons.buttons-together.bottom-right {
15364
+ right: 10px;
15365
+ }
15366
+
15367
+ .buttons.buttons-together.top-left,
15368
+ .buttons.buttons-together.top-center,
15369
+ .buttons.buttons-together.top-right {
15370
+ top: 10px;
15371
+ }
15372
+
15373
+ .buttons.buttons-together.bottom-left,
15374
+ .buttons.buttons-together.bottom-center,
15375
+ .buttons.buttons-together.bottom-right {
15376
+ bottom: 10px;
15377
+ }
15378
+
15379
+ .buttons.buttons-together.middle-left,
15380
+ .buttons.buttons-together.middle-right {
15381
+ top: 50%;
15382
+ transform: translateY(-50%);
15383
+ flex-direction: column;
15384
+ }
15385
+
15386
+ .buttons.buttons-together.middle-left {
15387
+ left: 10px;
15388
+ }
15389
+
15390
+ .buttons.buttons-together.middle-right {
15391
+ right: 10px;
15392
+ }
15393
+
15394
+ @media (max-width: 768px) {
15395
+ .buttons button {
15396
+ padding: 8px 12px;
15397
+ font-size: 14px;
15398
+ }
15399
+
15400
+ .dots .dot {
15401
+ width: 8px;
15402
+ height: 8px;
15403
+ }
15404
+ }
15405
+ `;
15406
+
15407
+ let CarouselElement;
15408
+ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined') {
15409
+ class CustomCarouselElement extends HTMLElement {
15410
+ constructor() {
15411
+ super();
15412
+ this.currentSlide = 0;
15413
+ this.dotElements = [];
15414
+ this.prevButton = null;
15415
+ this.nextButton = null;
15416
+ this.autoplayInterval = null;
15417
+ this.useDots = false;
15418
+ this.useButtons = false;
15419
+ this.attachShadow({ mode: 'open' });
15420
+ }
15421
+ connectedCallback() {
15422
+ this.initializeOptions();
15423
+ this.setupResizeObserver();
15424
+ this.render();
15425
+ this.setupCarousel();
15426
+ }
15427
+ disconnectedCallback() {
15428
+ var _a;
15429
+ this.stopAutoplay();
15430
+ (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
15431
+ }
15432
+ initializeOptions() {
15433
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
15434
+ 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';
15435
+ 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';
15436
+ this.autoplay = (_f = (_e = this.data) === null || _e === void 0 ? void 0 : _e.autoplay) !== null && _f !== void 0 ? _f : true;
15437
+ this.interval = (_h = (_g = this.data) === null || _g === void 0 ? void 0 : _g.interval) !== null && _h !== void 0 ? _h : CustomCarouselElement.defaultInterval;
15438
+ this.dotsOptions = {
15439
+ position: 'bottom-center',
15440
+ color: '#d9d9d9',
15441
+ activeColor: '#b5914a',
15442
+ ...(typeof ((_j = this.data) === null || _j === void 0 ? void 0 : _j.useDots) === 'object' ? this.data.useDots : {}),
15443
+ };
15444
+ this.buttonsOptions = {
15445
+ together: false,
15446
+ position: 'middle-sides',
15447
+ textColor: '#000000',
15448
+ backgroundColor: '#ffffff',
15449
+ borderRadius: '50%',
15450
+ prev: 'Prev',
15451
+ next: 'Next',
15452
+ ...(typeof ((_k = this.data) === null || _k === void 0 ? void 0 : _k.useButtons) === 'object' ? this.data.useButtons : {}),
15453
+ };
15454
+ this.validateOptions();
15455
+ }
15456
+ setupResizeObserver() {
15457
+ if (this.data) {
15458
+ this.resizeObserver = new ResizeObserverService({
15459
+ element: this,
15460
+ maxSize: {
15461
+ width: this.data.width,
15462
+ height: this.data.height,
15463
+ },
15464
+ minScale: this.data.minScale,
15465
+ });
15466
+ this.addEventListener('spotSizeChanged', this.handleCarouselSizeChanged.bind(this));
15467
+ }
15468
+ }
15469
+ handleCarouselSizeChanged(event) {
15470
+ console.info('Carousel Size Changed', event);
15471
+ }
15472
+ render() {
15473
+ var _a;
15474
+ if (!this.shadowRoot)
15475
+ return;
15476
+ const style = document.createElement('style');
15477
+ style.textContent = CAROUSEL_COMPONENT_STYLE(this.data);
15478
+ this.shadowRoot.appendChild(style);
15479
+ const slides = this.renderSlides();
15480
+ this.shadowRoot.appendChild(slides);
15481
+ this.slidesContainer = (_a = this.shadowRoot.querySelector('.slides')) !== null && _a !== void 0 ? _a : undefined;
15482
+ if (this.useDots) {
15483
+ const dots = this.renderDots();
15484
+ if (dots)
15485
+ this.shadowRoot.appendChild(dots);
15486
+ }
15487
+ if (this.useButtons) {
15488
+ const buttons = this.renderButtons();
15489
+ if (buttons)
15490
+ this.shadowRoot.appendChild(buttons);
15491
+ }
15492
+ }
15493
+ setupCarousel() {
15494
+ this.setupDots();
15495
+ this.setupButtons();
15496
+ if (this.autoplay) {
15497
+ this.startAutoplay();
15498
+ }
15499
+ this.updateCarousel();
15500
+ }
15501
+ renderSlides() {
15502
+ const slidesContainer = document.createElement('div');
15503
+ slidesContainer.className = 'slides';
15504
+ this.slides.forEach((slide, index) => {
15505
+ const slideElement = document.createElement('div');
15506
+ slideElement.className = `slide ${index === this.currentSlide ? 'active' : ''}`;
15507
+ if (slide instanceof HTMLElement) {
15508
+ slideElement.appendChild(slide);
15509
+ }
15510
+ slidesContainer.appendChild(slideElement);
15511
+ });
15512
+ return slidesContainer;
15513
+ }
15514
+ renderDots() {
15515
+ const dotsContainer = document.createElement('div');
15516
+ dotsContainer.className = `dots ${this.dotsOptions.position}`;
15517
+ this.slides.forEach((_, index) => {
15518
+ const dot = document.createElement('span');
15519
+ dot.className = `dot ${index === this.currentSlide ? 'active' : ''}`;
15520
+ dot.style.backgroundColor = this.dotsOptions.color;
15521
+ dotsContainer.appendChild(dot);
15522
+ });
15523
+ return dotsContainer;
15524
+ }
15525
+ renderButtons() {
15526
+ const buttonsContainer = document.createElement('div');
15527
+ const buttonsClass = this.buttonsOptions.together
15528
+ ? `buttons-together ${this.buttonsOptions.position}`
15529
+ : 'buttons-separate';
15530
+ buttonsContainer.className = `buttons ${buttonsClass}`;
15531
+ this.prevButton = this.createButton('prev-button', this.buttonsOptions.prev);
15532
+ this.nextButton = this.createButton('next-button', this.buttonsOptions.next);
15533
+ buttonsContainer.appendChild(this.prevButton);
15534
+ buttonsContainer.appendChild(this.nextButton);
15535
+ return buttonsContainer;
15536
+ }
15537
+ createButton(className, text) {
15538
+ const button = document.createElement('button');
15539
+ button.className = className;
15540
+ button.textContent = text;
15541
+ button.style.color = this.buttonsOptions.textColor;
15542
+ button.style.backgroundColor = this.buttonsOptions.backgroundColor;
15543
+ button.style.borderRadius = this.buttonsOptions.borderRadius;
15544
+ return button;
15545
+ }
15546
+ setupDots() {
15547
+ if (!this.shadowRoot || !this.useDots)
15548
+ return;
15549
+ this.dotElements = Array.from(this.shadowRoot.querySelectorAll('.dot'));
15550
+ this.dotElements.forEach((dot, index) => {
15551
+ dot.addEventListener('click', () => {
15552
+ this.goToSlide(index);
15553
+ this.resetAutoplay();
15554
+ });
15555
+ });
15556
+ }
15557
+ setupButtons() {
15558
+ var _a, _b;
15559
+ if (!this.useButtons)
15560
+ return;
15561
+ (_a = this.prevButton) === null || _a === void 0 ? void 0 : _a.addEventListener('click', () => {
15562
+ this.prevSlide();
15563
+ this.resetAutoplay();
15564
+ });
15565
+ (_b = this.nextButton) === null || _b === void 0 ? void 0 : _b.addEventListener('click', () => {
15566
+ this.nextSlide();
15567
+ this.resetAutoplay();
15568
+ });
15569
+ }
15570
+ nextSlide() {
15571
+ this.goToSlide((this.currentSlide + 1) % this.slides.length);
15572
+ }
15573
+ prevSlide() {
15574
+ this.goToSlide((this.currentSlide - 1 + this.slides.length) % this.slides.length);
15575
+ }
15576
+ goToSlide(index) {
15577
+ this.currentSlide = index;
15578
+ this.updateCarousel();
15579
+ }
15580
+ updateCarousel() {
15581
+ if (!this.slidesContainer)
15582
+ return;
15583
+ const slides = Array.from(this.slidesContainer.children);
15584
+ slides.forEach((slide, index) => {
15585
+ slide.classList.toggle('active', index === this.currentSlide);
15586
+ });
15587
+ this.updateDots();
15588
+ }
15589
+ updateDots() {
15590
+ if (!this.useDots)
15591
+ return;
15592
+ this.dotElements.forEach((dot, index) => {
15593
+ const isActive = index === this.currentSlide;
15594
+ dot.classList.toggle('active', isActive);
15595
+ dot.style.backgroundColor = isActive
15596
+ ? this.dotsOptions.activeColor
15597
+ : this.dotsOptions.color;
15598
+ });
15599
+ }
15600
+ startAutoplay() {
15601
+ this.autoplayInterval = window.setInterval(() => this.nextSlide(), this.interval);
15602
+ }
15603
+ stopAutoplay() {
15604
+ if (this.autoplayInterval !== null) {
15605
+ window.clearInterval(this.autoplayInterval);
15606
+ this.autoplayInterval = null;
15607
+ }
15608
+ }
15609
+ resetAutoplay() {
15610
+ if (this.autoplay) {
15611
+ this.stopAutoplay();
15612
+ this.startAutoplay();
15613
+ }
15614
+ }
15615
+ validateOptions() {
15616
+ this.validatePosition(this.dotsOptions.position, 'dotsPosition', 'bottom-center');
15617
+ this.validateButtonsPosition();
15618
+ }
15619
+ validatePosition(position, optionName, defaultValue) {
15620
+ if (!CustomCarouselElement.validPositions.includes(position)) {
15621
+ console.warn(`Invalid ${optionName}: ${position}. Defaulting to '${defaultValue}'.`);
15622
+ if (optionName === 'dotsPosition') {
15623
+ this.dotsOptions.position = defaultValue;
15624
+ }
15625
+ else if (optionName === 'buttonsPosition') {
15626
+ this.buttonsOptions.position = defaultValue;
15627
+ }
15628
+ }
15629
+ }
15630
+ validateButtonsPosition() {
15631
+ if (this.useButtons) {
15632
+ if (this.buttonsOptions.together) {
15633
+ this.validatePosition(this.buttonsOptions.position, 'buttonsPosition', 'bottom-center');
15634
+ }
15635
+ else if (this.buttonsOptions.position !== 'middle-sides') {
15636
+ console.warn(`Invalid buttonsPosition: ${this.buttonsOptions.position}. When buttons are not together, only 'middle-sides' is allowed. Defaulting to 'middle-sides'.`);
15637
+ this.buttonsOptions.position = 'middle-sides';
15638
+ }
15639
+ }
15640
+ }
15641
+ }
15642
+ CustomCarouselElement.defaultInterval = 5000;
15643
+ CustomCarouselElement.validPositions = [
15644
+ 'top-left',
15645
+ 'top-center',
15646
+ 'top-right',
15647
+ 'bottom-left',
15648
+ 'bottom-center',
15649
+ 'bottom-right',
15650
+ 'middle-left',
15651
+ 'middle-right',
15652
+ 'middle-sides',
15653
+ ];
15654
+ CarouselElement = CustomCarouselElement;
15655
+ }
15656
+
15657
+ let SpotElement;
15658
+ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined') {
15659
+ class CustomSpotElement extends HTMLElement {
15660
+ constructor() {
15661
+ super();
15662
+ this.originalFontSizes = new Map();
15663
+ this.attachShadow({ mode: 'open' });
15664
+ }
15665
+ connectedCallback() {
15666
+ this.setupResizeObserver();
15667
+ this.render();
15668
+ }
15669
+ disconnectedCallback() {
15670
+ var _a;
15671
+ this.removeEventListener('spotSizeChanged', this.handleSpotSizeChanged);
15672
+ (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
15673
+ }
15674
+ /**
15675
+ * Setup observers for the spot element
15676
+ * #########################################################
15677
+ */
15678
+ setupResizeObserver() {
15679
+ if (this.data) {
15680
+ this.resizeObserver = new ResizeObserverService({
15681
+ element: this,
15682
+ maxSize: {
15683
+ width: this.data.width,
15684
+ height: this.data.height,
15685
+ },
15686
+ minScale: this.data.minScale,
15687
+ });
15688
+ this.addEventListener('spotSizeChanged', this.handleSpotSizeChanged.bind(this));
15689
+ }
15690
+ }
15691
+ /**
15692
+ * Observer additional event handlers
15693
+ * #########################################################
15694
+ */
15695
+ handleSpotSizeChanged(event) {
15696
+ console.info('Spot Size Changed', event);
15697
+ // Adjust text elements font size based on the scale factor
15698
+ this.adjustFontSize(event.detail.scale);
15699
+ }
15700
+ adjustFontSize(elementScale) {
15701
+ var _a;
15702
+ const scaleFactor = this.calculateScaleFactor(elementScale);
15703
+ // Find all text elements within the shadow root
15704
+ const elements = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('h1, h2, h3, h4, p, span');
15705
+ elements === null || elements === void 0 ? void 0 : elements.forEach((element) => {
15706
+ if (element instanceof HTMLElement) {
15707
+ if (!this.originalFontSizes.has(element)) {
15708
+ const orignalSize = parseFloat(window.getComputedStyle(element).fontSize);
15709
+ this.originalFontSizes.set(element, orignalSize);
15710
+ }
15711
+ const originalSize = this.originalFontSizes.get(element);
15712
+ const newFontSize = originalSize * scaleFactor;
15713
+ element.style.fontSize = `${newFontSize}px`;
15714
+ }
15715
+ });
15716
+ }
15717
+ calculateScaleFactor(elementScale) {
15718
+ // Step 1: Apply square root for non-linear scaling
15719
+ // This creates a more gradual scaling effect, especially for larger changes
15720
+ // For example:
15721
+ // - elementScale of 0.25 (1/4 size) becomes 0.5
15722
+ // - elementScale of 1 (unchanged) remains 1
15723
+ // - elementScale of 4 (4x size) becomes 2
15724
+ const baseFactor = Math.sqrt(elementScale);
15725
+ // Step 2: Apply additional dampening to further soften the scaling effect
15726
+ // The dampening factor (0.5) can be adjusted:
15727
+ // - Lower values (closer to 0) make scaling more subtle
15728
+ // - Higher values (closer to 1) make scaling more pronounced
15729
+ const dampening = 0.5;
15730
+ // Calculate the scaleFactor:
15731
+ // 1. (baseFactor - 1) represents the change from the original size
15732
+ // 2. Multiply by dampening to reduce the effect
15733
+ // 3. Add 1 to center the scaling around the original size
15734
+ // For example, if baseFactor is 2:
15735
+ // scaleFactor = 1 + (2 - 1) * 0.5 = 1.5
15736
+ const scaleFactor = 1 + (baseFactor - 1) * dampening;
15737
+ // Step 3: Define the allowed range for the scale factor
15738
+ // This ensures that the font size never changes too drastically
15739
+ const minScale = 0.5; // Font will never be smaller than 90% of original
15740
+ const maxScale = 1.5; // Font will never be larger than 110% of original
15741
+ // Step 4: Clamp the scale factor to the defined range
15742
+ // Math.min ensures the value doesn't exceed maxScale
15743
+ // Math.max ensures the value isn't less than minScale
15744
+ return Math.max(minScale, Math.min(maxScale, scaleFactor));
15745
+ }
15746
+ /**
15747
+ * Spot element rendering
15748
+ * #########################################################
15749
+ */
15750
+ render() {
15751
+ if (!this.shadowRoot || !this.data || !this.content)
15752
+ return;
15753
+ const style = this.getTemplateStyle(this.data.width, this.data.height);
15754
+ if (this.content instanceof HTMLElement) {
15755
+ this.shadowRoot.replaceChildren(style, this.content);
15756
+ }
15757
+ }
15758
+ getTemplateStyle(width, height) {
15759
+ const style = document.createElement('style');
15760
+ style.textContent = `
15761
+ :host {
15762
+ display: block;
15763
+ position: relative;
15764
+ box-sizing: border-box;
15765
+ overflow: hidden;
15766
+ width: ${this.data.fluid ? '100%' : `${width}px`};
15767
+ height: ${this.data.fluid ? '100%' : `${height}px`};
15768
+ }
15769
+ `;
15770
+ return style;
15771
+ }
15772
+ }
15773
+ SpotElement = CustomSpotElement;
15774
+ }
15775
+
15776
+ class ElementService {
15777
+ static getInstance() {
15778
+ return SingletonManager.getInstance('ElementService', () => new ElementService());
15779
+ }
15780
+ /**
15781
+ * Creates the html element based on the provided data, content and configs using shadow dom.
15782
+ *
15783
+ * This method is only available in browser environments.
15784
+ *
15785
+ * @param {ICreateSpotElementParams} params - The parameters to create the final element.
15786
+ *
15787
+ * @return {HTMLElement | null} - The html element or null if the browser environment is not available.
15788
+ */
15789
+ createSpotElement({ content, config }) {
15790
+ var _a;
15791
+ if (!this.ensureBrowserEnvironmentAndDefineElement()) {
15792
+ return null;
15793
+ }
15794
+ const spot = document.createElement(SPOT_ELEMENT_TAG);
15795
+ spot.data = {
15796
+ fluid: (_a = config === null || config === void 0 ? void 0 : config.fluid) !== null && _a !== void 0 ? _a : false,
15797
+ ...config,
15798
+ };
15799
+ spot.content = content;
15800
+ return spot;
15801
+ }
15802
+ /**
15803
+ * Creates the carousel html element based on the provided slides and configs using shadow dom.
15804
+ *
15805
+ * This method is only available in browser environments.
15806
+ *
15807
+ * @param {ICreateCarouselElementParams} params - The parameters to create the final element.
15808
+ *
15809
+ * @return {HTMLElement | null} - The html element or null if the browser environment is not available.
15810
+ */
15811
+ createCarouselElement({ slides, config, }) {
15812
+ if (!this.ensureBrowserEnvironmentAndDefineElement()) {
15813
+ return null;
15814
+ }
15815
+ const carousel = document.createElement(CAROUSEL_ELEMENT_TAG);
15816
+ carousel.data = {
15817
+ fluid: false,
15818
+ ...config,
15819
+ };
15820
+ carousel.slides = slides;
15821
+ return carousel;
15822
+ }
15823
+ /**
15824
+ * Overrides the spot colors with the provided colors.
15825
+ *
15826
+ * @param {ISpot} spot - The spot data.
15827
+ * @param {ISpotColors} colors - The colors to override.
15828
+ *
15829
+ * @return {ISpot} - The spot data with the colors overridden.
15830
+ */
15831
+ overrideSpotColors(spot, colors) {
15832
+ if (!colors)
15833
+ return spot;
15834
+ const { textColor, backgroundColor, ctaTextColor, ctaBorderColor } = colors;
15835
+ return {
15836
+ ...spot,
15837
+ textColor: textColor !== null && textColor !== void 0 ? textColor : spot.textColor,
15838
+ backgroundColor: backgroundColor !== null && backgroundColor !== void 0 ? backgroundColor : spot.backgroundColor,
15839
+ ctaTextColor: ctaTextColor !== null && ctaTextColor !== void 0 ? ctaTextColor : spot.ctaTextColor,
15840
+ ctaBorderColor: ctaBorderColor !== null && ctaBorderColor !== void 0 ? ctaBorderColor : spot.ctaBorderColor,
15841
+ };
15842
+ }
15843
+ /**
15844
+ * @returns {boolean} - True if the browser environment is available and the element is defined.
15845
+ */
15846
+ ensureBrowserEnvironmentAndDefineElement() {
15847
+ if (typeof window === 'undefined' || typeof document === 'undefined') {
15848
+ console.warn('LiquidCommerce Rmn Sdk: Methods which create elements are only available in browser environments.');
15849
+ return false;
15850
+ }
15851
+ if (!window.customElements.get(SPOT_ELEMENT_TAG)) {
15852
+ window.customElements.define(SPOT_ELEMENT_TAG, SpotElement);
15853
+ }
15854
+ if (!window.customElements.get(CAROUSEL_ELEMENT_TAG)) {
15855
+ window.customElements.define(CAROUSEL_ELEMENT_TAG, CarouselElement);
15856
+ }
15857
+ return true;
15858
+ }
15859
+ }
15860
+
15861
+ function linearGradientColorStop(overlay, fallback) {
15862
+ if (!overlay || overlay.length === 0) {
15863
+ return fallback;
15864
+ }
15865
+ return overlay.map(({ color, colorStop }) => `${color} ${colorStop}`).join(', ');
15866
+ }
15867
+ function spotHtmlStringToElement(htmlString) {
15868
+ const spot = document.createElement('div');
15869
+ spot.className = 'spot';
15870
+ spot.innerHTML = htmlString;
15871
+ Object.assign(spot.style, {
15872
+ position: 'relative',
15873
+ display: 'block',
15874
+ width: '100%',
15875
+ height: '100%',
15876
+ margin: '0',
15877
+ padding: '0',
15878
+ });
15879
+ return spot;
15880
+ }
15202
15881
 
15203
15882
  const STYLES$i = ({ primaryImage, secondaryImage }) => `
15204
15883
  <style>
@@ -16017,175 +16696,214 @@ function wideSkyscraperV1Template(spot) {
16017
16696
  `;
16018
16697
  }
16019
16698
 
16020
- const STYLES$7 = ({ primaryImage, mobilePrimaryImage = primaryImage }) => `
16021
- <style>
16022
- :host {
16023
- min-width: 320px;
16024
- min-height: 223px;
16025
- }
16026
- .content {
16027
- display: block;
16028
- width: 100%;
16029
- height: 100%;
16030
- background-image: url("${mobilePrimaryImage}");
16031
- background-size: cover;
16032
- background-repeat: no-repeat;
16033
- background-position: center;
16034
- cursor: pointer;
16035
- }
16036
- @media (min-width: 640px) {
16037
- .content {
16038
- background-image: url("${primaryImage}");
16039
- }
16699
+ const STYLES$7 = ({ primaryImage, mobilePrimaryImage = primaryImage }, { prefix }) => `
16700
+ <style>
16701
+ :host {
16702
+ min-width: 320px;
16703
+ min-height: 223px;
16704
+ }
16705
+
16706
+ .${prefix}__content {
16707
+ display: block;
16708
+ width: 100%;
16709
+ height: 100%;
16710
+ background-image: url("${mobilePrimaryImage}");
16711
+ background-size: cover;
16712
+ background-repeat: no-repeat;
16713
+ background-position: center;
16714
+ cursor: pointer;
16715
+ }
16716
+
16717
+ @media (min-width: 640px) {
16718
+ .${prefix}__content {
16719
+ background-image: url("${primaryImage}");
16040
16720
  }
16041
- </style>
16721
+ }
16722
+ </style>
16042
16723
  `;
16043
- function rbCollectionBannerWithoutTextBlockTemplate(spot) {
16724
+ function rbCollectionBannerWithoutTextBlockTemplate(spot, config) {
16725
+ const { prefix = '' } = config;
16044
16726
  return `
16045
- ${STYLES$7(spot)}
16046
- <div class="content"></div>
16727
+ ${STYLES$7(spot, config)}
16728
+ <div class="${prefix}__content"></div>
16047
16729
  `;
16048
16730
  }
16049
16731
 
16050
- const STYLES$6 = ({ textColor = '#ffffff', ctaTextColor = textColor, ctaBorderColor = ctaTextColor, primaryImage, mobilePrimaryImage = primaryImage, }) => `
16051
- <style>
16052
- :host {
16053
- min-width: 320px;
16054
- min-height: 388px;
16055
- }
16056
- .content {
16057
- display: flex;
16058
- flex-direction: column;
16059
- justify-content: flex-end;
16060
- align-items: flex-start;
16061
- width: 100%;
16062
- height: 100%;
16063
- background-image: url("${mobilePrimaryImage}");
16064
- background-size: cover;
16065
- background-repeat: no-repeat;
16066
- background-position: center;
16067
- padding: 3%;
16068
- box-sizing: border-box;
16069
- color: ${textColor};
16070
- cursor: pointer;
16071
- }
16072
- .text {
16073
- display: flex;
16074
- flex-direction: column;
16075
- justify-content: flex-start;
16076
- align-items: flex-start;
16077
- width: 100%;
16078
- height: fit-content;
16079
- gap: 5px;
16080
- }
16081
- .header {
16082
- font-size: 18px;
16083
- margin: 0;
16084
- font-family: "Cormorant";
16085
- font-style: normal;
16086
- font-weight: 300;
16087
- line-height: normal;
16088
- }
16089
- .description {
16090
- font-size: 10px;
16091
- font-family: "Source Sans 3", system-ui;
16092
- font-style: normal;
16093
- font-weight: 400;
16094
- line-height: 20px;
16095
- margin: 0;
16096
- }
16097
- .cta-button {
16098
- font-size: 8px;
16099
- font-family: "Source Sans 3", system-ui;
16100
- font-style: normal;
16101
- font-weight: 400;
16102
- line-height: 18px;
16103
- border-radius: 5px;
16104
- border: 0.5px solid ${ctaBorderColor};
16105
- display: inline-block;
16106
- padding: 7px 20px;
16107
- color: ${ctaTextColor};
16108
- transition: background-color 0.3s ease;
16109
- }
16110
- .content:hover .cta-button {
16111
- background-color: ${ctaBorderColor.length === 7 ? `${ctaBorderColor}15` : `${ctaBorderColor}`};
16112
- }
16113
- @media (min-width: 640px) {
16114
- .content {
16115
- background-image: url("${primaryImage}");
16116
- }
16117
- }
16118
- @media (min-width: 768px) {
16119
- .primary-image {
16120
- width: 66.66666%;
16732
+ const STYLES$6 = ({ textColor = '#ffffff', ctaTextColor = textColor, ctaBorderColor = ctaTextColor, primaryImage, mobilePrimaryImage = primaryImage, }, { prefix, overlay }) => {
16733
+ const linearGradient = linearGradientColorStop(overlay || [], 'rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 40%');
16734
+ return `
16735
+ <style>
16736
+ .${prefix} {
16737
+ min-width: 320px;
16738
+ min-height: 388px;
16739
+ width: 100%;
16121
16740
  height: 100%;
16741
+ display: block;
16742
+ position: relative;
16743
+ container-type: inline-size;
16122
16744
  }
16123
- .main {
16745
+
16746
+ .${prefix}__content {
16747
+ display: flex;
16124
16748
  flex-direction: column;
16749
+ justify-content: flex-end;
16750
+ align-items: flex-start;
16751
+ width: 100%;
16125
16752
  height: 100%;
16126
- width: 33.33333%;
16753
+ background-image: linear-gradient(to top, ${linearGradient}), url("${mobilePrimaryImage}");
16754
+ background-size: cover;
16755
+ background-repeat: no-repeat;
16756
+ background-position: center;
16757
+ padding: 3%;
16758
+ box-sizing: border-box;
16759
+ color: ${textColor};
16760
+ cursor: pointer;
16127
16761
  }
16128
- .secondary-image {
16762
+
16763
+ .${prefix}__text {
16764
+ display: flex;
16765
+ flex-direction: column;
16766
+ justify-content: flex-start;
16767
+ align-items: flex-start;
16129
16768
  width: 100%;
16130
- height: 50%;
16131
- }
16132
- .header {
16133
- font-size: 22px;
16769
+ height: fit-content;
16770
+ gap: 5px;
16134
16771
  }
16135
- .description {
16136
- font-size: 12px;
16772
+
16773
+ .${prefix}__header {
16774
+ font-size: 18px;
16775
+ margin: 0;
16776
+ font-family: "Cormorant";
16777
+ font-style: normal;
16778
+ font-weight: 300;
16779
+ line-height: normal;
16137
16780
  }
16138
- .cta-button {
16139
- font-size: 12px;
16781
+
16782
+ .${prefix}__description {
16783
+ font-size: 10px;
16784
+ font-family: "Source Sans 3", system-ui;
16785
+ font-style: normal;
16786
+ font-weight: 400;
16787
+ line-height: 20px;
16788
+ margin: 0;
16140
16789
  }
16141
- }
16142
- @media (min-width: 1024px) {
16143
- .header {
16144
- font-size: 24px;
16790
+
16791
+ .${prefix}__cta-button {
16792
+ font-size: 8px;
16793
+ font-family: "Source Sans 3", system-ui;
16794
+ font-style: normal;
16795
+ font-weight: 400;
16796
+ line-height: 18px;
16797
+ border-radius: 5px;
16798
+ border: 0.5px solid ${ctaBorderColor};
16799
+ display: inline-block;
16800
+ padding: 7px 20px;
16801
+ color: ${ctaTextColor};
16802
+ transition: background-color 0.3s ease;
16145
16803
  }
16146
- .description {
16147
- font-size: 13px;
16804
+
16805
+ .${prefix}__content:hover .cta-button {
16806
+ background-color: ${ctaBorderColor.length === 7 ? `${ctaBorderColor}15` : `${ctaBorderColor}`};
16148
16807
  }
16149
- .cta-button {
16150
- font-size: 13px;
16808
+
16809
+ @media (min-width: 640px) {
16810
+ .${prefix}__content {
16811
+ background-image: linear-gradient(to top, ${linearGradient}), url("${primaryImage}");
16812
+ }
16151
16813
  }
16152
- }
16153
- @media (min-width: 1280px) {
16154
- .header {
16155
- font-size: 28px;
16814
+
16815
+ @media (min-width: 768px) {
16816
+ .${prefix}__primary-image {
16817
+ width: 66.66666%;
16818
+ height: 100%;
16819
+ }
16820
+
16821
+ .${prefix}__main {
16822
+ flex-direction: column;
16823
+ height: 100%;
16824
+ width: 33.33333%;
16825
+ }
16826
+
16827
+ .${prefix}__secondary-image {
16828
+ width: 100%;
16829
+ height: 50%;
16830
+ }
16831
+
16832
+ .${prefix}__header {
16833
+ font-size: 22px;
16834
+ }
16835
+
16836
+ .${prefix}__description {
16837
+ font-size: 12px;
16838
+ }
16839
+
16840
+ .${prefix}__cta-button {
16841
+ font-size: 12px;
16842
+ }
16156
16843
  }
16157
- .description {
16158
- font-size: 14px;
16844
+
16845
+ @media (min-width: 1024px) {
16846
+ .${prefix}__header {
16847
+ font-size: 24px;
16848
+ }
16849
+
16850
+ .${prefix}__description {
16851
+ font-size: 13px;
16852
+ }
16853
+
16854
+ .${prefix}__cta-button {
16855
+ font-size: 13px;
16856
+ }
16159
16857
  }
16160
- .cta-button {
16161
- font-size: 14px;
16858
+
16859
+ @media (min-width: 1280px) {
16860
+ .${prefix}__header {
16861
+ font-size: 28px;
16862
+ }
16863
+
16864
+ .${prefix}__description {
16865
+ font-size: 14px;
16866
+ }
16867
+
16868
+ .${prefix}__cta-button {
16869
+ font-size: 14px;
16870
+ }
16162
16871
  }
16163
- }
16164
- </style>
16165
- `;
16166
- function rbHomepageHeroFullImageTemplate(spot) {
16872
+ </style>
16873
+ `;
16874
+ };
16875
+ function rbHomepageHeroFullImageTemplate(spot, config) {
16876
+ const { prefix = '' } = config;
16167
16877
  return `
16168
16878
  ${GFONT_PRECONNECT}
16169
16879
  ${GFONT_SOURCE_SANS_3}
16170
16880
  ${GFONT_CORMORANT}
16171
- ${STYLES$6(spot)}
16172
- <div class="content">
16173
- <div class="text">
16174
- ${spot.header ? `<h2 class="header">${spot.header}</h2>` : ''}
16175
- ${spot.description ? `<p class="description">${spot.description}</p>` : ''}
16176
- ${spot.ctaText ? `<span class="cta-button">${spot.ctaText}</span>` : ''}
16881
+ ${STYLES$6(spot, config)}
16882
+ <div class="${prefix}">
16883
+ <div class="${prefix}__content">
16884
+ <div class="${prefix}__text">
16885
+ ${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
16886
+ ${spot.description ? `<p class="${prefix}__description">${spot.description}</p>` : ''}
16887
+ ${spot.ctaText ? `<span class="${prefix}__cta-button">${spot.ctaText}</span>` : ''}
16888
+ </div>
16177
16889
  </div>
16178
16890
  </div>
16179
16891
  `;
16180
16892
  }
16181
16893
 
16182
- const STYLES$5 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextColor = textColor, primaryImage, mobilePrimaryImage = primaryImage, secondaryImage, mobileSecondaryImage = secondaryImage, }) => `
16183
- <style>
16184
- :host {
16894
+ const STYLES$5 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextColor = textColor, primaryImage, mobilePrimaryImage = primaryImage, secondaryImage, mobileSecondaryImage = secondaryImage, }, { prefix }) => `
16895
+ <style>
16896
+ .${prefix} {
16185
16897
  min-width: 320px;
16186
16898
  min-height: 388px;
16899
+ width: 100%;
16900
+ height: 100%;
16901
+ display: block;
16902
+ position: relative;
16903
+ container-type: inline-size;
16187
16904
  }
16188
- .content {
16905
+
16906
+ .${prefix}__content {
16189
16907
  width: 100%;
16190
16908
  height: 100%;
16191
16909
  display: flex;
@@ -16195,7 +16913,8 @@ const STYLES$5 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
16195
16913
  color: inherit;
16196
16914
  cursor: pointer;
16197
16915
  }
16198
- .primary-image {
16916
+
16917
+ .${prefix}__primary-image {
16199
16918
  width: 100%;
16200
16919
  height: 60%;
16201
16920
  background-image: url("${mobilePrimaryImage}");
@@ -16203,14 +16922,16 @@ const STYLES$5 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
16203
16922
  background-repeat: no-repeat;
16204
16923
  background-size: cover;
16205
16924
  }
16206
- .main {
16925
+
16926
+ .${prefix}__main {
16207
16927
  width: 100%;
16208
16928
  height: 40%;
16209
16929
  display: flex;
16210
16930
  flex-direction: row;
16211
16931
  gap: 5px;
16212
16932
  }
16213
- .secondary-image {
16933
+
16934
+ .${prefix}__secondary-image {
16214
16935
  width: 50%;
16215
16936
  height: 100%;
16216
16937
  background-image: url("${mobileSecondaryImage}");
@@ -16218,7 +16939,8 @@ const STYLES$5 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
16218
16939
  background-repeat: no-repeat;
16219
16940
  background-size: cover;
16220
16941
  }
16221
- .text {
16942
+
16943
+ .${prefix}__text {
16222
16944
  color: ${textColor};
16223
16945
  background-color: ${backgroundColor};
16224
16946
  text-align: center;
@@ -16232,7 +16954,8 @@ const STYLES$5 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
16232
16954
  padding: 0 10px;
16233
16955
  box-sizing: border-box;
16234
16956
  }
16235
- .header {
16957
+
16958
+ .${prefix}__header {
16236
16959
  color: inherit;
16237
16960
  margin: 0;
16238
16961
  font-size: 18px;
@@ -16241,7 +16964,8 @@ const STYLES$5 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
16241
16964
  font-weight: 700;
16242
16965
  line-height: normal;
16243
16966
  }
16244
- .description {
16967
+
16968
+ .${prefix}__description {
16245
16969
  color: inherit;
16246
16970
  margin: 0;
16247
16971
  font-size: 10px;
@@ -16249,7 +16973,8 @@ const STYLES$5 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
16249
16973
  font-style: normal;
16250
16974
  font-weight: 400;
16251
16975
  }
16252
- .cta-button {
16976
+
16977
+ .${prefix}__cta-button {
16253
16978
  color: ${ctaTextColor};
16254
16979
  background-color: transparent;
16255
16980
  font-size: 8px;
@@ -16264,99 +16989,85 @@ const STYLES$5 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
16264
16989
  padding: 0;
16265
16990
  transition: opacity 0.3s ease;
16266
16991
  }
16267
- .content:hover .cta-button {
16992
+
16993
+ .${prefix}__content:hover .${prefix}__cta-button {
16268
16994
  opacity: 0.8;
16269
16995
  }
16996
+
16270
16997
  @media (min-width: 640px) {
16271
- .primary-image {
16998
+ .${prefix}__primary-image {
16272
16999
  background-image: url("${primaryImage}");
16273
17000
  }
16274
- .secondary-image {
17001
+
17002
+ .${prefix}__secondary-image {
16275
17003
  background-image: url("${secondaryImage}");
16276
17004
  }
16277
17005
  }
17006
+
16278
17007
  @media (min-width: 768px) {
16279
- .content {
17008
+ .${prefix}__content {
16280
17009
  flex-direction: row;
16281
17010
  }
16282
- .primary-image {
17011
+
17012
+ .${prefix}__primary-image {
16283
17013
  width: 66.66666%;
16284
17014
  height: 100%;
16285
17015
  }
16286
- .main {
17016
+
17017
+ .${prefix}__main {
16287
17018
  flex-direction: column;
16288
17019
  height: 100%;
16289
17020
  width: 33.33333%;
16290
17021
  }
16291
- .secondary-image {
17022
+
17023
+ .${prefix}__secondary-image {
16292
17024
  width: 100%;
16293
17025
  height: 50%;
16294
17026
  }
16295
- .text {
17027
+
17028
+ .${prefix}__text {
16296
17029
  width: 100%;
16297
17030
  height: 50%;
16298
17031
  }
16299
- .header {
16300
- font-size: 22px;
16301
- }
16302
- .description {
16303
- font-size: 12px;
16304
- }
16305
- .cta-button {
16306
- font-size: 12px;
16307
- }
16308
- }
16309
- @media (min-width: 1024px) {
16310
- .header {
16311
- font-size: 24px;
16312
- }
16313
- .description {
16314
- font-size: 13px;
16315
- }
16316
- .cta-button {
16317
- font-size: 13px;
16318
- }
16319
- }
16320
- @media (min-width: 1280px) {
16321
- .header {
16322
- font-size: 28px;
16323
- }
16324
- .description {
16325
- font-size: 14px;
16326
- }
16327
- .cta-button {
16328
- font-size: 14px;
16329
- }
16330
17032
  }
16331
- </style>
17033
+ </style>
16332
17034
  `;
16333
- function rbHomepageHeroThreeTileTemplate(spot) {
17035
+ function rbHomepageHeroThreeTileTemplate(spot, config) {
17036
+ const { prefix = '' } = config;
16334
17037
  return `
16335
17038
  ${GFONT_PRECONNECT}
16336
17039
  ${GFONT_SOURCE_SANS_3}
16337
17040
  ${GFONT_CORMORANT}
16338
- ${STYLES$5(spot)}
16339
- <div class="content">
16340
- <div class="primary-image"></div>
16341
- <div class="main">
16342
- <div class="secondary-image"></div>
16343
- <div class="text">
16344
- ${spot.header ? `<h2 class="header">${spot.header}</h2>` : ''}
16345
- ${spot.description ? `<p class="description">${spot.description}</p>` : ''}
16346
- ${spot.ctaText ? `<span class="cta-button">${spot.ctaText}</span>` : ''}
17041
+ ${STYLES$5(spot, config)}
17042
+ <div class="${prefix}">
17043
+ <div class="${prefix}__content">
17044
+ <div class="${prefix}__primary-image"></div>
17045
+ <div class="${prefix}__main">
17046
+ <div class="${prefix}__secondary-image"></div>
17047
+ <div class="${prefix}__text">
17048
+ ${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
17049
+ ${spot.description ? `<p class="${prefix}__description">${spot.description}</p>` : ''}
17050
+ ${spot.ctaText ? `<span class="${prefix}__cta-button">${spot.ctaText}</span>` : ''}
17051
+ </div>
16347
17052
  </div>
16348
17053
  </div>
16349
17054
  </div>
16350
17055
  `;
16351
17056
  }
16352
17057
 
16353
- const STYLES$4 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextColor = textColor, primaryImage, mobilePrimaryImage = primaryImage, }) => `
17058
+ const STYLES$4 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextColor = textColor, primaryImage, mobilePrimaryImage = primaryImage, }, { prefix }) => `
16354
17059
  <style>
16355
- :host {
17060
+ .${prefix} {
16356
17061
  min-width: 320px;
16357
17062
  min-height: 388px;
17063
+ width: 100%;
17064
+ height: 100%;
17065
+ display: block;
17066
+ position: relative;
17067
+ container-type: inline-size;
16358
17068
  }
16359
- .content {
17069
+
17070
+ .${prefix}__content {
16360
17071
  width: 100%;
16361
17072
  height: 100%;
16362
17073
  display: flex;
@@ -16365,7 +17076,8 @@ const STYLES$4 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
16365
17076
  gap: 5px;
16366
17077
  cursor: pointer;
16367
17078
  }
16368
- .image {
17079
+
17080
+ .${prefix}__image {
16369
17081
  width: 100%;
16370
17082
  height: 100%;
16371
17083
  background-image: url("${mobilePrimaryImage}");
@@ -16373,7 +17085,8 @@ const STYLES$4 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
16373
17085
  background-repeat: no-repeat;
16374
17086
  background-size: cover;
16375
17087
  }
16376
- .text {
17088
+
17089
+ .${prefix}__text {
16377
17090
  color: ${textColor};
16378
17091
  background-color: ${backgroundColor};
16379
17092
  text-align: center;
@@ -16387,7 +17100,8 @@ const STYLES$4 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
16387
17100
  padding: 0 10px;
16388
17101
  box-sizing: border-box;
16389
17102
  }
16390
- .header {
17103
+
17104
+ .${prefix}__header {
16391
17105
  font-size: 18px;
16392
17106
  margin: 0;
16393
17107
  color: inherit;
@@ -16396,7 +17110,8 @@ const STYLES$4 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
16396
17110
  font-weight: 700;
16397
17111
  line-height: normal;
16398
17112
  }
16399
- .description {
17113
+
17114
+ .${prefix}__description {
16400
17115
  color: inherit;
16401
17116
  margin: 0;
16402
17117
  font-size: 10px;
@@ -16404,7 +17119,8 @@ const STYLES$4 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
16404
17119
  font-style: normal;
16405
17120
  font-weight: 400;
16406
17121
  }
16407
- .cta-button {
17122
+
17123
+ .${prefix}__cta-button {
16408
17124
  color: ${ctaTextColor};
16409
17125
  background-color: transparent;
16410
17126
  font-size: 8px;
@@ -16419,205 +17135,204 @@ const STYLES$4 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
16419
17135
  padding: 0;
16420
17136
  transition: opacity 0.3s ease;
16421
17137
  }
16422
- .content:hover .cta-button {
17138
+
17139
+ .${prefix}__content:hover .${prefix}__cta-button {
16423
17140
  opacity: 0.8;
16424
17141
  }
17142
+
16425
17143
  @media (min-width: 640px) {
16426
- .image {
17144
+ .${prefix}__image {
16427
17145
  background-image: url("${primaryImage}");
16428
17146
  }
16429
17147
  }
16430
17148
  @media (min-width: 768px) {
16431
- .content {
17149
+ .${prefix}__content {
16432
17150
  flex-direction: row;
16433
17151
  }
16434
- .image {
17152
+
17153
+ .${prefix}__image {
16435
17154
  width: 66.66666%;
16436
17155
  height: 100%;
16437
17156
  }
16438
- .text {
16439
- width: 33.333%;
17157
+
17158
+ .${prefix}__text {
17159
+ width: 33.33333%;
16440
17160
  height: 100%;
16441
17161
  }
16442
- .header {
16443
- font-size: 22px;
16444
- }
16445
- .description {
16446
- font-size: 12px;
16447
- }
16448
- .cta-button {
16449
- font-size: 12px;
16450
- }
16451
- }
16452
- @media (min-width: 1024px) {
16453
- .header {
16454
- font-size: 24px;
16455
- }
16456
- .description {
16457
- font-size: 13px;
16458
- }
16459
- .cta-button {
16460
- font-size: 13px;
16461
- }
16462
- }
16463
- @media (min-width: 1280px) {
16464
- .header {
16465
- font-size: 28px;
16466
- }
16467
- .description {
16468
- font-size: 14px;
16469
- }
16470
- .cta-button {
16471
- font-size: 14px;
16472
- }
16473
17162
  }
16474
17163
  </style>
16475
17164
  `;
16476
- function rbHomepageHeroTwoTileTemplate(spot) {
17165
+ function rbHomepageHeroTwoTileTemplate(spot, config) {
17166
+ const { prefix = '' } = config;
16477
17167
  return `
16478
17168
  ${GFONT_PRECONNECT}
16479
17169
  ${GFONT_SOURCE_SANS_3}
16480
17170
  ${GFONT_CORMORANT}
16481
- ${STYLES$4(spot)}
16482
- <div class="content">
16483
- <div class="text">
16484
- ${spot.header ? `<h2 class="header">${spot.header}</h2>` : ''}
16485
- ${spot.description ? `<p class="description">${spot.description}</p>` : ''}
16486
- ${spot.ctaText ? `<span class="cta-button">${spot.ctaText}</span>` : ''}
17171
+ ${STYLES$4(spot, config)}
17172
+ <div class="${prefix}">
17173
+ <div class="${prefix}__content">
17174
+ <div class="${prefix}__text">
17175
+ ${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
17176
+ ${spot.description ? `<p class="${prefix}__description">${spot.description}</p>` : ''}
17177
+ ${spot.ctaText ? `<span class="${prefix}__cta-button">${spot.ctaText}</span>` : ''}
17178
+ </div>
17179
+ <div class="${prefix}__image"></div>
16487
17180
  </div>
16488
- <div class="image"></div>
16489
17181
  </div>
16490
17182
  `;
16491
17183
  }
16492
17184
 
16493
- const STYLES$3 = ({ textColor = '#ffffff', ctaTextColor = textColor, ctaBorderColor = ctaTextColor, primaryImage, mobilePrimaryImage = primaryImage, }) => `
16494
- <style>
16495
- :host {
16496
- min-width: 320px;
16497
- min-height: 334px;
16498
- }
16499
- .content {
16500
- width: 100%;
16501
- height: 100%;
16502
- display: flex;
16503
- flex-direction: column;
16504
- justify-content: flex-end;
16505
- background-image: url("${mobilePrimaryImage}");
16506
- background-size: cover;
16507
- background-repeat: no-repeat;
16508
- background-position: center;
16509
- border-radius: 5px;
16510
- overflow: hidden;
16511
- cursor: pointer;
16512
- color: ${textColor};
16513
- }
16514
- .text {
16515
- padding: 20px;
16516
- width: 70%;
16517
- display: flex;
16518
- flex-direction: column;
16519
- justify-content: center;
16520
- align-items: flex-start;
16521
- gap: 10px;
16522
- }
16523
- .header {
16524
- color: inherit;
16525
- margin: 0;
16526
- font-size: 20px;
16527
- font-family: "Cormorant";
16528
- font-style: normal;
16529
- font-weight: 300;
16530
- line-height: normal;
16531
- }
16532
- .description {
16533
- color: inherit;
16534
- font-size: 12px;
16535
- line-height: 16px;
16536
- font-family: "Source Sans 3", system-ui;
16537
- font-style: normal;
16538
- font-weight: 400;
16539
- margin: 0;
16540
- }
16541
- .cta-button {
16542
- width: fit-content;
16543
- display: inline-block;
16544
- padding: 7px 20px;
16545
- border: 0.5px solid ${ctaBorderColor};
16546
- border-radius: 5px;
16547
- color: ${ctaTextColor};
16548
- font-size: 8px;
16549
- transition: background-color 0.3s ease;
16550
- font-family: "Source Sans 3", system-ui;
16551
- font-style: normal;
16552
- font-weight: 400;
16553
- }
16554
- .content:hover .cta-button {
16555
- background-color: ${ctaBorderColor.length === 7 ? `${ctaBorderColor}15` : `${ctaBorderColor}`};
16556
- }
16557
- @media (min-width: 640px) {
16558
- .content {
16559
- background-image: url("${primaryImage}");
17185
+ const STYLES$3 = ({ textColor = '#ffffff', ctaTextColor = textColor, ctaBorderColor = ctaTextColor, primaryImage, mobilePrimaryImage = primaryImage, }, { prefix, overlay }) => {
17186
+ const linearGradient = linearGradientColorStop(overlay || [], 'rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 30%');
17187
+ return `
17188
+ <style>
17189
+ :host {
17190
+ min-width: 320px;
17191
+ min-height: 334px;
16560
17192
  }
16561
- }
16562
- @media (min-width: 768px) {
16563
- .text {
16564
- padding: 25px;
17193
+
17194
+ .${prefix}__content {
17195
+ width: 100%;
17196
+ height: 100%;
17197
+ display: flex;
17198
+ flex-direction: column;
17199
+ justify-content: flex-end;
17200
+ background-image: linear-gradient(to top, ${linearGradient}), url("${mobilePrimaryImage}");
17201
+ background-size: cover;
17202
+ background-repeat: no-repeat;
17203
+ background-position: center;
17204
+ border-radius: 5px;
17205
+ overflow: hidden;
17206
+ cursor: pointer;
17207
+ color: ${textColor};
16565
17208
  }
16566
- .header {
16567
- font-size: 24px;
17209
+
17210
+ .${prefix}__text {
17211
+ padding: 20px;
17212
+ width: 70%;
17213
+ display: flex;
17214
+ flex-direction: column;
17215
+ justify-content: center;
17216
+ align-items: flex-start;
17217
+ gap: 10px;
16568
17218
  }
16569
- .description {
16570
- font-size: 13px;
16571
- line-height: 18px;
17219
+
17220
+ .${prefix}__header {
17221
+ color: inherit;
17222
+ margin: 0;
17223
+ font-size: 20px;
17224
+ font-family: "Cormorant";
17225
+ font-style: normal;
17226
+ font-weight: 300;
17227
+ line-height: normal;
16572
17228
  }
16573
- .cta-button {
17229
+
17230
+ .${prefix}__description {
17231
+ color: inherit;
16574
17232
  font-size: 12px;
17233
+ line-height: 16px;
17234
+ font-family: "Source Sans 3", system-ui;
17235
+ font-style: normal;
17236
+ font-weight: 400;
17237
+ margin: 0;
16575
17238
  }
16576
- }
16577
- @media (min-width: 1024px) {
16578
- .text {
16579
- padding: 30px;
17239
+
17240
+ .${prefix}__cta-button {
17241
+ width: fit-content;
17242
+ display: inline-block;
17243
+ padding: 7px 20px;
17244
+ border: 0.5px solid ${ctaBorderColor};
17245
+ border-radius: 5px;
17246
+ color: ${ctaTextColor};
17247
+ font-size: 8px;
17248
+ transition: background-color 0.3s ease;
17249
+ font-family: "Source Sans 3", system-ui;
17250
+ font-style: normal;
17251
+ font-weight: 400;
16580
17252
  }
16581
- .header {
16582
- font-size: 28px;
17253
+
17254
+ .${prefix}__content:hover .${prefix}__cta-button {
17255
+ background-color: ${ctaBorderColor.length === 7 ? `${ctaBorderColor}15` : `${ctaBorderColor}`};
16583
17256
  }
16584
- .description {
16585
- font-size: 14px;
17257
+
17258
+ @media (min-width: 640px) {
17259
+ .${prefix}__content {
17260
+ background-image: linear-gradient(to top, ${linearGradient}), url("${primaryImage}");
17261
+ }
16586
17262
  }
16587
- .cta-button {
16588
- font-size: 13px;
17263
+
17264
+ @media (min-width: 768px) {
17265
+ .${prefix}__text {
17266
+ padding: 25px;
17267
+ }
17268
+
17269
+ .${prefix}__header {
17270
+ font-size: 24px;
17271
+ }
17272
+
17273
+ .${prefix}__description {
17274
+ font-size: 13px;
17275
+ line-height: 18px;
17276
+ }
17277
+
17278
+ .${prefix}__cta-button {
17279
+ font-size: 12px;
17280
+ }
16589
17281
  }
16590
- }
16591
- @media (min-width: 1280px) {
16592
- .cta-button {
16593
- font-size: 14px;
17282
+
17283
+ @media (min-width: 1024px) {
17284
+ .${prefix}__text {
17285
+ padding: 30px;
17286
+ }
17287
+
17288
+ .${prefix}__header {
17289
+ font-size: 28px;
17290
+ }
17291
+
17292
+ .${prefix}__description {
17293
+ font-size: 14px;
17294
+ }
17295
+
17296
+ .${prefix}__cta-button {
17297
+ font-size: 13px;
17298
+ }
16594
17299
  }
16595
- }
16596
- </style>
16597
- `;
16598
- function rbLargeCategoryImageToutTemplate(spot) {
17300
+
17301
+ @media (min-width: 1280px) {
17302
+ .${prefix}__cta-button {
17303
+ font-size: 14px;
17304
+ }
17305
+ }
17306
+ </style>
17307
+ `;
17308
+ };
17309
+ function rbLargeCategoryImageToutTemplate(spot, config) {
17310
+ const { prefix = '' } = config;
16599
17311
  return `
16600
17312
  ${GFONT_PRECONNECT}
16601
17313
  ${GFONT_SOURCE_SANS_3}
16602
17314
  ${GFONT_CORMORANT}
16603
- ${STYLES$3(spot)}
16604
- <div class="content">
16605
- <div class="text">
16606
- ${spot.header ? `<h2 class="header">${spot.header}</h2>` : ''}
16607
- ${spot.description ? `<p class="description">${spot.description}</p>` : ''}
16608
- ${spot.ctaText ? `<span class="cta-button">${spot.ctaText}</span>` : ''}
17315
+ ${STYLES$3(spot, config)}
17316
+ <div class="${prefix}__content">
17317
+ <div class="${prefix}__text">
17318
+ ${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
17319
+ ${spot.description ? `<p class="${prefix}__description">${spot.description}</p>` : ''}
17320
+ ${spot.ctaText ? `<span class="${prefix}__cta-button">${spot.ctaText}</span>` : ''}
16609
17321
  </div>
16610
17322
  </div>
16611
17323
  `;
16612
17324
  }
16613
17325
 
16614
- const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = primaryImage, }) => `
17326
+ const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = primaryImage }, { prefix, overlay }) => {
17327
+ const linearGradient = linearGradientColorStop(overlay || [], 'rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 30%');
17328
+ return `
16615
17329
  <style>
16616
17330
  :host {
16617
17331
  min-width: 320px;
16618
17332
  min-height: 150px;
16619
17333
  }
16620
- .content {
17334
+
17335
+ .${prefix}__content {
16621
17336
  width: 100%;
16622
17337
  height: 100%;
16623
17338
  display: flex;
@@ -16626,17 +17341,18 @@ const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = pr
16626
17341
  border-radius: 5px;
16627
17342
  overflow: hidden;
16628
17343
  cursor: pointer;
16629
- background-image: url("${mobilePrimaryImage}");
17344
+ background-image: linear-gradient(to top, ${linearGradient}), url("${mobilePrimaryImage}");
16630
17345
  background-size: cover;
16631
17346
  background-position: center;
16632
- background-blend-mode: overlay;
16633
17347
  background-repeat: no-repeat;
16634
17348
  }
16635
- .text {
17349
+
17350
+ .${prefix}__text {
16636
17351
  padding: 15px 10%;
16637
17352
  width: fit-content;
16638
17353
  }
16639
- .header {
17354
+
17355
+ .${prefix}__header {
16640
17356
  font-size: 16px;
16641
17357
  color: ${textColor};
16642
17358
  line-height: 20px;
@@ -16645,102 +17361,117 @@ const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = pr
16645
17361
  font-style: normal;
16646
17362
  margin: 0;
16647
17363
  }
17364
+
16648
17365
  @media (min-width: 640px) {
16649
- .content {
16650
- background-image: url("${primaryImage}");
17366
+ .${prefix}__content {
17367
+ background-image: linear-gradient(to top, ${linearGradient}), url("${primaryImage}");
16651
17368
  }
16652
17369
  }
17370
+
16653
17371
  @media (min-width: 768px) {
16654
- .header {
17372
+ .${prefix}__header {
16655
17373
  font-size: 22px;
16656
17374
  }
16657
17375
  }
17376
+
16658
17377
  @media (min-width: 1024px) {
16659
- .header {
17378
+ .${prefix}__header {
16660
17379
  font-size: 24px;
16661
17380
  }
16662
17381
  }
17382
+
16663
17383
  @media (min-width: 1280px) {
16664
- .header {
17384
+ .${prefix}__header {
16665
17385
  font-size: 28px;
16666
17386
  }
16667
17387
  }
16668
17388
  </style>
16669
17389
  `;
16670
- function rbNavigationBannerTemplate(spot) {
17390
+ };
17391
+ function rbNavigationBannerTemplate(spot, config) {
17392
+ const { prefix = '' } = config;
16671
17393
  return `
16672
17394
  ${GFONT_PRECONNECT}
16673
17395
  ${GFONT_SOURCE_SANS_3}
16674
- ${STYLES$2(spot)}
16675
- <div class="content">
16676
- <div class="text">
16677
- ${spot.header ? `<h2 class="header">${spot.header}</h2>` : ''}
17396
+ ${STYLES$2(spot, config)}
17397
+ <div class="${prefix}__content">
17398
+ <div class="${prefix}__text">
17399
+ ${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
16678
17400
  </div>
16679
17401
  </div>
16680
17402
  `;
16681
17403
  }
16682
17404
 
16683
- const STYLES$1 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = primaryImage, }) => `
16684
- <style>
16685
- :host {
16686
- min-width: 165px;
16687
- min-height: 300px;
16688
- }
16689
- .content {
16690
- width: 100%;
16691
- height: 100%;
16692
- display: flex;
16693
- flex-direction: column;
16694
- justify-content: flex-end;
16695
- background-image: url("${mobilePrimaryImage}");
16696
- background-size: cover;
16697
- background-repeat: no-repeat;
16698
- background-position: center;
16699
- border-radius: 5px;
16700
- overflow: hidden;
16701
- cursor: pointer;
16702
- }
16703
- .text {
16704
- padding: 10px;
16705
- width: 70%;
16706
- }
16707
- .header {
16708
- font-size: 12px;
16709
- color: ${textColor};
16710
- line-height: 16px;
16711
- font-family: "Source Sans 3", system-ui;
16712
- font-style: normal;
16713
- font-weight: 400;
16714
- line-height: normal;
16715
- margin: 0;
16716
- }
16717
- @media (min-width: 640px) {
16718
- .content {
16719
- background-image: url("${primaryImage}");
17405
+ const STYLES$1 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = primaryImage }, { prefix, overlay }) => {
17406
+ const linearGradient = linearGradientColorStop(overlay || [], 'rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 30%');
17407
+ return `
17408
+ <style>
17409
+ :host {
17410
+ min-width: 165px;
17411
+ min-height: 300px;
16720
17412
  }
16721
- }
16722
- </style>
16723
- `;
16724
- function rbSmallCategoryImageToutTemplate(spot) {
17413
+
17414
+ .${prefix}__content {
17415
+ width: 100%;
17416
+ height: 100%;
17417
+ display: flex;
17418
+ flex-direction: column;
17419
+ justify-content: flex-end;
17420
+ background-image: linear-gradient(to top, ${linearGradient}), url("${mobilePrimaryImage}");
17421
+ background-size: cover;
17422
+ background-repeat: no-repeat;
17423
+ background-position: center;
17424
+ border-radius: 5px;
17425
+ overflow: hidden;
17426
+ cursor: pointer;
17427
+ }
17428
+
17429
+ .${prefix}__text {
17430
+ padding: 10px;
17431
+ width: 70%;
17432
+ }
17433
+
17434
+ .${prefix}__header {
17435
+ font-size: 12px;
17436
+ color: ${textColor};
17437
+ line-height: 16px;
17438
+ font-family: "Source Sans 3", system-ui;
17439
+ font-style: normal;
17440
+ font-weight: 400;
17441
+ line-height: normal;
17442
+ margin: 0;
17443
+ }
17444
+
17445
+ @media (min-width: 640px) {
17446
+ .${prefix}__content {
17447
+ background-image: linear-gradient(to top, ${linearGradient}), url("${primaryImage}");
17448
+ }
17449
+ }
17450
+ </style>
17451
+ `;
17452
+ };
17453
+ function rbSmallCategoryImageToutTemplate(spot, config) {
17454
+ const { prefix = '' } = config;
16725
17455
  return `
16726
17456
  ${GFONT_PRECONNECT}
16727
17457
  ${GFONT_CORMORANT}
16728
- ${STYLES$1(spot)}
16729
- <div class="content">
16730
- <div class="text">
16731
- ${spot.header ? `<h2 class="header">${spot.header}</h2>` : ''}
17458
+ ${STYLES$1(spot, config)}
17459
+ <div class="${prefix}__content">
17460
+ <div class="${prefix}__text">
17461
+ ${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
16732
17462
  </div>
16733
17463
  </div>
16734
17464
  `;
16735
17465
  }
16736
17466
 
16737
- const STYLES = ({ textColor = '#000000', backgroundColor = 'transparent', primaryImage, mobilePrimaryImage = primaryImage, }) => `
17467
+ const STYLES = ({ textColor = '#000000', backgroundColor = 'transparent', primaryImage, mobilePrimaryImage = primaryImage, }, { prefix }) => `
16738
17468
  <style>
16739
17469
  :host {
16740
17470
  min-width: 165px;
16741
17471
  min-height: 250px;
16742
17472
  }
16743
- .content {
17473
+
17474
+ .${prefix}__content {
16744
17475
  width: 100%;
16745
17476
  height: 100%;
16746
17477
  background-color: ${backgroundColor};
@@ -16749,7 +17480,8 @@ const STYLES = ({ textColor = '#000000', backgroundColor = 'transparent', primar
16749
17480
  flex-direction: column;
16750
17481
  border-radius: 5px;
16751
17482
  }
16752
- .image {
17483
+
17484
+ .${prefix}__image {
16753
17485
  width: 100%;
16754
17486
  height: 100%;
16755
17487
  background-image: url("${mobilePrimaryImage}");
@@ -16758,7 +17490,8 @@ const STYLES = ({ textColor = '#000000', backgroundColor = 'transparent', primar
16758
17490
  background-position: center;
16759
17491
  border-radius: 5px;
16760
17492
  }
16761
- .text {
17493
+
17494
+ .${prefix}__text {
16762
17495
  text-align: left;
16763
17496
  display: flex;
16764
17497
  flex-direction: row;
@@ -16768,7 +17501,8 @@ const STYLES = ({ textColor = '#000000', backgroundColor = 'transparent', primar
16768
17501
  height: fit-content;
16769
17502
  position: relative;
16770
17503
  }
16771
- .header {
17504
+
17505
+ .${prefix}__header {
16772
17506
  font-size: 12px;
16773
17507
  color: ${textColor};
16774
17508
  padding-top: 5px;
@@ -16779,43 +17513,39 @@ const STYLES = ({ textColor = '#000000', backgroundColor = 'transparent', primar
16779
17513
  line-height: normal;
16780
17514
  margin: 0;
16781
17515
  }
17516
+
16782
17517
  @media (min-width: 640px) {
16783
- .image {
17518
+ .${prefix}__image {
16784
17519
  background-image: url("${primaryImage}");
16785
17520
  }
16786
17521
  }
16787
17522
  </style>
16788
17523
  `;
16789
- function rbSmallDiscoverToutTemplate(spot) {
17524
+ function rbSmallDiscoverToutTemplate(spot, config) {
17525
+ const { prefix = '' } = config;
16790
17526
  return `
16791
17527
  ${GFONT_PRECONNECT}
16792
17528
  ${GFONT_CORMORANT}
16793
- ${STYLES(spot)}
16794
- <div class="content">
16795
- <div class="image"></div>
16796
- <div class="text">
16797
- ${spot.header ? `<h2 class="header">${spot.header}</h2>` : ''}
17529
+ ${STYLES(spot, config)}
17530
+ <div class="${prefix}__content">
17531
+ <div class="${prefix}__image"></div>
17532
+ <div class="${prefix}__text">
17533
+ ${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
16798
17534
  </div>
16799
17535
  </div>
16800
17536
  `;
16801
17537
  }
16802
17538
 
16803
- var ENUM_SPOT_ELEMENT_ATTRIBUTE;
16804
- (function (ENUM_SPOT_ELEMENT_ATTRIBUTE) {
16805
- ENUM_SPOT_ELEMENT_ATTRIBUTE["WIDTH"] = "width";
16806
- ENUM_SPOT_ELEMENT_ATTRIBUTE["HEIGHT"] = "height";
16807
- ENUM_SPOT_ELEMENT_ATTRIBUTE["FLUID"] = "fluid";
16808
- ENUM_SPOT_ELEMENT_ATTRIBUTE["REDIRECT_ON_CLICK"] = "redirect-on-click";
16809
- })(ENUM_SPOT_ELEMENT_ATTRIBUTE || (ENUM_SPOT_ELEMENT_ATTRIBUTE = {}));
16810
17539
  /**
16811
17540
  * Creates the spot html string based on the provided spot data.
16812
17541
  *
16813
- * @param {ISpot} data - The spot data.
17542
+ * @param {ISpot} spot - The spot data.
16814
17543
  *
16815
17544
  * @return {string} - The spot html string.
16816
17545
  */
16817
- const GET_SPOT_TEMPLATE_HTML_STRING = (data) => {
17546
+ const SPOT_TEMPLATE_HTML_ELEMENT = (spot, config) => {
16818
17547
  const templates = {
17548
+ // Reserve Bar Spot Templates
16819
17549
  [RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE]: {
16820
17550
  rbHomepageHeroThreeTile: rbHomepageHeroThreeTileTemplate,
16821
17551
  },
@@ -16843,6 +17573,7 @@ const GET_SPOT_TEMPLATE_HTML_STRING = (data) => {
16843
17573
  [RMN_SPOT_TYPE.RB_PRODUCT_UPCS]: {
16844
17574
  rbProductUpcs: () => '', // No template for this spot type, it will be handled by ReserveBar App.
16845
17575
  },
17576
+ // IAB Standard Spot Templates
16846
17577
  [RMN_SPOT_TYPE.BILLBOARD]: {
16847
17578
  billboardV1: billboardV1Template,
16848
17579
  billboardV2: billboardV2Template,
@@ -16869,178 +17600,28 @@ const GET_SPOT_TEMPLATE_HTML_STRING = (data) => {
16869
17600
  inTextV1: inTextV1Template,
16870
17601
  },
16871
17602
  };
16872
- const spotVariants = templates[data.spot];
17603
+ const spotVariants = templates[spot.spot];
16873
17604
  if (!spotVariants) {
16874
- return '';
17605
+ return null;
16875
17606
  }
16876
- const variantTemplate = spotVariants[data.variant];
17607
+ const variantTemplate = spotVariants[spot.variant];
16877
17608
  if (!variantTemplate) {
16878
- return '';
17609
+ return null;
16879
17610
  }
16880
- return variantTemplate(data);
17611
+ // Generate a random prefix to avoid conflicts with other elements.
17612
+ const prefix = 's' + Math.random().toString(36).substring(6);
17613
+ const spotHtmlString = variantTemplate(spot, { ...config, prefix });
17614
+ return spotHtmlStringToElement(spotHtmlString);
16881
17615
  };
16882
17616
 
16883
- let SpotElement;
16884
- if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined') {
16885
- class CustomSpotElement extends HTMLElement {
16886
- constructor() {
16887
- super();
16888
- this.hasCustomContent = false;
16889
- this.handleClick = this.handleClick.bind(this);
16890
- this.attachShadow({ mode: 'open' });
16891
- }
16892
- connectedCallback() {
16893
- this.hasCustomContent = Boolean(this.customContent);
16894
- this.addEventListener('click', this.handleClick);
16895
- this.setupIntersectionObserver();
16896
- this.render();
16897
- }
16898
- disconnectedCallback() {
16899
- var _a;
16900
- (_a = this.observer) === null || _a === void 0 ? void 0 : _a.disconnect();
16901
- this.removeEventListener('click', this.handleClick);
16902
- }
16903
- attributeChangedCallback(_name, oldValue, newValue) {
16904
- if (oldValue !== newValue) {
16905
- this.render();
16906
- }
16907
- }
16908
- render() {
16909
- if (!this.shadowRoot || !this.data)
16910
- return;
16911
- const { style, wrapper, slot } = SPOT_ELEMENT_TEMPLATE(this.data.width, this.data.height, this.hasCustomContent);
16912
- this.shadowRoot.replaceChildren(style, slot);
16913
- if (this.hasCustomContent) {
16914
- this.setCustomContent();
16915
- }
16916
- if (!this.hasCustomContent) {
16917
- wrapper.innerHTML = GET_SPOT_TEMPLATE_HTML_STRING(this.data);
16918
- this.shadowRoot.appendChild(wrapper);
16919
- }
16920
- }
16921
- setCustomContent() {
16922
- const wrapper = document.createElement('div');
16923
- wrapper.setAttribute('slot', SPOT_ELEMENT_SLOT_NAME);
16924
- if (typeof this.customContent === 'string') {
16925
- wrapper.innerHTML = this.customContent;
16926
- }
16927
- if (this.customContent instanceof HTMLElement) {
16928
- wrapper.appendChild(this.customContent);
16929
- }
16930
- this.appendChild(wrapper);
16931
- }
16932
- setupIntersectionObserver() {
16933
- const options = {
16934
- root: null,
16935
- rootMargin: '0px',
16936
- threshold: 0.5, // The element is considered visible when 50% of it is visible
16937
- };
16938
- this.observer = new IntersectionObserver((entries) => {
16939
- var _a;
16940
- if (entries[0].isIntersecting) {
16941
- this.registerEvent(RMN_SPOT_EVENT.IMPRESSION);
16942
- (_a = this.observer) === null || _a === void 0 ? void 0 : _a.disconnect();
16943
- }
16944
- }, options);
16945
- this.observer.observe(this);
16946
- }
16947
- handleClick() {
16948
- this.registerEvent(RMN_SPOT_EVENT.CLICK);
16949
- }
16950
- async registerEvent(event) {
16951
- var _a, _b;
16952
- if (!this.data)
16953
- return;
16954
- const shouldRedirectOnClick = this.getAttribute(ENUM_SPOT_ELEMENT_ATTRIBUTE.REDIRECT_ON_CLICK) === 'true';
16955
- const eventUrl = (_b = (_a = this.data.events.find((e) => e.event === event)) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : '';
16956
- try {
16957
- const options = {
16958
- method: 'POST',
16959
- redirect: event === RMN_SPOT_EVENT.CLICK && shouldRedirectOnClick ? 'follow' : 'manual',
16960
- };
16961
- const response = await fetch(eventUrl, options);
16962
- if (response.ok && event === RMN_SPOT_EVENT.CLICK && shouldRedirectOnClick) {
16963
- window.location.href = this.getRedirectUrlFromPayload(eventUrl);
16964
- }
16965
- }
16966
- catch (error) {
16967
- console.error(`Rmn error sending ${event} event:`, error);
16968
- }
16969
- }
16970
- getRedirectUrlFromPayload(url) {
16971
- var _a, _b;
16972
- const base64String = (_a = new URL(url).searchParams.get('e')) !== null && _a !== void 0 ? _a : '';
16973
- try {
16974
- const data = JSON.parse(atob(base64String));
16975
- return (_b = data.ur) !== null && _b !== void 0 ? _b : '';
16976
- }
16977
- catch (_c) {
16978
- return '';
16979
- }
16980
- }
16981
- }
16982
- CustomSpotElement.observedAttributes = Object.values(ENUM_SPOT_ELEMENT_ATTRIBUTE);
16983
- SpotElement = CustomSpotElement;
16984
- }
16985
-
16986
- class SpotHtmlService {
16987
- static getInstance() {
16988
- return SingletonManager.getInstance('SpotHtmlService', () => new SpotHtmlService());
16989
- }
16990
- /**
16991
- * Creates the html element based on the provided spot data using shadow dom.
16992
- *
16993
- * This method is only available in browser environments.
16994
- *
16995
- * @param {ISpot} spot - The spot data.
16996
- * @param {ICreateSpotElementConfig} config - The configuration object.
16997
- * @param {ICreateSpotElementConfig.fluid} config.fluid - If the spot should be fluid or not.
16998
- * @param {ICreateSpotElementConfig.customContent} config.customContent - Use a custom html element/string.
16999
- * @param {ICreateSpotElementConfig.redirectOnClick} config.redirectOnClick - If the spot should redirect on click.
17000
- *
17001
- * @return {HTMLElement | null} - The spot html element or null if the browser environment is not available.
17002
- */
17003
- createSpotHtmlElement(spot, config) {
17004
- var _a, _b;
17005
- if (!this.ensureBrowserEnvironmentAndDefineElement()) {
17006
- return null;
17007
- }
17008
- const isFluid = (_a = config === null || config === void 0 ? void 0 : config.fluid) !== null && _a !== void 0 ? _a : false;
17009
- const shouldRedirectOnClick = (_b = config === null || config === void 0 ? void 0 : config.redirectOnClick) !== null && _b !== void 0 ? _b : true;
17010
- const element = document.createElement(SPOT_ELEMENT_TAG);
17011
- element.setAttribute(ENUM_SPOT_ELEMENT_ATTRIBUTE.WIDTH, spot.width.toString());
17012
- element.setAttribute(ENUM_SPOT_ELEMENT_ATTRIBUTE.HEIGHT, spot.height.toString());
17013
- element.setAttribute(ENUM_SPOT_ELEMENT_ATTRIBUTE.FLUID, isFluid.toString());
17014
- element.setAttribute(ENUM_SPOT_ELEMENT_ATTRIBUTE.REDIRECT_ON_CLICK, shouldRedirectOnClick.toString());
17015
- // Share the spot data with the element
17016
- element.data = spot;
17017
- // Set custom content
17018
- if (config === null || config === void 0 ? void 0 : config.customContent) {
17019
- element.customContent = config.customContent;
17020
- }
17021
- return element;
17022
- }
17023
- /**
17024
- * @returns {boolean} - True if the browser environment is available and the element is defined.
17025
- */
17026
- ensureBrowserEnvironmentAndDefineElement() {
17027
- if (typeof window === 'undefined' || typeof document === 'undefined') {
17028
- console.warn('LiquidCommerce Rmn Sdk: createSpotElement is only available in browser environments!!!');
17029
- return false;
17030
- }
17031
- if (!customElements.get(SPOT_ELEMENT_TAG)) {
17032
- customElements.define(SPOT_ELEMENT_TAG, SpotElement);
17033
- }
17034
- return true;
17035
- }
17036
- }
17617
+ const SELECTION_API_PATH = '/spots/selection';
17037
17618
 
17038
- class SpotSelectionService extends BaseApi {
17619
+ class SelectionService extends BaseApi {
17039
17620
  constructor(auth) {
17040
17621
  super(auth);
17041
17622
  }
17042
17623
  static getInstance(auth) {
17043
- return SingletonManager.getInstance('SpotSelectionService', () => new SpotSelectionService(auth));
17624
+ return SingletonManager.getInstance('SelectionService', () => new SelectionService(auth));
17044
17625
  }
17045
17626
  /**
17046
17627
  * Makes a selection request on our server based on the provided data.
@@ -17050,7 +17631,7 @@ class SpotSelectionService extends BaseApi {
17050
17631
  * @return {Promise<ISpots>} - The spots response object.
17051
17632
  */
17052
17633
  async spotSelection(data) {
17053
- const { isOk, val, isErr } = await this.post(SPOTS_SELECTION_API_PATH, data, {});
17634
+ const { isOk, val, isErr } = await this.post(SELECTION_API_PATH, data, {});
17054
17635
  if (isErr) {
17055
17636
  throw new Error(`There was an error during spot selection: (${isErr === null || isErr === void 0 ? void 0 : isErr.errorMessage})`);
17056
17637
  }
@@ -17065,8 +17646,8 @@ class SpotSelectionService extends BaseApi {
17065
17646
 
17066
17647
  class LiquidCommerceRmnClient {
17067
17648
  constructor(auth) {
17068
- this.spotSelectionService = SpotSelectionService.getInstance(auth);
17069
- this.spotHtmlService = SpotHtmlService.getInstance();
17649
+ this.selectionService = SelectionService.getInstance(auth);
17650
+ this.elementService = ElementService.getInstance();
17070
17651
  }
17071
17652
  /**
17072
17653
  * Makes a selection request on our server based on the provided data.
@@ -17078,23 +17659,145 @@ class LiquidCommerceRmnClient {
17078
17659
  * @return {Promise<ISpots>} - The spots response object.
17079
17660
  */
17080
17661
  async spotSelection(data) {
17081
- return this.spotSelectionService.spotSelection(data);
17662
+ return this.selectionService.spotSelection(data);
17663
+ }
17664
+ /**
17665
+ * Injects the spot elements into their provided placement.
17666
+ *
17667
+ * @param {IInjectSpotElement[]} data - The spot element's data.
17668
+ * @param {IInjectSpotElementConfig} config - The configuration object.
17669
+ *
17670
+ * @return {Promise<void>} - A promise that resolves when the spot elements are injected.
17671
+ */
17672
+ async injectSpotElement(data, config) {
17673
+ if (!data.length) {
17674
+ console.warn('RmnSdk: Failed to request spot selection. No spot elements provided.');
17675
+ return;
17676
+ }
17677
+ const spotSelectionRequest = data.map((item) => {
17678
+ var _a;
17679
+ return ({
17680
+ spot: item.spotType,
17681
+ count: (_a = item === null || item === void 0 ? void 0 : item.count) !== null && _a !== void 0 ? _a : 1,
17682
+ });
17683
+ });
17684
+ const response = await this.spotSelection({
17685
+ spots: spotSelectionRequest,
17686
+ url: config === null || config === void 0 ? void 0 : config.url,
17687
+ });
17688
+ const normalizedData = this.normalizeDataSpotType(data);
17689
+ for (const item of normalizedData) {
17690
+ const spots = response[item.spotType];
17691
+ if (!(spots === null || spots === void 0 ? void 0 : spots.length)) {
17692
+ console.warn(`RmnSdk: Failed to inject spot element. No spots found for type "${item.spotType}".`);
17693
+ continue;
17694
+ }
17695
+ const placementId = item.placementId.replace('#', '');
17696
+ const placement = document.getElementById(placementId);
17697
+ if (!placement) {
17698
+ console.warn(`RmnSdk: Failed to inject spot element. Placement not found for id "#${placementId}".`);
17699
+ continue;
17700
+ }
17701
+ if (spots.length === 1) {
17702
+ this.injectOneSpotElement(item, placement, spots[0], config);
17703
+ }
17704
+ if (spots.length > 1) {
17705
+ this.injectCarouselSpotElement(placement, spots, config);
17706
+ }
17707
+ }
17082
17708
  }
17083
17709
  /**
17084
- * Creates the spot html element based on the provided data using shadow dom.
17710
+ * Injects a carousel element with the provided spots into the placement.
17711
+ *
17712
+ * @param {HTMLElement} placement - The placement element.
17713
+ * @param {ISpot[]} spots - The spot data.
17714
+ * @param {IInjectSpotElementConfig} config - The configuration object.
17085
17715
  *
17086
- * This method is useful when you are initializing the client in a browser environment, so you can create the spot html element directly from the RmnClient instance.
17716
+ * @return {void}
17717
+ */
17718
+ injectCarouselSpotElement(placement, spots, config) {
17719
+ var _a;
17720
+ const carouselSlides = [];
17721
+ for (const spotItem of spots) {
17722
+ const spot = this.elementService.overrideSpotColors(spotItem, config === null || config === void 0 ? void 0 : config.colors);
17723
+ const content = SPOT_TEMPLATE_HTML_ELEMENT(spot, { overlay: config === null || config === void 0 ? void 0 : config.overlay });
17724
+ if (!content) {
17725
+ console.warn(`RmnSdk: Failed to inject carousel spot element. Could not create element for type "${spot.spot}".`);
17726
+ return;
17727
+ }
17728
+ carouselSlides.push(content);
17729
+ }
17730
+ const { maxWidth, maxHeight } = spots.reduce((max, spot) => ({
17731
+ maxWidth: Math.max(max.maxWidth, spot.width),
17732
+ maxHeight: Math.max(max.maxHeight, spot.height),
17733
+ }), { maxWidth: 0, maxHeight: 0 });
17734
+ const carouselElement = this.elementService.createCarouselElement({
17735
+ slides: carouselSlides,
17736
+ config: {
17737
+ width: maxWidth,
17738
+ height: maxHeight,
17739
+ 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
17740
+ ...config === null || config === void 0 ? void 0 : config.carousel,
17741
+ },
17742
+ });
17743
+ if (!carouselElement) {
17744
+ console.warn(`RmnSdk: Failed to inject spot carousel element. Could not create spot carousel element.`);
17745
+ return;
17746
+ }
17747
+ placement.replaceChildren(carouselElement);
17748
+ }
17749
+ /**
17750
+ * Injects a single spot element into the provided placement.
17087
17751
  *
17752
+ * @param {IInjectSpotElement} injectItem - The inject item data.
17753
+ * @param {HTMLElement} placement - The placement element.
17088
17754
  * @param {ISpot} spot - The spot data.
17089
- * @param {ICreateSpotElementConfig} config - The configuration object.
17090
- * @param {ICreateSpotElementConfig.fluid} config.fluid - If the spot should be fluid or not.
17091
- * @param {ICreateSpotElementConfig.customContent} config.customContent - Use a custom html element/string.
17092
- * @param {ICreateSpotElementConfig.redirectOnClick} config.redirectOnClick - If the spot should redirect on click.
17755
+ * @param {IInjectSpotElementConfig} config - The configuration object.
17756
+ *
17757
+ * @return {void}
17758
+ */
17759
+ injectOneSpotElement(injectItem, placement, spot, config) {
17760
+ var _a;
17761
+ const spotData = this.elementService.overrideSpotColors(spot, config === null || config === void 0 ? void 0 : config.colors);
17762
+ const content = SPOT_TEMPLATE_HTML_ELEMENT(spotData, { overlay: config === null || config === void 0 ? void 0 : config.overlay });
17763
+ if (!content) {
17764
+ console.warn(`RmnSdk: Failed to inject spot element. Could not create element for type "${injectItem.spotType}".`);
17765
+ return;
17766
+ }
17767
+ const spotElement = this.elementService.createSpotElement({
17768
+ content,
17769
+ config: {
17770
+ width: spot.width,
17771
+ height: spot.height,
17772
+ 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
17773
+ },
17774
+ });
17775
+ if (!spotElement) {
17776
+ console.warn(`RmnSdk: Failed to inject spot element. Could not create element for type "${injectItem.spotType}".`);
17777
+ return;
17778
+ }
17779
+ placement.replaceChildren(spotElement);
17780
+ }
17781
+ /**
17782
+ * Normalizes the spot type data by adding a number suffix to the spot type.
17093
17783
  *
17094
- * @return {HTMLElement | null} - The spot html element or null if the browser environment is not available.
17784
+ * @param {IInjectSpotElement[]} spots - The spot type data.
17785
+ *
17786
+ * @return {IInjectSpotElement[]} - The normalized spot type data.
17095
17787
  */
17096
- createSpotElement(spot, config) {
17097
- return this.spotHtmlService.createSpotHtmlElement(spot, config);
17788
+ normalizeDataSpotType(spots) {
17789
+ const spotTypeCounts = {};
17790
+ return spots.map((spot) => {
17791
+ const { spotType } = spot;
17792
+ spotTypeCounts[spotType] = (spotTypeCounts[spotType] || 0) + 1;
17793
+ if (spotTypeCounts[spotType] === 1) {
17794
+ return spot;
17795
+ }
17796
+ return {
17797
+ ...spot,
17798
+ spotType: `${spotType}${spotTypeCounts[spotType]}`,
17799
+ };
17800
+ });
17098
17801
  }
17099
17802
  }
17100
17803
  /**
@@ -17114,20 +17817,32 @@ async function RmnClient(apiKey, config) {
17114
17817
  * Creates the spot html element based on the provided data using shadow dom.
17115
17818
  *
17116
17819
  * This method is useful when you are initializing the client in a non-browser environment.
17117
- * When you request a spot selection, you will receive the spot data in server-side and return them back to the client.
17820
+ * When you request a spot selection, you will receive the spot data in server-side and return them to the client.
17118
17821
  * Then you can use this function to create the spot html element based on the provided data without the need of the RmnClient instance.
17119
17822
  *
17120
17823
  * @param {ISpot} spot - The spot data.
17121
- * @param {ICreateSpotElementConfig} config - The configuration object.
17122
- * @param {ICreateSpotElementConfig.fluid} config.fluid - If the spot should be fluid or not.
17123
- * @param {ICreateSpotElementConfig.customContent} config.customContent - Use a custom html element/string.
17124
- * @param {ICreateSpotElementConfig.redirectOnClick} config.redirectOnClick - If the spot should redirect on click.
17824
+ * @param {IRmnCreateSpotElementConfig} config - The configuration object.
17125
17825
  *
17126
17826
  * @return {HTMLElement | null} - The spot html element or null if the browser environment is not available.
17127
17827
  */
17128
17828
  function RmnCreateSpotElement(spot, config) {
17129
- const spotHtmlService = SpotHtmlService.getInstance();
17130
- return spotHtmlService.createSpotHtmlElement(spot, config);
17829
+ var _a;
17830
+ const elementService = ElementService.getInstance();
17831
+ const spotData = elementService.overrideSpotColors(spot, config === null || config === void 0 ? void 0 : config.colors);
17832
+ const content = SPOT_TEMPLATE_HTML_ELEMENT(spotData, { overlay: config === null || config === void 0 ? void 0 : config.overlay });
17833
+ if (!content) {
17834
+ console.warn(`RmnSdk: Failed to create spot element for type "${spotData.spot}".`);
17835
+ return null;
17836
+ }
17837
+ return elementService.createSpotElement({
17838
+ content,
17839
+ config: {
17840
+ fluid: true,
17841
+ width: spot.width,
17842
+ height: spot.height,
17843
+ 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
17844
+ },
17845
+ });
17131
17846
  }
17132
17847
 
17133
17848
  export { LiquidCommerceRmnClient, RMN_ENV, RMN_FILTER_PROPERTIES, RMN_SPOT_EVENT, RMN_SPOT_TYPE, RmnClient, RmnCreateSpotElement };