@liquidcommercedev/rmn-sdk 1.5.0-beta.12 → 1.5.0-beta.14
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.
- package/dist/index.cjs +343 -120
- package/dist/index.esm.js +343 -120
- package/dist/types/common/helpers/utils.helper.d.ts +5 -4
- package/dist/types/modules/element/component/skeleton/index.d.ts +2 -0
- package/dist/types/modules/element/component/skeleton/skeleton.component.d.ts +3 -0
- package/dist/types/modules/element/component/skeleton/skeleton.interface.d.ts +13 -0
- package/dist/types/modules/element/component/skeleton/skeleton.template.d.ts +2 -0
- package/dist/types/modules/element/element.constant.d.ts +3 -0
- package/dist/types/modules/element/element.service.d.ts +11 -0
- package/dist/types/modules/monitor/monitor.interface.d.ts +4 -0
- package/dist/types/rmn-client.d.ts +24 -9
- package/package.json +1 -1
- package/umd/liquidcommerce-rmn-sdk.min.js +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6866,40 +6866,60 @@ class ObjectHelper {
|
|
|
6866
6866
|
/**
|
|
6867
6867
|
* Recursively extracts ID values from a nested data structure.
|
|
6868
6868
|
* Searches for specified property names and collects their primitive values (strings/numbers).
|
|
6869
|
+
* Captures properties ending with 'id' and any additional specified property names.
|
|
6869
6870
|
*
|
|
6870
6871
|
* @param data - The data structure to search through (can be nested objects/arrays)
|
|
6871
|
-
* @param propertyNames - Array of property names to look for
|
|
6872
|
+
* @param propertyNames - Array of additional property names to look for (optional)
|
|
6872
6873
|
* @returns Array of extracted ID values (strings/numbers only)
|
|
6873
6874
|
*
|
|
6874
6875
|
* @example
|
|
6875
6876
|
* const data = {
|
|
6876
6877
|
* id: [1, 2, 3],
|
|
6877
|
-
* nested: { id: 'abc' },
|
|
6878
|
-
* items: [{ id: 456 }]
|
|
6878
|
+
* nested: { id: 'abc', userId: 123 },
|
|
6879
|
+
* items: [{ id: 456, productId: '789', sku: 'ABC123' }]
|
|
6879
6880
|
* };
|
|
6880
|
-
* extractDeepIds(data); // Returns [1, 2, 3, 'abc', 456]
|
|
6881
|
+
* extractDeepIds(data); // Returns [1, 2, 3, 'abc', 123, 456, '789', 'ABC123']
|
|
6881
6882
|
*/
|
|
6882
6883
|
function extractDeepIds(data, propertyNames) {
|
|
6883
6884
|
const ids = [];
|
|
6884
|
-
const
|
|
6885
|
-
|
|
6886
|
-
'
|
|
6887
|
-
'
|
|
6888
|
-
'
|
|
6889
|
-
'
|
|
6890
|
-
'
|
|
6891
|
-
'
|
|
6892
|
-
'
|
|
6893
|
-
'
|
|
6885
|
+
const defaultPropertyNames = [
|
|
6886
|
+
// Universal product identifiers
|
|
6887
|
+
'gtin', // Global Trade Item Number
|
|
6888
|
+
'gtin8', // 8-digit GTIN
|
|
6889
|
+
'gtin12', // 12-digit GTIN (UPC)
|
|
6890
|
+
'gtin13', // 13-digit GTIN (EAN)
|
|
6891
|
+
'gtin14', // 14-digit GTIN
|
|
6892
|
+
'mpn', // Manufacturer Part Number
|
|
6893
|
+
'sku', // Stock Keeping Unit
|
|
6894
|
+
'upc', // Universal Product Code
|
|
6895
|
+
'ean', // European Article Number
|
|
6896
|
+
'isbn', // International Standard Book Number
|
|
6897
|
+
'isbn10', // 10-digit ISBN
|
|
6898
|
+
'isbn13', // 13-digit ISBN
|
|
6899
|
+
'asin', // Amazon Standard Identification Number
|
|
6900
|
+
// Product codes and references
|
|
6901
|
+
'coupon',
|
|
6902
|
+
'barcode',
|
|
6903
|
+
'product_code',
|
|
6904
|
+
'part_number',
|
|
6894
6905
|
'model_number',
|
|
6895
|
-
'
|
|
6896
|
-
'variant_id',
|
|
6906
|
+
'item_variant',
|
|
6897
6907
|
'item_number',
|
|
6898
|
-
'
|
|
6899
|
-
'
|
|
6908
|
+
'article_number',
|
|
6909
|
+
'reference',
|
|
6910
|
+
'groupingId',
|
|
6900
6911
|
];
|
|
6901
|
-
//
|
|
6902
|
-
const
|
|
6912
|
+
// Convert property names to lowercase for consistent comparison
|
|
6913
|
+
const additionalProperties = new Set((defaultPropertyNames).map((name) => name.toLowerCase()));
|
|
6914
|
+
/**
|
|
6915
|
+
* Checks if a property name is an ID field
|
|
6916
|
+
* @param key - The property name to check
|
|
6917
|
+
* @returns boolean indicating if the key is an ID field
|
|
6918
|
+
*/
|
|
6919
|
+
const isIdField = (key) => {
|
|
6920
|
+
const lowercaseKey = key.toLowerCase();
|
|
6921
|
+
return lowercaseKey.endsWith('id') || additionalProperties.has(lowercaseKey);
|
|
6922
|
+
};
|
|
6903
6923
|
/**
|
|
6904
6924
|
* Processes a value and extracts IDs if it matches criteria
|
|
6905
6925
|
* @param value - The value to process
|
|
@@ -6910,7 +6930,7 @@ function extractDeepIds(data, propertyNames) {
|
|
|
6910
6930
|
if (value == null)
|
|
6911
6931
|
return;
|
|
6912
6932
|
// If current key matches our target properties
|
|
6913
|
-
if (currentKey &&
|
|
6933
|
+
if (currentKey && isIdField(currentKey)) {
|
|
6914
6934
|
if (Array.isArray(value)) {
|
|
6915
6935
|
// Filter and push valid array values in one pass
|
|
6916
6936
|
ids.push(...value.filter((item) => typeof item === 'string' || typeof item === 'number'));
|
|
@@ -6932,7 +6952,7 @@ function extractDeepIds(data, propertyNames) {
|
|
|
6932
6952
|
}
|
|
6933
6953
|
};
|
|
6934
6954
|
processValue(data);
|
|
6935
|
-
return ids;
|
|
6955
|
+
return ids;
|
|
6936
6956
|
}
|
|
6937
6957
|
// Fallback method using fetch if sendBeacon isn't available
|
|
6938
6958
|
async function fallbackEventFire(url) {
|
|
@@ -16125,6 +16145,7 @@ class AuthService extends BaseApi {
|
|
|
16125
16145
|
|
|
16126
16146
|
const SPOT_ELEMENT_TAG = 'spot-element';
|
|
16127
16147
|
const CAROUSEL_ELEMENT_TAG = 'spot-carousel-element';
|
|
16148
|
+
const SKELETON_ELEMENT_TAG = 'spot-skeleton-element';
|
|
16128
16149
|
const GFONT_PRECONNECT = `
|
|
16129
16150
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
16130
16151
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
@@ -16135,6 +16156,45 @@ const GFONT_SOURCE_SANS_3 = `
|
|
|
16135
16156
|
const GFONT_CORMORANT = `
|
|
16136
16157
|
<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">
|
|
16137
16158
|
`;
|
|
16159
|
+
const SPOT_DIMENSIONS = {
|
|
16160
|
+
[exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO]: { width: 1140, height: 640 },
|
|
16161
|
+
[exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE]: { width: 1140, height: 640 },
|
|
16162
|
+
[exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE]: { width: 1140, height: 640 },
|
|
16163
|
+
[exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE]: { width: 1140, height: 640 },
|
|
16164
|
+
[exports.RMN_SPOT_TYPE.RB_LARGE_CATEGORY_IMAGE_TOUT]: { width: 468, height: 410 },
|
|
16165
|
+
[exports.RMN_SPOT_TYPE.RB_SMALL_DISCOVER_TOUT]: { width: 224, height: 378 },
|
|
16166
|
+
[exports.RMN_SPOT_TYPE.RB_SMALL_CATEGORY_IMAGE_TOUT]: { width: 224, height: 410 },
|
|
16167
|
+
[exports.RMN_SPOT_TYPE.RB_COLLECTION_BANNER_WITHOUT_TEXT_BLOCK]: { width: 887, height: 344 },
|
|
16168
|
+
[exports.RMN_SPOT_TYPE.RB_PRODUCT_UPCS]: { width: 1, height: 1 },
|
|
16169
|
+
[exports.RMN_SPOT_TYPE.RB_NAVIGATION_BANNER]: { width: 440, height: 220 },
|
|
16170
|
+
[exports.RMN_SPOT_TYPE.SMALL_RECTANGLE]: { width: 180, height: 150 },
|
|
16171
|
+
[exports.RMN_SPOT_TYPE.MEDIUM_RECTANGLE]: { width: 300, height: 250 },
|
|
16172
|
+
[exports.RMN_SPOT_TYPE.LARGE_RECTANGLE]: { width: 336, height: 280 },
|
|
16173
|
+
[exports.RMN_SPOT_TYPE.VERTICAL_RECTANGLE]: { width: 240, height: 400 },
|
|
16174
|
+
[exports.RMN_SPOT_TYPE.BANNER]: { width: 468, height: 60 },
|
|
16175
|
+
[exports.RMN_SPOT_TYPE.LEADERBOARD]: { width: 728, height: 90 },
|
|
16176
|
+
[exports.RMN_SPOT_TYPE.LARGE_LEADERBOARD]: { width: 970, height: 90 },
|
|
16177
|
+
[exports.RMN_SPOT_TYPE.BILLBOARD]: { width: 970, height: 250 },
|
|
16178
|
+
[exports.RMN_SPOT_TYPE.SKYSCRAPER]: { width: 120, height: 600 },
|
|
16179
|
+
[exports.RMN_SPOT_TYPE.WIDE_SKYSCRAPER]: { width: 160, height: 600 },
|
|
16180
|
+
[exports.RMN_SPOT_TYPE.HALF_PAGE]: { width: 300, height: 600 },
|
|
16181
|
+
[exports.RMN_SPOT_TYPE.SMALL_SQUARE]: { width: 200, height: 200 },
|
|
16182
|
+
[exports.RMN_SPOT_TYPE.SQUARE]: { width: 250, height: 250 },
|
|
16183
|
+
[exports.RMN_SPOT_TYPE.VERTICAL_BANNER]: { width: 120, height: 240 },
|
|
16184
|
+
[exports.RMN_SPOT_TYPE.BUTTON_2]: { width: 120, height: 60 },
|
|
16185
|
+
[exports.RMN_SPOT_TYPE.MICRO_BAR]: { width: 88, height: 31 },
|
|
16186
|
+
[exports.RMN_SPOT_TYPE.POP_UP]: { width: 550, height: 480 },
|
|
16187
|
+
[exports.RMN_SPOT_TYPE.PORTRAIT]: { width: 300, height: 1050 },
|
|
16188
|
+
[exports.RMN_SPOT_TYPE.SMARTPHONE_BANNER_1]: { width: 300, height: 50 },
|
|
16189
|
+
[exports.RMN_SPOT_TYPE.SMARTPHONE_BANNER_2]: { width: 320, height: 50 },
|
|
16190
|
+
[exports.RMN_SPOT_TYPE.MOBILE_PHONE_INTERSTITIAL_1]: { width: 640, height: 1136 },
|
|
16191
|
+
[exports.RMN_SPOT_TYPE.MOBILE_PHONE_INTERSTITIAL_2]: { width: 750, height: 1334 },
|
|
16192
|
+
[exports.RMN_SPOT_TYPE.MOBILE_PHONE_INTERSTITIAL_3]: { width: 1080, height: 1920 },
|
|
16193
|
+
[exports.RMN_SPOT_TYPE.FEATURE_PHONE_SMALL_BANNER]: { width: 120, height: 20 },
|
|
16194
|
+
[exports.RMN_SPOT_TYPE.FEATURE_PHONE_MEDIUM_BANNER]: { width: 168, height: 28 },
|
|
16195
|
+
[exports.RMN_SPOT_TYPE.FEATURE_PHONE_LARGE_BANNER]: { width: 216, height: 36 },
|
|
16196
|
+
[exports.RMN_SPOT_TYPE.IN_TEXT]: { width: 1, height: 1 },
|
|
16197
|
+
};
|
|
16138
16198
|
|
|
16139
16199
|
class IntersectionObserverService {
|
|
16140
16200
|
constructor(defaultOptions = {}) {
|
|
@@ -16973,6 +17033,118 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
|
|
|
16973
17033
|
CarouselElement = CustomCarouselElement;
|
|
16974
17034
|
}
|
|
16975
17035
|
|
|
17036
|
+
function SkeletonTemplate({ fluid, width, height }) {
|
|
17037
|
+
return `
|
|
17038
|
+
<style>
|
|
17039
|
+
:host {
|
|
17040
|
+
display: block;
|
|
17041
|
+
position: relative;
|
|
17042
|
+
box-sizing: border-box;
|
|
17043
|
+
overflow: hidden;
|
|
17044
|
+
width: ${fluid ? '100%' : `${width}px`};
|
|
17045
|
+
height: ${fluid ? '100%' : `${height}px`};
|
|
17046
|
+
background: #ffffff;
|
|
17047
|
+
padding: 20px;
|
|
17048
|
+
border-radius: 5px;
|
|
17049
|
+
}
|
|
17050
|
+
|
|
17051
|
+
.content {
|
|
17052
|
+
height: 100%;
|
|
17053
|
+
display: flex;
|
|
17054
|
+
flex-direction: column;
|
|
17055
|
+
gap: 20px;
|
|
17056
|
+
}
|
|
17057
|
+
|
|
17058
|
+
.image-placeholder {
|
|
17059
|
+
width: 100%;
|
|
17060
|
+
height: 100%;
|
|
17061
|
+
background: #f0f0f0;
|
|
17062
|
+
border-radius: 4px;
|
|
17063
|
+
position: relative;
|
|
17064
|
+
overflow: hidden;
|
|
17065
|
+
}
|
|
17066
|
+
|
|
17067
|
+
.lines-container {
|
|
17068
|
+
display: flex;
|
|
17069
|
+
flex-direction: column;
|
|
17070
|
+
justify-content: flex-end;
|
|
17071
|
+
}
|
|
17072
|
+
|
|
17073
|
+
.line {
|
|
17074
|
+
height: 20px;
|
|
17075
|
+
background: #f0f0f0;
|
|
17076
|
+
border-radius: 4px;
|
|
17077
|
+
margin-bottom: 15px;
|
|
17078
|
+
position: relative;
|
|
17079
|
+
overflow: hidden;
|
|
17080
|
+
}
|
|
17081
|
+
|
|
17082
|
+
.image-placeholder::after,
|
|
17083
|
+
.line::after {
|
|
17084
|
+
content: "";
|
|
17085
|
+
position: absolute;
|
|
17086
|
+
top: 0;
|
|
17087
|
+
left: 0;
|
|
17088
|
+
width: 100%;
|
|
17089
|
+
height: 100%;
|
|
17090
|
+
background: linear-gradient(
|
|
17091
|
+
90deg,
|
|
17092
|
+
rgba(255, 255, 255, 0) 0%,
|
|
17093
|
+
rgba(255, 255, 255, 0.5) 50%,
|
|
17094
|
+
rgba(255, 255, 255, 0) 100%
|
|
17095
|
+
);
|
|
17096
|
+
animation: shimmer 1.5s infinite;
|
|
17097
|
+
}
|
|
17098
|
+
|
|
17099
|
+
.line.header {
|
|
17100
|
+
width: 25%;
|
|
17101
|
+
}
|
|
17102
|
+
|
|
17103
|
+
.line.description {
|
|
17104
|
+
width: 65%;
|
|
17105
|
+
}
|
|
17106
|
+
|
|
17107
|
+
.line.button {
|
|
17108
|
+
width: 40%;
|
|
17109
|
+
}
|
|
17110
|
+
|
|
17111
|
+
@keyframes shimmer {
|
|
17112
|
+
0% {
|
|
17113
|
+
transform: translateX(-100%);
|
|
17114
|
+
}
|
|
17115
|
+
100% {
|
|
17116
|
+
transform: translateX(100%);
|
|
17117
|
+
}
|
|
17118
|
+
}
|
|
17119
|
+
</style>
|
|
17120
|
+
|
|
17121
|
+
<div class="content">
|
|
17122
|
+
<div class="image-placeholder"></div>
|
|
17123
|
+
<div class="lines-container">
|
|
17124
|
+
<div class="line header"></div>
|
|
17125
|
+
<div class="line description"></div>
|
|
17126
|
+
<div class="line button"></div>
|
|
17127
|
+
</div>
|
|
17128
|
+
</div>
|
|
17129
|
+
`;
|
|
17130
|
+
}
|
|
17131
|
+
|
|
17132
|
+
let SkeletonElement;
|
|
17133
|
+
if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined') {
|
|
17134
|
+
class CustomSkeletonElement extends HTMLElement {
|
|
17135
|
+
constructor() {
|
|
17136
|
+
super();
|
|
17137
|
+
this.attachShadow({ mode: 'open' });
|
|
17138
|
+
}
|
|
17139
|
+
connectedCallback() {
|
|
17140
|
+
if (!this.shadowRoot || !this.data)
|
|
17141
|
+
return;
|
|
17142
|
+
this.shadowRoot.innerHTML = SkeletonTemplate(this.data);
|
|
17143
|
+
}
|
|
17144
|
+
}
|
|
17145
|
+
SkeletonElement = CustomSkeletonElement;
|
|
17146
|
+
}
|
|
17147
|
+
|
|
16976
17148
|
let SpotElement;
|
|
16977
17149
|
if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined') {
|
|
16978
17150
|
class CustomSpotElement extends HTMLElement {
|
|
@@ -17080,15 +17252,14 @@ class ElementService {
|
|
|
17080
17252
|
* @return {HTMLElement | null} - The html element or null if the browser environment is not available.
|
|
17081
17253
|
*/
|
|
17082
17254
|
createSpotElement({ content, config }) {
|
|
17083
|
-
var _a
|
|
17255
|
+
var _a;
|
|
17084
17256
|
if (!this.ensureBrowserEnvironmentAndDefineElement()) {
|
|
17085
17257
|
return null;
|
|
17086
17258
|
}
|
|
17087
17259
|
const spot = document.createElement(SPOT_ELEMENT_TAG);
|
|
17088
|
-
spot.setAttribute('type', (_a = config === null || config === void 0 ? void 0 : config.spot) !== null && _a !== void 0 ? _a : '');
|
|
17089
17260
|
spot.data = {
|
|
17090
17261
|
spot: config === null || config === void 0 ? void 0 : config.spot,
|
|
17091
|
-
fluid: (
|
|
17262
|
+
fluid: (_a = config === null || config === void 0 ? void 0 : config.fluid) !== null && _a !== void 0 ? _a : false,
|
|
17092
17263
|
...config,
|
|
17093
17264
|
};
|
|
17094
17265
|
spot.content = content;
|
|
@@ -17116,6 +17287,27 @@ class ElementService {
|
|
|
17116
17287
|
carousel.slides = slides;
|
|
17117
17288
|
return carousel;
|
|
17118
17289
|
}
|
|
17290
|
+
/**
|
|
17291
|
+
* Creates the skeleton html element based on the provided data using shadow dom.
|
|
17292
|
+
*
|
|
17293
|
+
* This method is only available in browser environments.
|
|
17294
|
+
*
|
|
17295
|
+
* @param {ICreateSkeletonElementParams} params - The parameters to create the final element.
|
|
17296
|
+
*
|
|
17297
|
+
* @return {HTMLElement | null} - The html element or null if the browser environment is not available.
|
|
17298
|
+
*/
|
|
17299
|
+
createSkeletonElement(params) {
|
|
17300
|
+
if (!this.ensureBrowserEnvironmentAndDefineElement()) {
|
|
17301
|
+
return null;
|
|
17302
|
+
}
|
|
17303
|
+
const skeleton = document.createElement(SKELETON_ELEMENT_TAG);
|
|
17304
|
+
const dimensions = SPOT_DIMENSIONS[params.spotType];
|
|
17305
|
+
skeleton.data = {
|
|
17306
|
+
fluid: params.fluid,
|
|
17307
|
+
...dimensions,
|
|
17308
|
+
};
|
|
17309
|
+
return skeleton;
|
|
17310
|
+
}
|
|
17119
17311
|
/**
|
|
17120
17312
|
* Overrides the spot colors with the provided colors.
|
|
17121
17313
|
*
|
|
@@ -17150,6 +17342,9 @@ class ElementService {
|
|
|
17150
17342
|
if (!window.customElements.get(CAROUSEL_ELEMENT_TAG)) {
|
|
17151
17343
|
window.customElements.define(CAROUSEL_ELEMENT_TAG, CarouselElement);
|
|
17152
17344
|
}
|
|
17345
|
+
if (!window.customElements.get(SKELETON_ELEMENT_TAG)) {
|
|
17346
|
+
window.customElements.define(SKELETON_ELEMENT_TAG, SkeletonElement);
|
|
17347
|
+
}
|
|
17153
17348
|
return true;
|
|
17154
17349
|
}
|
|
17155
17350
|
}
|
|
@@ -18986,7 +19181,7 @@ class DataLayerMonitor {
|
|
|
18986
19181
|
if (!eventName) {
|
|
18987
19182
|
return null;
|
|
18988
19183
|
}
|
|
18989
|
-
const productIds = extractDeepIds(data
|
|
19184
|
+
const productIds = extractDeepIds(data);
|
|
18990
19185
|
return {
|
|
18991
19186
|
event: eventName,
|
|
18992
19187
|
productIds,
|
|
@@ -19295,6 +19490,7 @@ class LiquidCommerceRmnClient {
|
|
|
19295
19490
|
this.selectionService = SelectionService.getInstance(auth);
|
|
19296
19491
|
this.elementService = ElementService.getInstance();
|
|
19297
19492
|
this.eventService = EventService.getInstance();
|
|
19493
|
+
this.intersectionObserver = new IntersectionObserverService();
|
|
19298
19494
|
}
|
|
19299
19495
|
/**
|
|
19300
19496
|
* Makes a selection request on our server based on the provided data.
|
|
@@ -19318,24 +19514,29 @@ class LiquidCommerceRmnClient {
|
|
|
19318
19514
|
async injectSpotElement(params) {
|
|
19319
19515
|
var _a;
|
|
19320
19516
|
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
19321
|
-
console.warn('LiquidCommerce Rmn Sdk:
|
|
19517
|
+
console.warn('LiquidCommerce Rmn Sdk: injectSpotElement method is only available in the browser environment.');
|
|
19322
19518
|
return;
|
|
19323
19519
|
}
|
|
19324
19520
|
const config = params.config;
|
|
19325
19521
|
let inject = params.inject;
|
|
19522
|
+
// Handle no spots error state
|
|
19326
19523
|
if (!inject.length) {
|
|
19327
|
-
// Handle no spots error state
|
|
19328
19524
|
this.eventService.handleSpotState('all', {
|
|
19329
19525
|
state: {
|
|
19330
19526
|
error: 'No spot elements provided for injection.',
|
|
19331
|
-
loading: false,
|
|
19332
|
-
mounted: false,
|
|
19333
19527
|
},
|
|
19334
19528
|
});
|
|
19335
19529
|
return;
|
|
19336
19530
|
}
|
|
19337
|
-
//
|
|
19338
|
-
|
|
19531
|
+
// Identify the spot elements
|
|
19532
|
+
for (const item of inject) {
|
|
19533
|
+
this.eventService.handleSpotState(item.placementId, {
|
|
19534
|
+
identifier: {
|
|
19535
|
+
placementId: item.placementId,
|
|
19536
|
+
spotType: item.spotType,
|
|
19537
|
+
},
|
|
19538
|
+
}, false);
|
|
19539
|
+
}
|
|
19339
19540
|
// Prevent duplicate placement ids
|
|
19340
19541
|
const hasDuplicatePlacementIds = this.preventDuplicateSpotPlacementIds(inject);
|
|
19341
19542
|
if (!hasDuplicatePlacementIds) {
|
|
@@ -19343,35 +19544,9 @@ class LiquidCommerceRmnClient {
|
|
|
19343
19544
|
}
|
|
19344
19545
|
// Prevent non-existent spot types
|
|
19345
19546
|
inject = this.preventNonExistentSpotTypes(inject);
|
|
19346
|
-
//
|
|
19347
|
-
|
|
19348
|
-
// const response = await this.useSpotSelectionExample(inject);
|
|
19349
|
-
// Handle the response
|
|
19350
|
-
if (typeof response === 'object' && 'error' in response) {
|
|
19351
|
-
// Handle request error state
|
|
19352
|
-
this.eventService.handleSpotState('all', {
|
|
19353
|
-
state: {
|
|
19354
|
-
error: response.error,
|
|
19355
|
-
mounted: false,
|
|
19356
|
-
loading: false,
|
|
19357
|
-
},
|
|
19358
|
-
});
|
|
19359
|
-
return;
|
|
19360
|
-
}
|
|
19547
|
+
// Add Intersection Observer to the spot elements to track visibility
|
|
19548
|
+
// This is useful for lazy loading the spot elements
|
|
19361
19549
|
for (const item of inject) {
|
|
19362
|
-
const itemConfig = (_a = item.config) !== null && _a !== void 0 ? _a : config;
|
|
19363
|
-
const spots = response[item.placementId];
|
|
19364
|
-
if (!(spots === null || spots === void 0 ? void 0 : spots.length)) {
|
|
19365
|
-
// Handle no spots found error state
|
|
19366
|
-
this.eventService.handleSpotState(item.placementId, {
|
|
19367
|
-
state: {
|
|
19368
|
-
error: `No spots found for type "${item.spotType}".`,
|
|
19369
|
-
mounted: false,
|
|
19370
|
-
loading: false,
|
|
19371
|
-
},
|
|
19372
|
-
});
|
|
19373
|
-
continue;
|
|
19374
|
-
}
|
|
19375
19550
|
const placementId = item.placementId.replace('#', '');
|
|
19376
19551
|
const placement = document.getElementById(placementId);
|
|
19377
19552
|
if (!placement) {
|
|
@@ -19379,8 +19554,6 @@ class LiquidCommerceRmnClient {
|
|
|
19379
19554
|
this.eventService.handleSpotState(item.placementId, {
|
|
19380
19555
|
state: {
|
|
19381
19556
|
error: `Placement not found for id "${placementId}".`,
|
|
19382
|
-
mounted: false,
|
|
19383
|
-
loading: false,
|
|
19384
19557
|
},
|
|
19385
19558
|
});
|
|
19386
19559
|
continue;
|
|
@@ -19394,43 +19567,73 @@ class LiquidCommerceRmnClient {
|
|
|
19394
19567
|
display: 'flex',
|
|
19395
19568
|
justifyContent: 'center',
|
|
19396
19569
|
});
|
|
19397
|
-
|
|
19398
|
-
|
|
19399
|
-
|
|
19400
|
-
|
|
19401
|
-
|
|
19402
|
-
|
|
19570
|
+
const skeletonElement = this.elementService.createSkeletonElement({
|
|
19571
|
+
fluid: (_a = config === null || config === void 0 ? void 0 : config.fluid) !== null && _a !== void 0 ? _a : false,
|
|
19572
|
+
spotType: item.spotType,
|
|
19573
|
+
});
|
|
19574
|
+
if (!skeletonElement) {
|
|
19575
|
+
this.eventService.handleSpotState(item.placementId, {
|
|
19576
|
+
state: {
|
|
19577
|
+
error: `Failed to create skeleton loader element.`,
|
|
19578
|
+
mounted: false,
|
|
19579
|
+
loading: true,
|
|
19580
|
+
},
|
|
19581
|
+
});
|
|
19582
|
+
continue;
|
|
19403
19583
|
}
|
|
19404
|
-
|
|
19405
|
-
|
|
19406
|
-
|
|
19407
|
-
|
|
19408
|
-
|
|
19584
|
+
placement.replaceChildren(skeletonElement);
|
|
19585
|
+
const spotPlacementIsNear = async () => {
|
|
19586
|
+
var _a;
|
|
19587
|
+
// Set the spot element to loading state
|
|
19588
|
+
this.eventService.handleSpotState(item.placementId, {
|
|
19589
|
+
state: {
|
|
19590
|
+
loading: true,
|
|
19591
|
+
},
|
|
19592
|
+
});
|
|
19593
|
+
// Stop observing the placement
|
|
19594
|
+
this.intersectionObserver.unobserve(placement);
|
|
19595
|
+
// Make the spot selection request
|
|
19596
|
+
const response = await this.spotSelectionRequest({ ...params, inject: [item] });
|
|
19597
|
+
// const response = await this.useSpotSelectionExample(inject);
|
|
19598
|
+
// Handle request error state
|
|
19599
|
+
if (typeof response === 'object' && 'error' in response) {
|
|
19600
|
+
this.eventService.handleSpotState(item.placementId, {
|
|
19601
|
+
state: {
|
|
19602
|
+
error: response.error,
|
|
19603
|
+
mounted: false,
|
|
19604
|
+
loading: false,
|
|
19605
|
+
},
|
|
19606
|
+
});
|
|
19607
|
+
this.clearPlacement(item.placementId);
|
|
19608
|
+
return;
|
|
19409
19609
|
}
|
|
19410
|
-
|
|
19610
|
+
const itemConfig = (_a = item.config) !== null && _a !== void 0 ? _a : config;
|
|
19611
|
+
const spots = response[item.placementId];
|
|
19612
|
+
if (!(spots === null || spots === void 0 ? void 0 : spots.length)) {
|
|
19613
|
+
// Handle no spots found error state
|
|
19614
|
+
this.eventService.handleSpotState(item.placementId, {
|
|
19615
|
+
state: {
|
|
19616
|
+
error: `No spots found for type "${item.spotType}".`,
|
|
19617
|
+
mounted: false,
|
|
19618
|
+
loading: false,
|
|
19619
|
+
},
|
|
19620
|
+
});
|
|
19621
|
+
this.clearPlacement(item.placementId);
|
|
19622
|
+
return;
|
|
19623
|
+
}
|
|
19624
|
+
// Handle single spot
|
|
19625
|
+
if (spots.length === 1) {
|
|
19626
|
+
this.injectOneSpotElement(item, placement, spots[0], itemConfig);
|
|
19627
|
+
}
|
|
19628
|
+
// Handle multiple spots (carousel)
|
|
19629
|
+
if (spots.length > 1) {
|
|
19630
|
+
this.injectCarouselSpotElement(placement, spots, itemConfig);
|
|
19631
|
+
}
|
|
19632
|
+
};
|
|
19633
|
+
this.intersectionObserver.observe(placement, spotPlacementIsNear, { rootMargin: '500px' });
|
|
19411
19634
|
}
|
|
19412
19635
|
}
|
|
19413
|
-
/**
|
|
19414
|
-
* Makes a selection request on our server based on the provided data.
|
|
19415
|
-
*
|
|
19416
|
-
* @param {IInjectSpotElementParams} params - Parameters for injecting spot elements.
|
|
19417
|
-
*
|
|
19418
|
-
* @return {Promise<ISpots | {error: string}>} - The spots response object.
|
|
19419
|
-
*/
|
|
19420
|
-
async spotSelectionRequest(params) {
|
|
19421
|
-
const { inject, filter, config } = params;
|
|
19422
|
-
const request = {
|
|
19423
|
-
url: config === null || config === void 0 ? void 0 : config.url,
|
|
19424
|
-
filter,
|
|
19425
|
-
spots: inject.map((item) => ({
|
|
19426
|
-
placementId: item.placementId,
|
|
19427
|
-
spot: item.spotType,
|
|
19428
|
-
count: item === null || item === void 0 ? void 0 : item.count,
|
|
19429
|
-
...item === null || item === void 0 ? void 0 : item.filter,
|
|
19430
|
-
})),
|
|
19431
|
-
};
|
|
19432
|
-
return this.spotSelection(request);
|
|
19433
|
-
}
|
|
19636
|
+
/** ========================= HELPER METHODS ========================= **/
|
|
19434
19637
|
/**
|
|
19435
19638
|
* Injects a carousel element with the provided spots into the placement.
|
|
19436
19639
|
*
|
|
@@ -19499,7 +19702,8 @@ class LiquidCommerceRmnClient {
|
|
|
19499
19702
|
loading: false,
|
|
19500
19703
|
},
|
|
19501
19704
|
});
|
|
19502
|
-
|
|
19705
|
+
this.clearPlacement(placement.id);
|
|
19706
|
+
return;
|
|
19503
19707
|
}
|
|
19504
19708
|
placement.replaceChildren(carouselElement);
|
|
19505
19709
|
this.eventService.handleSpotState(placement.id, {
|
|
@@ -19513,7 +19717,6 @@ class LiquidCommerceRmnClient {
|
|
|
19513
19717
|
error: undefined,
|
|
19514
19718
|
},
|
|
19515
19719
|
});
|
|
19516
|
-
return true;
|
|
19517
19720
|
}
|
|
19518
19721
|
/**
|
|
19519
19722
|
* Injects a single spot element into the provided placement.
|
|
@@ -19549,7 +19752,8 @@ class LiquidCommerceRmnClient {
|
|
|
19549
19752
|
loading: false,
|
|
19550
19753
|
},
|
|
19551
19754
|
});
|
|
19552
|
-
|
|
19755
|
+
this.clearPlacement(injectItem.placementId);
|
|
19756
|
+
return;
|
|
19553
19757
|
}
|
|
19554
19758
|
// Create the spot element
|
|
19555
19759
|
const spotElement = this.elementService.createSpotElement({
|
|
@@ -19570,7 +19774,8 @@ class LiquidCommerceRmnClient {
|
|
|
19570
19774
|
loading: false,
|
|
19571
19775
|
},
|
|
19572
19776
|
});
|
|
19573
|
-
|
|
19777
|
+
this.clearPlacement(injectItem.placementId);
|
|
19778
|
+
return;
|
|
19574
19779
|
}
|
|
19575
19780
|
this.eventService.registerSpot({
|
|
19576
19781
|
spot: spotData,
|
|
@@ -19589,7 +19794,38 @@ class LiquidCommerceRmnClient {
|
|
|
19589
19794
|
error: undefined,
|
|
19590
19795
|
},
|
|
19591
19796
|
});
|
|
19592
|
-
|
|
19797
|
+
}
|
|
19798
|
+
/**
|
|
19799
|
+
* Clears the placement element by removing all its children.
|
|
19800
|
+
*
|
|
19801
|
+
* @param {string} placementId - The placement id.
|
|
19802
|
+
*
|
|
19803
|
+
* @return {void}
|
|
19804
|
+
*/
|
|
19805
|
+
clearPlacement(placementId) {
|
|
19806
|
+
var _a;
|
|
19807
|
+
(_a = document.getElementById(placementId)) === null || _a === void 0 ? void 0 : _a.replaceChildren();
|
|
19808
|
+
}
|
|
19809
|
+
/**
|
|
19810
|
+
* Makes a selection request on our server based on the provided data.
|
|
19811
|
+
*
|
|
19812
|
+
* @param {IInjectSpotElementParams} params - Parameters for injecting spot elements.
|
|
19813
|
+
*
|
|
19814
|
+
* @return {Promise<ISpots | {error: string}>} - The spots response object.
|
|
19815
|
+
*/
|
|
19816
|
+
async spotSelectionRequest(params) {
|
|
19817
|
+
const { inject, filter, config } = params;
|
|
19818
|
+
const request = {
|
|
19819
|
+
url: config === null || config === void 0 ? void 0 : config.url,
|
|
19820
|
+
filter,
|
|
19821
|
+
spots: inject.map((item) => ({
|
|
19822
|
+
placementId: item.placementId,
|
|
19823
|
+
spot: item.spotType,
|
|
19824
|
+
count: item === null || item === void 0 ? void 0 : item.count,
|
|
19825
|
+
...item === null || item === void 0 ? void 0 : item.filter,
|
|
19826
|
+
})),
|
|
19827
|
+
};
|
|
19828
|
+
return this.spotSelection(request);
|
|
19593
19829
|
}
|
|
19594
19830
|
/**
|
|
19595
19831
|
* Prevents duplicate placement ids in the inject data.
|
|
@@ -19607,8 +19843,6 @@ class LiquidCommerceRmnClient {
|
|
|
19607
19843
|
this.eventService.handleSpotState(item.placementId, {
|
|
19608
19844
|
state: {
|
|
19609
19845
|
error: `Duplicate placement id (${item.placementId}) found. Please provide a unique placement id for each spot element.`,
|
|
19610
|
-
mounted: false,
|
|
19611
|
-
loading: false,
|
|
19612
19846
|
},
|
|
19613
19847
|
});
|
|
19614
19848
|
return false;
|
|
@@ -19617,6 +19851,12 @@ class LiquidCommerceRmnClient {
|
|
|
19617
19851
|
}
|
|
19618
19852
|
return true;
|
|
19619
19853
|
}
|
|
19854
|
+
/**
|
|
19855
|
+
* Prevents non-existent spot types in the inject data.
|
|
19856
|
+
*
|
|
19857
|
+
* @param {IInjectSpotElement[]} inject - The inject data.
|
|
19858
|
+
* @return {IInjectSpotElement[]} - The filtered inject data.
|
|
19859
|
+
*/
|
|
19620
19860
|
preventNonExistentSpotTypes(inject) {
|
|
19621
19861
|
const newInject = [];
|
|
19622
19862
|
for (const item of inject) {
|
|
@@ -19624,8 +19864,6 @@ class LiquidCommerceRmnClient {
|
|
|
19624
19864
|
this.eventService.handleSpotState(item.placementId, {
|
|
19625
19865
|
state: {
|
|
19626
19866
|
error: `Invalid spot type (${item.spotType}) found. Please provide a valid spot type for each spot element.`,
|
|
19627
|
-
mounted: false,
|
|
19628
|
-
loading: false,
|
|
19629
19867
|
},
|
|
19630
19868
|
});
|
|
19631
19869
|
continue;
|
|
@@ -19634,22 +19872,7 @@ class LiquidCommerceRmnClient {
|
|
|
19634
19872
|
}
|
|
19635
19873
|
return newInject;
|
|
19636
19874
|
}
|
|
19637
|
-
//
|
|
19638
|
-
updateSpotsState(inject) {
|
|
19639
|
-
for (const item of inject) {
|
|
19640
|
-
this.eventService.handleSpotState(item.placementId, {
|
|
19641
|
-
identifier: {
|
|
19642
|
-
placementId: item.placementId,
|
|
19643
|
-
spotType: item.spotType,
|
|
19644
|
-
},
|
|
19645
|
-
state: {
|
|
19646
|
-
loading: true,
|
|
19647
|
-
mounted: false,
|
|
19648
|
-
error: undefined,
|
|
19649
|
-
},
|
|
19650
|
-
});
|
|
19651
|
-
}
|
|
19652
|
-
}
|
|
19875
|
+
// Use spot selection example data for private testing
|
|
19653
19876
|
useSpotSelectionExample(inject) {
|
|
19654
19877
|
const examples = { ...RB_SPOTS_SELECTION_EXAMPLE, ...IAB_SPOTS_SELECTION_EXAMPLE };
|
|
19655
19878
|
const data = {};
|