@liquidcommercedev/rmn-sdk 1.5.0-beta.20 → 1.5.0-beta.22

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.cjs CHANGED
@@ -19205,8 +19205,13 @@ class DataLayerMonitor {
19205
19205
  start() {
19206
19206
  window.dataLayer.push = (...args) => {
19207
19207
  const result = this.originalPush.apply(window.dataLayer, args);
19208
- const pushedEvent = args[0];
19209
- if (this.listener) {
19208
+ if (!this.listener) {
19209
+ return result;
19210
+ }
19211
+ if (!Array.isArray(args) || args.length === 0) {
19212
+ return result;
19213
+ }
19214
+ for (const pushedEvent of args) {
19210
19215
  const normalizedData = this.cleanEventData(pushedEvent);
19211
19216
  if (normalizedData) {
19212
19217
  this.listener(normalizedData);
@@ -20203,6 +20208,7 @@ function clearPlacement(placementId) {
20203
20208
  function prepareSpotPlacement(placement) {
20204
20209
  placement.removeAttribute('style');
20205
20210
  placement.removeAttribute('class');
20211
+ placement.setAttribute('data-spot-parent', 'true');
20206
20212
  const styles = {
20207
20213
  width: '100%',
20208
20214
  height: '100%',
@@ -20211,24 +20217,6 @@ function prepareSpotPlacement(placement) {
20211
20217
  };
20212
20218
  Object.assign(placement.style, styles);
20213
20219
  }
20214
- /**
20215
- * Waits for the DOM to be ready before continuing.
20216
- *
20217
- * @return {Promise<void>} - A promise that resolves when the DOM is ready.
20218
- */
20219
- async function waitForDOM() {
20220
- if (!isBrowserEnvironment()) {
20221
- return;
20222
- }
20223
- if (document.readyState === 'complete' || document.readyState === 'interactive') {
20224
- return;
20225
- }
20226
- return new Promise((resolve) => {
20227
- document.addEventListener('DOMContentLoaded', () => {
20228
- resolve();
20229
- });
20230
- });
20231
- }
20232
20220
  // Sets the id for the user who is browsing the website
20233
20221
  // This id is used to identify the user and provide personalized content
20234
20222
  function setUserId() {
@@ -20237,6 +20225,35 @@ function setUserId() {
20237
20225
  localStorageService.setUserId();
20238
20226
  }
20239
20227
  }
20228
+ function initDOMObserver(elementIds, callback) {
20229
+ const checkElement = (element) => {
20230
+ if (element.id &&
20231
+ elementIds.includes(element.id) &&
20232
+ !element.getAttribute('data-spot-parent')) {
20233
+ callback(element);
20234
+ }
20235
+ };
20236
+ const observer = new MutationObserver((mutations) => {
20237
+ mutations.forEach((mutation) => {
20238
+ if (mutation.type === 'childList') {
20239
+ mutation.addedNodes.forEach((node) => {
20240
+ if (node.nodeType === Node.ELEMENT_NODE) {
20241
+ checkElement(node);
20242
+ node
20243
+ .querySelectorAll('*')
20244
+ .forEach((el) => checkElement(el));
20245
+ }
20246
+ });
20247
+ }
20248
+ });
20249
+ });
20250
+ observer.observe(document.body, {
20251
+ childList: true,
20252
+ subtree: true,
20253
+ });
20254
+ document.querySelectorAll('*').forEach((el) => checkElement(el));
20255
+ return observer;
20256
+ }
20240
20257
 
20241
20258
  /**
20242
20259
  * LiquidCommerce Rmn Client
@@ -20270,9 +20287,6 @@ class LiquidCommerceRmnClient {
20270
20287
  * @return {Promise<void>} - A promise that resolves when the spot elements are injected.
20271
20288
  */
20272
20289
  async injectSpotElement(params) {
20273
- var _a;
20274
- // Wait for the DOM to be ready before continuing, to avoid issues with the spot placements
20275
- await waitForDOM();
20276
20290
  const config = params.config;
20277
20291
  // Handle no spots error state
20278
20292
  if (!params.inject.length) {
@@ -20285,41 +20299,42 @@ class LiquidCommerceRmnClient {
20285
20299
  }
20286
20300
  // Validate inject data
20287
20301
  const inject = validateInjectData(params.inject);
20288
- for (const item of inject) {
20289
- // Identify the spot element
20290
- this.eventService.handleSpotState(item.placementId, {
20291
- identifier: {
20292
- placementId: item.placementId,
20293
- spotType: item.spotType,
20294
- },
20295
- }, false);
20296
- const placement = document.getElementById(item.placementId);
20302
+ const placementElementShowedInDOM = (placement) => {
20303
+ var _a;
20304
+ const data = inject.find((item) => item.placementId === placement.id);
20297
20305
  // Handle placement not found error state
20298
- if (!placement) {
20299
- this.eventService.handleSpotState(item.placementId, {
20306
+ if (!data) {
20307
+ this.eventService.handleSpotState(placement.id, {
20300
20308
  state: {
20301
- error: `Placement not found for id "${item.placementId}".`,
20309
+ error: `Placement not found for id "${placement.id}".`,
20302
20310
  mounted: false,
20303
20311
  loading: false,
20304
20312
  },
20305
20313
  });
20306
- continue;
20314
+ return;
20307
20315
  }
20316
+ // Identify the spot element
20317
+ this.eventService.handleSpotState(data.placementId, {
20318
+ identifier: {
20319
+ placementId: data.placementId,
20320
+ spotType: data.spotType,
20321
+ },
20322
+ }, false);
20308
20323
  prepareSpotPlacement(placement);
20309
20324
  const skeletonElement = this.elementService.createSkeletonElement({
20310
20325
  fluid: (_a = config === null || config === void 0 ? void 0 : config.fluid) !== null && _a !== void 0 ? _a : false,
20311
- spotType: item.spotType,
20326
+ spotType: data.spotType,
20312
20327
  });
20313
20328
  // Handle skeleton loader error state
20314
20329
  if (!skeletonElement) {
20315
- this.eventService.handleSpotState(item.placementId, {
20330
+ this.eventService.handleSpotState(data.placementId, {
20316
20331
  state: {
20317
20332
  error: `Failed to create skeleton loader element.`,
20318
20333
  mounted: false,
20319
20334
  loading: true,
20320
20335
  },
20321
20336
  });
20322
- continue;
20337
+ return;
20323
20338
  }
20324
20339
  placement.replaceChildren(skeletonElement);
20325
20340
  const spotPlacementIsNearCallback = async () => {
@@ -20327,34 +20342,34 @@ class LiquidCommerceRmnClient {
20327
20342
  // Stop observing the placement, as we only need to do this once
20328
20343
  this.intersectionObserver.unobserve(placement);
20329
20344
  // Set the spot element to loading state
20330
- this.eventService.handleSpotState(item.placementId, { state: { loading: true } });
20345
+ this.eventService.handleSpotState(data.placementId, { state: { loading: true } });
20331
20346
  // Make the spot selection request
20332
- const response = await this.injectSpotSelectionRequest({ ...params, inject: [item] });
20347
+ const response = await this.injectSpotSelectionRequest({ ...params, inject: [data] });
20333
20348
  // const response = await useSpotSelectionExample(inject);
20334
20349
  // Handle request error state
20335
20350
  if (typeof response === 'object' && 'error' in response) {
20336
- this.eventService.handleSpotState(item.placementId, {
20351
+ this.eventService.handleSpotState(data.placementId, {
20337
20352
  state: {
20338
20353
  error: response.error,
20339
20354
  mounted: false,
20340
20355
  loading: false,
20341
20356
  },
20342
20357
  });
20343
- clearPlacement(item.placementId);
20358
+ clearPlacement(data.placementId);
20344
20359
  return;
20345
20360
  }
20346
- const itemConfig = (_a = item.config) !== null && _a !== void 0 ? _a : config;
20347
- const spots = response[item.placementId];
20361
+ const itemConfig = (_a = data.config) !== null && _a !== void 0 ? _a : config;
20362
+ const spots = response[data.placementId];
20348
20363
  // Handle no spots found error state
20349
20364
  if (!(spots === null || spots === void 0 ? void 0 : spots.length)) {
20350
- this.eventService.handleSpotState(item.placementId, {
20365
+ this.eventService.handleSpotState(data.placementId, {
20351
20366
  state: {
20352
- error: `No spots found for type "${item.spotType}".`,
20367
+ error: `No spots found for type "${data.spotType}".`,
20353
20368
  mounted: false,
20354
20369
  loading: false,
20355
20370
  },
20356
20371
  });
20357
- clearPlacement(item.placementId);
20372
+ clearPlacement(data.placementId);
20358
20373
  return;
20359
20374
  }
20360
20375
  // Handle single spot
@@ -20374,7 +20389,8 @@ class LiquidCommerceRmnClient {
20374
20389
  rootMargin: '1000px',
20375
20390
  threshold: 0,
20376
20391
  });
20377
- }
20392
+ };
20393
+ initDOMObserver(inject.map((item) => item.placementId), placementElementShowedInDOM);
20378
20394
  }
20379
20395
  /**
20380
20396
  * Injects a single spot element into the provided placement.
package/dist/index.esm.js CHANGED
@@ -19203,8 +19203,13 @@ class DataLayerMonitor {
19203
19203
  start() {
19204
19204
  window.dataLayer.push = (...args) => {
19205
19205
  const result = this.originalPush.apply(window.dataLayer, args);
19206
- const pushedEvent = args[0];
19207
- if (this.listener) {
19206
+ if (!this.listener) {
19207
+ return result;
19208
+ }
19209
+ if (!Array.isArray(args) || args.length === 0) {
19210
+ return result;
19211
+ }
19212
+ for (const pushedEvent of args) {
19208
19213
  const normalizedData = this.cleanEventData(pushedEvent);
19209
19214
  if (normalizedData) {
19210
19215
  this.listener(normalizedData);
@@ -20201,6 +20206,7 @@ function clearPlacement(placementId) {
20201
20206
  function prepareSpotPlacement(placement) {
20202
20207
  placement.removeAttribute('style');
20203
20208
  placement.removeAttribute('class');
20209
+ placement.setAttribute('data-spot-parent', 'true');
20204
20210
  const styles = {
20205
20211
  width: '100%',
20206
20212
  height: '100%',
@@ -20209,24 +20215,6 @@ function prepareSpotPlacement(placement) {
20209
20215
  };
20210
20216
  Object.assign(placement.style, styles);
20211
20217
  }
20212
- /**
20213
- * Waits for the DOM to be ready before continuing.
20214
- *
20215
- * @return {Promise<void>} - A promise that resolves when the DOM is ready.
20216
- */
20217
- async function waitForDOM() {
20218
- if (!isBrowserEnvironment()) {
20219
- return;
20220
- }
20221
- if (document.readyState === 'complete' || document.readyState === 'interactive') {
20222
- return;
20223
- }
20224
- return new Promise((resolve) => {
20225
- document.addEventListener('DOMContentLoaded', () => {
20226
- resolve();
20227
- });
20228
- });
20229
- }
20230
20218
  // Sets the id for the user who is browsing the website
20231
20219
  // This id is used to identify the user and provide personalized content
20232
20220
  function setUserId() {
@@ -20235,6 +20223,35 @@ function setUserId() {
20235
20223
  localStorageService.setUserId();
20236
20224
  }
20237
20225
  }
20226
+ function initDOMObserver(elementIds, callback) {
20227
+ const checkElement = (element) => {
20228
+ if (element.id &&
20229
+ elementIds.includes(element.id) &&
20230
+ !element.getAttribute('data-spot-parent')) {
20231
+ callback(element);
20232
+ }
20233
+ };
20234
+ const observer = new MutationObserver((mutations) => {
20235
+ mutations.forEach((mutation) => {
20236
+ if (mutation.type === 'childList') {
20237
+ mutation.addedNodes.forEach((node) => {
20238
+ if (node.nodeType === Node.ELEMENT_NODE) {
20239
+ checkElement(node);
20240
+ node
20241
+ .querySelectorAll('*')
20242
+ .forEach((el) => checkElement(el));
20243
+ }
20244
+ });
20245
+ }
20246
+ });
20247
+ });
20248
+ observer.observe(document.body, {
20249
+ childList: true,
20250
+ subtree: true,
20251
+ });
20252
+ document.querySelectorAll('*').forEach((el) => checkElement(el));
20253
+ return observer;
20254
+ }
20238
20255
 
20239
20256
  /**
20240
20257
  * LiquidCommerce Rmn Client
@@ -20268,9 +20285,6 @@ class LiquidCommerceRmnClient {
20268
20285
  * @return {Promise<void>} - A promise that resolves when the spot elements are injected.
20269
20286
  */
20270
20287
  async injectSpotElement(params) {
20271
- var _a;
20272
- // Wait for the DOM to be ready before continuing, to avoid issues with the spot placements
20273
- await waitForDOM();
20274
20288
  const config = params.config;
20275
20289
  // Handle no spots error state
20276
20290
  if (!params.inject.length) {
@@ -20283,41 +20297,42 @@ class LiquidCommerceRmnClient {
20283
20297
  }
20284
20298
  // Validate inject data
20285
20299
  const inject = validateInjectData(params.inject);
20286
- for (const item of inject) {
20287
- // Identify the spot element
20288
- this.eventService.handleSpotState(item.placementId, {
20289
- identifier: {
20290
- placementId: item.placementId,
20291
- spotType: item.spotType,
20292
- },
20293
- }, false);
20294
- const placement = document.getElementById(item.placementId);
20300
+ const placementElementShowedInDOM = (placement) => {
20301
+ var _a;
20302
+ const data = inject.find((item) => item.placementId === placement.id);
20295
20303
  // Handle placement not found error state
20296
- if (!placement) {
20297
- this.eventService.handleSpotState(item.placementId, {
20304
+ if (!data) {
20305
+ this.eventService.handleSpotState(placement.id, {
20298
20306
  state: {
20299
- error: `Placement not found for id "${item.placementId}".`,
20307
+ error: `Placement not found for id "${placement.id}".`,
20300
20308
  mounted: false,
20301
20309
  loading: false,
20302
20310
  },
20303
20311
  });
20304
- continue;
20312
+ return;
20305
20313
  }
20314
+ // Identify the spot element
20315
+ this.eventService.handleSpotState(data.placementId, {
20316
+ identifier: {
20317
+ placementId: data.placementId,
20318
+ spotType: data.spotType,
20319
+ },
20320
+ }, false);
20306
20321
  prepareSpotPlacement(placement);
20307
20322
  const skeletonElement = this.elementService.createSkeletonElement({
20308
20323
  fluid: (_a = config === null || config === void 0 ? void 0 : config.fluid) !== null && _a !== void 0 ? _a : false,
20309
- spotType: item.spotType,
20324
+ spotType: data.spotType,
20310
20325
  });
20311
20326
  // Handle skeleton loader error state
20312
20327
  if (!skeletonElement) {
20313
- this.eventService.handleSpotState(item.placementId, {
20328
+ this.eventService.handleSpotState(data.placementId, {
20314
20329
  state: {
20315
20330
  error: `Failed to create skeleton loader element.`,
20316
20331
  mounted: false,
20317
20332
  loading: true,
20318
20333
  },
20319
20334
  });
20320
- continue;
20335
+ return;
20321
20336
  }
20322
20337
  placement.replaceChildren(skeletonElement);
20323
20338
  const spotPlacementIsNearCallback = async () => {
@@ -20325,34 +20340,34 @@ class LiquidCommerceRmnClient {
20325
20340
  // Stop observing the placement, as we only need to do this once
20326
20341
  this.intersectionObserver.unobserve(placement);
20327
20342
  // Set the spot element to loading state
20328
- this.eventService.handleSpotState(item.placementId, { state: { loading: true } });
20343
+ this.eventService.handleSpotState(data.placementId, { state: { loading: true } });
20329
20344
  // Make the spot selection request
20330
- const response = await this.injectSpotSelectionRequest({ ...params, inject: [item] });
20345
+ const response = await this.injectSpotSelectionRequest({ ...params, inject: [data] });
20331
20346
  // const response = await useSpotSelectionExample(inject);
20332
20347
  // Handle request error state
20333
20348
  if (typeof response === 'object' && 'error' in response) {
20334
- this.eventService.handleSpotState(item.placementId, {
20349
+ this.eventService.handleSpotState(data.placementId, {
20335
20350
  state: {
20336
20351
  error: response.error,
20337
20352
  mounted: false,
20338
20353
  loading: false,
20339
20354
  },
20340
20355
  });
20341
- clearPlacement(item.placementId);
20356
+ clearPlacement(data.placementId);
20342
20357
  return;
20343
20358
  }
20344
- const itemConfig = (_a = item.config) !== null && _a !== void 0 ? _a : config;
20345
- const spots = response[item.placementId];
20359
+ const itemConfig = (_a = data.config) !== null && _a !== void 0 ? _a : config;
20360
+ const spots = response[data.placementId];
20346
20361
  // Handle no spots found error state
20347
20362
  if (!(spots === null || spots === void 0 ? void 0 : spots.length)) {
20348
- this.eventService.handleSpotState(item.placementId, {
20363
+ this.eventService.handleSpotState(data.placementId, {
20349
20364
  state: {
20350
- error: `No spots found for type "${item.spotType}".`,
20365
+ error: `No spots found for type "${data.spotType}".`,
20351
20366
  mounted: false,
20352
20367
  loading: false,
20353
20368
  },
20354
20369
  });
20355
- clearPlacement(item.placementId);
20370
+ clearPlacement(data.placementId);
20356
20371
  return;
20357
20372
  }
20358
20373
  // Handle single spot
@@ -20372,7 +20387,8 @@ class LiquidCommerceRmnClient {
20372
20387
  rootMargin: '1000px',
20373
20388
  threshold: 0,
20374
20389
  });
20375
- }
20390
+ };
20391
+ initDOMObserver(inject.map((item) => item.placementId), placementElementShowedInDOM);
20376
20392
  }
20377
20393
  /**
20378
20394
  * Injects a single spot element into the provided placement.
@@ -29,13 +29,8 @@ export declare function clearPlacement(placementId: string): void;
29
29
  * @return {void}
30
30
  */
31
31
  export declare function prepareSpotPlacement(placement: HTMLElement): void;
32
- /**
33
- * Waits for the DOM to be ready before continuing.
34
- *
35
- * @return {Promise<void>} - A promise that resolves when the DOM is ready.
36
- */
37
- export declare function waitForDOM(): Promise<void>;
38
32
  export declare function useSpotSelectionExample(inject: IInjectSpotElement[]): Promise<ISpots | {
39
33
  error: string;
40
34
  }>;
41
35
  export declare function setUserId(): void;
36
+ export declare function initDOMObserver(elementIds: string[], callback: (element: HTMLElement) => void): MutationObserver;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@liquidcommercedev/rmn-sdk",
3
3
  "description": "LiquidCommerce RMN SDK",
4
4
  "author": "LiquidCommerce Tech",
5
- "version": "1.5.0-beta.20",
5
+ "version": "1.5.0-beta.22",
6
6
  "homepage": "https://docs.liquidcommerce.co/rmn-sdk",
7
7
  "main": "./dist/index.cjs",
8
8
  "module": "./dist/index.esm.js",