@liquidcommercedev/rmn-sdk 1.5.0-beta.1 → 1.5.0-beta.10

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.
Files changed (26) hide show
  1. package/dist/index.cjs +1192 -407
  2. package/dist/index.esm.js +1193 -408
  3. package/dist/types/common/helpers/utils.helper.d.ts +50 -0
  4. package/dist/types/enums.d.ts +6 -1
  5. package/dist/types/modules/element/element.interface.d.ts +5 -2
  6. package/dist/types/modules/event/event.interface.d.ts +6 -32
  7. package/dist/types/modules/event/event.service.d.ts +7 -22
  8. package/dist/types/modules/event/index.d.ts +0 -1
  9. package/dist/types/modules/{event/helpers → helper-service}/index.d.ts +1 -0
  10. package/dist/types/modules/{event/helpers → helper-service}/intersection.service.d.ts +1 -1
  11. package/dist/types/modules/helper-service/localstorage.service.d.ts +56 -0
  12. package/dist/types/modules/{event/pubsub.d.ts → helper-service/pubsub.service.d.ts} +8 -8
  13. package/dist/types/modules/{event/helpers → helper-service}/resize.service.d.ts +1 -1
  14. package/dist/types/modules/monitor/index.d.ts +2 -0
  15. package/dist/types/modules/monitor/monitor.enums.d.ts +4 -0
  16. package/dist/types/modules/monitor/monitor.interface.d.ts +11 -0
  17. package/dist/types/modules/monitor/monitor.service.d.ts +12 -0
  18. package/dist/types/modules/monitor/monitors/datalayer.monitor.d.ts +12 -0
  19. package/dist/types/modules/selection/selection.interface.d.ts +3 -1
  20. package/dist/types/rmn-client.d.ts +1 -1
  21. package/dist/types/types.d.ts +5 -4
  22. package/package.json +1 -1
  23. package/umd/liquidcommerce-rmn-sdk.min.js +1 -1
  24. package/dist/types/modules/element/component/utils.d.ts +0 -1
  25. package/dist/types/modules/event/helpers/localstorage.service.d.ts +0 -26
  26. /package/dist/types/{static.constant.d.ts → example.constant.d.ts} +0 -0
package/dist/index.cjs CHANGED
@@ -3,6 +3,7 @@
3
3
  exports.RMN_SPOT_TYPE = void 0;
4
4
  (function (RMN_SPOT_TYPE) {
5
5
  // Reserve Bar Spot Types
6
+ RMN_SPOT_TYPE["RB_HOMEPAGE_HERO"] = "rbHomepageHero";
6
7
  RMN_SPOT_TYPE["RB_HOMEPAGE_HERO_THREE_TILE"] = "rbHomepageHeroThreeTile";
7
8
  RMN_SPOT_TYPE["RB_HOMEPAGE_HERO_TWO_TILE"] = "rbHomepageHeroTwoTile";
8
9
  RMN_SPOT_TYPE["RB_HOMEPAGE_HERO_FULL_IMAGE"] = "rbHomepageHeroFullImage";
@@ -54,13 +55,18 @@ exports.RMN_FILTER_PROPERTIES = void 0;
54
55
  RMN_FILTER_PROPERTIES["PUBLISHERS"] = "publishers";
55
56
  RMN_FILTER_PROPERTIES["SECTION"] = "section";
56
57
  })(exports.RMN_FILTER_PROPERTIES || (exports.RMN_FILTER_PROPERTIES = {}));
58
+ exports.RMN_EVENT = void 0;
59
+ (function (RMN_EVENT) {
60
+ RMN_EVENT["LIFECYCLE_STATE"] = "LIFECYCLE_STATE";
61
+ RMN_EVENT["SPOT_EVENT"] = "SPOT_EVENT";
62
+ })(exports.RMN_EVENT || (exports.RMN_EVENT = {}));
57
63
  exports.RMN_SPOT_EVENT = void 0;
58
64
  (function (RMN_SPOT_EVENT) {
59
- RMN_SPOT_EVENT["LIFECYCLE_STATE"] = "LIFECYCLE_STATE";
60
65
  RMN_SPOT_EVENT["IMPRESSION"] = "IMPRESSION";
61
66
  RMN_SPOT_EVENT["CLICK"] = "CLICK";
62
67
  RMN_SPOT_EVENT["PURCHASE"] = "PURCHASE";
63
68
  RMN_SPOT_EVENT["ADD_TO_CART"] = "ADD_TO_CART";
69
+ RMN_SPOT_EVENT["REMOVE_FROM_CART"] = "REMOVE_FROM_CART";
64
70
  RMN_SPOT_EVENT["ADD_TO_WISHLIST"] = "ADD_TO_WISHLIST";
65
71
  RMN_SPOT_EVENT["BUY_NOW"] = "BUY_NOW";
66
72
  })(exports.RMN_SPOT_EVENT || (exports.RMN_SPOT_EVENT = {}));
@@ -72,6 +78,511 @@ exports.RMN_ENV = void 0;
72
78
  RMN_ENV["PRODUCTION"] = "production";
73
79
  })(exports.RMN_ENV || (exports.RMN_ENV = {}));
74
80
 
81
+ const SPOT_EVENTS_EXAMPLE = [
82
+ {
83
+ event: exports.RMN_SPOT_EVENT.CLICK,
84
+ url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwidXIiOm51bGx9&s=hWz37kbxi_u95EVNn2aoQhc5Aas',
85
+ },
86
+ {
87
+ event: exports.RMN_SPOT_EVENT.IMPRESSION,
88
+ url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiYmEiOjEsImZxIjowfQ&s=djoysjCimurf-5T11AlNAwwLSS8',
89
+ },
90
+ {
91
+ event: exports.RMN_SPOT_EVENT.PURCHASE,
92
+ url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiZXQiOjU5fQ&s=AAPAw-3SfZ0JMzjEGFSwt9L-2S4',
93
+ },
94
+ {
95
+ event: exports.RMN_SPOT_EVENT.ADD_TO_CART,
96
+ url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiZXQiOjYwfQ&s=uzQFcjgL7m9XqUG8FvTPVN5YkZY',
97
+ },
98
+ {
99
+ event: exports.RMN_SPOT_EVENT.ADD_TO_WISHLIST,
100
+ url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiZXQiOjYzfQ&s=m3ISU_iIy-OFtXrTKpI6cJAEC0k',
101
+ },
102
+ {
103
+ event: exports.RMN_SPOT_EVENT.BUY_NOW,
104
+ url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiZXQiOjY5fQ&s=l6MOscQC-q-FkC2Ksd7w6jjySCQ',
105
+ },
106
+ ];
107
+ const RB_SPOTS_SELECTION_EXAMPLE = {
108
+ rbHomepageHero: [
109
+ {
110
+ id: 'abc123',
111
+ spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
112
+ variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
113
+ width: 1140,
114
+ height: 640,
115
+ header: 'Premium Wine Collection',
116
+ description: 'Discover our exclusive selection of vintage wines',
117
+ ctaText: 'Shop Wines',
118
+ textColor: '#ffffff',
119
+ ctaTextColor: '#ffffff',
120
+ primaryImage: 'https://placehold.co/1140x640/png?text=Wine+Collection',
121
+ mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Wine',
122
+ events: SPOT_EVENTS_EXAMPLE,
123
+ productIds: [1, 2, 3],
124
+ },
125
+ {
126
+ id: 'jkl012',
127
+ spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
128
+ variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
129
+ width: 1140,
130
+ height: 640,
131
+ header: 'Whiskey Collection',
132
+ description: 'Premium whiskeys from around the world',
133
+ ctaText: 'Shop Whiskeys',
134
+ textColor: '#ffffff',
135
+ backgroundColor: '#2c1810',
136
+ ctaTextColor: '#2c1810',
137
+ primaryImage: 'https://placehold.co/1140x640/png?text=Whiskey',
138
+ mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Whiskey',
139
+ events: SPOT_EVENTS_EXAMPLE,
140
+ productIds: [10, 11],
141
+ },
142
+ {
143
+ id: 'stu901',
144
+ spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
145
+ variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
146
+ width: 1140,
147
+ height: 640,
148
+ header: 'Summer Cocktails',
149
+ description: 'Essential spirits for summer mixing',
150
+ ctaText: 'Mix It Up',
151
+ textColor: '#ffffff',
152
+ backgroundColor: '#4d3a0a',
153
+ ctaTextColor: '#4d3a0a',
154
+ primaryImage: 'https://placehold.co/1140x640/png?text=Cocktails',
155
+ secondaryImage: 'https://placehold.co/1140x640/png?text=Mixers',
156
+ mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Cocktails',
157
+ mobileSecondaryImage: 'https://placehold.co/640x320/png?text=Mobile+Mixers',
158
+ events: SPOT_EVENTS_EXAMPLE,
159
+ productIds: [16, 17, 18],
160
+ },
161
+ {
162
+ id: 'def456',
163
+ spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
164
+ variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
165
+ width: 1140,
166
+ height: 640,
167
+ header: 'Craft Beer Festival',
168
+ description: 'Local breweries and exclusive releases',
169
+ ctaText: 'Explore Beers',
170
+ textColor: '#ffffff',
171
+ ctaTextColor: '#ffffff',
172
+ primaryImage: 'https://placehold.co/1140x640/png?text=Beer+Festival',
173
+ mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Beer',
174
+ events: SPOT_EVENTS_EXAMPLE,
175
+ productIds: [4, 5, 6],
176
+ },
177
+ {
178
+ id: 'mno345',
179
+ spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
180
+ variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
181
+ width: 1140,
182
+ height: 640,
183
+ header: 'Champagne Selection',
184
+ description: 'Finest champagnes for every occasion',
185
+ ctaText: 'View Champagnes',
186
+ textColor: '#ffffff',
187
+ backgroundColor: '#1a1a1a',
188
+ ctaTextColor: '#1a1a1a',
189
+ primaryImage: 'https://placehold.co/1140x640/png?text=Champagne',
190
+ mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Champagne',
191
+ events: SPOT_EVENTS_EXAMPLE,
192
+ productIds: [12, 13],
193
+ },
194
+ {
195
+ id: 'vwx234',
196
+ spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
197
+ variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
198
+ width: 1140,
199
+ height: 640,
200
+ header: 'Wine Regions',
201
+ description: 'Explore wines from top regions',
202
+ ctaText: 'Tour Regions',
203
+ textColor: '#ffffff',
204
+ backgroundColor: '#4d0a0a',
205
+ ctaTextColor: '#4d0a0a',
206
+ primaryImage: 'https://placehold.co/1140x640/png?text=Wine+Regions',
207
+ secondaryImage: 'https://placehold.co/1140x640/png?text=Vineyards',
208
+ mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Regions',
209
+ mobileSecondaryImage: 'https://placehold.co/640x320/png?text=Mobile+Vineyards',
210
+ events: SPOT_EVENTS_EXAMPLE,
211
+ productIds: [19, 20, 21],
212
+ },
213
+ {
214
+ id: 'ghi789',
215
+ spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
216
+ variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
217
+ width: 1140,
218
+ height: 640,
219
+ header: 'Rare Spirits',
220
+ description: 'Limited edition spirits collection',
221
+ ctaText: 'View Collection',
222
+ textColor: '#ffffff',
223
+ ctaTextColor: '#ffffff',
224
+ primaryImage: 'https://placehold.co/1140x640/png?text=Rare+Spirits',
225
+ mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Spirits',
226
+ events: SPOT_EVENTS_EXAMPLE,
227
+ productIds: [7, 8, 9],
228
+ },
229
+ {
230
+ id: 'pqr678',
231
+ spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
232
+ variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
233
+ width: 1140,
234
+ height: 640,
235
+ header: 'Gin Collection',
236
+ description: 'Artisanal gins and botanicals',
237
+ ctaText: 'Explore Gins',
238
+ textColor: '#ffffff',
239
+ backgroundColor: '#0a4d4d',
240
+ ctaTextColor: '#0a4d4d',
241
+ primaryImage: 'https://placehold.co/1140x640/png?text=Gin',
242
+ mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Gin',
243
+ events: SPOT_EVENTS_EXAMPLE,
244
+ productIds: [14, 15],
245
+ },
246
+ {
247
+ id: 'yz5678',
248
+ spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
249
+ variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
250
+ width: 1140,
251
+ height: 640,
252
+ header: 'Tequila Collection',
253
+ description: 'Premium tequilas and mezcals',
254
+ ctaText: 'Shop Tequila',
255
+ textColor: '#ffffff',
256
+ backgroundColor: '#0a4d2b',
257
+ ctaTextColor: '#0a4d2b',
258
+ primaryImage: 'https://placehold.co/1140x640/png?text=Tequila',
259
+ secondaryImage: 'https://placehold.co/1140x640/png?text=Mezcal',
260
+ mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Tequila',
261
+ mobileSecondaryImage: 'https://placehold.co/640x320/png?text=Mobile+Mezcal',
262
+ events: SPOT_EVENTS_EXAMPLE,
263
+ productIds: [22, 23, 24],
264
+ },
265
+ ],
266
+ rbHomepageHeroFullImage: [
267
+ {
268
+ id: 'hjk567',
269
+ spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
270
+ variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
271
+ width: 1140,
272
+ height: 640,
273
+ header: 'Holiday Gift Guide',
274
+ description: 'Perfect spirits for every occasion',
275
+ ctaText: 'Shop Gifts',
276
+ textColor: '#ffffff',
277
+ ctaTextColor: '#ffffff',
278
+ primaryImage: 'https://placehold.co/1140x640/png?text=Gift+Guide',
279
+ mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Gifts',
280
+ events: SPOT_EVENTS_EXAMPLE,
281
+ productIds: [25, 26],
282
+ },
283
+ {
284
+ id: 'qwe890',
285
+ spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
286
+ variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
287
+ width: 1140,
288
+ height: 640,
289
+ header: 'Summer Wine Festival',
290
+ description: 'Refreshing wines for summer',
291
+ ctaText: 'Shop Festival',
292
+ textColor: '#ffffff',
293
+ ctaTextColor: '#ffffff',
294
+ primaryImage: 'https://placehold.co/1140x640/png?text=Wine+Festival',
295
+ mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Festival',
296
+ events: SPOT_EVENTS_EXAMPLE,
297
+ productIds: [27, 28],
298
+ },
299
+ ],
300
+ rbHomepageHeroTwoTile: [
301
+ {
302
+ id: 'iop987',
303
+ spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
304
+ variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
305
+ width: 1140,
306
+ height: 640,
307
+ header: 'Bourbon Selection',
308
+ description: "Kentucky's finest bourbons",
309
+ ctaText: 'Shop Bourbon',
310
+ textColor: '#ffffff',
311
+ backgroundColor: '#2c1810',
312
+ ctaTextColor: '#2c1810',
313
+ primaryImage: 'https://placehold.co/1140x640/png?text=Bourbon',
314
+ mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Bourbon',
315
+ events: SPOT_EVENTS_EXAMPLE,
316
+ productIds: [29, 30],
317
+ },
318
+ {
319
+ id: 'lkj012',
320
+ spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
321
+ variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
322
+ width: 1140,
323
+ height: 640,
324
+ header: 'Vodka Collection',
325
+ description: 'Premium vodkas from around the world',
326
+ ctaText: 'Shop Vodka',
327
+ textColor: '#ffffff',
328
+ backgroundColor: '#1a1a1a',
329
+ ctaTextColor: '#1a1a1a',
330
+ primaryImage: 'https://placehold.co/1140x640/png?text=Vodka',
331
+ mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Vodka',
332
+ events: SPOT_EVENTS_EXAMPLE,
333
+ productIds: [31, 32],
334
+ },
335
+ ],
336
+ rbHomepageHeroThreeTile: [
337
+ {
338
+ id: 'bnm345',
339
+ spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
340
+ variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
341
+ width: 1140,
342
+ height: 640,
343
+ header: 'Rum Collection',
344
+ description: 'Caribbean and craft rums',
345
+ ctaText: 'Shop Rum',
346
+ textColor: '#ffffff',
347
+ backgroundColor: '#4d3a0a',
348
+ ctaTextColor: '#4d3a0a',
349
+ primaryImage: 'https://placehold.co/1140x640/png?text=Rum',
350
+ secondaryImage: 'https://placehold.co/1140x640/png?text=Craft+Rum',
351
+ mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Rum',
352
+ mobileSecondaryImage: 'https://placehold.co/640x320/png?text=Mobile+Craft',
353
+ events: SPOT_EVENTS_EXAMPLE,
354
+ productIds: [33, 34],
355
+ },
356
+ {
357
+ id: 'fgh678',
358
+ spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
359
+ variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
360
+ width: 1140,
361
+ height: 640,
362
+ header: 'Scotch Selection',
363
+ description: 'Single malts and blends',
364
+ ctaText: 'Shop Scotch',
365
+ textColor: '#ffffff',
366
+ backgroundColor: '#4d0a0a',
367
+ ctaTextColor: '#4d0a0a',
368
+ primaryImage: 'https://placehold.co/1140x640/png?text=Scotch',
369
+ secondaryImage: 'https://placehold.co/1140x640/png?text=Single+Malts',
370
+ mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Scotch',
371
+ mobileSecondaryImage: 'https://placehold.co/640x320/png?text=Mobile+Malts',
372
+ events: SPOT_EVENTS_EXAMPLE,
373
+ productIds: [35, 36],
374
+ },
375
+ ],
376
+ rbLargeCategoryImageTout: [
377
+ {
378
+ id: 'cde567',
379
+ spot: exports.RMN_SPOT_TYPE.RB_LARGE_CATEGORY_IMAGE_TOUT,
380
+ variant: exports.RMN_SPOT_TYPE.RB_LARGE_CATEGORY_IMAGE_TOUT,
381
+ width: 468,
382
+ height: 410,
383
+ header: 'Rare & Limited Edition',
384
+ description: 'Discover our collection of hard-to-find and limited release spirits.',
385
+ textColor: '#ffffff',
386
+ ctaTextColor: '#ffffff',
387
+ primaryImage: 'https://placehold.co/468x410/png?text=Rare+Spirits',
388
+ mobilePrimaryImage: 'https://placehold.co/468x410/png?text=Mobile+Rare+Spirits',
389
+ ctaText: 'Shop Rare Spirits',
390
+ events: SPOT_EVENTS_EXAMPLE,
391
+ productIds: [37, 38, 39, 40, 41],
392
+ },
393
+ {
394
+ id: 'efg789',
395
+ spot: exports.RMN_SPOT_TYPE.RB_LARGE_CATEGORY_IMAGE_TOUT,
396
+ variant: exports.RMN_SPOT_TYPE.RB_LARGE_CATEGORY_IMAGE_TOUT,
397
+ width: 468,
398
+ height: 410,
399
+ header: 'Vintage Champagnes',
400
+ description: 'Explore our prestigious collection of aged champagnes.',
401
+ textColor: '#ffffff',
402
+ ctaTextColor: '#ffffff',
403
+ primaryImage: 'https://placehold.co/468x410/png?text=Vintage+Champagne',
404
+ mobilePrimaryImage: 'https://placehold.co/468x410/png?text=Mobile+Champagne',
405
+ ctaText: 'View Collection',
406
+ events: SPOT_EVENTS_EXAMPLE,
407
+ productIds: [42, 43, 44, 45, 46],
408
+ },
409
+ {
410
+ id: 'ghi012',
411
+ spot: exports.RMN_SPOT_TYPE.RB_LARGE_CATEGORY_IMAGE_TOUT,
412
+ variant: exports.RMN_SPOT_TYPE.RB_LARGE_CATEGORY_IMAGE_TOUT,
413
+ width: 468,
414
+ height: 410,
415
+ header: 'Small Batch Bourbon',
416
+ description: 'Hand-selected premium bourbon from craft distilleries.',
417
+ textColor: '#ffffff',
418
+ ctaTextColor: '#ffffff',
419
+ primaryImage: 'https://placehold.co/468x410/png?text=Craft+Bourbon',
420
+ mobilePrimaryImage: 'https://placehold.co/468x410/png?text=Mobile+Bourbon',
421
+ ctaText: 'Explore Bourbon',
422
+ events: SPOT_EVENTS_EXAMPLE,
423
+ productIds: [47, 48, 49, 50, 51],
424
+ },
425
+ ],
426
+ rbSmallDiscoverTout: [
427
+ {
428
+ id: 'jkl345',
429
+ spot: exports.RMN_SPOT_TYPE.RB_SMALL_DISCOVER_TOUT,
430
+ variant: exports.RMN_SPOT_TYPE.RB_SMALL_DISCOVER_TOUT,
431
+ width: 224,
432
+ height: 378,
433
+ header: 'Château Margaux 2015 Bordeaux',
434
+ textColor: '#ffffff',
435
+ primaryImage: 'https://placehold.co/224x378/png?text=Château+Margaux',
436
+ mobilePrimaryImage: 'https://placehold.co/224x378/png?text=Mobile+Château+Margaux',
437
+ events: SPOT_EVENTS_EXAMPLE,
438
+ productIds: [52, 53, 54, 55, 56],
439
+ },
440
+ {
441
+ id: 'lmn678',
442
+ spot: exports.RMN_SPOT_TYPE.RB_SMALL_DISCOVER_TOUT,
443
+ variant: exports.RMN_SPOT_TYPE.RB_SMALL_DISCOVER_TOUT,
444
+ width: 224,
445
+ height: 378,
446
+ header: 'Macallan 25 Year',
447
+ textColor: '#ffffff',
448
+ primaryImage: 'https://placehold.co/224x378/png?text=Macallan+25',
449
+ mobilePrimaryImage: 'https://placehold.co/224x378/png?text=Mobile+Macallan',
450
+ events: SPOT_EVENTS_EXAMPLE,
451
+ productIds: [57, 58, 59, 60, 61],
452
+ },
453
+ {
454
+ id: 'nop901',
455
+ spot: exports.RMN_SPOT_TYPE.RB_SMALL_DISCOVER_TOUT,
456
+ variant: exports.RMN_SPOT_TYPE.RB_SMALL_DISCOVER_TOUT,
457
+ width: 224,
458
+ height: 378,
459
+ header: 'Louis XIII Cognac',
460
+ textColor: '#ffffff',
461
+ primaryImage: 'https://placehold.co/224x378/png?text=Louis+XIII',
462
+ mobilePrimaryImage: 'https://placehold.co/224x378/png?text=Mobile+Louis+XIII',
463
+ events: SPOT_EVENTS_EXAMPLE,
464
+ productIds: [62, 63, 64, 65, 66],
465
+ },
466
+ ],
467
+ rbSmallCategoryImageTout: [
468
+ {
469
+ id: 'qrs234',
470
+ spot: exports.RMN_SPOT_TYPE.RB_SMALL_CATEGORY_IMAGE_TOUT,
471
+ variant: exports.RMN_SPOT_TYPE.RB_SMALL_CATEGORY_IMAGE_TOUT,
472
+ width: 224,
473
+ height: 410,
474
+ header: 'Japanese Sake',
475
+ textColor: '#ffffff',
476
+ primaryImage: 'https://placehold.co/224x410/png?text=Japanese+Sake',
477
+ mobilePrimaryImage: 'https://placehold.co/224x410/png?text=Mobile+Japanese+Sake',
478
+ events: SPOT_EVENTS_EXAMPLE,
479
+ productIds: [67, 68, 69, 70, 71],
480
+ },
481
+ {
482
+ id: 'stu567',
483
+ spot: exports.RMN_SPOT_TYPE.RB_SMALL_CATEGORY_IMAGE_TOUT,
484
+ variant: exports.RMN_SPOT_TYPE.RB_SMALL_CATEGORY_IMAGE_TOUT,
485
+ width: 224,
486
+ height: 410,
487
+ header: 'Craft Vermouth',
488
+ textColor: '#ffffff',
489
+ primaryImage: 'https://placehold.co/224x410/png?text=Craft+Vermouth',
490
+ mobilePrimaryImage: 'https://placehold.co/224x410/png?text=Mobile+Vermouth',
491
+ events: SPOT_EVENTS_EXAMPLE,
492
+ productIds: [72, 73, 74, 75, 76],
493
+ },
494
+ {
495
+ id: 'vwx890',
496
+ spot: exports.RMN_SPOT_TYPE.RB_SMALL_CATEGORY_IMAGE_TOUT,
497
+ variant: exports.RMN_SPOT_TYPE.RB_SMALL_CATEGORY_IMAGE_TOUT,
498
+ width: 224,
499
+ height: 410,
500
+ header: 'Premium Mezcal',
501
+ textColor: '#ffffff',
502
+ primaryImage: 'https://placehold.co/224x410/png?text=Premium+Mezcal',
503
+ mobilePrimaryImage: 'https://placehold.co/224x410/png?text=Mobile+Mezcal',
504
+ events: SPOT_EVENTS_EXAMPLE,
505
+ productIds: [77, 78, 79, 80, 81],
506
+ },
507
+ ],
508
+ rbCollectionBannerWithoutTextBlock: [
509
+ {
510
+ id: 'yz1234',
511
+ spot: exports.RMN_SPOT_TYPE.RB_COLLECTION_BANNER_WITHOUT_TEXT_BLOCK,
512
+ variant: exports.RMN_SPOT_TYPE.RB_COLLECTION_BANNER_WITHOUT_TEXT_BLOCK,
513
+ width: 887,
514
+ height: 344,
515
+ primaryImage: 'https://placehold.co/887x344/png?text=Summer+Cocktails',
516
+ mobilePrimaryImage: 'https://placehold.co/887x344/png?text=Mobile+Summer+Cocktails',
517
+ events: SPOT_EVENTS_EXAMPLE,
518
+ productIds: [82, 83, 84, 85, 86],
519
+ },
520
+ {
521
+ id: 'abc567',
522
+ spot: exports.RMN_SPOT_TYPE.RB_COLLECTION_BANNER_WITHOUT_TEXT_BLOCK,
523
+ variant: exports.RMN_SPOT_TYPE.RB_COLLECTION_BANNER_WITHOUT_TEXT_BLOCK,
524
+ width: 887,
525
+ height: 344,
526
+ primaryImage: 'https://placehold.co/887x344/png?text=Holiday+Spirits',
527
+ mobilePrimaryImage: 'https://placehold.co/887x344/png?text=Mobile+Holiday+Spirits',
528
+ events: SPOT_EVENTS_EXAMPLE,
529
+ productIds: [87, 88, 89, 90, 91],
530
+ },
531
+ {
532
+ id: 'def901',
533
+ spot: exports.RMN_SPOT_TYPE.RB_COLLECTION_BANNER_WITHOUT_TEXT_BLOCK,
534
+ variant: exports.RMN_SPOT_TYPE.RB_COLLECTION_BANNER_WITHOUT_TEXT_BLOCK,
535
+ width: 887,
536
+ height: 344,
537
+ primaryImage: 'https://placehold.co/887x344/png?text=Wine+Essentials',
538
+ mobilePrimaryImage: 'https://placehold.co/887x344/png?text=Mobile+Wine+Essentials',
539
+ events: SPOT_EVENTS_EXAMPLE,
540
+ productIds: [92, 93, 94, 95, 96],
541
+ },
542
+ ],
543
+ rbNavigationBanner: [
544
+ {
545
+ id: 'ghi234',
546
+ spot: exports.RMN_SPOT_TYPE.RB_NAVIGATION_BANNER,
547
+ variant: exports.RMN_SPOT_TYPE.RB_NAVIGATION_BANNER,
548
+ width: 440,
549
+ height: 220,
550
+ header: 'Explore Tequilas',
551
+ textColor: '#ffffff',
552
+ primaryImage: 'https://placehold.co/440x220/png?text=Tequila+Collection',
553
+ mobilePrimaryImage: 'https://placehold.co/440x220/png?text=Mobile+Tequila+Collection',
554
+ events: SPOT_EVENTS_EXAMPLE,
555
+ productIds: [97, 98, 99, 100, 101],
556
+ },
557
+ {
558
+ id: 'jkl678',
559
+ spot: exports.RMN_SPOT_TYPE.RB_NAVIGATION_BANNER,
560
+ variant: exports.RMN_SPOT_TYPE.RB_NAVIGATION_BANNER,
561
+ width: 440,
562
+ height: 220,
563
+ header: 'Craft Gin Selection',
564
+ textColor: '#ffffff',
565
+ primaryImage: 'https://placehold.co/440x220/png?text=Gin+Selection',
566
+ mobilePrimaryImage: 'https://placehold.co/440x220/png?text=Mobile+Gin+Selection',
567
+ events: SPOT_EVENTS_EXAMPLE,
568
+ productIds: [102, 103, 104, 105, 106],
569
+ },
570
+ {
571
+ id: 'mno012',
572
+ spot: exports.RMN_SPOT_TYPE.RB_NAVIGATION_BANNER,
573
+ variant: exports.RMN_SPOT_TYPE.RB_NAVIGATION_BANNER,
574
+ width: 440,
575
+ height: 220,
576
+ header: 'Premium Vodka',
577
+ textColor: '#ffffff',
578
+ primaryImage: 'https://placehold.co/440x220/png?text=Vodka+Premium',
579
+ mobilePrimaryImage: 'https://placehold.co/440x220/png?text=Mobile+Vodka+Premium',
580
+ events: SPOT_EVENTS_EXAMPLE,
581
+ productIds: [107, 108, 109, 110, 111],
582
+ },
583
+ ],
584
+ };
585
+
75
586
  const REQUEST_CLOUD_PARTNER_SITE = 'X-Liquid-Partner-Site';
76
587
  const REQUEST_CLOUD_PROTECTED_KEY = 'X-Liquid-Protected';
77
588
  const REQUEST_CLOUD_PROTECTED_TIMESTAMP = 'X-Liquid-Timestamp';
@@ -15141,29 +15652,230 @@ class AuthService extends BaseApi {
15141
15652
  if (isErr) {
15142
15653
  throw new Error(`There was an error during authentication: (${isErr === null || isErr === void 0 ? void 0 : isErr.errorMessage})`);
15143
15654
  }
15144
- if (isOk && (val === null || val === void 0 ? void 0 : val.data.token)) {
15145
- this.authInfo.token = val.data.token;
15146
- this.authInfo.authenticated = true;
15655
+ if (isOk && (val === null || val === void 0 ? void 0 : val.data.token)) {
15656
+ this.authInfo.token = val.data.token;
15657
+ this.authInfo.authenticated = true;
15658
+ }
15659
+ else {
15660
+ throw new Error('Auth response was not successful');
15661
+ }
15662
+ return this.authInfo;
15663
+ }
15664
+ }
15665
+
15666
+ const SPOT_ELEMENT_TAG = 'spot-element';
15667
+ const CAROUSEL_ELEMENT_TAG = 'spot-carousel-element';
15668
+ const GFONT_PRECONNECT = `
15669
+ <link rel="preconnect" href="https://fonts.googleapis.com">
15670
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
15671
+ `;
15672
+ const GFONT_SOURCE_SANS_3 = `
15673
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Source+Sans+3:ital,wght@0,200..900;1,200..900&display=swap">
15674
+ `;
15675
+ const GFONT_CORMORANT = `
15676
+ <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">
15677
+ `;
15678
+
15679
+ /**
15680
+ * Determines the event type from a raw event string.
15681
+ *
15682
+ * @param {string} [event] - The raw event string to evaluate.
15683
+ * @returns {RMN_SPOT_EVENT | null} - The corresponding RMN_SPOT_EVENT or null if no match is found.
15684
+ */
15685
+ function getEventTypeFromRawEvent(event) {
15686
+ if (!event) {
15687
+ return null;
15688
+ }
15689
+ if (event.includes('cart')) {
15690
+ if (event.includes('add')) {
15691
+ return exports.RMN_SPOT_EVENT.ADD_TO_CART;
15692
+ }
15693
+ if (event.includes('remove')) {
15694
+ return exports.RMN_SPOT_EVENT.REMOVE_FROM_CART;
15695
+ }
15696
+ }
15697
+ if (event.includes('purchase')) {
15698
+ return exports.RMN_SPOT_EVENT.PURCHASE;
15699
+ }
15700
+ // if(event.includes('refund')) {
15701
+ // return RMN_SPOT_EVENT.REFUND;
15702
+ // }
15703
+ if (event.includes('wishlist') && event.includes('add')) {
15704
+ return exports.RMN_SPOT_EVENT.ADD_TO_WISHLIST;
15705
+ }
15706
+ return null;
15707
+ }
15708
+ /**
15709
+ * Recursively extracts ID values from a nested data structure.
15710
+ * Searches for specified property names and collects their primitive values (strings/numbers).
15711
+ *
15712
+ * @param data - The data structure to search through (can be nested objects/arrays)
15713
+ * @param propertyNames - Array of property names to look for
15714
+ * @returns Array of extracted ID values (strings/numbers only)
15715
+ *
15716
+ * @example
15717
+ * const data = {
15718
+ * id: [1, 2, 3],
15719
+ * nested: { id: 'abc' },
15720
+ * items: [{ id: 456 }]
15721
+ * };
15722
+ * extractDeepIds(data); // Returns [1, 2, 3, 'abc', 456]
15723
+ */
15724
+ function extractDeepIds(data, propertyNames) {
15725
+ const ids = [];
15726
+ const defaulPropertyNames = [
15727
+ 'id',
15728
+ 'upc',
15729
+ 'groupingId',
15730
+ 'sku',
15731
+ 'productId',
15732
+ 'item_id',
15733
+ 'isbn',
15734
+ 'asin',
15735
+ 'mpn',
15736
+ 'model_number',
15737
+ 'article_number',
15738
+ 'variant_id',
15739
+ 'item_number',
15740
+ 'catalog_id',
15741
+ 'reference_id',
15742
+ ];
15743
+ // Set for faster property name lookups
15744
+ const propertySet = new Set(defaulPropertyNames);
15745
+ /**
15746
+ * Processes a value and extracts IDs if it matches criteria
15747
+ * @param value - The value to process
15748
+ * @param currentKey - The property name of the current value
15749
+ */
15750
+ const processValue = (value, currentKey) => {
15751
+ // Early exit for null/undefined values
15752
+ if (value == null)
15753
+ return;
15754
+ // If current key matches our target properties
15755
+ if (currentKey && propertySet.has(currentKey)) {
15756
+ if (Array.isArray(value)) {
15757
+ // Filter and push valid array values in one pass
15758
+ ids.push(...value.filter((item) => typeof item === 'string' || typeof item === 'number'));
15759
+ }
15760
+ else if (typeof value === 'string' || typeof value === 'number') {
15761
+ ids.push(value);
15762
+ }
15763
+ return; // Stop processing this branch after handling the ID
15764
+ }
15765
+ // Recursively process nested structures
15766
+ if (Array.isArray(value)) {
15767
+ value.forEach((item) => processValue(item));
15147
15768
  }
15148
- else {
15149
- throw new Error('Auth response was not successful');
15769
+ else if (typeof value === 'object') {
15770
+ // Process all enumerable properties
15771
+ for (const [key, val] of Object.entries(value)) {
15772
+ processValue(val, key);
15773
+ }
15150
15774
  }
15151
- return this.authInfo;
15775
+ };
15776
+ processValue(data);
15777
+ return ids; // No need to filter nulls as we handle that during collection
15778
+ }
15779
+ // Fallback method using fetch if sendBeacon isn't available
15780
+ async function fallbackEventFire(url) {
15781
+ try {
15782
+ const racePromise = Promise.race([
15783
+ // Promise #1: The fetch request
15784
+ fetch(url, {
15785
+ method: 'POST',
15786
+ keepalive: true,
15787
+ }),
15788
+ // Promise #2: The timeout
15789
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Request timeout')), 2000)),
15790
+ ]);
15791
+ /**
15792
+ * Prevent requests from hanging indefinitely
15793
+ * Improve user experience by failing fast
15794
+ * Handle slow network conditions gracefully
15795
+ * Ensure resources are freed up in a timely manner
15796
+ */
15797
+ const response = await racePromise;
15798
+ return response.ok;
15799
+ }
15800
+ catch (_a) {
15801
+ return false;
15152
15802
  }
15153
15803
  }
15154
-
15155
- const SPOT_ELEMENT_TAG = 'spot-element';
15156
- const CAROUSEL_ELEMENT_TAG = 'spot-carousel-element';
15157
- const GFONT_PRECONNECT = `
15158
- <link rel="preconnect" href="https://fonts.googleapis.com">
15159
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
15160
- `;
15161
- const GFONT_SOURCE_SANS_3 = `
15162
- <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Source+Sans+3:ital,wght@0,200..900;1,200..900&display=swap">
15163
- `;
15164
- const GFONT_CORMORANT = `
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">
15166
- `;
15804
+ /**
15805
+ * Extracts and decodes a URL from a base64-encoded query parameter.
15806
+ *
15807
+ * @param {string} url - The URL containing the base64-encoded query parameter.
15808
+ * @returns {string | null} - The decoded URL or null if not found or invalid.
15809
+ */
15810
+ function getRedirectUrlFromPayload(url) {
15811
+ try {
15812
+ const base64String = new URL(url).searchParams.get('e');
15813
+ if (!base64String) {
15814
+ return null;
15815
+ }
15816
+ const data = JSON.parse(atob(base64String));
15817
+ return data.ur || null;
15818
+ }
15819
+ catch (_a) {
15820
+ return null;
15821
+ }
15822
+ }
15823
+ /**
15824
+ * Fires an event using the navigator.sendBeacon method or a fallback method if sendBeacon is not available.
15825
+ * If the event is a click event and a redirect URL is found, it redirects the user to that URL.
15826
+ *
15827
+ * @param {IFireEventParams} params - The parameters for firing the event.
15828
+ * @param {RMN_SPOT_EVENT} params.event - The event type.
15829
+ * @param {string} params.eventUrl - The URL to which the event is sent.
15830
+ * @returns {Promise<void>} - A promise that resolves when the event is fired.
15831
+ */
15832
+ async function fireEvent({ event, eventUrl }) {
15833
+ var _a;
15834
+ try {
15835
+ const didFireEvent = ((_a = navigator === null || navigator === void 0 ? void 0 : navigator.sendBeacon) === null || _a === void 0 ? void 0 : _a.call(navigator, eventUrl)) || (await fallbackEventFire(eventUrl));
15836
+ if (!didFireEvent) {
15837
+ return;
15838
+ }
15839
+ if (event === exports.RMN_SPOT_EVENT.CLICK) {
15840
+ const redirectUrl = getRedirectUrlFromPayload(eventUrl);
15841
+ if (redirectUrl) {
15842
+ window.location.href = redirectUrl;
15843
+ }
15844
+ }
15845
+ }
15846
+ catch (_b) {
15847
+ // Handle errors silently
15848
+ }
15849
+ }
15850
+ function calculateScaleFactor(elementScale) {
15851
+ // Step 1: Apply square root for non-linear scaling
15852
+ // This creates a more gradual scaling effect, especially for larger changes
15853
+ // For example:
15854
+ // - elementScale of 0.25 (1/4 size) becomes 0.5
15855
+ // - elementScale of 1 (unchanged) remains 1
15856
+ // - elementScale of 4 (4x size) becomes 2
15857
+ const baseFactor = Math.sqrt(elementScale);
15858
+ // Step 2: Apply additional dampening to further soften the scaling effect
15859
+ // The dampening factor (0.5) can be adjusted:
15860
+ // - Lower values (closer to 0) make scaling more subtle
15861
+ // - Higher values (closer to 1) make scaling more pronounced
15862
+ const dampening = 0.35;
15863
+ // Calculate the scaleFactor:
15864
+ // 1. (baseFactor - 1) represents the change from the original size
15865
+ // 2. Multiply by dampening to reduce the effect
15866
+ // 3. Add 1 to center the scaling around the original size
15867
+ // For example, if baseFactor is 2:
15868
+ // scaleFactor = 1 + (2 - 1) * 0.5 = 1.5
15869
+ const scaleFactor = 1 + (baseFactor - 1) * dampening;
15870
+ // Step 3: Define the allowed range for the scale factor
15871
+ // This ensures that the font size never changes too drastically
15872
+ const minScale = 0.35; // Font will never be smaller than 50% of original
15873
+ const maxScale = 1.5; // Font will never be larger than 150% of original
15874
+ // Step 4: Clamp the scale factor to the defined range
15875
+ // Math.min ensures the value doesn't exceed maxScale
15876
+ // Math.max ensures the value isn't less than minScale
15877
+ return Math.max(minScale, Math.min(maxScale, scaleFactor));
15878
+ }
15167
15879
 
15168
15880
  class IntersectionObserverService {
15169
15881
  constructor(defaultOptions = {}) {
@@ -15205,8 +15917,21 @@ class IntersectionObserverService {
15205
15917
  }
15206
15918
  }
15207
15919
 
15208
- class LocalStorage {
15920
+ var ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX;
15921
+ (function (ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX) {
15922
+ ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["PLACEMENT_ID"] = 0] = "PLACEMENT_ID";
15923
+ ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["SPOT_ID"] = 1] = "SPOT_ID";
15924
+ ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["SPOT_TYPE"] = 2] = "SPOT_TYPE";
15925
+ ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["EVENTS"] = 3] = "EVENTS";
15926
+ ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["PRODUCT_IDS"] = 4] = "PRODUCT_IDS";
15927
+ ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["CREATED_AT"] = 5] = "CREATED_AT";
15928
+ })(ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX || (ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX = {}));
15929
+ class LocalStorageService {
15209
15930
  constructor() {
15931
+ if (typeof window.localStorage === 'undefined') {
15932
+ console.warn('Local storage is not supported in this environment');
15933
+ return;
15934
+ }
15210
15935
  this.spots = new Map();
15211
15936
  // Sync local storage with the current state
15212
15937
  this.syncLocalStorage();
@@ -15214,19 +15939,23 @@ class LocalStorage {
15214
15939
  this.removeExpiredSpots();
15215
15940
  }
15216
15941
  static getInstance() {
15217
- if (!LocalStorage.instance) {
15218
- LocalStorage.instance = new LocalStorage();
15942
+ if (!LocalStorageService.instance) {
15943
+ LocalStorageService.instance = new LocalStorageService();
15219
15944
  }
15220
- return LocalStorage.instance;
15945
+ return LocalStorageService.instance;
15221
15946
  }
15222
15947
  syncLocalStorage() {
15223
- const localStorageData = localStorage.getItem(LocalStorage.localStorageKey);
15224
- // TODO: Encrypt the data before storing it in the local storage
15948
+ const localStorageData = window.localStorage.getItem(LocalStorageService.localStorageKey);
15225
15949
  if (localStorageData) {
15226
15950
  try {
15227
- const parsedData = JSON.parse(localStorageData);
15951
+ const decryptedData = this.decryptData(localStorageData);
15952
+ const parsedData = JSON.parse(decryptedData);
15228
15953
  if (parsedData && typeof parsedData === 'object') {
15229
- this.spots = this.objToMap(parsedData);
15954
+ const data = {};
15955
+ for (const [key, value] of Object.entries(parsedData)) {
15956
+ data[key] = this.arrayToObject(value);
15957
+ }
15958
+ this.spots = this.objectToMap(data);
15230
15959
  }
15231
15960
  else {
15232
15961
  this.clearLocalStorage();
@@ -15239,43 +15968,176 @@ class LocalStorage {
15239
15968
  }
15240
15969
  }
15241
15970
  setSpot(spotId, data) {
15971
+ var _a;
15242
15972
  data.createdAt = Date.now();
15243
- this.spots.set(spotId, data);
15973
+ (_a = this.spots) === null || _a === void 0 ? void 0 : _a.set(spotId, data);
15244
15974
  this.updateLocalStorage();
15245
15975
  }
15246
- getSpot(spotId) {
15247
- return this.spots.get(spotId);
15248
- }
15249
15976
  removeSpot(spotId) {
15250
- this.spots.delete(spotId);
15977
+ var _a;
15978
+ (_a = this.spots) === null || _a === void 0 ? void 0 : _a.delete(spotId);
15251
15979
  this.updateLocalStorage();
15252
15980
  }
15981
+ getSpot(spotId) {
15982
+ var _a;
15983
+ return (_a = this.spots) === null || _a === void 0 ? void 0 : _a.get(spotId);
15984
+ }
15985
+ getSpots() {
15986
+ if (!this.spots)
15987
+ return undefined;
15988
+ return this.mapToObject(this.spots);
15989
+ }
15253
15990
  updateLocalStorage() {
15254
- const data = this.mapToObj(this.spots);
15255
- localStorage.setItem(LocalStorage.localStorageKey, JSON.stringify(data));
15991
+ if (!this.spots)
15992
+ return undefined;
15993
+ const data = this.mapToObject(this.spots);
15994
+ const dataArray = {};
15995
+ for (const [key, value] of Object.entries(data)) {
15996
+ dataArray[key] = this.objectToArray(value);
15997
+ }
15998
+ try {
15999
+ const encryptedData = this.encryptData(JSON.stringify(dataArray));
16000
+ window.localStorage.setItem(LocalStorageService.localStorageKey, encryptedData);
16001
+ }
16002
+ catch (_a) {
16003
+ // If there is an error parsing the data, clear the local storage to prevent any issues
16004
+ this.clearLocalStorage();
16005
+ }
15256
16006
  }
15257
16007
  clearLocalStorage() {
15258
- localStorage.removeItem(LocalStorage.localStorageKey);
16008
+ window.localStorage.removeItem(LocalStorageService.localStorageKey);
15259
16009
  }
15260
16010
  removeExpiredSpots() {
16011
+ var _a;
15261
16012
  const currentTime = Date.now();
15262
- this.spots.forEach((spot, spotId) => {
15263
- var _a;
15264
- if (currentTime - ((_a = spot.createdAt) !== null && _a !== void 0 ? _a : 0) > LocalStorage.spotExpirationTime) {
15265
- this.spots.delete(spotId);
16013
+ (_a = this.spots) === null || _a === void 0 ? void 0 : _a.forEach((spot, spotId) => {
16014
+ var _a, _b;
16015
+ if (currentTime - ((_a = spot.createdAt) !== null && _a !== void 0 ? _a : 0) > LocalStorageService.spotExpirationTime) {
16016
+ (_b = this.spots) === null || _b === void 0 ? void 0 : _b.delete(spotId);
15266
16017
  }
15267
16018
  });
15268
16019
  this.updateLocalStorage();
15269
16020
  }
15270
- mapToObj(map) {
16021
+ mapToObject(map) {
15271
16022
  return Object.fromEntries(map);
15272
16023
  }
15273
- objToMap(obj) {
16024
+ objectToMap(obj) {
15274
16025
  return new Map(Object.entries(obj));
15275
16026
  }
16027
+ objectToArray(obj) {
16028
+ return [obj.placementId, obj.spotId, obj.spotType, obj.events, obj.productIds, obj.createdAt];
16029
+ }
16030
+ arrayToObject(arr) {
16031
+ return {
16032
+ placementId: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.PLACEMENT_ID],
16033
+ spotId: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.SPOT_ID],
16034
+ spotType: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.SPOT_TYPE],
16035
+ events: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.EVENTS],
16036
+ productIds: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.PRODUCT_IDS],
16037
+ createdAt: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.CREATED_AT],
16038
+ };
16039
+ }
16040
+ encryptData(data) {
16041
+ if (!LocalStorageService.encryptData)
16042
+ return data;
16043
+ // For now, we are using base64 encoding to encrypt the data
16044
+ // Later we will use Jose encryption
16045
+ const encryptedData = btoa(data);
16046
+ return encryptedData;
16047
+ }
16048
+ decryptData(data) {
16049
+ if (!LocalStorageService.encryptData)
16050
+ return data;
16051
+ // For now, we are using base64 encoding to encrypt
16052
+ // Later we will use Jose encryption
16053
+ const decryptedData = atob(data);
16054
+ return decryptedData;
16055
+ }
16056
+ }
16057
+ LocalStorageService.localStorageKey = 'lc_rmn';
16058
+ LocalStorageService.spotExpirationTime = 1000 * 60 * 60 * 24 * 7; // 7 days
16059
+ LocalStorageService.encryptData = true;
16060
+
16061
+ /**
16062
+ * PubsubService class
16063
+ * Manages event subscriptions and publications
16064
+ * @template IRmnEventMap A record type defining the structure of events and their data
16065
+ */
16066
+ class PubsubService {
16067
+ constructor() {
16068
+ /**
16069
+ * Object to store subscribers for each event type
16070
+ */
16071
+ this.subscribers = {};
16072
+ }
16073
+ static getInstance() {
16074
+ if (!PubsubService.instance) {
16075
+ PubsubService.instance = new PubsubService();
16076
+ }
16077
+ return PubsubService.instance;
16078
+ }
16079
+ /**
16080
+ * Subscribe to an event
16081
+ * @param eventType - The type of event to subscribe to
16082
+ * @param callback - The function to be called when the event is published
16083
+ * @returns A function to unsubscribe from the event
16084
+ *
16085
+ * @Example:
16086
+ * const unsubscribe = pubSub.subscribe('userLogin', (data) => {
16087
+ * console.log(`User ${data.username} logged in`);
16088
+ * });
16089
+ */
16090
+ subscribe(eventType, callback) {
16091
+ if (!this.subscribers[eventType]) {
16092
+ this.subscribers[eventType] = [];
16093
+ }
16094
+ this.subscribers[eventType].push(callback);
16095
+ // Return an unsubscribe function
16096
+ return () => {
16097
+ this.subscribers[eventType] = this.subscribers[eventType].filter((cb) => cb !== callback);
16098
+ };
16099
+ }
16100
+ /**
16101
+ * Publish an event
16102
+ * @param eventType - The type of event to publish
16103
+ * @param data - The data to be passed to the event subscribers
16104
+ *
16105
+ * @Example:
16106
+ * pubSub.publish('userLogin', { username: 'john_doe', timestamp: Date.now() });
16107
+ */
16108
+ publish(eventType, data) {
16109
+ if (!this.subscribers[eventType]) {
16110
+ return;
16111
+ }
16112
+ this.subscribers[eventType].forEach((callback) => callback(data));
16113
+ }
15276
16114
  }
15277
- LocalStorage.localStorageKey = 'lc_rmn';
15278
- LocalStorage.spotExpirationTime = 1000 * 60 * 60 * 24 * 7; // 7 days
16115
+ /**
16116
+ * Usage Example:
16117
+ *
16118
+ * interface IRmnEventMap {
16119
+ * userLogin: { username: string; timestamp: number };
16120
+ * pageView: { url: string; timestamp: number };
16121
+ * }
16122
+ *
16123
+ * const pubSub = new PubsubService<IRmnEventMap>();
16124
+ *
16125
+ * // Subscribe to events
16126
+ * const unsubscribeLogin = pubSub.subscribe('userLogin', (data) => {
16127
+ * console.log(`User ${data.username} logged in at ${new Date(data.timestamp)}`);
16128
+ * });
16129
+ *
16130
+ * pubSub.subscribe('pageView', (data) => {
16131
+ * console.log(`Page ${data.url} viewed at ${new Date(data.timestamp)}`);
16132
+ * });
16133
+ *
16134
+ * // Publish events
16135
+ * pubSub.publish('userLogin', { username: 'john_doe', timestamp: Date.now() });
16136
+ * pubSub.publish('pageView', { url: '/home', timestamp: Date.now() });
16137
+ *
16138
+ * // Unsubscribe from an event
16139
+ * unsubscribeLogin();
16140
+ */
15279
16141
 
15280
16142
  class ResizeObserverService {
15281
16143
  constructor({ element, maxSize, minScale }) {
@@ -15345,36 +16207,6 @@ class ResizeObserverService {
15345
16207
  }
15346
16208
  }
15347
16209
 
15348
- function calculateScaleFactor(elementScale) {
15349
- // Step 1: Apply square root for non-linear scaling
15350
- // This creates a more gradual scaling effect, especially for larger changes
15351
- // For example:
15352
- // - elementScale of 0.25 (1/4 size) becomes 0.5
15353
- // - elementScale of 1 (unchanged) remains 1
15354
- // - elementScale of 4 (4x size) becomes 2
15355
- const baseFactor = Math.sqrt(elementScale);
15356
- // Step 2: Apply additional dampening to further soften the scaling effect
15357
- // The dampening factor (0.5) can be adjusted:
15358
- // - Lower values (closer to 0) make scaling more subtle
15359
- // - Higher values (closer to 1) make scaling more pronounced
15360
- const dampening = 0.35;
15361
- // Calculate the scaleFactor:
15362
- // 1. (baseFactor - 1) represents the change from the original size
15363
- // 2. Multiply by dampening to reduce the effect
15364
- // 3. Add 1 to center the scaling around the original size
15365
- // For example, if baseFactor is 2:
15366
- // scaleFactor = 1 + (2 - 1) * 0.5 = 1.5
15367
- const scaleFactor = 1 + (baseFactor - 1) * dampening;
15368
- // Step 3: Define the allowed range for the scale factor
15369
- // This ensures that the font size never changes too drastically
15370
- const minScale = 0.35; // Font will never be smaller than 50% of original
15371
- const maxScale = 1.5; // Font will never be larger than 150% of original
15372
- // Step 4: Clamp the scale factor to the defined range
15373
- // Math.min ensures the value doesn't exceed maxScale
15374
- // Math.max ensures the value isn't less than minScale
15375
- return Math.max(minScale, Math.min(maxScale, scaleFactor));
15376
- }
15377
-
15378
16210
  const CAROUSEL_COMPONENT_STYLE = ({ width, height, fluid }) => `
15379
16211
  :host {
15380
16212
  position: relative;
@@ -15389,11 +16221,13 @@ const CAROUSEL_COMPONENT_STYLE = ({ width, height, fluid }) => `
15389
16221
  position: relative;
15390
16222
  height: 100%;
15391
16223
  width: 100%;
16224
+ display: flex;
16225
+ transition: transform 0.5s ease-in-out;
15392
16226
  }
15393
16227
 
15394
16228
  .slide {
15395
- display: none;
15396
-
16229
+ flex: 0 0 100%;
16230
+ display: flex;
15397
16231
  justify-content: center;
15398
16232
  align-items: center;
15399
16233
  height: 100%;
@@ -15698,9 +16532,9 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
15698
16532
  renderSlides() {
15699
16533
  const slidesContainer = document.createElement('div');
15700
16534
  slidesContainer.className = 'slides';
15701
- this.slides.forEach((slide, index) => {
16535
+ this.slides.forEach((slide) => {
15702
16536
  const slideElement = document.createElement('div');
15703
- slideElement.className = `slide ${index === this.currentSlide ? 'active' : ''}`;
16537
+ slideElement.className = 'slide';
15704
16538
  if (slide instanceof HTMLElement) {
15705
16539
  slideElement.appendChild(slide);
15706
16540
  }
@@ -15779,10 +16613,9 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
15779
16613
  updateCarousel() {
15780
16614
  if (!this.slidesContainer)
15781
16615
  return;
15782
- const slides = Array.from(this.slidesContainer.children);
15783
- slides.forEach((slide, index) => {
15784
- slide.classList.toggle('active', index === this.currentSlide);
15785
- });
16616
+ // Calculate the translation distance based on current slide
16617
+ const translateX = -this.currentSlide * 100;
16618
+ this.slidesContainer.style.transform = `translateX(${translateX}%)`;
15786
16619
  this.updateDots();
15787
16620
  }
15788
16621
  updateDots() {
@@ -16206,12 +17039,13 @@ function spotHtmlStringToElement(htmlString) {
16206
17039
  spot.className = 'spot';
16207
17040
  spot.innerHTML = htmlString;
16208
17041
  Object.assign(spot.style, {
16209
- position: 'relative',
16210
17042
  display: 'block',
16211
17043
  width: '100%',
16212
17044
  height: '100%',
16213
17045
  margin: '0',
16214
17046
  padding: '0',
17047
+ containerType: 'inline-size',
17048
+ position: 'relative',
16215
17049
  });
16216
17050
  return spot;
16217
17051
  }
@@ -17081,7 +17915,6 @@ const STYLES$6 = ({ textColor = '#ffffff', ctaTextColor = textColor, ctaBorderCo
17081
17915
  box-sizing: border-box;
17082
17916
  color: ${textColor};
17083
17917
  cursor: pointer;
17084
- container-type: inline-size;
17085
17918
  }
17086
17919
 
17087
17920
  .${prefix}__text {
@@ -17097,7 +17930,7 @@ const STYLES$6 = ({ textColor = '#ffffff', ctaTextColor = textColor, ctaBorderCo
17097
17930
  .${prefix}__header {
17098
17931
  font-size: 24px;
17099
17932
  margin: 0;
17100
- font-family: "Cormorant";
17933
+ font-family: "Cormorant", system-ui;
17101
17934
  font-style: normal;
17102
17935
  font-weight: 300;
17103
17936
  line-height: normal;
@@ -17216,7 +18049,6 @@ const STYLES$5 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
17216
18049
  height: 100%;
17217
18050
  display: block;
17218
18051
  position: relative;
17219
- container-type: inline-size;
17220
18052
  }
17221
18053
 
17222
18054
  .${prefix}__content {
@@ -17407,15 +18239,20 @@ function rbHomepageHeroThreeTileTemplate(spot, config) {
17407
18239
  const STYLES$4 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextColor = textColor, primaryImage, mobilePrimaryImage = primaryImage, }, { prefix }) => `
17408
18240
  <style>
17409
18241
  .${prefix} {
18242
+ width: 100%;
18243
+ height: 100%;
18244
+ background-color: transparent;
18245
+ cursor: pointer;
18246
+ position: relative;
18247
+ }
18248
+
18249
+ .${prefix}__content {
17410
18250
  width: 100%;
17411
18251
  height: 100%;
17412
18252
  display: flex;
17413
18253
  flex-direction: column-reverse;
17414
18254
  background-color: transparent;
17415
18255
  gap: 6px;
17416
- cursor: pointer;
17417
- container-type: inline-size;
17418
- position: relative;
17419
18256
  }
17420
18257
 
17421
18258
  .${prefix}__image {
@@ -17446,7 +18283,7 @@ const STYLES$4 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
17446
18283
  font-size: 18px;
17447
18284
  margin: 0;
17448
18285
  color: inherit;
17449
- font-family: "Cormorant";
18286
+ font-family: "Cormorant", system-ui;
17450
18287
  font-style: normal;
17451
18288
  font-weight: 700;
17452
18289
  line-height: normal;
@@ -17488,7 +18325,7 @@ const STYLES$4 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
17488
18325
  }
17489
18326
 
17490
18327
  @container (min-width: 768px) {
17491
- .${prefix} {
18328
+ .${prefix}__content {
17492
18329
  flex-direction: row;
17493
18330
  }
17494
18331
  .${prefix}__image {
@@ -17543,12 +18380,14 @@ function rbHomepageHeroTwoTileTemplate(spot, config) {
17543
18380
  ${GFONT_CORMORANT}
17544
18381
  ${STYLES$4(spot, config)}
17545
18382
  <div class="${prefix}">
17546
- <div class="${prefix}__text">
17547
- ${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
17548
- ${spot.description ? `<p class="${prefix}__description">${spot.description}</p>` : ''}
17549
- ${spot.ctaText ? `<span class="${prefix}__cta-button">${spot.ctaText}</span>` : ''}
17550
- </div>
17551
- <div class="${prefix}__image"></div>
18383
+ <div class="${prefix}__content">
18384
+ <div class="${prefix}__text">
18385
+ ${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
18386
+ ${spot.description ? `<p class="${prefix}__description">${spot.description}</p>` : ''}
18387
+ ${spot.ctaText ? `<span class="${prefix}__cta-button">${spot.ctaText}</span>` : ''}
18388
+ </div>
18389
+ <div class="${prefix}__image"></div>
18390
+ </div>
17552
18391
  </div>
17553
18392
  `;
17554
18393
  }
@@ -17571,12 +18410,10 @@ const STYLES$3 = ({ textColor = '#ffffff', ctaTextColor = textColor, ctaBorderCo
17571
18410
  overflow: hidden;
17572
18411
  cursor: pointer;
17573
18412
  color: ${textColor};
17574
- container-type: inline-size;
17575
18413
  }
17576
18414
 
17577
18415
  .${prefix}__text {
17578
18416
  padding: 20px;
17579
- width: 70%;
17580
18417
  display: flex;
17581
18418
  flex-direction: column;
17582
18419
  justify-content: center;
@@ -17588,7 +18425,7 @@ const STYLES$3 = ({ textColor = '#ffffff', ctaTextColor = textColor, ctaBorderCo
17588
18425
  color: inherit;
17589
18426
  margin: 0;
17590
18427
  font-size: 20px;
17591
- font-family: "Cormorant";
18428
+ font-family: "Cormorant", system-ui;
17592
18429
  font-style: normal;
17593
18430
  font-weight: 300;
17594
18431
  line-height: normal;
@@ -17707,7 +18544,6 @@ const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = pr
17707
18544
  background-size: cover;
17708
18545
  background-position: center;
17709
18546
  background-repeat: no-repeat;
17710
- container-type: inline-size;
17711
18547
  position: relative;
17712
18548
  }
17713
18549
 
@@ -17777,12 +18613,7 @@ const STYLES$1 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = pr
17777
18613
  border-radius: 5px;
17778
18614
  overflow: hidden;
17779
18615
  cursor: pointer;
17780
- container-type: inline-size;
17781
- }
17782
-
17783
- .${prefix}__text {
17784
- padding: 10px;
17785
- width: 70%;
18616
+ position: relative;
17786
18617
  }
17787
18618
 
17788
18619
  .${prefix}__header {
@@ -17793,6 +18624,7 @@ const STYLES$1 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = pr
17793
18624
  font-style: normal;
17794
18625
  font-weight: 400;
17795
18626
  margin: 0;
18627
+ padding: 10px;
17796
18628
  }
17797
18629
 
17798
18630
  @container (min-width: 640px) {
@@ -17810,9 +18642,7 @@ function rbSmallCategoryImageToutTemplate(spot, config) {
17810
18642
  ${GFONT_CORMORANT}
17811
18643
  ${STYLES$1(spot, config)}
17812
18644
  <div class="${prefix}">
17813
- <div class="${prefix}__text">
17814
- ${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
17815
- </div>
18645
+ ${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
17816
18646
  </div>
17817
18647
  `;
17818
18648
  }
@@ -17827,7 +18657,6 @@ const STYLES = ({ textColor = '#000000', backgroundColor = 'transparent', primar
17827
18657
  display: flex;
17828
18658
  flex-direction: column;
17829
18659
  border-radius: 5px;
17830
- container-type: inline-size;
17831
18660
  }
17832
18661
 
17833
18662
  .${prefix}__image {
@@ -17963,94 +18792,198 @@ const SPOT_TEMPLATE_HTML_ELEMENT = (spot, config) => {
17963
18792
  return spotHtmlStringToElement(spotHtmlString);
17964
18793
  };
17965
18794
 
17966
- /**
17967
- * PubSub class
17968
- * Manages event subscriptions and publications
17969
- * @template IEventMap A record type defining the structure of events and their data
17970
- */
17971
- class PubSub {
18795
+ // For the moment, we will only focus on sites that use Google Analytics,
18796
+ // but we will add support for other analytics tools in the future.
18797
+ var AnalyticsTool;
18798
+ (function (AnalyticsTool) {
18799
+ AnalyticsTool["GoogleAnalytics"] = "google-analytics";
18800
+ AnalyticsTool["Other"] = "Other";
18801
+ })(AnalyticsTool || (AnalyticsTool = {}));
18802
+
18803
+ class DataLayerMonitor {
18804
+ constructor() {
18805
+ if (!window.dataLayer) {
18806
+ return;
18807
+ }
18808
+ this.originalPush = window.dataLayer.push;
18809
+ }
18810
+ static getInstance() {
18811
+ if (!DataLayerMonitor.instance) {
18812
+ DataLayerMonitor.instance = new DataLayerMonitor();
18813
+ }
18814
+ return DataLayerMonitor.instance;
18815
+ }
18816
+ setListener(listener) {
18817
+ this.listener = listener;
18818
+ }
18819
+ start() {
18820
+ window.dataLayer.push = (...args) => {
18821
+ const result = this.originalPush.apply(window.dataLayer, args);
18822
+ const pushedEvent = args[0];
18823
+ if (this.listener) {
18824
+ const normalizedData = this.cleanEventData(pushedEvent);
18825
+ if (normalizedData) {
18826
+ this.listener(normalizedData);
18827
+ }
18828
+ }
18829
+ return result;
18830
+ };
18831
+ }
18832
+ cleanEventData(data) {
18833
+ const eventName = getEventTypeFromRawEvent(data.event);
18834
+ if (!eventName) {
18835
+ return null;
18836
+ }
18837
+ const productIds = extractDeepIds(data.value);
18838
+ return {
18839
+ event: eventName,
18840
+ productIds,
18841
+ };
18842
+ }
18843
+ stop() {
18844
+ if (this.originalPush) {
18845
+ window.dataLayer.push = this.originalPush;
18846
+ }
18847
+ this.listener = undefined;
18848
+ }
18849
+ }
18850
+
18851
+ // @TODO: Add support for user to push events to our own data layer, if they don't use any analytics tool.
18852
+ // window.rmnDataLayer = window.rmnDataLayer || [];
18853
+ class MonitorService {
17972
18854
  constructor() {
17973
- /**
17974
- * Object to store subscribers for each event type
17975
- */
17976
- this.subscribers = {};
18855
+ const analyticsTool = this.detectAnalyticsTool();
18856
+ switch (analyticsTool) {
18857
+ case AnalyticsTool.GoogleAnalytics:
18858
+ this.implementedMonitor = DataLayerMonitor.getInstance();
18859
+ break;
18860
+ case AnalyticsTool.Other:
18861
+ default:
18862
+ console.warn('This site uses an unsupported analytics tool.');
18863
+ break;
18864
+ }
18865
+ if (analyticsTool === AnalyticsTool.Other) {
18866
+ return;
18867
+ }
18868
+ this.pubSubService = PubsubService.getInstance();
18869
+ this.localStorageService = LocalStorageService.getInstance();
17977
18870
  }
17978
18871
  static getInstance() {
17979
- if (!PubSub.instance) {
17980
- PubSub.instance = new PubSub();
18872
+ if (!MonitorService.instance) {
18873
+ MonitorService.instance = new MonitorService();
17981
18874
  }
17982
- return PubSub.instance;
18875
+ return MonitorService.instance;
17983
18876
  }
17984
- /**
17985
- * Subscribe to an event
17986
- * @param eventType - The type of event to subscribe to
17987
- * @param callback - The function to be called when the event is published
17988
- * @returns A function to unsubscribe from the event
17989
- *
17990
- * @Example:
17991
- * const unsubscribe = pubSub.subscribe('userLogin', (data) => {
17992
- * console.log(`User ${data.username} logged in`);
17993
- * });
17994
- */
17995
- subscribe(eventType, callback) {
17996
- if (!this.subscribers[eventType]) {
17997
- this.subscribers[eventType] = [];
18877
+ start() {
18878
+ if (!this.implementedMonitor)
18879
+ return;
18880
+ this.implementedMonitor.setListener(async (eventData) => {
18881
+ var _a;
18882
+ await this.matchAndFireEvent(eventData, (_a = this.localStorageService) === null || _a === void 0 ? void 0 : _a.getSpots());
18883
+ });
18884
+ this.implementedMonitor.start();
18885
+ }
18886
+ async matchAndFireEvent(eventData, spots) {
18887
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
18888
+ if (!spots)
18889
+ return;
18890
+ const eventProductIds = new Set(eventData.productIds);
18891
+ for (const spot of Object.values(spots)) {
18892
+ if (!spot.productIds.length)
18893
+ continue;
18894
+ const hasCommonProductIds = spot.productIds.find((productId) => eventProductIds.has(productId));
18895
+ if (hasCommonProductIds) {
18896
+ switch (eventData.event) {
18897
+ case exports.RMN_SPOT_EVENT.ADD_TO_CART:
18898
+ await this.fireAndPublishSpotEvent({
18899
+ spotEvent: exports.RMN_SPOT_EVENT.ADD_TO_CART,
18900
+ eventUrl: (_b = (_a = spot.events.find((event) => event.event === exports.RMN_SPOT_EVENT.ADD_TO_CART)) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : '',
18901
+ placementId: spot.placementId,
18902
+ spotId: spot.spotId,
18903
+ });
18904
+ break;
18905
+ case exports.RMN_SPOT_EVENT.REMOVE_FROM_CART:
18906
+ await this.fireAndPublishSpotEvent({
18907
+ spotEvent: exports.RMN_SPOT_EVENT.REMOVE_FROM_CART,
18908
+ eventUrl: (_d = (_c = spot.events.find((event) => event.event === exports.RMN_SPOT_EVENT.REMOVE_FROM_CART)) === null || _c === void 0 ? void 0 : _c.url) !== null && _d !== void 0 ? _d : '',
18909
+ placementId: spot.placementId,
18910
+ spotId: spot.spotId,
18911
+ });
18912
+ break;
18913
+ case exports.RMN_SPOT_EVENT.PURCHASE:
18914
+ await this.fireAndPublishSpotEvent({
18915
+ spotEvent: exports.RMN_SPOT_EVENT.PURCHASE,
18916
+ eventUrl: (_f = (_e = spot.events.find((event) => event.event === exports.RMN_SPOT_EVENT.PURCHASE)) === null || _e === void 0 ? void 0 : _e.url) !== null && _f !== void 0 ? _f : '',
18917
+ placementId: spot.placementId,
18918
+ spotId: spot.spotId,
18919
+ });
18920
+ break;
18921
+ case exports.RMN_SPOT_EVENT.ADD_TO_WISHLIST:
18922
+ await this.fireAndPublishSpotEvent({
18923
+ spotEvent: exports.RMN_SPOT_EVENT.ADD_TO_WISHLIST,
18924
+ eventUrl: (_h = (_g = spot.events.find((event) => event.event === exports.RMN_SPOT_EVENT.ADD_TO_WISHLIST)) === null || _g === void 0 ? void 0 : _g.url) !== null && _h !== void 0 ? _h : '',
18925
+ placementId: spot.placementId,
18926
+ spotId: spot.spotId,
18927
+ });
18928
+ break;
18929
+ case exports.RMN_SPOT_EVENT.BUY_NOW:
18930
+ await this.fireAndPublishSpotEvent({
18931
+ spotEvent: exports.RMN_SPOT_EVENT.BUY_NOW,
18932
+ eventUrl: (_k = (_j = spot.events.find((event) => event.event === exports.RMN_SPOT_EVENT.BUY_NOW)) === null || _j === void 0 ? void 0 : _j.url) !== null && _k !== void 0 ? _k : '',
18933
+ placementId: spot.placementId,
18934
+ spotId: spot.spotId,
18935
+ });
18936
+ break;
18937
+ }
18938
+ }
17998
18939
  }
17999
- this.subscribers[eventType].push(callback);
18000
- // Return an unsubscribe function
18001
- return () => {
18002
- this.subscribers[eventType] = this.subscribers[eventType].filter((cb) => cb !== callback);
18003
- };
18004
18940
  }
18005
- /**
18006
- * Publish an event
18007
- * @param eventType - The type of event to publish
18008
- * @param data - The data to be passed to the event subscribers
18009
- *
18010
- * @Example:
18011
- * pubSub.publish('userLogin', { username: 'john_doe', timestamp: Date.now() });
18012
- */
18013
- publish(eventType, data) {
18014
- if (!this.subscribers[eventType]) {
18941
+ async fireAndPublishSpotEvent({ spotEvent, eventUrl, placementId, spotId, }) {
18942
+ await fireEvent({
18943
+ event: spotEvent,
18944
+ eventUrl,
18945
+ });
18946
+ if (!this.pubSubService)
18015
18947
  return;
18948
+ this.pubSubService.publish(exports.RMN_EVENT.SPOT_EVENT, {
18949
+ eventType: spotEvent,
18950
+ placementId,
18951
+ spotId,
18952
+ });
18953
+ }
18954
+ detectAnalyticsTool() {
18955
+ let analyticsTool = AnalyticsTool.Other;
18956
+ // Check for Google Analytics
18957
+ if (typeof window.ga !== 'undefined') {
18958
+ analyticsTool = AnalyticsTool.GoogleAnalytics;
18016
18959
  }
18017
- this.subscribers[eventType].forEach((callback) => callback(data));
18960
+ // Check for Google Analytics 4
18961
+ if (typeof window.gtag !== 'undefined') {
18962
+ analyticsTool = AnalyticsTool.GoogleAnalytics;
18963
+ }
18964
+ // Check for Google Tag Manager
18965
+ if (typeof window.google_tag_manager !== 'undefined') {
18966
+ analyticsTool = AnalyticsTool.GoogleAnalytics;
18967
+ }
18968
+ // @TODO: Add support for other analytics tools
18969
+ // Check for Heap Analytics
18970
+ // Check for Mixpanel
18971
+ // Check for Woopra
18972
+ // Check for Segment
18973
+ // Check for Amplitude
18974
+ return analyticsTool;
18018
18975
  }
18019
18976
  }
18020
- /**
18021
- * Usage Example:
18022
- *
18023
- * interface IEventMap {
18024
- * userLogin: { username: string; timestamp: number };
18025
- * pageView: { url: string; timestamp: number };
18026
- * }
18027
- *
18028
- * const pubSub = new PubSub<IEventMap>();
18029
- *
18030
- * // Subscribe to events
18031
- * const unsubscribeLogin = pubSub.subscribe('userLogin', (data) => {
18032
- * console.log(`User ${data.username} logged in at ${new Date(data.timestamp)}`);
18033
- * });
18034
- *
18035
- * pubSub.subscribe('pageView', (data) => {
18036
- * console.log(`Page ${data.url} viewed at ${new Date(data.timestamp)}`);
18037
- * });
18038
- *
18039
- * // Publish events
18040
- * pubSub.publish('userLogin', { username: 'john_doe', timestamp: Date.now() });
18041
- * pubSub.publish('pageView', { url: '/home', timestamp: Date.now() });
18042
- *
18043
- * // Unsubscribe from an event
18044
- * unsubscribeLogin();
18045
- */
18046
18977
 
18047
18978
  class EventService {
18048
18979
  constructor() {
18049
- this.pubSub = PubSub.getInstance();
18050
- this.localStorage = LocalStorage.getInstance();
18980
+ this.pubSubService = PubsubService.getInstance();
18981
+ this.localStorageService = LocalStorageService.getInstance();
18051
18982
  this.activeSpots = new Map();
18052
18983
  this.spotStates = new Map();
18053
18984
  this.intersectionObserver = new IntersectionObserverService();
18985
+ // Start the user monitor, which will track and check user interactions
18986
+ MonitorService.getInstance().start();
18054
18987
  }
18055
18988
  static getInstance() {
18056
18989
  if (!EventService.instance) {
@@ -18059,16 +18992,16 @@ class EventService {
18059
18992
  return EventService.instance;
18060
18993
  }
18061
18994
  subscribe(eventType, callback) {
18062
- return this.pubSub.subscribe(eventType, callback);
18995
+ return this.pubSubService.subscribe(eventType, callback);
18063
18996
  }
18064
18997
  publish(eventType, data) {
18065
- this.pubSub.publish(eventType, data);
18998
+ this.pubSubService.publish(eventType, data);
18066
18999
  }
18067
19000
  registerSpot(params) {
18068
19001
  const { placementId, spot, spotElement } = params;
18069
19002
  this.activeSpots.set(placementId, { spotElement });
18070
19003
  // Fire impression event
18071
- this.fireImpressionEvent(placementId, spot, spotElement);
19004
+ this.fireImpressionEvent(placementId, spot);
18072
19005
  // Handle intersection observer
18073
19006
  this.handleIntersectionObserver(placementId, spot, spotElement);
18074
19007
  // Attach click event listener
@@ -18143,30 +19076,42 @@ class EventService {
18143
19076
  },
18144
19077
  };
18145
19078
  }
18146
- this.spotStates.set(placementId, { ...currentState, ...updates });
19079
+ const merged = this.deepMerge(currentState, updates);
19080
+ this.spotStates.set(placementId, merged);
18147
19081
  if (publish) {
18148
- this.pubSub.publish(exports.RMN_SPOT_EVENT.LIFECYCLE_STATE, this.spotStates.get(placementId));
19082
+ this.pubSubService.publish(exports.RMN_EVENT.LIFECYCLE_STATE, this.spotStates.get(placementId));
18149
19083
  }
18150
19084
  }
18151
- async handleClick({ placementId, spot, spotElement, }) {
19085
+ deepMerge(current, updates) {
19086
+ return {
19087
+ identifier: updates.identifier
19088
+ ? { ...current.identifier, ...updates.identifier }
19089
+ : current.identifier,
19090
+ dom: updates.dom ? { ...current.dom, ...updates.dom } : current.dom,
19091
+ state: updates.state ? { ...current.state, ...updates.state } : current.state,
19092
+ displayConfig: updates.displayConfig
19093
+ ? { ...current.displayConfig, ...updates.displayConfig }
19094
+ : current.displayConfig,
19095
+ };
19096
+ }
19097
+ async handleClick({ placementId, spot }) {
18152
19098
  var _a, _b, _c;
18153
- // Publish click event
18154
- this.pubSub.publish(exports.RMN_SPOT_EVENT.CLICK, {
19099
+ this.pubSubService.publish(exports.RMN_EVENT.SPOT_EVENT, {
19100
+ eventType: exports.RMN_SPOT_EVENT.CLICK,
18155
19101
  placementId,
18156
19102
  spotId: spot.id,
18157
- spotElement,
18158
19103
  });
18159
- // Fire click event
18160
- await this.fireEvent({
19104
+ await fireEvent({
18161
19105
  event: exports.RMN_SPOT_EVENT.CLICK,
18162
19106
  eventUrl: (_b = (_a = spot.events.find((event) => event.event === exports.RMN_SPOT_EVENT.CLICK)) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : '',
18163
19107
  });
18164
19108
  // Save spot to local storage for event tracking
18165
- this.localStorage.setSpot(spot.id, {
19109
+ this.localStorageService.setSpot(spot.id, {
19110
+ placementId,
18166
19111
  spotId: spot.id,
18167
19112
  spotType: spot.spot,
18168
19113
  events: spot.events,
18169
- productIds: (_c = spot.productIds) !== null && _c !== void 0 ? _c : [1, 'GROUPING-12345', 'DAN-12345', 131398103],
19114
+ productIds: (_c = spot.productIds) !== null && _c !== void 0 ? _c : [],
18170
19115
  });
18171
19116
  }
18172
19117
  handleIntersectionObserver(placementId, _spot, spotElement) {
@@ -18181,51 +19126,20 @@ class EventService {
18181
19126
  };
18182
19127
  this.intersectionObserver.observe(spotElement, spotIsVisibleCallback);
18183
19128
  }
18184
- fireImpressionEvent(placementId, spot, spotElement) {
18185
- this.pubSub.publish(exports.RMN_SPOT_EVENT.IMPRESSION, {
19129
+ fireImpressionEvent(placementId, spot) {
19130
+ this.pubSubService.publish(exports.RMN_EVENT.SPOT_EVENT, {
19131
+ eventType: exports.RMN_SPOT_EVENT.IMPRESSION,
18186
19132
  placementId,
18187
19133
  spotId: spot.id,
18188
- spotElement,
18189
19134
  });
18190
19135
  (async () => {
18191
19136
  var _a, _b;
18192
- await this.fireEvent({
19137
+ await fireEvent({
18193
19138
  event: exports.RMN_SPOT_EVENT.IMPRESSION,
18194
19139
  eventUrl: (_b = (_a = spot.events.find((event) => event.event === exports.RMN_SPOT_EVENT.IMPRESSION)) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : '',
18195
19140
  });
18196
19141
  })();
18197
19142
  }
18198
- /**
18199
- * Fires an event using the navigator.sendBeacon method and redirects the user if the event is a click event.
18200
- *
18201
- * @param {IFireEventParams} params - The parameters for firing the event.
18202
- * @param {RMN_SPOT_EVENT} params.event - The event type.
18203
- * @param {string} params.eventUrl - The URL to which the event is sent.
18204
- * @returns {Promise<void>} - A promise that resolves when the event is fired.
18205
- */
18206
- async fireEvent({ event, eventUrl }) {
18207
- const didFireEvent = navigator.sendBeacon(eventUrl);
18208
- if (didFireEvent && event === exports.RMN_SPOT_EVENT.CLICK) {
18209
- window.location.href = this.getRedirectUrlFromPayload(eventUrl);
18210
- }
18211
- }
18212
- /**
18213
- * Extracts and decodes a URL from a base64-encoded query parameter.
18214
- *
18215
- * @param {string} url - The URL containing the base64-encoded query parameter.
18216
- * @returns {string} - The decoded URL or an empty string if decoding fails.
18217
- */
18218
- getRedirectUrlFromPayload(url) {
18219
- var _a, _b;
18220
- const base64String = (_a = new URL(url).searchParams.get('e')) !== null && _a !== void 0 ? _a : '';
18221
- try {
18222
- const data = JSON.parse(atob(base64String));
18223
- return (_b = data.ur) !== null && _b !== void 0 ? _b : '';
18224
- }
18225
- catch (_c) {
18226
- return '';
18227
- }
18228
- }
18229
19143
  }
18230
19144
 
18231
19145
  const SELECTION_API_PATH = '/spots/selection';
@@ -18258,176 +19172,6 @@ class SelectionService extends BaseApi {
18258
19172
  }
18259
19173
  }
18260
19174
 
18261
- const SPOT_EVENTS_EXAMPLE = [
18262
- {
18263
- event: exports.RMN_SPOT_EVENT.CLICK,
18264
- url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwidXIiOm51bGx9&s=hWz37kbxi_u95EVNn2aoQhc5Aas',
18265
- },
18266
- {
18267
- event: exports.RMN_SPOT_EVENT.IMPRESSION,
18268
- url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiYmEiOjEsImZxIjowfQ&s=djoysjCimurf-5T11AlNAwwLSS8',
18269
- },
18270
- {
18271
- event: exports.RMN_SPOT_EVENT.PURCHASE,
18272
- url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiZXQiOjU5fQ&s=AAPAw-3SfZ0JMzjEGFSwt9L-2S4',
18273
- },
18274
- {
18275
- event: exports.RMN_SPOT_EVENT.ADD_TO_CART,
18276
- url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiZXQiOjYwfQ&s=uzQFcjgL7m9XqUG8FvTPVN5YkZY',
18277
- },
18278
- {
18279
- event: exports.RMN_SPOT_EVENT.ADD_TO_WISHLIST,
18280
- url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiZXQiOjYzfQ&s=m3ISU_iIy-OFtXrTKpI6cJAEC0k',
18281
- },
18282
- {
18283
- event: exports.RMN_SPOT_EVENT.BUY_NOW,
18284
- url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiZXQiOjY5fQ&s=l6MOscQC-q-FkC2Ksd7w6jjySCQ',
18285
- },
18286
- ];
18287
- const RB_SPOTS_SELECTION_EXAMPLE = {
18288
- rbHomepageHeroFullImage: [
18289
- {
18290
- id: '111111_111111',
18291
- spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
18292
- variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
18293
- width: 1140,
18294
- height: 640,
18295
- header: 'Artisanal Craft Beer Collection',
18296
- description: 'Discover our curated selection of small-batch, flavor-packed craft beers.',
18297
- ctaText: 'Explore the Collection',
18298
- textColor: '#ffffff',
18299
- ctaTextColor: '#ffffff',
18300
- primaryImage: 'https://placehold.co/1140x640/png?text=Craft+Beer+Collection',
18301
- mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Craft+Beer',
18302
- events: SPOT_EVENTS_EXAMPLE,
18303
- },
18304
- {
18305
- id: '222222_222222',
18306
- spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
18307
- variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
18308
- width: 1140,
18309
- height: 640,
18310
- header: 'Summer Wine Spectacular',
18311
- description: 'Refresh your palate with our handpicked selection of crisp, summer wines.',
18312
- ctaText: 'Shop Summer Wines',
18313
- textColor: '#000000',
18314
- ctaTextColor: '#ffffff',
18315
- primaryImage: 'https://placehold.co/1140x640/png?text=Summer+Wines',
18316
- mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Summer+Wines',
18317
- events: SPOT_EVENTS_EXAMPLE,
18318
- },
18319
- ],
18320
- rbHomepageHeroTwoTile: [
18321
- {
18322
- id: '333333_333333',
18323
- spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
18324
- variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
18325
- width: 1140,
18326
- height: 640,
18327
- header: 'Whiskey Wonderland',
18328
- description: 'Embark on a journey through our premium whiskey selection.',
18329
- ctaText: 'Discover Whiskeys',
18330
- textColor: '#ffffff',
18331
- backgroundColor: '#2c1a05',
18332
- ctaTextColor: '#2c1a05',
18333
- primaryImage: 'https://placehold.co/1140x640/png?text=Whiskey+Collection',
18334
- mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Whiskey',
18335
- events: SPOT_EVENTS_EXAMPLE,
18336
- },
18337
- ],
18338
- rbHomepageHeroThreeTile: [
18339
- {
18340
- id: '444444_444444',
18341
- spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
18342
- variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
18343
- width: 1140,
18344
- height: 640,
18345
- header: 'Cocktail Essentials',
18346
- description: 'Stock your bar with premium spirits and mixers for the perfect cocktail.',
18347
- ctaText: 'Build Your Bar',
18348
- textColor: '#ffffff',
18349
- backgroundColor: '#1a3c4d',
18350
- ctaTextColor: '#1a3c4d',
18351
- primaryImage: 'https://placehold.co/1140x640/png?text=Cocktail+Spirits',
18352
- secondaryImage: 'https://placehold.co/1140x640/png?text=Cocktail+Mixers',
18353
- mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Cocktail+Kit',
18354
- mobileSecondaryImage: 'https://placehold.co/640x320/png?text=Mobile+Cocktail+Mixers',
18355
- events: SPOT_EVENTS_EXAMPLE,
18356
- },
18357
- ],
18358
- rbLargeCategoryImageTout: [
18359
- {
18360
- id: '555555_555555',
18361
- spot: exports.RMN_SPOT_TYPE.RB_LARGE_CATEGORY_IMAGE_TOUT,
18362
- variant: exports.RMN_SPOT_TYPE.RB_LARGE_CATEGORY_IMAGE_TOUT,
18363
- width: 468,
18364
- height: 410,
18365
- header: 'Rare & Limited Edition',
18366
- description: 'Discover our collection of hard-to-find and limited release spirits.',
18367
- textColor: '#ffffff',
18368
- ctaTextColor: '#ffffff',
18369
- primaryImage: 'https://placehold.co/468x410/png?text=Rare+Spirits',
18370
- mobilePrimaryImage: 'https://placehold.co/468x410/png?text=Mobile+Rare+Spirits',
18371
- ctaText: 'Shop Rare Spirits',
18372
- events: SPOT_EVENTS_EXAMPLE,
18373
- },
18374
- ],
18375
- rbSmallDiscoverTout: [
18376
- {
18377
- id: '666666_666666',
18378
- spot: exports.RMN_SPOT_TYPE.RB_SMALL_DISCOVER_TOUT,
18379
- variant: exports.RMN_SPOT_TYPE.RB_SMALL_DISCOVER_TOUT,
18380
- width: 224,
18381
- height: 378,
18382
- header: 'Château Margaux 2015 Bordeaux',
18383
- textColor: '#ffffff',
18384
- primaryImage: 'https://placehold.co/224x378/png?text=Château+Margaux',
18385
- mobilePrimaryImage: 'https://placehold.co/224x378/png?text=Mobile+Château+Margaux',
18386
- events: SPOT_EVENTS_EXAMPLE,
18387
- },
18388
- ],
18389
- rbSmallCategoryImageTout: [
18390
- {
18391
- id: '777777_777777',
18392
- spot: exports.RMN_SPOT_TYPE.RB_SMALL_CATEGORY_IMAGE_TOUT,
18393
- variant: exports.RMN_SPOT_TYPE.RB_SMALL_CATEGORY_IMAGE_TOUT,
18394
- width: 224,
18395
- height: 410,
18396
- header: 'Japanese Sake',
18397
- textColor: '#ffffff',
18398
- primaryImage: 'https://placehold.co/224x410/png?text=Japanese+Sake',
18399
- mobilePrimaryImage: 'https://placehold.co/224x410/png?text=Mobile+Japanese+Sake',
18400
- events: SPOT_EVENTS_EXAMPLE,
18401
- },
18402
- ],
18403
- rbCollectionBannerWithoutTextBlock: [
18404
- {
18405
- id: '888888_888888',
18406
- spot: exports.RMN_SPOT_TYPE.RB_COLLECTION_BANNER_WITHOUT_TEXT_BLOCK,
18407
- variant: exports.RMN_SPOT_TYPE.RB_COLLECTION_BANNER_WITHOUT_TEXT_BLOCK,
18408
- width: 887,
18409
- height: 344,
18410
- primaryImage: 'https://placehold.co/887x344/png?text=Summer+Cocktails',
18411
- mobilePrimaryImage: 'https://placehold.co/887x344/png?text=Mobile+Summer+Cocktails',
18412
- events: SPOT_EVENTS_EXAMPLE,
18413
- },
18414
- ],
18415
- rbNavigationBanner: [
18416
- {
18417
- id: '999999_999999',
18418
- spot: exports.RMN_SPOT_TYPE.RB_NAVIGATION_BANNER,
18419
- variant: exports.RMN_SPOT_TYPE.RB_NAVIGATION_BANNER,
18420
- width: 440,
18421
- height: 220,
18422
- header: 'Explore Tequilas',
18423
- textColor: '#ffffff',
18424
- primaryImage: 'https://placehold.co/440x220/png?text=Tequila+Collection',
18425
- mobilePrimaryImage: 'https://placehold.co/440x220/png?text=Mobile+Tequila+Collection',
18426
- events: SPOT_EVENTS_EXAMPLE,
18427
- },
18428
- ],
18429
- };
18430
-
18431
19175
  class LiquidCommerceRmnClient {
18432
19176
  constructor(auth) {
18433
19177
  this.selectionService = SelectionService.getInstance(auth);
@@ -18441,7 +19185,7 @@ class LiquidCommerceRmnClient {
18441
19185
  *
18442
19186
  * @param {ISpotSelectionParams} params - Spots selection parameters.
18443
19187
  *
18444
- * @return {Promise<ISpots | {error : string}>} - The spots response object.
19188
+ * @return {Promise<ISpots | { error : string }>} - The spots response object.
18445
19189
  */
18446
19190
  async spotSelection(params) {
18447
19191
  return this.selectionService.spotSelection(params);
@@ -18455,13 +19199,19 @@ class LiquidCommerceRmnClient {
18455
19199
  */
18456
19200
  async injectSpotElement(params) {
18457
19201
  var _a;
19202
+ if (typeof window === 'undefined' || typeof document === 'undefined') {
19203
+ console.warn('LiquidCommerce Rmn Sdk: Methods which create elements are only available in browser environments.');
19204
+ return;
19205
+ }
18458
19206
  const config = params.config;
18459
19207
  let inject = params.inject;
18460
19208
  if (!inject.length) {
19209
+ // Handle no spots error state
18461
19210
  this.eventService.handleSpotState('all', {
18462
19211
  state: {
18463
19212
  error: 'No spot elements provided for injection.',
18464
19213
  loading: false,
19214
+ mounted: false,
18465
19215
  },
18466
19216
  });
18467
19217
  return;
@@ -18480,9 +19230,12 @@ class LiquidCommerceRmnClient {
18480
19230
  // const response = await this.useSpotSelectionExample(inject);
18481
19231
  // Handle the response
18482
19232
  if (typeof response === 'object' && 'error' in response) {
19233
+ // Handle request error state
18483
19234
  this.eventService.handleSpotState('all', {
18484
19235
  state: {
18485
19236
  error: response.error,
19237
+ mounted: false,
19238
+ loading: false,
18486
19239
  },
18487
19240
  });
18488
19241
  return;
@@ -18491,9 +19244,11 @@ class LiquidCommerceRmnClient {
18491
19244
  const itemConfig = (_a = item.config) !== null && _a !== void 0 ? _a : config;
18492
19245
  const spots = response[item.placementId];
18493
19246
  if (!(spots === null || spots === void 0 ? void 0 : spots.length)) {
19247
+ // Handle no spots found error state
18494
19248
  this.eventService.handleSpotState(item.placementId, {
18495
19249
  state: {
18496
19250
  error: `No spots found for type "${item.spotType}".`,
19251
+ mounted: false,
18497
19252
  loading: false,
18498
19253
  },
18499
19254
  });
@@ -18502,9 +19257,11 @@ class LiquidCommerceRmnClient {
18502
19257
  const placementId = item.placementId.replace('#', '');
18503
19258
  const placement = document.getElementById(placementId);
18504
19259
  if (!placement) {
19260
+ // Handle placement not found error state
18505
19261
  this.eventService.handleSpotState(item.placementId, {
18506
19262
  state: {
18507
19263
  error: `Placement not found for id "${placementId}".`,
19264
+ mounted: false,
18508
19265
  loading: false,
18509
19266
  },
18510
19267
  });
@@ -18515,16 +19272,18 @@ class LiquidCommerceRmnClient {
18515
19272
  placement.removeAttribute('class');
18516
19273
  Object.assign(placement.style, {
18517
19274
  width: '100%',
18518
- height: 'auto',
19275
+ height: '100%',
18519
19276
  display: 'flex',
18520
19277
  justifyContent: 'center',
18521
19278
  });
19279
+ // Handle single spot
18522
19280
  if (spots.length === 1) {
18523
19281
  const isInjected = this.injectOneSpotElement(item, placement, spots[0], itemConfig);
18524
19282
  if (!isInjected) {
18525
19283
  continue;
18526
19284
  }
18527
19285
  }
19286
+ // Handle multiple spots (carousel)
18528
19287
  if (spots.length > 1) {
18529
19288
  const isInjected = this.injectCarouselSpotElement(placement, spots, itemConfig);
18530
19289
  if (!isInjected) {
@@ -18568,18 +19327,24 @@ class LiquidCommerceRmnClient {
18568
19327
  const carouselSlides = [];
18569
19328
  for (const spotItem of spots) {
18570
19329
  this.eventService.handleSpotState(placement.id, {
19330
+ identifier: {
19331
+ placementId: placement.id,
19332
+ spotType: spotItem.spot,
19333
+ spotId: spotItem.id,
19334
+ },
18571
19335
  displayConfig: {
19336
+ isSingleItem: false,
18572
19337
  isCarousel: true,
18573
19338
  isCarouselItem: true,
18574
- isSingleItem: false,
18575
19339
  },
18576
- }, false);
19340
+ });
18577
19341
  const spot = this.elementService.overrideSpotColors(spotItem, config === null || config === void 0 ? void 0 : config.colors);
18578
19342
  const content = SPOT_TEMPLATE_HTML_ELEMENT(spot, { overlay: config === null || config === void 0 ? void 0 : config.overlay });
18579
19343
  if (!content) {
18580
19344
  this.eventService.handleSpotState(placement.id, {
18581
19345
  state: {
18582
19346
  error: `Failed to inject carousel spot item element. Could not create element for type "${spot.spot}".`,
19347
+ mounted: false,
18583
19348
  loading: false,
18584
19349
  },
18585
19350
  });
@@ -18612,6 +19377,7 @@ class LiquidCommerceRmnClient {
18612
19377
  this.eventService.handleSpotState(placement.id, {
18613
19378
  state: {
18614
19379
  error: `Failed to inject spot carousel element. Could not create spot carousel element.`,
19380
+ mounted: false,
18615
19381
  loading: false,
18616
19382
  },
18617
19383
  });
@@ -18621,10 +19387,12 @@ class LiquidCommerceRmnClient {
18621
19387
  this.eventService.handleSpotState(placement.id, {
18622
19388
  dom: {
18623
19389
  spotElement: carouselElement,
19390
+ visibleOnViewport: false,
18624
19391
  },
18625
19392
  state: {
18626
19393
  mounted: true,
18627
19394
  loading: false,
19395
+ error: undefined,
18628
19396
  },
18629
19397
  });
18630
19398
  return true;
@@ -18641,18 +19409,25 @@ class LiquidCommerceRmnClient {
18641
19409
  */
18642
19410
  injectOneSpotElement(injectItem, placement, spot, config) {
18643
19411
  var _a;
18644
- const spotData = this.elementService.overrideSpotColors(spot, config === null || config === void 0 ? void 0 : config.colors);
18645
19412
  this.eventService.handleSpotState(injectItem.placementId, {
19413
+ identifier: {
19414
+ placementId: injectItem.placementId,
19415
+ spotType: injectItem.spotType,
19416
+ spotId: spot.id,
19417
+ },
18646
19418
  displayConfig: {
18647
19419
  isSingleItem: true,
19420
+ isCarousel: false,
19421
+ isCarouselItem: false,
18648
19422
  },
18649
- }, false);
18650
- // Create the spot template element
19423
+ });
19424
+ const spotData = this.elementService.overrideSpotColors(spot, config === null || config === void 0 ? void 0 : config.colors);
18651
19425
  const content = SPOT_TEMPLATE_HTML_ELEMENT(spotData, { overlay: config === null || config === void 0 ? void 0 : config.overlay });
18652
19426
  if (!content) {
18653
19427
  this.eventService.handleSpotState(injectItem.placementId, {
18654
19428
  state: {
18655
19429
  error: `Failed to inject spot element. Could not create element for type "${injectItem.spotType}".`,
19430
+ mounted: false,
18656
19431
  loading: false,
18657
19432
  },
18658
19433
  });
@@ -18673,6 +19448,7 @@ class LiquidCommerceRmnClient {
18673
19448
  this.eventService.handleSpotState(injectItem.placementId, {
18674
19449
  state: {
18675
19450
  error: `Failed to inject spot element. Could not create element for type "${injectItem.spotType}".`,
19451
+ mounted: false,
18676
19452
  loading: false,
18677
19453
  },
18678
19454
  });
@@ -18687,10 +19463,12 @@ class LiquidCommerceRmnClient {
18687
19463
  this.eventService.handleSpotState(injectItem.placementId, {
18688
19464
  dom: {
18689
19465
  spotElement,
19466
+ visibleOnViewport: false,
18690
19467
  },
18691
19468
  state: {
18692
19469
  mounted: true,
18693
19470
  loading: false,
19471
+ error: undefined,
18694
19472
  },
18695
19473
  });
18696
19474
  return true;
@@ -18711,6 +19489,8 @@ class LiquidCommerceRmnClient {
18711
19489
  this.eventService.handleSpotState(item.placementId, {
18712
19490
  state: {
18713
19491
  error: `Duplicate placement id (${item.placementId}) found. Please provide a unique placement id for each spot element.`,
19492
+ mounted: false,
19493
+ loading: false,
18714
19494
  },
18715
19495
  });
18716
19496
  return false;
@@ -18726,6 +19506,8 @@ class LiquidCommerceRmnClient {
18726
19506
  this.eventService.handleSpotState(item.placementId, {
18727
19507
  state: {
18728
19508
  error: `Invalid spot type (${item.spotType}) found. Please provide a valid spot type for each spot element.`,
19509
+ mounted: false,
19510
+ loading: false,
18729
19511
  },
18730
19512
  });
18731
19513
  continue;
@@ -18734,6 +19516,7 @@ class LiquidCommerceRmnClient {
18734
19516
  }
18735
19517
  return newInject;
18736
19518
  }
19519
+ // Initialize spots with loading state and identifiers
18737
19520
  updateSpotsState(inject) {
18738
19521
  for (const item of inject) {
18739
19522
  this.eventService.handleSpotState(item.placementId, {
@@ -18743,6 +19526,8 @@ class LiquidCommerceRmnClient {
18743
19526
  },
18744
19527
  state: {
18745
19528
  loading: true,
19529
+ mounted: false,
19530
+ error: undefined,
18746
19531
  },
18747
19532
  });
18748
19533
  }