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