@liquidcommercedev/rmn-sdk 1.4.6-beta.3 → 1.4.6-beta.5

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.esm.js CHANGED
@@ -42,6 +42,7 @@ var RMN_SPOT_TYPE;
42
42
  var RMN_FILTER_PROPERTIES;
43
43
  (function (RMN_FILTER_PROPERTIES) {
44
44
  RMN_FILTER_PROPERTIES["KEYWORDS"] = "keywords";
45
+ RMN_FILTER_PROPERTIES["PAGE_LOCATION"] = "pageLocation";
45
46
  RMN_FILTER_PROPERTIES["PARENTCO"] = "parentCo";
46
47
  RMN_FILTER_PROPERTIES["BRAND"] = "brand";
47
48
  RMN_FILTER_PROPERTIES["CATEGORY"] = "category";
@@ -53,6 +54,9 @@ var RMN_FILTER_PROPERTIES;
53
54
  })(RMN_FILTER_PROPERTIES || (RMN_FILTER_PROPERTIES = {}));
54
55
  var RMN_SPOT_EVENT;
55
56
  (function (RMN_SPOT_EVENT) {
57
+ RMN_SPOT_EVENT["MOUNTED"] = "MOUNTED";
58
+ RMN_SPOT_EVENT["UNMOUNTED"] = "UNMOUNTED";
59
+ RMN_SPOT_EVENT["RESIZED"] = "RESIZED";
56
60
  RMN_SPOT_EVENT["IMPRESSION"] = "IMPRESSION";
57
61
  RMN_SPOT_EVENT["CLICK"] = "CLICK";
58
62
  RMN_SPOT_EVENT["PURCHASE"] = "PURCHASE";
@@ -15161,6 +15165,46 @@ const GFONT_CORMORANT = `
15161
15165
  <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">
15162
15166
  `;
15163
15167
 
15168
+ class IntersectionObserverService {
15169
+ constructor(defaultOptions = {}) {
15170
+ this.observers = new Map();
15171
+ this.defaultOptions = {
15172
+ root: null,
15173
+ rootMargin: '0px',
15174
+ threshold: 0.5,
15175
+ ...defaultOptions,
15176
+ };
15177
+ }
15178
+ observe(element, callback, options = {}) {
15179
+ const mergedOptions = { ...this.defaultOptions, ...options };
15180
+ const ioCallback = (entries) => {
15181
+ entries.forEach((entry) => {
15182
+ if (entry.isIntersecting) {
15183
+ callback(entry);
15184
+ }
15185
+ });
15186
+ };
15187
+ const observer = new IntersectionObserver(ioCallback, mergedOptions);
15188
+ this.observers.set(element, observer);
15189
+ observer.observe(element);
15190
+ }
15191
+ unobserve(element) {
15192
+ const observer = this.observers.get(element);
15193
+ if (observer) {
15194
+ observer.unobserve(element);
15195
+ observer.disconnect();
15196
+ this.observers.delete(element);
15197
+ }
15198
+ }
15199
+ unobserveAll() {
15200
+ this.observers.forEach((observer, element) => {
15201
+ observer.unobserve(element);
15202
+ observer.disconnect();
15203
+ });
15204
+ this.observers.clear();
15205
+ }
15206
+ }
15207
+
15164
15208
  class ResizeObserverService {
15165
15209
  constructor({ element, maxSize, minScale }) {
15166
15210
  this.element = element;
@@ -15466,8 +15510,9 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
15466
15510
  this.addEventListener('spotSizeChanged', this.handleCarouselSizeChanged.bind(this));
15467
15511
  }
15468
15512
  }
15469
- handleCarouselSizeChanged(event) {
15470
- console.info('Carousel Size Changed', event);
15513
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
15514
+ handleCarouselSizeChanged(_event) {
15515
+ // console.info('Carousel Size Changed', event);
15471
15516
  }
15472
15517
  render() {
15473
15518
  var _a;
@@ -15693,7 +15738,7 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
15693
15738
  * #########################################################
15694
15739
  */
15695
15740
  handleSpotSizeChanged(event) {
15696
- console.info('Spot Size Changed', event);
15741
+ // console.info('Spot Size Changed', event);
15697
15742
  // Adjust text elements font size based on the scale factor
15698
15743
  this.adjustFontSize(event.detail.scale);
15699
15744
  }
@@ -15705,8 +15750,8 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
15705
15750
  elements === null || elements === void 0 ? void 0 : elements.forEach((element) => {
15706
15751
  if (element instanceof HTMLElement) {
15707
15752
  if (!this.originalFontSizes.has(element)) {
15708
- const orignalSize = parseFloat(window.getComputedStyle(element).fontSize);
15709
- this.originalFontSizes.set(element, orignalSize);
15753
+ const originalSize = parseFloat(window.getComputedStyle(element).fontSize);
15754
+ this.originalFontSizes.set(element, originalSize);
15710
15755
  }
15711
15756
  const originalSize = this.originalFontSizes.get(element);
15712
15757
  const newFontSize = originalSize * scaleFactor;
@@ -17537,11 +17582,12 @@ function rbSmallDiscoverToutTemplate(spot, config) {
17537
17582
  }
17538
17583
 
17539
17584
  /**
17540
- * Creates the spot html string based on the provided spot data.
17585
+ * Returns the HTML element for the given spot.
17541
17586
  *
17542
- * @param {ISpot} spot - The spot data.
17587
+ * @param {ISpot} spot - The spot object.
17588
+ * @param {ISpotTemplateConfig} config - The spot template configuration.
17543
17589
  *
17544
- * @return {string} - The spot html string.
17590
+ * @return {HTMLElement | null} - The HTML element for the given spot or null if the spot template is not found.
17545
17591
  */
17546
17592
  const SPOT_TEMPLATE_HTML_ELEMENT = (spot, config) => {
17547
17593
  const templates = {
@@ -17614,6 +17660,228 @@ const SPOT_TEMPLATE_HTML_ELEMENT = (spot, config) => {
17614
17660
  return spotHtmlStringToElement(spotHtmlString);
17615
17661
  };
17616
17662
 
17663
+ /**
17664
+ * PubSub class
17665
+ * Manages event subscriptions and publications
17666
+ * @template IEventMap A record type defining the structure of events and their data
17667
+ */
17668
+ class PubSub {
17669
+ constructor() {
17670
+ /**
17671
+ * Object to store subscribers for each event type
17672
+ */
17673
+ this.subscribers = {};
17674
+ }
17675
+ /**
17676
+ * Subscribe to an event
17677
+ * @param eventType - The type of event to subscribe to
17678
+ * @param callback - The function to be called when the event is published
17679
+ * @returns A function to unsubscribe from the event
17680
+ *
17681
+ * @Example:
17682
+ * const unsubscribe = pubSub.subscribe('userLogin', (data) => {
17683
+ * console.log(`User ${data.username} logged in`);
17684
+ * });
17685
+ */
17686
+ subscribe(eventType, callback) {
17687
+ if (!this.subscribers[eventType]) {
17688
+ this.subscribers[eventType] = [];
17689
+ }
17690
+ this.subscribers[eventType].push(callback);
17691
+ // Return an unsubscribe function
17692
+ return () => {
17693
+ this.subscribers[eventType] = this.subscribers[eventType].filter((cb) => cb !== callback);
17694
+ };
17695
+ }
17696
+ /**
17697
+ * Publish an event
17698
+ * @param eventType - The type of event to publish
17699
+ * @param data - The data to be passed to the event subscribers
17700
+ *
17701
+ * @Example:
17702
+ * pubSub.publish('userLogin', { username: 'john_doe', timestamp: Date.now() });
17703
+ */
17704
+ publish(eventType, data) {
17705
+ if (!this.subscribers[eventType]) {
17706
+ return;
17707
+ }
17708
+ this.subscribers[eventType].forEach((callback) => callback(data));
17709
+ }
17710
+ }
17711
+ /**
17712
+ * Usage Example:
17713
+ *
17714
+ * interface IEventMap {
17715
+ * userLogin: { username: string; timestamp: number };
17716
+ * pageView: { url: string; timestamp: number };
17717
+ * }
17718
+ *
17719
+ * const pubSub = new PubSub<IEventMap>();
17720
+ *
17721
+ * // Subscribe to events
17722
+ * const unsubscribeLogin = pubSub.subscribe('userLogin', (data) => {
17723
+ * console.log(`User ${data.username} logged in at ${new Date(data.timestamp)}`);
17724
+ * });
17725
+ *
17726
+ * pubSub.subscribe('pageView', (data) => {
17727
+ * console.log(`Page ${data.url} viewed at ${new Date(data.timestamp)}`);
17728
+ * });
17729
+ *
17730
+ * // Publish events
17731
+ * pubSub.publish('userLogin', { username: 'john_doe', timestamp: Date.now() });
17732
+ * pubSub.publish('pageView', { url: '/home', timestamp: Date.now() });
17733
+ *
17734
+ * // Unsubscribe from an event
17735
+ * unsubscribeLogin();
17736
+ */
17737
+
17738
+ class EventService {
17739
+ constructor() {
17740
+ this.pubSub = new PubSub();
17741
+ this.activeSpots = new Map();
17742
+ this.intersectionObserver = new IntersectionObserverService();
17743
+ }
17744
+ static getInstance() {
17745
+ if (!EventService.instance) {
17746
+ EventService.instance = new EventService();
17747
+ }
17748
+ return EventService.instance;
17749
+ }
17750
+ registerSpot({ placementId, element, spot }) {
17751
+ this.activeSpots.set(spot.id, {
17752
+ placementId,
17753
+ element,
17754
+ impressionTracked: false,
17755
+ });
17756
+ // Handle resize observer
17757
+ // this.handleResizeObserver(placementId, spot, element);
17758
+ // Handle intersection observer
17759
+ this.handleIntersectionObserver(placementId, spot, element);
17760
+ // Attach click event listener
17761
+ element.addEventListener('click', async () => {
17762
+ var _a, _b;
17763
+ this.pubSub.publish(RMN_SPOT_EVENT.CLICK, {
17764
+ placementId,
17765
+ spotId: spot.id,
17766
+ element,
17767
+ });
17768
+ // Fire click event
17769
+ await this.fireEvent({
17770
+ event: RMN_SPOT_EVENT.CLICK,
17771
+ eventUrl: (_b = (_a = spot.events.find((event) => event.event === RMN_SPOT_EVENT.CLICK)) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : '',
17772
+ });
17773
+ });
17774
+ // Publish spot created event
17775
+ this.pubSub.publish(RMN_SPOT_EVENT.MOUNTED, {
17776
+ placementId,
17777
+ spotId: spot.id,
17778
+ spotType: spot.spot,
17779
+ spotVariant: spot.variant,
17780
+ element,
17781
+ });
17782
+ }
17783
+ unregisterSpot(spotId) {
17784
+ const spotData = this.activeSpots.get(spotId);
17785
+ if (spotData) {
17786
+ this.intersectionObserver.unobserve(spotData.element);
17787
+ // this.resizeObserver?.disconnect();
17788
+ this.pubSub.publish(RMN_SPOT_EVENT.UNMOUNTED, {
17789
+ placementId: spotData.placementId,
17790
+ spotId,
17791
+ });
17792
+ this.activeSpots.delete(spotId);
17793
+ }
17794
+ }
17795
+ // private handleResizeObserver(placementId: string, spot: ISpot, element: HTMLElement): void {
17796
+ // // this.resizeObserver = new ResizeObserverService({
17797
+ // // element,
17798
+ // // maxSize: {
17799
+ // // width: spot.width,
17800
+ // // height: spot.height,
17801
+ // // },
17802
+ // // minScale: 0.25,
17803
+ // // });
17804
+ //
17805
+ // const sizeChangedCb = (event: ISizeChangedEvent) => {
17806
+ // // Publish spot resized event
17807
+ // this.pubSub.publish(RMN_SPOT_EVENT.RESIZED, {
17808
+ // placementId,
17809
+ // spotId: spot.id,
17810
+ // scale: event.detail.scale,
17811
+ // previousDimensions: {
17812
+ // width: event.detail.width,
17813
+ // height: event.detail.height,
17814
+ // },
17815
+ // currentDimensions: {
17816
+ // width: event.detail.newWidth,
17817
+ // height: event.detail.newHeight,
17818
+ // },
17819
+ // });
17820
+ // };
17821
+ //
17822
+ // element.addEventListener('spotSizeChanged', sizeChangedCb as EventListener);
17823
+ // }
17824
+ handleIntersectionObserver(placementId, spot, element) {
17825
+ const spotIsVisibleCb = async () => {
17826
+ var _a, _b;
17827
+ this.pubSub.publish(RMN_SPOT_EVENT.IMPRESSION, {
17828
+ placementId,
17829
+ spotId: spot.id,
17830
+ element,
17831
+ });
17832
+ this.intersectionObserver.unobserve(element);
17833
+ this.activeSpots.set(spot.id, {
17834
+ placementId,
17835
+ element,
17836
+ impressionTracked: true,
17837
+ });
17838
+ // Fire impression event
17839
+ await this.fireEvent({
17840
+ event: RMN_SPOT_EVENT.IMPRESSION,
17841
+ eventUrl: (_b = (_a = spot.events.find((event) => event.event === RMN_SPOT_EVENT.IMPRESSION)) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : '',
17842
+ });
17843
+ };
17844
+ this.intersectionObserver.observe(element, spotIsVisibleCb);
17845
+ }
17846
+ subscribe(eventType, callback) {
17847
+ return this.pubSub.subscribe(eventType, callback);
17848
+ }
17849
+ publish(eventType, data) {
17850
+ this.pubSub.publish(eventType, data);
17851
+ }
17852
+ /**
17853
+ * Fires an event using the navigator.sendBeacon method and redirects the user if the event is a click event.
17854
+ *
17855
+ * @param {IFireEventParams} params - The parameters for firing the event.
17856
+ * @param {RMN_SPOT_EVENT} params.event - The event type.
17857
+ * @param {string} params.eventUrl - The URL to which the event is sent.
17858
+ * @returns {Promise<void>} - A promise that resolves when the event is fired.
17859
+ */
17860
+ async fireEvent({ event, eventUrl }) {
17861
+ const didFireEvent = navigator.sendBeacon(eventUrl);
17862
+ if (didFireEvent && event === RMN_SPOT_EVENT.CLICK) {
17863
+ window.location.href = this.getRedirectUrlFromPayload(eventUrl);
17864
+ }
17865
+ }
17866
+ /**
17867
+ * Extracts and decodes a URL from a base64-encoded query parameter.
17868
+ *
17869
+ * @param {string} url - The URL containing the base64-encoded query parameter.
17870
+ * @returns {string} - The decoded URL or an empty string if decoding fails.
17871
+ */
17872
+ getRedirectUrlFromPayload(url) {
17873
+ var _a, _b;
17874
+ const base64String = (_a = new URL(url).searchParams.get('e')) !== null && _a !== void 0 ? _a : '';
17875
+ try {
17876
+ const data = JSON.parse(atob(base64String));
17877
+ return (_b = data.ur) !== null && _b !== void 0 ? _b : '';
17878
+ }
17879
+ catch (_c) {
17880
+ return '';
17881
+ }
17882
+ }
17883
+ }
17884
+
17617
17885
  const SELECTION_API_PATH = '/spots/selection';
17618
17886
 
17619
17887
  class SelectionService extends BaseApi {
@@ -17648,46 +17916,39 @@ class LiquidCommerceRmnClient {
17648
17916
  constructor(auth) {
17649
17917
  this.selectionService = SelectionService.getInstance(auth);
17650
17918
  this.elementService = ElementService.getInstance();
17919
+ this.eventService = EventService.getInstance();
17651
17920
  }
17652
17921
  /**
17653
17922
  * Makes a selection request on our server based on the provided data.
17654
17923
  *
17655
17924
  * To create a spot html element, use the RmnCreateSpotElement function.
17656
17925
  *
17657
- * @param {ISpotSelectionParams} data - Spots selection parameters.
17926
+ * @param {ISpotSelectionParams} params - Spots selection parameters.
17658
17927
  *
17659
17928
  * @return {Promise<ISpots>} - The spots response object.
17660
17929
  */
17661
- async spotSelection(data) {
17662
- return this.selectionService.spotSelection(data);
17930
+ async spotSelection(params) {
17931
+ return this.selectionService.spotSelection(params);
17663
17932
  }
17664
17933
  /**
17665
17934
  * Injects the spot elements into their provided placement.
17666
17935
  *
17667
- * @param {IInjectSpotElement[]} data - The spot element's data.
17668
- * @param {IInjectSpotElementConfig} config - The configuration object.
17936
+ * @param {IInjectSpotElementParams} params - Parameters for injecting spot elements.
17669
17937
  *
17670
17938
  * @return {Promise<void>} - A promise that resolves when the spot elements are injected.
17671
17939
  */
17672
- async injectSpotElement(data, config) {
17673
- if (!data.length) {
17674
- console.warn('RmnSdk: Failed to request spot selection. No spot elements provided.');
17940
+ async injectSpotElement(params) {
17941
+ var _a;
17942
+ const { inject, config } = params;
17943
+ if (!inject.length) {
17944
+ console.warn('RmnSdk: Failed to inject spot element. Please provide at least one spot element to inject.');
17675
17945
  return;
17676
17946
  }
17677
- const spotSelectionRequest = data.map((item) => {
17678
- var _a;
17679
- return ({
17680
- spot: item.spotType,
17681
- count: (_a = item === null || item === void 0 ? void 0 : item.count) !== null && _a !== void 0 ? _a : 1,
17682
- });
17683
- });
17684
- const response = await this.spotSelection({
17685
- spots: spotSelectionRequest,
17686
- url: config === null || config === void 0 ? void 0 : config.url,
17687
- });
17688
- const normalizedData = this.normalizeDataSpotType(data);
17689
- for (const item of normalizedData) {
17690
- const spots = response[item.spotType];
17947
+ this.preventDuplicateSpotPlacementIds(inject);
17948
+ const response = await this.spotSelectionRequest(params);
17949
+ for (const item of inject) {
17950
+ const itemConfig = (_a = item.config) !== null && _a !== void 0 ? _a : config;
17951
+ const spots = response[item.placementId];
17691
17952
  if (!(spots === null || spots === void 0 ? void 0 : spots.length)) {
17692
17953
  console.warn(`RmnSdk: Failed to inject spot element. No spots found for type "${item.spotType}".`);
17693
17954
  continue;
@@ -17699,13 +17960,42 @@ class LiquidCommerceRmnClient {
17699
17960
  continue;
17700
17961
  }
17701
17962
  if (spots.length === 1) {
17702
- this.injectOneSpotElement(item, placement, spots[0], config);
17963
+ this.injectOneSpotElement(item, placement, spots[0], itemConfig);
17703
17964
  }
17704
17965
  if (spots.length > 1) {
17705
- this.injectCarouselSpotElement(placement, spots, config);
17966
+ this.injectCarouselSpotElement(placement, spots, itemConfig);
17706
17967
  }
17707
17968
  }
17708
17969
  }
17970
+ /**
17971
+ * Returns the event manager instance.
17972
+ *
17973
+ * @return {EventService} - The event manager instance.
17974
+ */
17975
+ eventManager() {
17976
+ return this.eventService;
17977
+ }
17978
+ /**
17979
+ * Makes a selection request on our server based on the provided data.
17980
+ *
17981
+ * @param {IInjectSpotElementParams} params - Parameters for injecting spot elements.
17982
+ *
17983
+ * @return {Promise<ISpots>} - The spots response object.
17984
+ */
17985
+ async spotSelectionRequest(params) {
17986
+ const { inject, filter, config } = params;
17987
+ const request = {
17988
+ url: config === null || config === void 0 ? void 0 : config.url,
17989
+ filter,
17990
+ spots: inject.map((item) => ({
17991
+ placementId: item.placementId,
17992
+ spot: item.spotType,
17993
+ count: item === null || item === void 0 ? void 0 : item.count,
17994
+ ...item === null || item === void 0 ? void 0 : item.filter,
17995
+ })),
17996
+ };
17997
+ return this.spotSelection(request);
17998
+ }
17709
17999
  /**
17710
18000
  * Injects a carousel element with the provided spots into the placement.
17711
18001
  *
@@ -17725,6 +18015,11 @@ class LiquidCommerceRmnClient {
17725
18015
  console.warn(`RmnSdk: Failed to inject carousel spot element. Could not create element for type "${spot.spot}".`);
17726
18016
  return;
17727
18017
  }
18018
+ this.eventSpotElement({
18019
+ spot,
18020
+ placementId: placement.id,
18021
+ element: content,
18022
+ });
17728
18023
  carouselSlides.push(content);
17729
18024
  }
17730
18025
  const { maxWidth, maxHeight } = spots.reduce((max, spot) => ({
@@ -17776,28 +18071,37 @@ class LiquidCommerceRmnClient {
17776
18071
  console.warn(`RmnSdk: Failed to inject spot element. Could not create element for type "${injectItem.spotType}".`);
17777
18072
  return;
17778
18073
  }
18074
+ this.eventSpotElement({
18075
+ spot,
18076
+ placementId: injectItem.placementId,
18077
+ element: spotElement,
18078
+ });
17779
18079
  placement.replaceChildren(spotElement);
17780
18080
  }
18081
+ eventSpotElement({ spot, placementId, element, }) {
18082
+ this.eventService.registerSpot({
18083
+ placementId,
18084
+ element,
18085
+ spot,
18086
+ });
18087
+ }
17781
18088
  /**
17782
- * Normalizes the spot type data by adding a number suffix to the spot type.
18089
+ * Prevents duplicate placement ids in the inject data.
18090
+ *
18091
+ * @param {IInjectSpotElement[]} inject - The inject data.
17783
18092
  *
17784
- * @param {IInjectSpotElement[]} spots - The spot type data.
18093
+ * @throws {Error} - If a duplicate placement id is found.
17785
18094
  *
17786
- * @return {IInjectSpotElement[]} - The normalized spot type data.
18095
+ * @return {void}
17787
18096
  */
17788
- normalizeDataSpotType(spots) {
17789
- const spotTypeCounts = {};
17790
- return spots.map((spot) => {
17791
- const { spotType } = spot;
17792
- spotTypeCounts[spotType] = (spotTypeCounts[spotType] || 0) + 1;
17793
- if (spotTypeCounts[spotType] === 1) {
17794
- return spot;
18097
+ preventDuplicateSpotPlacementIds(inject) {
18098
+ const placementIds = new Set();
18099
+ for (const item of inject) {
18100
+ if (placementIds.has(item.placementId)) {
18101
+ throw new Error(`RmnSdk: Duplicate placement id (${item.placementId}) found. Please provide a unique placement id for each spot element.`);
17795
18102
  }
17796
- return {
17797
- ...spot,
17798
- spotType: `${spotType}${spotTypeCounts[spotType]}`,
17799
- };
17800
- });
18103
+ placementIds.add(item.placementId);
18104
+ }
17801
18105
  }
17802
18106
  }
17803
18107
  /**
@@ -38,6 +38,7 @@ export declare enum RMN_SPOT_TYPE {
38
38
  }
39
39
  export declare enum RMN_FILTER_PROPERTIES {
40
40
  KEYWORDS = "keywords",
41
+ PAGE_LOCATION = "pageLocation",
41
42
  PARENTCO = "parentCo",
42
43
  BRAND = "brand",
43
44
  CATEGORY = "category",
@@ -48,6 +49,9 @@ export declare enum RMN_FILTER_PROPERTIES {
48
49
  SECTION = "section"
49
50
  }
50
51
  export declare enum RMN_SPOT_EVENT {
52
+ MOUNTED = "MOUNTED",
53
+ UNMOUNTED = "UNMOUNTED",
54
+ RESIZED = "RESIZED",
51
55
  IMPRESSION = "IMPRESSION",
52
56
  CLICK = "CLICK",
53
57
  PURCHASE = "PURCHASE",
@@ -1,12 +1,12 @@
1
1
  import type { ICreateElementConfig } from 'modules/element';
2
- export type CarouselNavPosition = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right' | 'middle-left' | 'middle-right' | 'middle-sides';
2
+ export type CarouselNavPositionType = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right' | 'middle-left' | 'middle-right' | 'middle-sides';
3
3
  export interface ICarouselDotOptions {
4
- position: CarouselNavPosition;
4
+ position: CarouselNavPositionType;
5
5
  color: string;
6
6
  activeColor: string;
7
7
  }
8
8
  export interface ICarouselButtonOptions {
9
- position: CarouselNavPosition;
9
+ position: CarouselNavPositionType;
10
10
  together: boolean;
11
11
  textColor: string;
12
12
  backgroundColor: string;
@@ -1,6 +1,7 @@
1
1
  import type { RMN_SPOT_TYPE } from 'enums';
2
- import type { ICarouselOptions, ICreateCarouselElementParams } from './component/carousel';
3
- import type { ICreateSpotElementParams } from './component/spot';
2
+ import type { ICarouselOptions, ICreateCarouselElementParams } from 'modules/element/component/carousel';
3
+ import type { ICreateSpotElementParams } from 'modules/element/component/spot';
4
+ import type { RmnFilterType } from 'modules/selection';
4
5
  export interface ISpotColors {
5
6
  textColor?: string;
6
7
  backgroundColor?: string;
@@ -11,11 +12,6 @@ export interface ISpotOverlay {
11
12
  color: string;
12
13
  colorStop: string;
13
14
  }
14
- export interface IInjectSpotElement {
15
- placementId: string;
16
- spotType: RMN_SPOT_TYPE | string;
17
- count?: number;
18
- }
19
15
  export interface IInjectSpotElementConfig {
20
16
  url?: string;
21
17
  colors?: ISpotColors;
@@ -23,15 +19,27 @@ export interface IInjectSpotElementConfig {
23
19
  overlay?: ISpotOverlay[];
24
20
  carousel?: ICarouselOptions;
25
21
  }
22
+ export interface IInjectSpotElement {
23
+ placementId: string;
24
+ spotType: RMN_SPOT_TYPE | string;
25
+ count?: number;
26
+ config?: Omit<IInjectSpotElementConfig, 'url'>;
27
+ filter?: Partial<RmnFilterType>;
28
+ }
26
29
  export interface ICreateElementConfig {
27
30
  width: number;
28
31
  height: number;
29
32
  fluid?: boolean;
30
33
  minScale: number;
31
34
  }
35
+ export interface IInjectSpotElementParams {
36
+ inject: IInjectSpotElement[];
37
+ config?: IInjectSpotElementConfig;
38
+ filter?: Partial<RmnFilterType>;
39
+ }
32
40
  export interface IElementService {
33
- createSpotElement(data: ICreateSpotElementParams): HTMLElement | null;
34
- createCarouselElement(data: ICreateCarouselElementParams): HTMLElement | null;
41
+ createSpotElement(params: ICreateSpotElementParams): HTMLElement | null;
42
+ createCarouselElement(params: ICreateCarouselElementParams): HTMLElement | null;
35
43
  }
36
44
  export interface IRmnCreateSpotElementConfig {
37
45
  fluid?: boolean;
@@ -1,10 +1,11 @@
1
1
  import type { ISpot } from 'types';
2
2
  import type { ISpotTemplateConfig } from './template.type';
3
3
  /**
4
- * Creates the spot html string based on the provided spot data.
4
+ * Returns the HTML element for the given spot.
5
5
  *
6
- * @param {ISpot} spot - The spot data.
6
+ * @param {ISpot} spot - The spot object.
7
+ * @param {ISpotTemplateConfig} config - The spot template configuration.
7
8
  *
8
- * @return {string} - The spot html string.
9
+ * @return {HTMLElement | null} - The HTML element for the given spot or null if the spot template is not found.
9
10
  */
10
11
  export declare const SPOT_TEMPLATE_HTML_ELEMENT: (spot: ISpot, config?: ISpotTemplateConfig) => HTMLElement | null;
@@ -1,5 +1,72 @@
1
1
  import type { RMN_SPOT_EVENT } from 'enums';
2
+ import type { ISpot } from '../selection';
2
3
  export interface IFireEventParams {
3
4
  event: RMN_SPOT_EVENT;
4
5
  eventUrl: string;
5
6
  }
7
+ export interface IMountedEvent {
8
+ placementId: string;
9
+ spotId: string;
10
+ spotType: string;
11
+ spotVariant: string;
12
+ element: HTMLElement;
13
+ }
14
+ export interface IUnMountedEvent {
15
+ placementId: string;
16
+ spotId: string;
17
+ }
18
+ export interface IResizedEvent {
19
+ placementId: string;
20
+ spotId: string;
21
+ scale: number;
22
+ previousDimensions: {
23
+ width: number;
24
+ height: number;
25
+ };
26
+ currentDimensions: {
27
+ width: number;
28
+ height: number;
29
+ };
30
+ }
31
+ export interface IClickEvent {
32
+ placementId: string;
33
+ spotId: string;
34
+ element: HTMLElement;
35
+ }
36
+ export interface IImpressionEvent {
37
+ placementId: string;
38
+ spotId: string;
39
+ element: HTMLElement;
40
+ }
41
+ export interface IAddToCartEvent {
42
+ placementId: string;
43
+ spotId: string;
44
+ }
45
+ export interface IAddToWishlistEvent {
46
+ placementId: string;
47
+ spotId: string;
48
+ }
49
+ export interface IPurchaseEvent {
50
+ placementId: string;
51
+ spotId: string;
52
+ }
53
+ export interface IBuyNowEvent {
54
+ placementId: string;
55
+ spotId: string;
56
+ }
57
+ export interface IEventMap {
58
+ [RMN_SPOT_EVENT.MOUNTED]: IMountedEvent;
59
+ [RMN_SPOT_EVENT.UNMOUNTED]: IUnMountedEvent;
60
+ [RMN_SPOT_EVENT.RESIZED]: IResizedEvent;
61
+ [RMN_SPOT_EVENT.CLICK]: IClickEvent;
62
+ [RMN_SPOT_EVENT.IMPRESSION]: IImpressionEvent;
63
+ [RMN_SPOT_EVENT.ADD_TO_CART]: IAddToCartEvent;
64
+ [RMN_SPOT_EVENT.ADD_TO_WISHLIST]: IAddToWishlistEvent;
65
+ [RMN_SPOT_EVENT.PURCHASE]: IPurchaseEvent;
66
+ [RMN_SPOT_EVENT.BUY_NOW]: IBuyNowEvent;
67
+ }
68
+ export interface IRegisterSpotParams {
69
+ placementId: string;
70
+ element: HTMLElement;
71
+ spot: ISpot;
72
+ }