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

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