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

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 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",