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

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
@@ -20203,6 +20203,7 @@ function clearPlacement(placementId) {
20203
20203
  function prepareSpotPlacement(placement) {
20204
20204
  placement.removeAttribute('style');
20205
20205
  placement.removeAttribute('class');
20206
+ placement.setAttribute('data-spot-parent', 'true');
20206
20207
  const styles = {
20207
20208
  width: '100%',
20208
20209
  height: '100%',
@@ -20211,24 +20212,6 @@ function prepareSpotPlacement(placement) {
20211
20212
  };
20212
20213
  Object.assign(placement.style, styles);
20213
20214
  }
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
20215
  // Sets the id for the user who is browsing the website
20233
20216
  // This id is used to identify the user and provide personalized content
20234
20217
  function setUserId() {
@@ -20237,6 +20220,35 @@ function setUserId() {
20237
20220
  localStorageService.setUserId();
20238
20221
  }
20239
20222
  }
20223
+ function initDOMObserver(elementIds, callback) {
20224
+ const checkElement = (element) => {
20225
+ if (element.id &&
20226
+ elementIds.includes(element.id) &&
20227
+ !element.getAttribute('data-spot-parent')) {
20228
+ callback(element);
20229
+ }
20230
+ };
20231
+ const observer = new MutationObserver((mutations) => {
20232
+ mutations.forEach((mutation) => {
20233
+ if (mutation.type === 'childList') {
20234
+ mutation.addedNodes.forEach((node) => {
20235
+ if (node.nodeType === Node.ELEMENT_NODE) {
20236
+ checkElement(node);
20237
+ node
20238
+ .querySelectorAll('*')
20239
+ .forEach((el) => checkElement(el));
20240
+ }
20241
+ });
20242
+ }
20243
+ });
20244
+ });
20245
+ observer.observe(document.body, {
20246
+ childList: true,
20247
+ subtree: true,
20248
+ });
20249
+ document.querySelectorAll('*').forEach((el) => checkElement(el));
20250
+ return observer;
20251
+ }
20240
20252
 
20241
20253
  /**
20242
20254
  * LiquidCommerce Rmn Client
@@ -20270,9 +20282,6 @@ class LiquidCommerceRmnClient {
20270
20282
  * @return {Promise<void>} - A promise that resolves when the spot elements are injected.
20271
20283
  */
20272
20284
  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
20285
  const config = params.config;
20277
20286
  // Handle no spots error state
20278
20287
  if (!params.inject.length) {
@@ -20285,41 +20294,42 @@ class LiquidCommerceRmnClient {
20285
20294
  }
20286
20295
  // Validate inject data
20287
20296
  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);
20297
+ const placementElementShowedInDOM = (placement) => {
20298
+ var _a;
20299
+ const data = inject.find((item) => item.placementId === placement.id);
20297
20300
  // Handle placement not found error state
20298
- if (!placement) {
20299
- this.eventService.handleSpotState(item.placementId, {
20301
+ if (!data) {
20302
+ this.eventService.handleSpotState(placement.id, {
20300
20303
  state: {
20301
- error: `Placement not found for id "${item.placementId}".`,
20304
+ error: `Placement not found for id "${placement.id}".`,
20302
20305
  mounted: false,
20303
20306
  loading: false,
20304
20307
  },
20305
20308
  });
20306
- continue;
20309
+ return;
20307
20310
  }
20311
+ // Identify the spot element
20312
+ this.eventService.handleSpotState(data.placementId, {
20313
+ identifier: {
20314
+ placementId: data.placementId,
20315
+ spotType: data.spotType,
20316
+ },
20317
+ }, false);
20308
20318
  prepareSpotPlacement(placement);
20309
20319
  const skeletonElement = this.elementService.createSkeletonElement({
20310
20320
  fluid: (_a = config === null || config === void 0 ? void 0 : config.fluid) !== null && _a !== void 0 ? _a : false,
20311
- spotType: item.spotType,
20321
+ spotType: data.spotType,
20312
20322
  });
20313
20323
  // Handle skeleton loader error state
20314
20324
  if (!skeletonElement) {
20315
- this.eventService.handleSpotState(item.placementId, {
20325
+ this.eventService.handleSpotState(data.placementId, {
20316
20326
  state: {
20317
20327
  error: `Failed to create skeleton loader element.`,
20318
20328
  mounted: false,
20319
20329
  loading: true,
20320
20330
  },
20321
20331
  });
20322
- continue;
20332
+ return;
20323
20333
  }
20324
20334
  placement.replaceChildren(skeletonElement);
20325
20335
  const spotPlacementIsNearCallback = async () => {
@@ -20327,34 +20337,34 @@ class LiquidCommerceRmnClient {
20327
20337
  // Stop observing the placement, as we only need to do this once
20328
20338
  this.intersectionObserver.unobserve(placement);
20329
20339
  // Set the spot element to loading state
20330
- this.eventService.handleSpotState(item.placementId, { state: { loading: true } });
20340
+ this.eventService.handleSpotState(data.placementId, { state: { loading: true } });
20331
20341
  // Make the spot selection request
20332
- const response = await this.injectSpotSelectionRequest({ ...params, inject: [item] });
20342
+ const response = await this.injectSpotSelectionRequest({ ...params, inject: [data] });
20333
20343
  // const response = await useSpotSelectionExample(inject);
20334
20344
  // Handle request error state
20335
20345
  if (typeof response === 'object' && 'error' in response) {
20336
- this.eventService.handleSpotState(item.placementId, {
20346
+ this.eventService.handleSpotState(data.placementId, {
20337
20347
  state: {
20338
20348
  error: response.error,
20339
20349
  mounted: false,
20340
20350
  loading: false,
20341
20351
  },
20342
20352
  });
20343
- clearPlacement(item.placementId);
20353
+ clearPlacement(data.placementId);
20344
20354
  return;
20345
20355
  }
20346
- const itemConfig = (_a = item.config) !== null && _a !== void 0 ? _a : config;
20347
- const spots = response[item.placementId];
20356
+ const itemConfig = (_a = data.config) !== null && _a !== void 0 ? _a : config;
20357
+ const spots = response[data.placementId];
20348
20358
  // Handle no spots found error state
20349
20359
  if (!(spots === null || spots === void 0 ? void 0 : spots.length)) {
20350
- this.eventService.handleSpotState(item.placementId, {
20360
+ this.eventService.handleSpotState(data.placementId, {
20351
20361
  state: {
20352
- error: `No spots found for type "${item.spotType}".`,
20362
+ error: `No spots found for type "${data.spotType}".`,
20353
20363
  mounted: false,
20354
20364
  loading: false,
20355
20365
  },
20356
20366
  });
20357
- clearPlacement(item.placementId);
20367
+ clearPlacement(data.placementId);
20358
20368
  return;
20359
20369
  }
20360
20370
  // Handle single spot
@@ -20374,7 +20384,8 @@ class LiquidCommerceRmnClient {
20374
20384
  rootMargin: '1000px',
20375
20385
  threshold: 0,
20376
20386
  });
20377
- }
20387
+ };
20388
+ initDOMObserver(inject.map((item) => item.placementId), placementElementShowedInDOM);
20378
20389
  }
20379
20390
  /**
20380
20391
  * Injects a single spot element into the provided placement.
package/dist/index.esm.js CHANGED
@@ -20201,6 +20201,7 @@ function clearPlacement(placementId) {
20201
20201
  function prepareSpotPlacement(placement) {
20202
20202
  placement.removeAttribute('style');
20203
20203
  placement.removeAttribute('class');
20204
+ placement.setAttribute('data-spot-parent', 'true');
20204
20205
  const styles = {
20205
20206
  width: '100%',
20206
20207
  height: '100%',
@@ -20209,24 +20210,6 @@ function prepareSpotPlacement(placement) {
20209
20210
  };
20210
20211
  Object.assign(placement.style, styles);
20211
20212
  }
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
20213
  // Sets the id for the user who is browsing the website
20231
20214
  // This id is used to identify the user and provide personalized content
20232
20215
  function setUserId() {
@@ -20235,6 +20218,35 @@ function setUserId() {
20235
20218
  localStorageService.setUserId();
20236
20219
  }
20237
20220
  }
20221
+ function initDOMObserver(elementIds, callback) {
20222
+ const checkElement = (element) => {
20223
+ if (element.id &&
20224
+ elementIds.includes(element.id) &&
20225
+ !element.getAttribute('data-spot-parent')) {
20226
+ callback(element);
20227
+ }
20228
+ };
20229
+ const observer = new MutationObserver((mutations) => {
20230
+ mutations.forEach((mutation) => {
20231
+ if (mutation.type === 'childList') {
20232
+ mutation.addedNodes.forEach((node) => {
20233
+ if (node.nodeType === Node.ELEMENT_NODE) {
20234
+ checkElement(node);
20235
+ node
20236
+ .querySelectorAll('*')
20237
+ .forEach((el) => checkElement(el));
20238
+ }
20239
+ });
20240
+ }
20241
+ });
20242
+ });
20243
+ observer.observe(document.body, {
20244
+ childList: true,
20245
+ subtree: true,
20246
+ });
20247
+ document.querySelectorAll('*').forEach((el) => checkElement(el));
20248
+ return observer;
20249
+ }
20238
20250
 
20239
20251
  /**
20240
20252
  * LiquidCommerce Rmn Client
@@ -20268,9 +20280,6 @@ class LiquidCommerceRmnClient {
20268
20280
  * @return {Promise<void>} - A promise that resolves when the spot elements are injected.
20269
20281
  */
20270
20282
  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
20283
  const config = params.config;
20275
20284
  // Handle no spots error state
20276
20285
  if (!params.inject.length) {
@@ -20283,41 +20292,42 @@ class LiquidCommerceRmnClient {
20283
20292
  }
20284
20293
  // Validate inject data
20285
20294
  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);
20295
+ const placementElementShowedInDOM = (placement) => {
20296
+ var _a;
20297
+ const data = inject.find((item) => item.placementId === placement.id);
20295
20298
  // Handle placement not found error state
20296
- if (!placement) {
20297
- this.eventService.handleSpotState(item.placementId, {
20299
+ if (!data) {
20300
+ this.eventService.handleSpotState(placement.id, {
20298
20301
  state: {
20299
- error: `Placement not found for id "${item.placementId}".`,
20302
+ error: `Placement not found for id "${placement.id}".`,
20300
20303
  mounted: false,
20301
20304
  loading: false,
20302
20305
  },
20303
20306
  });
20304
- continue;
20307
+ return;
20305
20308
  }
20309
+ // Identify the spot element
20310
+ this.eventService.handleSpotState(data.placementId, {
20311
+ identifier: {
20312
+ placementId: data.placementId,
20313
+ spotType: data.spotType,
20314
+ },
20315
+ }, false);
20306
20316
  prepareSpotPlacement(placement);
20307
20317
  const skeletonElement = this.elementService.createSkeletonElement({
20308
20318
  fluid: (_a = config === null || config === void 0 ? void 0 : config.fluid) !== null && _a !== void 0 ? _a : false,
20309
- spotType: item.spotType,
20319
+ spotType: data.spotType,
20310
20320
  });
20311
20321
  // Handle skeleton loader error state
20312
20322
  if (!skeletonElement) {
20313
- this.eventService.handleSpotState(item.placementId, {
20323
+ this.eventService.handleSpotState(data.placementId, {
20314
20324
  state: {
20315
20325
  error: `Failed to create skeleton loader element.`,
20316
20326
  mounted: false,
20317
20327
  loading: true,
20318
20328
  },
20319
20329
  });
20320
- continue;
20330
+ return;
20321
20331
  }
20322
20332
  placement.replaceChildren(skeletonElement);
20323
20333
  const spotPlacementIsNearCallback = async () => {
@@ -20325,34 +20335,34 @@ class LiquidCommerceRmnClient {
20325
20335
  // Stop observing the placement, as we only need to do this once
20326
20336
  this.intersectionObserver.unobserve(placement);
20327
20337
  // Set the spot element to loading state
20328
- this.eventService.handleSpotState(item.placementId, { state: { loading: true } });
20338
+ this.eventService.handleSpotState(data.placementId, { state: { loading: true } });
20329
20339
  // Make the spot selection request
20330
- const response = await this.injectSpotSelectionRequest({ ...params, inject: [item] });
20340
+ const response = await this.injectSpotSelectionRequest({ ...params, inject: [data] });
20331
20341
  // const response = await useSpotSelectionExample(inject);
20332
20342
  // Handle request error state
20333
20343
  if (typeof response === 'object' && 'error' in response) {
20334
- this.eventService.handleSpotState(item.placementId, {
20344
+ this.eventService.handleSpotState(data.placementId, {
20335
20345
  state: {
20336
20346
  error: response.error,
20337
20347
  mounted: false,
20338
20348
  loading: false,
20339
20349
  },
20340
20350
  });
20341
- clearPlacement(item.placementId);
20351
+ clearPlacement(data.placementId);
20342
20352
  return;
20343
20353
  }
20344
- const itemConfig = (_a = item.config) !== null && _a !== void 0 ? _a : config;
20345
- const spots = response[item.placementId];
20354
+ const itemConfig = (_a = data.config) !== null && _a !== void 0 ? _a : config;
20355
+ const spots = response[data.placementId];
20346
20356
  // Handle no spots found error state
20347
20357
  if (!(spots === null || spots === void 0 ? void 0 : spots.length)) {
20348
- this.eventService.handleSpotState(item.placementId, {
20358
+ this.eventService.handleSpotState(data.placementId, {
20349
20359
  state: {
20350
- error: `No spots found for type "${item.spotType}".`,
20360
+ error: `No spots found for type "${data.spotType}".`,
20351
20361
  mounted: false,
20352
20362
  loading: false,
20353
20363
  },
20354
20364
  });
20355
- clearPlacement(item.placementId);
20365
+ clearPlacement(data.placementId);
20356
20366
  return;
20357
20367
  }
20358
20368
  // Handle single spot
@@ -20372,7 +20382,8 @@ class LiquidCommerceRmnClient {
20372
20382
  rootMargin: '1000px',
20373
20383
  threshold: 0,
20374
20384
  });
20375
- }
20385
+ };
20386
+ initDOMObserver(inject.map((item) => item.placementId), placementElementShowedInDOM);
20376
20387
  }
20377
20388
  /**
20378
20389
  * 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.21",
6
6
  "homepage": "https://docs.liquidcommerce.co/rmn-sdk",
7
7
  "main": "./dist/index.cjs",
8
8
  "module": "./dist/index.esm.js",