@liquidcommercedev/rmn-sdk 1.4.6-beta.8 → 1.5.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +620 -121
- package/dist/index.esm.js +620 -122
- package/dist/types/common/helpers/uuid.helper.d.ts +49 -0
- package/dist/types/index.umd.d.ts +2 -2
- package/dist/types/modules/element/component/carousel/carousel.interface.d.ts +4 -0
- package/dist/types/modules/element/element.interface.d.ts +4 -3
- package/dist/types/modules/element/template/helper.d.ts +2 -1
- package/dist/types/modules/element/template/template.type.d.ts +1 -1
- package/dist/types/modules/event/event.interface.d.ts +5 -5
- package/dist/types/modules/event/event.service.d.ts +14 -2
- package/dist/types/modules/event/helpers/index.d.ts +1 -0
- package/dist/types/modules/event/helpers/localstorage.service.d.ts +26 -0
- package/dist/types/modules/event/pubsub.d.ts +5 -3
- package/dist/types/modules/selection/selection.interface.d.ts +1 -0
- package/dist/types/rmn-client.d.ts +9 -13
- package/dist/types/static.constant.d.ts +1 -0
- package/dist/types/types.d.ts +5 -4
- package/package.json +1 -1
- package/umd/liquidcommerce-rmn-sdk.min.js +1 -1
package/dist/index.esm.js
CHANGED
@@ -14998,7 +14998,7 @@ class BaseApi extends BaseApiAbstract {
|
|
14998
14998
|
*/
|
14999
14999
|
async post(path, data, configOverrides) {
|
15000
15000
|
let requestData = data;
|
15001
|
-
if (this.authInfo.env
|
15001
|
+
if (![RMN_ENV.LOCAL, RMN_ENV.DEVELOPMENT].includes(this.authInfo.env)) {
|
15002
15002
|
const timestamp = new Date().getTime();
|
15003
15003
|
configOverrides = {
|
15004
15004
|
...configOverrides,
|
@@ -15203,6 +15203,78 @@ class IntersectionObserverService {
|
|
15203
15203
|
}
|
15204
15204
|
}
|
15205
15205
|
|
15206
|
+
class LocalStorage {
|
15207
|
+
constructor() {
|
15208
|
+
this.spots = new Map();
|
15209
|
+
// Sync local storage with the current state
|
15210
|
+
this.syncLocalStorage();
|
15211
|
+
// Remove expired spots
|
15212
|
+
this.removeExpiredSpots();
|
15213
|
+
}
|
15214
|
+
static getInstance() {
|
15215
|
+
if (!LocalStorage.instance) {
|
15216
|
+
LocalStorage.instance = new LocalStorage();
|
15217
|
+
}
|
15218
|
+
return LocalStorage.instance;
|
15219
|
+
}
|
15220
|
+
syncLocalStorage() {
|
15221
|
+
const localStorageData = localStorage.getItem(LocalStorage.localStorageKey);
|
15222
|
+
// TODO: Encrypt the data before storing it in the local storage
|
15223
|
+
if (localStorageData) {
|
15224
|
+
try {
|
15225
|
+
const parsedData = JSON.parse(localStorageData);
|
15226
|
+
if (parsedData && typeof parsedData === 'object') {
|
15227
|
+
this.spots = this.objToMap(parsedData);
|
15228
|
+
}
|
15229
|
+
else {
|
15230
|
+
this.clearLocalStorage();
|
15231
|
+
}
|
15232
|
+
}
|
15233
|
+
catch (_a) {
|
15234
|
+
// If there is an error parsing the data, clear the local storage to prevent any issues
|
15235
|
+
this.clearLocalStorage();
|
15236
|
+
}
|
15237
|
+
}
|
15238
|
+
}
|
15239
|
+
setSpot(spotId, data) {
|
15240
|
+
data.createdAt = Date.now();
|
15241
|
+
this.spots.set(spotId, data);
|
15242
|
+
this.updateLocalStorage();
|
15243
|
+
}
|
15244
|
+
getSpot(spotId) {
|
15245
|
+
return this.spots.get(spotId);
|
15246
|
+
}
|
15247
|
+
removeSpot(spotId) {
|
15248
|
+
this.spots.delete(spotId);
|
15249
|
+
this.updateLocalStorage();
|
15250
|
+
}
|
15251
|
+
updateLocalStorage() {
|
15252
|
+
const data = this.mapToObj(this.spots);
|
15253
|
+
localStorage.setItem(LocalStorage.localStorageKey, JSON.stringify(data));
|
15254
|
+
}
|
15255
|
+
clearLocalStorage() {
|
15256
|
+
localStorage.removeItem(LocalStorage.localStorageKey);
|
15257
|
+
}
|
15258
|
+
removeExpiredSpots() {
|
15259
|
+
const currentTime = Date.now();
|
15260
|
+
this.spots.forEach((spot, spotId) => {
|
15261
|
+
var _a;
|
15262
|
+
if (currentTime - ((_a = spot.createdAt) !== null && _a !== void 0 ? _a : 0) > LocalStorage.spotExpirationTime) {
|
15263
|
+
this.spots.delete(spotId);
|
15264
|
+
}
|
15265
|
+
});
|
15266
|
+
this.updateLocalStorage();
|
15267
|
+
}
|
15268
|
+
mapToObj(map) {
|
15269
|
+
return Object.fromEntries(map);
|
15270
|
+
}
|
15271
|
+
objToMap(obj) {
|
15272
|
+
return new Map(Object.entries(obj));
|
15273
|
+
}
|
15274
|
+
}
|
15275
|
+
LocalStorage.localStorageKey = 'lc_rmn';
|
15276
|
+
LocalStorage.spotExpirationTime = 1000 * 60 * 60 * 24 * 7; // 7 days
|
15277
|
+
|
15206
15278
|
class ResizeObserverService {
|
15207
15279
|
constructor({ element, maxSize, minScale }) {
|
15208
15280
|
this.element = element;
|
@@ -15335,11 +15407,25 @@ const CAROUSEL_COMPONENT_STYLE = ({ width, height, fluid }) => `
|
|
15335
15407
|
display: flex;
|
15336
15408
|
align-items: center;
|
15337
15409
|
gap: 8px;
|
15410
|
+
opacity: var(--opacity, 1);
|
15338
15411
|
}
|
15339
15412
|
|
15340
|
-
.dots .dot {
|
15413
|
+
.dots.small .dot {
|
15414
|
+
width: 8px;
|
15415
|
+
height: 8px;
|
15416
|
+
}
|
15417
|
+
|
15418
|
+
.dots.base .dot {
|
15341
15419
|
width: 12px;
|
15342
15420
|
height: 12px;
|
15421
|
+
}
|
15422
|
+
|
15423
|
+
.dots.large .dot {
|
15424
|
+
width: 16px;
|
15425
|
+
height: 16px;
|
15426
|
+
}
|
15427
|
+
|
15428
|
+
.dots .dot {
|
15343
15429
|
border-radius: 50%;
|
15344
15430
|
cursor: pointer;
|
15345
15431
|
transition: all 0.3s ease;
|
@@ -15387,6 +15473,10 @@ const CAROUSEL_COMPONENT_STYLE = ({ width, height, fluid }) => `
|
|
15387
15473
|
flex-direction: column;
|
15388
15474
|
}
|
15389
15475
|
|
15476
|
+
.buttons {
|
15477
|
+
opacity: var(--opacity, 1);
|
15478
|
+
}
|
15479
|
+
|
15390
15480
|
.buttons button {
|
15391
15481
|
background-color: #00000080;
|
15392
15482
|
color: #fff;
|
@@ -15396,6 +15486,18 @@ const CAROUSEL_COMPONENT_STYLE = ({ width, height, fluid }) => `
|
|
15396
15486
|
transition: background-color 0.3s ease;
|
15397
15487
|
}
|
15398
15488
|
|
15489
|
+
.buttons.small button {
|
15490
|
+
padding: 6px;
|
15491
|
+
}
|
15492
|
+
|
15493
|
+
.buttons.base button {
|
15494
|
+
padding: 10px;
|
15495
|
+
}
|
15496
|
+
|
15497
|
+
.buttons.large button {
|
15498
|
+
padding: 14px;
|
15499
|
+
}
|
15500
|
+
|
15399
15501
|
.buttons button:hover {
|
15400
15502
|
background-color: #000000b3;
|
15401
15503
|
}
|
@@ -15468,11 +15570,6 @@ const CAROUSEL_COMPONENT_STYLE = ({ width, height, fluid }) => `
|
|
15468
15570
|
padding: 8px 12px;
|
15469
15571
|
font-size: 14px;
|
15470
15572
|
}
|
15471
|
-
|
15472
|
-
.dots .dot {
|
15473
|
-
width: 8px;
|
15474
|
-
height: 8px;
|
15475
|
-
}
|
15476
15573
|
}
|
15477
15574
|
`;
|
15478
15575
|
|
@@ -15512,6 +15609,8 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
|
|
15512
15609
|
position: 'bottom-center',
|
15513
15610
|
color: '#d9d9d9',
|
15514
15611
|
activeColor: '#b5914a',
|
15612
|
+
size: 'base',
|
15613
|
+
opacity: 1,
|
15515
15614
|
...(typeof ((_j = this.data) === null || _j === void 0 ? void 0 : _j.useDots) === 'object' ? this.data.useDots : {}),
|
15516
15615
|
};
|
15517
15616
|
this.buttonsOptions = {
|
@@ -15522,6 +15621,8 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
|
|
15522
15621
|
borderRadius: '50%',
|
15523
15622
|
prev: 'Prev',
|
15524
15623
|
next: 'Next',
|
15624
|
+
size: 'base',
|
15625
|
+
opacity: 1,
|
15525
15626
|
...(typeof ((_k = this.data) === null || _k === void 0 ? void 0 : _k.useButtons) === 'object' ? this.data.useButtons : {}),
|
15526
15627
|
};
|
15527
15628
|
this.validateOptions();
|
@@ -15607,7 +15708,8 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
|
|
15607
15708
|
}
|
15608
15709
|
renderDots() {
|
15609
15710
|
const dotsContainer = document.createElement('div');
|
15610
|
-
dotsContainer.className = `dots ${this.dotsOptions.position}`;
|
15711
|
+
dotsContainer.className = `dots ${this.dotsOptions.position} ${this.dotsOptions.size}`;
|
15712
|
+
dotsContainer.style.cssText = `--opacity: ${this.dotsOptions.opacity}`;
|
15611
15713
|
this.slides.forEach((_, index) => {
|
15612
15714
|
const dot = document.createElement('span');
|
15613
15715
|
dot.className = `dot ${index === this.currentSlide ? 'active' : ''}`;
|
@@ -15621,7 +15723,8 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
|
|
15621
15723
|
const buttonsClass = this.buttonsOptions.together
|
15622
15724
|
? `buttons-together ${this.buttonsOptions.position}`
|
15623
15725
|
: 'buttons-separate';
|
15624
|
-
buttonsContainer.className = `buttons ${buttonsClass}`;
|
15726
|
+
buttonsContainer.className = `buttons ${buttonsClass} ${this.buttonsOptions.size}`;
|
15727
|
+
buttonsContainer.style.cssText = `--opacity: ${this.buttonsOptions.opacity}`;
|
15625
15728
|
this.prevButton = this.createButton('prev-button', this.buttonsOptions.prev);
|
15626
15729
|
this.nextButton = this.createButton('next-button', this.buttonsOptions.next);
|
15627
15730
|
buttonsContainer.appendChild(this.prevButton);
|
@@ -15855,14 +15958,15 @@ class ElementService {
|
|
15855
15958
|
* @return {HTMLElement | null} - The html element or null if the browser environment is not available.
|
15856
15959
|
*/
|
15857
15960
|
createSpotElement({ content, config }) {
|
15858
|
-
var _a;
|
15961
|
+
var _a, _b;
|
15859
15962
|
if (!this.ensureBrowserEnvironmentAndDefineElement()) {
|
15860
15963
|
return null;
|
15861
15964
|
}
|
15862
15965
|
const spot = document.createElement(SPOT_ELEMENT_TAG);
|
15966
|
+
spot.setAttribute('type', (_a = config === null || config === void 0 ? void 0 : config.spot) !== null && _a !== void 0 ? _a : '');
|
15863
15967
|
spot.data = {
|
15864
15968
|
spot: config === null || config === void 0 ? void 0 : config.spot,
|
15865
|
-
fluid: (
|
15969
|
+
fluid: (_b = config === null || config === void 0 ? void 0 : config.fluid) !== null && _b !== void 0 ? _b : false,
|
15866
15970
|
...config,
|
15867
15971
|
};
|
15868
15972
|
spot.content = content;
|
@@ -15928,11 +16032,172 @@ class ElementService {
|
|
15928
16032
|
}
|
15929
16033
|
}
|
15930
16034
|
|
15931
|
-
|
15932
|
-
|
16035
|
+
class UniqueIdGenerator {
|
16036
|
+
/**
|
16037
|
+
* Initialize the generator with a node ID
|
16038
|
+
* @param nodeId Number between 0-1023 to identify this instance
|
16039
|
+
*/
|
16040
|
+
static initialize(nodeId = Math.floor(Math.random() * 1024)) {
|
16041
|
+
if (nodeId < 0 || nodeId >= 1 << this.nodeBits) {
|
16042
|
+
throw new Error(`Node ID must be between 0 and ${(1 << this.nodeBits) - 1}`);
|
16043
|
+
}
|
16044
|
+
this.nodeId = nodeId;
|
16045
|
+
}
|
16046
|
+
/**
|
16047
|
+
* Convert a number to base32 string with specified length
|
16048
|
+
*/
|
16049
|
+
static toBase32(num, length) {
|
16050
|
+
let result = '';
|
16051
|
+
while (num > 0) {
|
16052
|
+
result = this.base32Chars[Number(num % BigInt(32))] + result;
|
16053
|
+
// @ts-expect-error - TS doesn't support bigint division
|
16054
|
+
num = num / 32n;
|
16055
|
+
}
|
16056
|
+
return result.padStart(length, '0');
|
16057
|
+
}
|
16058
|
+
/**
|
16059
|
+
* Generate a cryptographically secure random number
|
16060
|
+
*/
|
16061
|
+
static getSecureRandom() {
|
16062
|
+
if (typeof crypto !== 'undefined') {
|
16063
|
+
const buffer = new Uint32Array(1);
|
16064
|
+
crypto.getRandomValues(buffer);
|
16065
|
+
return buffer[0];
|
16066
|
+
}
|
16067
|
+
return Math.floor(Math.random() * 0xffffffff);
|
16068
|
+
}
|
16069
|
+
/**
|
16070
|
+
* Wait until next millisecond
|
16071
|
+
*/
|
16072
|
+
static waitNextMillis(lastTimestamp) {
|
16073
|
+
let timestamp = Date.now();
|
16074
|
+
while (timestamp <= lastTimestamp) {
|
16075
|
+
timestamp = Date.now();
|
16076
|
+
}
|
16077
|
+
return timestamp;
|
16078
|
+
}
|
16079
|
+
/**
|
16080
|
+
* Generates a highly unique ID with the following format:
|
16081
|
+
* TTTTTTTTTTCCCCNNNNNRRRR
|
16082
|
+
* T: Timestamp (10 chars)
|
16083
|
+
* C: Counter (4 chars)
|
16084
|
+
* N: Node ID (5 chars)
|
16085
|
+
* R: Random (4 chars)
|
16086
|
+
*
|
16087
|
+
* Total length: 23 characters, always uppercase alphanumeric
|
16088
|
+
*/
|
16089
|
+
static generate() {
|
16090
|
+
if (this.nodeId === undefined) {
|
16091
|
+
this.initialize();
|
16092
|
+
}
|
16093
|
+
let timestamp = Date.now() - this.epoch;
|
16094
|
+
// Handle clock moving backwards or same millisecond
|
16095
|
+
if (timestamp < this.lastTimestamp) {
|
16096
|
+
throw new Error('Clock moved backwards. Refusing to generate ID.');
|
16097
|
+
}
|
16098
|
+
if (timestamp === this.lastTimestamp) {
|
16099
|
+
this.sequence = (this.sequence + 1) & ((1 << this.sequenceBits) - 1);
|
16100
|
+
if (this.sequence === 0) {
|
16101
|
+
timestamp = this.waitNextMillis(this.lastTimestamp);
|
16102
|
+
}
|
16103
|
+
}
|
16104
|
+
else {
|
16105
|
+
this.sequence = 0;
|
16106
|
+
}
|
16107
|
+
this.lastTimestamp = timestamp;
|
16108
|
+
// Generate random component
|
16109
|
+
const random = this.getSecureRandom() & 0xffff; // 16 bits of randomness
|
16110
|
+
// Combine all components into a BigInt
|
16111
|
+
// const id =
|
16112
|
+
// (BigInt(timestamp) << BigInt(this.nodeBits + this.sequenceBits + 16)) |
|
16113
|
+
// (BigInt(this.nodeId) << BigInt(this.sequenceBits + 16)) |
|
16114
|
+
// (BigInt(this.sequence) << BigInt(16)) |
|
16115
|
+
// BigInt(random);
|
16116
|
+
// Convert to base32 representation
|
16117
|
+
const timeComponent = this.toBase32(BigInt(timestamp), 10);
|
16118
|
+
const counterComponent = this.toBase32(BigInt(this.sequence), 4);
|
16119
|
+
const nodeComponent = this.toBase32(BigInt(this.nodeId), 5);
|
16120
|
+
const randomComponent = this.toBase32(BigInt(random), 4);
|
16121
|
+
return `${timeComponent}${counterComponent}${nodeComponent}${randomComponent}`;
|
16122
|
+
}
|
16123
|
+
/**
|
16124
|
+
* Validates if a string matches the expected ID format
|
16125
|
+
*/
|
16126
|
+
static isValid(id) {
|
16127
|
+
if (!/^[0-9A-HJ-NP-Z]{23}$/.test(id))
|
16128
|
+
return false;
|
16129
|
+
try {
|
16130
|
+
const timeComponent = id.slice(0, 10);
|
16131
|
+
const timestamp = this.decodeBase32(timeComponent);
|
16132
|
+
const now = Date.now() - this.epoch;
|
16133
|
+
return timestamp >= 0 && timestamp <= now;
|
16134
|
+
}
|
16135
|
+
catch (_a) {
|
16136
|
+
return false;
|
16137
|
+
}
|
16138
|
+
}
|
16139
|
+
/**
|
16140
|
+
* Decode base32 string to number
|
16141
|
+
*/
|
16142
|
+
static decodeBase32(str) {
|
16143
|
+
let result = 0;
|
16144
|
+
for (const char of str) {
|
16145
|
+
result = result * 32 + this.base32Chars.indexOf(char);
|
16146
|
+
}
|
16147
|
+
return result;
|
16148
|
+
}
|
16149
|
+
/**
|
16150
|
+
* Extract timestamp from ID
|
16151
|
+
*/
|
16152
|
+
static getTimestamp(id) {
|
16153
|
+
if (!this.isValid(id))
|
16154
|
+
throw new Error('Invalid ID format');
|
16155
|
+
const timeComponent = id.slice(0, 10);
|
16156
|
+
const timestamp = this.decodeBase32(timeComponent);
|
16157
|
+
return new Date(timestamp + this.epoch);
|
16158
|
+
}
|
16159
|
+
}
|
16160
|
+
// Constants for bit manipulation
|
16161
|
+
UniqueIdGenerator.epoch = 1577836800000; // 2020-01-01 as epoch
|
16162
|
+
UniqueIdGenerator.nodeBits = 10;
|
16163
|
+
UniqueIdGenerator.sequenceBits = 12;
|
16164
|
+
// Instance variables
|
16165
|
+
UniqueIdGenerator.lastTimestamp = -1;
|
16166
|
+
UniqueIdGenerator.sequence = 0;
|
16167
|
+
// Character set for base32 encoding (excluding similar looking characters)
|
16168
|
+
UniqueIdGenerator.base32Chars = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
|
16169
|
+
|
16170
|
+
function convertHexToRgba(hex, opacity = 1) {
|
16171
|
+
// Remove # if present
|
16172
|
+
const cleanHex = hex.replace('#', '');
|
16173
|
+
// Convert hex to RGB
|
16174
|
+
const r = parseInt(cleanHex.substring(0, 2), 16);
|
16175
|
+
const g = parseInt(cleanHex.substring(2, 4), 16);
|
16176
|
+
const b = parseInt(cleanHex.substring(4, 6), 16);
|
16177
|
+
// Return rgba string
|
16178
|
+
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
16179
|
+
}
|
16180
|
+
function generateGradientColor(overlay, fallback = '') {
|
16181
|
+
if (!overlay) {
|
15933
16182
|
return fallback;
|
15934
16183
|
}
|
15935
|
-
|
16184
|
+
const OVERLAY_SIZE = {
|
16185
|
+
small: 10,
|
16186
|
+
base: 30,
|
16187
|
+
large: 50,
|
16188
|
+
};
|
16189
|
+
const OVERLAY_OPACITY = {
|
16190
|
+
light: 0.1,
|
16191
|
+
medium: 0.4,
|
16192
|
+
dark: 0.6,
|
16193
|
+
};
|
16194
|
+
const { size, opacity, color } = overlay;
|
16195
|
+
const goTo = OVERLAY_SIZE[size];
|
16196
|
+
const overlayOpacity = OVERLAY_OPACITY[opacity];
|
16197
|
+
const fullColor = convertHexToRgba(color, 1);
|
16198
|
+
const transparentColor = convertHexToRgba(color, 0);
|
16199
|
+
const gradientColor = convertHexToRgba(color, overlayOpacity);
|
16200
|
+
return `${fullColor} 0%, ${gradientColor} ${goTo}%, ${transparentColor} 100%`;
|
15936
16201
|
}
|
15937
16202
|
function spotHtmlStringToElement(htmlString) {
|
15938
16203
|
const spot = document.createElement('div');
|
@@ -16796,7 +17061,7 @@ function rbCollectionBannerWithoutTextBlockTemplate(spot, config) {
|
|
16796
17061
|
}
|
16797
17062
|
|
16798
17063
|
const STYLES$6 = ({ textColor = '#ffffff', ctaTextColor = textColor, ctaBorderColor = ctaTextColor, primaryImage, mobilePrimaryImage = primaryImage, }, { prefix, overlay }) => {
|
16799
|
-
const linearGradient =
|
17064
|
+
const linearGradient = generateGradientColor(overlay, 'rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 40%');
|
16800
17065
|
return `
|
16801
17066
|
<style>
|
16802
17067
|
.${prefix} {
|
@@ -17287,7 +17552,7 @@ function rbHomepageHeroTwoTileTemplate(spot, config) {
|
|
17287
17552
|
}
|
17288
17553
|
|
17289
17554
|
const STYLES$3 = ({ textColor = '#ffffff', ctaTextColor = textColor, ctaBorderColor = ctaTextColor, primaryImage, mobilePrimaryImage = primaryImage, }, { prefix, overlay }) => {
|
17290
|
-
const linearGradient =
|
17555
|
+
const linearGradient = generateGradientColor(overlay, 'rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 30%');
|
17291
17556
|
return `
|
17292
17557
|
<style>
|
17293
17558
|
.${prefix} {
|
@@ -17424,7 +17689,7 @@ function rbLargeCategoryImageToutTemplate(spot, config) {
|
|
17424
17689
|
}
|
17425
17690
|
|
17426
17691
|
const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = primaryImage }, { prefix, overlay }) => {
|
17427
|
-
const linearGradient =
|
17692
|
+
const linearGradient = generateGradientColor(overlay, 'rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 30%');
|
17428
17693
|
return `
|
17429
17694
|
<style>
|
17430
17695
|
.${prefix} {
|
@@ -17441,11 +17706,7 @@ const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = pr
|
|
17441
17706
|
background-position: center;
|
17442
17707
|
background-repeat: no-repeat;
|
17443
17708
|
container-type: inline-size;
|
17444
|
-
|
17445
|
-
|
17446
|
-
.${prefix}__text {
|
17447
|
-
padding: 15px 10%;
|
17448
|
-
width: fit-content;
|
17709
|
+
position: relative;
|
17449
17710
|
}
|
17450
17711
|
|
17451
17712
|
.${prefix}__header {
|
@@ -17456,6 +17717,7 @@ const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = pr
|
|
17456
17717
|
font-family: "Source Sans 3", system-ui;
|
17457
17718
|
font-style: normal;
|
17458
17719
|
margin: 0;
|
17720
|
+
padding: 15px 10%;
|
17459
17721
|
}
|
17460
17722
|
|
17461
17723
|
@container (min-width: 640px) {
|
@@ -17491,15 +17753,13 @@ function rbNavigationBannerTemplate(spot, config) {
|
|
17491
17753
|
${GFONT_SOURCE_SANS_3}
|
17492
17754
|
${STYLES$2(spot, config)}
|
17493
17755
|
<div class="${prefix}">
|
17494
|
-
<div class="${prefix}__text">
|
17495
17756
|
${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
|
17496
|
-
</div>
|
17497
17757
|
</div>
|
17498
17758
|
`;
|
17499
17759
|
}
|
17500
17760
|
|
17501
17761
|
const STYLES$1 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = primaryImage }, { prefix, overlay }) => {
|
17502
|
-
const linearGradient =
|
17762
|
+
const linearGradient = generateGradientColor(overlay, 'rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 30%');
|
17503
17763
|
return `
|
17504
17764
|
<style>
|
17505
17765
|
.${prefix} {
|
@@ -17695,8 +17955,8 @@ const SPOT_TEMPLATE_HTML_ELEMENT = (spot, config) => {
|
|
17695
17955
|
if (!variantTemplate) {
|
17696
17956
|
return null;
|
17697
17957
|
}
|
17698
|
-
// Generate a
|
17699
|
-
const prefix = 's' +
|
17958
|
+
// Generate a highly unique prefix to avoid conflicts with other elements.
|
17959
|
+
const prefix = 's' + UniqueIdGenerator.generate().toLowerCase();
|
17700
17960
|
const spotHtmlString = variantTemplate(spot, { ...config, prefix });
|
17701
17961
|
return spotHtmlStringToElement(spotHtmlString);
|
17702
17962
|
};
|
@@ -17713,6 +17973,12 @@ class PubSub {
|
|
17713
17973
|
*/
|
17714
17974
|
this.subscribers = {};
|
17715
17975
|
}
|
17976
|
+
static getInstance() {
|
17977
|
+
if (!PubSub.instance) {
|
17978
|
+
PubSub.instance = new PubSub();
|
17979
|
+
}
|
17980
|
+
return PubSub.instance;
|
17981
|
+
}
|
17716
17982
|
/**
|
17717
17983
|
* Subscribe to an event
|
17718
17984
|
* @param eventType - The type of event to subscribe to
|
@@ -17778,7 +18044,8 @@ class PubSub {
|
|
17778
18044
|
|
17779
18045
|
class EventService {
|
17780
18046
|
constructor() {
|
17781
|
-
this.pubSub =
|
18047
|
+
this.pubSub = PubSub.getInstance();
|
18048
|
+
this.localStorage = LocalStorage.getInstance();
|
17782
18049
|
this.activeSpots = new Map();
|
17783
18050
|
this.spotStates = new Map();
|
17784
18051
|
this.intersectionObserver = new IntersectionObserverService();
|
@@ -17795,6 +18062,59 @@ class EventService {
|
|
17795
18062
|
publish(eventType, data) {
|
17796
18063
|
this.pubSub.publish(eventType, data);
|
17797
18064
|
}
|
18065
|
+
registerSpot(params) {
|
18066
|
+
const { placementId, spot, spotElement } = params;
|
18067
|
+
this.activeSpots.set(placementId, { spotElement });
|
18068
|
+
// Fire impression event
|
18069
|
+
this.fireImpressionEvent(placementId, spot, spotElement);
|
18070
|
+
// Handle intersection observer
|
18071
|
+
this.handleIntersectionObserver(placementId, spot, spotElement);
|
18072
|
+
// Attach click event listener
|
18073
|
+
spotElement.addEventListener('click', async () => await this.handleClick(params));
|
18074
|
+
}
|
18075
|
+
unregisterSpot(placementId) {
|
18076
|
+
const placementIdClean = placementId.replace('#', '');
|
18077
|
+
const spotData = this.activeSpots.get(placementIdClean);
|
18078
|
+
if (!spotData) {
|
18079
|
+
this.handleSpotState(placementIdClean, {
|
18080
|
+
state: {
|
18081
|
+
error: `Active spot with placementId ${placementIdClean} not found.`,
|
18082
|
+
},
|
18083
|
+
});
|
18084
|
+
return;
|
18085
|
+
}
|
18086
|
+
this.intersectionObserver.unobserve(spotData.spotElement);
|
18087
|
+
this.handleSpotState(placementIdClean, {
|
18088
|
+
dom: {
|
18089
|
+
spotElement: undefined,
|
18090
|
+
visibleOnViewport: false,
|
18091
|
+
},
|
18092
|
+
state: {
|
18093
|
+
unmounted: true,
|
18094
|
+
mounted: false,
|
18095
|
+
},
|
18096
|
+
});
|
18097
|
+
this.activeSpots.delete(placementIdClean);
|
18098
|
+
const placementElement = document.getElementById(placementIdClean);
|
18099
|
+
if (!placementElement) {
|
18100
|
+
this.handleSpotState(placementIdClean, {
|
18101
|
+
state: {
|
18102
|
+
error: `Placement element with id ${placementIdClean} not found.`,
|
18103
|
+
},
|
18104
|
+
});
|
18105
|
+
return;
|
18106
|
+
}
|
18107
|
+
placementElement.innerHTML = '';
|
18108
|
+
}
|
18109
|
+
/**
|
18110
|
+
* Updates the state of a spot.
|
18111
|
+
*
|
18112
|
+
* @param {string} placementId - The placement ID of the spot.
|
18113
|
+
* @param {Partial<ILifecycleState>} updates - The updates to apply to the spot state.
|
18114
|
+
* @param {boolean} publish - Whether to publish the updated state.
|
18115
|
+
*
|
18116
|
+
* @returns {void}
|
18117
|
+
*/
|
17798
18118
|
handleSpotState(placementId, updates, publish = true) {
|
17799
18119
|
let currentState = this.spotStates.get(placementId);
|
17800
18120
|
if (!currentState) {
|
@@ -17805,8 +18125,8 @@ class EventService {
|
|
17805
18125
|
spotType: '',
|
17806
18126
|
},
|
17807
18127
|
dom: {
|
17808
|
-
|
17809
|
-
|
18128
|
+
spotElement: undefined,
|
18129
|
+
visibleOnViewport: false,
|
17810
18130
|
},
|
17811
18131
|
state: {
|
17812
18132
|
mounted: false,
|
@@ -17821,81 +18141,57 @@ class EventService {
|
|
17821
18141
|
},
|
17822
18142
|
};
|
17823
18143
|
}
|
17824
|
-
this.spotStates.set(placementId, {
|
17825
|
-
...currentState,
|
17826
|
-
...updates,
|
17827
|
-
});
|
18144
|
+
this.spotStates.set(placementId, { ...currentState, ...updates });
|
17828
18145
|
if (publish) {
|
17829
18146
|
this.pubSub.publish(RMN_SPOT_EVENT.LIFECYCLE_STATE, this.spotStates.get(placementId));
|
17830
18147
|
}
|
17831
18148
|
}
|
17832
|
-
|
17833
|
-
|
18149
|
+
async handleClick({ placementId, spot, spotElement, }) {
|
18150
|
+
var _a, _b, _c;
|
18151
|
+
// Publish click event
|
18152
|
+
this.pubSub.publish(RMN_SPOT_EVENT.CLICK, {
|
17834
18153
|
placementId,
|
17835
|
-
|
17836
|
-
|
18154
|
+
spotId: spot.id,
|
18155
|
+
spotElement,
|
17837
18156
|
});
|
17838
|
-
//
|
17839
|
-
this.
|
17840
|
-
|
17841
|
-
|
17842
|
-
|
17843
|
-
|
17844
|
-
|
17845
|
-
|
17846
|
-
|
17847
|
-
|
17848
|
-
|
17849
|
-
await this.fireEvent({
|
17850
|
-
event: RMN_SPOT_EVENT.CLICK,
|
17851
|
-
eventUrl: (_b = (_a = spot.events.find((event) => event.event === RMN_SPOT_EVENT.CLICK)) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : '',
|
17852
|
-
});
|
18157
|
+
// Fire click event
|
18158
|
+
await this.fireEvent({
|
18159
|
+
event: RMN_SPOT_EVENT.CLICK,
|
18160
|
+
eventUrl: (_b = (_a = spot.events.find((event) => event.event === RMN_SPOT_EVENT.CLICK)) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : '',
|
18161
|
+
});
|
18162
|
+
// Save spot to local storage for event tracking
|
18163
|
+
this.localStorage.setSpot(spot.id, {
|
18164
|
+
spotId: spot.id,
|
18165
|
+
spotType: spot.spot,
|
18166
|
+
events: spot.events,
|
18167
|
+
productIds: (_c = spot.productIds) !== null && _c !== void 0 ? _c : [1, 'GROUPING-12345', 'DAN-12345', 131398103],
|
17853
18168
|
});
|
17854
18169
|
}
|
17855
|
-
|
17856
|
-
const
|
17857
|
-
|
17858
|
-
this.
|
17859
|
-
this.handleSpotState(spotData.placementId, {
|
18170
|
+
handleIntersectionObserver(placementId, _spot, spotElement) {
|
18171
|
+
const spotIsVisibleCallback = async () => {
|
18172
|
+
this.intersectionObserver.unobserve(spotElement);
|
18173
|
+
this.handleSpotState(placementId, {
|
17860
18174
|
dom: {
|
17861
|
-
|
17862
|
-
|
17863
|
-
},
|
17864
|
-
state: {
|
17865
|
-
unmounted: true,
|
17866
|
-
mounted: false,
|
18175
|
+
spotElement,
|
18176
|
+
visibleOnViewport: true,
|
17867
18177
|
},
|
17868
18178
|
});
|
17869
|
-
|
17870
|
-
|
18179
|
+
};
|
18180
|
+
this.intersectionObserver.observe(spotElement, spotIsVisibleCallback);
|
17871
18181
|
}
|
17872
|
-
|
17873
|
-
|
18182
|
+
fireImpressionEvent(placementId, spot, spotElement) {
|
18183
|
+
this.pubSub.publish(RMN_SPOT_EVENT.IMPRESSION, {
|
18184
|
+
placementId,
|
18185
|
+
spotId: spot.id,
|
18186
|
+
spotElement,
|
18187
|
+
});
|
18188
|
+
(async () => {
|
17874
18189
|
var _a, _b;
|
17875
|
-
this.pubSub.publish(RMN_SPOT_EVENT.IMPRESSION, {
|
17876
|
-
placementId,
|
17877
|
-
spotId: spot.id,
|
17878
|
-
element,
|
17879
|
-
});
|
17880
|
-
this.intersectionObserver.unobserve(element);
|
17881
|
-
this.activeSpots.set(spot.id, {
|
17882
|
-
placementId,
|
17883
|
-
element,
|
17884
|
-
impressionTracked: true,
|
17885
|
-
});
|
17886
|
-
this.handleSpotState(placementId, {
|
17887
|
-
dom: {
|
17888
|
-
element,
|
17889
|
-
visible: true,
|
17890
|
-
},
|
17891
|
-
});
|
17892
|
-
// Fire impression event
|
17893
18190
|
await this.fireEvent({
|
17894
18191
|
event: RMN_SPOT_EVENT.IMPRESSION,
|
17895
18192
|
eventUrl: (_b = (_a = spot.events.find((event) => event.event === RMN_SPOT_EVENT.IMPRESSION)) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : '',
|
17896
18193
|
});
|
17897
|
-
};
|
17898
|
-
this.intersectionObserver.observe(element, spotIsVisibleCb);
|
18194
|
+
})();
|
17899
18195
|
}
|
17900
18196
|
/**
|
17901
18197
|
* Fires an event using the navigator.sendBeacon method and redirects the user if the event is a click event.
|
@@ -17960,23 +18256,178 @@ class SelectionService extends BaseApi {
|
|
17960
18256
|
}
|
17961
18257
|
}
|
17962
18258
|
|
18259
|
+
const SPOT_EVENTS_EXAMPLE = [
|
18260
|
+
{
|
18261
|
+
event: RMN_SPOT_EVENT.CLICK,
|
18262
|
+
url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwidXIiOm51bGx9&s=hWz37kbxi_u95EVNn2aoQhc5Aas',
|
18263
|
+
},
|
18264
|
+
{
|
18265
|
+
event: RMN_SPOT_EVENT.IMPRESSION,
|
18266
|
+
url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiYmEiOjEsImZxIjowfQ&s=djoysjCimurf-5T11AlNAwwLSS8',
|
18267
|
+
},
|
18268
|
+
{
|
18269
|
+
event: RMN_SPOT_EVENT.PURCHASE,
|
18270
|
+
url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiZXQiOjU5fQ&s=AAPAw-3SfZ0JMzjEGFSwt9L-2S4',
|
18271
|
+
},
|
18272
|
+
{
|
18273
|
+
event: RMN_SPOT_EVENT.ADD_TO_CART,
|
18274
|
+
url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiZXQiOjYwfQ&s=uzQFcjgL7m9XqUG8FvTPVN5YkZY',
|
18275
|
+
},
|
18276
|
+
{
|
18277
|
+
event: RMN_SPOT_EVENT.ADD_TO_WISHLIST,
|
18278
|
+
url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiZXQiOjYzfQ&s=m3ISU_iIy-OFtXrTKpI6cJAEC0k',
|
18279
|
+
},
|
18280
|
+
{
|
18281
|
+
event: RMN_SPOT_EVENT.BUY_NOW,
|
18282
|
+
url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiZXQiOjY5fQ&s=l6MOscQC-q-FkC2Ksd7w6jjySCQ',
|
18283
|
+
},
|
18284
|
+
];
|
18285
|
+
const RB_SPOTS_SELECTION_EXAMPLE = {
|
18286
|
+
rbHomepageHeroFullImage: [
|
18287
|
+
{
|
18288
|
+
id: '111111_111111',
|
18289
|
+
spot: RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
|
18290
|
+
variant: RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
|
18291
|
+
width: 1140,
|
18292
|
+
height: 640,
|
18293
|
+
header: 'Artisanal Craft Beer Collection',
|
18294
|
+
description: 'Discover our curated selection of small-batch, flavor-packed craft beers.',
|
18295
|
+
ctaText: 'Explore the Collection',
|
18296
|
+
textColor: '#ffffff',
|
18297
|
+
ctaTextColor: '#ffffff',
|
18298
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Craft+Beer+Collection',
|
18299
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Craft+Beer',
|
18300
|
+
events: SPOT_EVENTS_EXAMPLE,
|
18301
|
+
},
|
18302
|
+
{
|
18303
|
+
id: '222222_222222',
|
18304
|
+
spot: RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
|
18305
|
+
variant: RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
|
18306
|
+
width: 1140,
|
18307
|
+
height: 640,
|
18308
|
+
header: 'Summer Wine Spectacular',
|
18309
|
+
description: 'Refresh your palate with our handpicked selection of crisp, summer wines.',
|
18310
|
+
ctaText: 'Shop Summer Wines',
|
18311
|
+
textColor: '#000000',
|
18312
|
+
ctaTextColor: '#ffffff',
|
18313
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Summer+Wines',
|
18314
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Summer+Wines',
|
18315
|
+
events: SPOT_EVENTS_EXAMPLE,
|
18316
|
+
},
|
18317
|
+
],
|
18318
|
+
rbHomepageHeroTwoTile: [
|
18319
|
+
{
|
18320
|
+
id: '333333_333333',
|
18321
|
+
spot: RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
|
18322
|
+
variant: RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
|
18323
|
+
width: 1140,
|
18324
|
+
height: 640,
|
18325
|
+
header: 'Whiskey Wonderland',
|
18326
|
+
description: 'Embark on a journey through our premium whiskey selection.',
|
18327
|
+
ctaText: 'Discover Whiskeys',
|
18328
|
+
textColor: '#ffffff',
|
18329
|
+
backgroundColor: '#2c1a05',
|
18330
|
+
ctaTextColor: '#2c1a05',
|
18331
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Whiskey+Collection',
|
18332
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Whiskey',
|
18333
|
+
events: SPOT_EVENTS_EXAMPLE,
|
18334
|
+
},
|
18335
|
+
],
|
18336
|
+
rbHomepageHeroThreeTile: [
|
18337
|
+
{
|
18338
|
+
id: '444444_444444',
|
18339
|
+
spot: RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
|
18340
|
+
variant: RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
|
18341
|
+
width: 1140,
|
18342
|
+
height: 640,
|
18343
|
+
header: 'Cocktail Essentials',
|
18344
|
+
description: 'Stock your bar with premium spirits and mixers for the perfect cocktail.',
|
18345
|
+
ctaText: 'Build Your Bar',
|
18346
|
+
textColor: '#ffffff',
|
18347
|
+
backgroundColor: '#1a3c4d',
|
18348
|
+
ctaTextColor: '#1a3c4d',
|
18349
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Cocktail+Spirits',
|
18350
|
+
secondaryImage: 'https://placehold.co/1140x640/png?text=Cocktail+Mixers',
|
18351
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Cocktail+Kit',
|
18352
|
+
mobileSecondaryImage: 'https://placehold.co/640x320/png?text=Mobile+Cocktail+Mixers',
|
18353
|
+
events: SPOT_EVENTS_EXAMPLE,
|
18354
|
+
},
|
18355
|
+
],
|
18356
|
+
rbLargeCategoryImageTout: [
|
18357
|
+
{
|
18358
|
+
id: '555555_555555',
|
18359
|
+
spot: RMN_SPOT_TYPE.RB_LARGE_CATEGORY_IMAGE_TOUT,
|
18360
|
+
variant: RMN_SPOT_TYPE.RB_LARGE_CATEGORY_IMAGE_TOUT,
|
18361
|
+
width: 468,
|
18362
|
+
height: 410,
|
18363
|
+
header: 'Rare & Limited Edition',
|
18364
|
+
description: 'Discover our collection of hard-to-find and limited release spirits.',
|
18365
|
+
textColor: '#ffffff',
|
18366
|
+
ctaTextColor: '#ffffff',
|
18367
|
+
primaryImage: 'https://placehold.co/468x410/png?text=Rare+Spirits',
|
18368
|
+
mobilePrimaryImage: 'https://placehold.co/468x410/png?text=Mobile+Rare+Spirits',
|
18369
|
+
ctaText: 'Shop Rare Spirits',
|
18370
|
+
events: SPOT_EVENTS_EXAMPLE,
|
18371
|
+
},
|
18372
|
+
],
|
18373
|
+
rbSmallDiscoverTout: [
|
18374
|
+
{
|
18375
|
+
id: '666666_666666',
|
18376
|
+
spot: RMN_SPOT_TYPE.RB_SMALL_DISCOVER_TOUT,
|
18377
|
+
variant: RMN_SPOT_TYPE.RB_SMALL_DISCOVER_TOUT,
|
18378
|
+
width: 224,
|
18379
|
+
height: 378,
|
18380
|
+
header: 'Château Margaux 2015 Bordeaux',
|
18381
|
+
textColor: '#ffffff',
|
18382
|
+
primaryImage: 'https://placehold.co/224x378/png?text=Château+Margaux',
|
18383
|
+
mobilePrimaryImage: 'https://placehold.co/224x378/png?text=Mobile+Château+Margaux',
|
18384
|
+
events: SPOT_EVENTS_EXAMPLE,
|
18385
|
+
},
|
18386
|
+
],
|
18387
|
+
rbSmallCategoryImageTout: [
|
18388
|
+
{
|
18389
|
+
id: '777777_777777',
|
18390
|
+
spot: RMN_SPOT_TYPE.RB_SMALL_CATEGORY_IMAGE_TOUT,
|
18391
|
+
variant: RMN_SPOT_TYPE.RB_SMALL_CATEGORY_IMAGE_TOUT,
|
18392
|
+
width: 224,
|
18393
|
+
height: 410,
|
18394
|
+
header: 'Japanese Sake',
|
18395
|
+
textColor: '#ffffff',
|
18396
|
+
primaryImage: 'https://placehold.co/224x410/png?text=Japanese+Sake',
|
18397
|
+
mobilePrimaryImage: 'https://placehold.co/224x410/png?text=Mobile+Japanese+Sake',
|
18398
|
+
events: SPOT_EVENTS_EXAMPLE,
|
18399
|
+
},
|
18400
|
+
],
|
18401
|
+
rbCollectionBannerWithoutTextBlock: [
|
18402
|
+
{
|
18403
|
+
id: '888888_888888',
|
18404
|
+
spot: RMN_SPOT_TYPE.RB_COLLECTION_BANNER_WITHOUT_TEXT_BLOCK,
|
18405
|
+
variant: RMN_SPOT_TYPE.RB_COLLECTION_BANNER_WITHOUT_TEXT_BLOCK,
|
18406
|
+
width: 887,
|
18407
|
+
height: 344,
|
18408
|
+
primaryImage: 'https://placehold.co/887x344/png?text=Summer+Cocktails',
|
18409
|
+
mobilePrimaryImage: 'https://placehold.co/887x344/png?text=Mobile+Summer+Cocktails',
|
18410
|
+
events: SPOT_EVENTS_EXAMPLE,
|
18411
|
+
},
|
18412
|
+
],
|
18413
|
+
rbNavigationBanner: [
|
18414
|
+
{
|
18415
|
+
id: '999999_999999',
|
18416
|
+
spot: RMN_SPOT_TYPE.RB_NAVIGATION_BANNER,
|
18417
|
+
variant: RMN_SPOT_TYPE.RB_NAVIGATION_BANNER,
|
18418
|
+
width: 440,
|
18419
|
+
height: 220,
|
18420
|
+
header: 'Explore Tequilas',
|
18421
|
+
textColor: '#ffffff',
|
18422
|
+
primaryImage: 'https://placehold.co/440x220/png?text=Tequila+Collection',
|
18423
|
+
mobilePrimaryImage: 'https://placehold.co/440x220/png?text=Mobile+Tequila+Collection',
|
18424
|
+
events: SPOT_EVENTS_EXAMPLE,
|
18425
|
+
},
|
18426
|
+
],
|
18427
|
+
};
|
18428
|
+
|
17963
18429
|
class LiquidCommerceRmnClient {
|
17964
18430
|
constructor(auth) {
|
17965
|
-
/**
|
17966
|
-
* Returns the event manager instance.
|
17967
|
-
*
|
17968
|
-
* @return {EventService} - The event manager instance.
|
17969
|
-
*/
|
17970
|
-
this.eventManager = {
|
17971
|
-
subscribe: (eventType, callback
|
17972
|
-
/* eslint-disable arrow-body-style */
|
17973
|
-
) => {
|
17974
|
-
return this.eventService.subscribe(eventType, callback);
|
17975
|
-
},
|
17976
|
-
publish: (eventType, data) => {
|
17977
|
-
this.eventService.publish(eventType, data);
|
17978
|
-
},
|
17979
|
-
};
|
17980
18431
|
this.selectionService = SelectionService.getInstance(auth);
|
17981
18432
|
this.elementService = ElementService.getInstance();
|
17982
18433
|
this.eventService = EventService.getInstance();
|
@@ -18024,6 +18475,7 @@ class LiquidCommerceRmnClient {
|
|
18024
18475
|
inject = this.preventNonExistentSpotTypes(inject);
|
18025
18476
|
// Make the spot selection request
|
18026
18477
|
const response = await this.spotSelectionRequest({ ...params, inject });
|
18478
|
+
// const response = await this.useSpotSelectionExample(inject);
|
18027
18479
|
// Handle the response
|
18028
18480
|
if (typeof response === 'object' && 'error' in response) {
|
18029
18481
|
this.eventService.handleSpotState('all', {
|
@@ -18056,6 +18508,15 @@ class LiquidCommerceRmnClient {
|
|
18056
18508
|
});
|
18057
18509
|
continue;
|
18058
18510
|
}
|
18511
|
+
// Take over placement styles
|
18512
|
+
placement.removeAttribute('style');
|
18513
|
+
placement.removeAttribute('class');
|
18514
|
+
Object.assign(placement.style, {
|
18515
|
+
width: '100%',
|
18516
|
+
height: 'auto',
|
18517
|
+
display: 'flex',
|
18518
|
+
justifyContent: 'center',
|
18519
|
+
});
|
18059
18520
|
if (spots.length === 1) {
|
18060
18521
|
const isInjected = this.injectOneSpotElement(item, placement, spots[0], itemConfig);
|
18061
18522
|
if (!isInjected) {
|
@@ -18082,14 +18543,12 @@ class LiquidCommerceRmnClient {
|
|
18082
18543
|
const request = {
|
18083
18544
|
url: config === null || config === void 0 ? void 0 : config.url,
|
18084
18545
|
filter,
|
18085
|
-
spots: inject.map((item) => {
|
18086
|
-
|
18087
|
-
|
18088
|
-
|
18089
|
-
|
18090
|
-
|
18091
|
-
};
|
18092
|
-
}),
|
18546
|
+
spots: inject.map((item) => ({
|
18547
|
+
placementId: item.placementId,
|
18548
|
+
spot: item.spotType,
|
18549
|
+
count: item === null || item === void 0 ? void 0 : item.count,
|
18550
|
+
...item === null || item === void 0 ? void 0 : item.filter,
|
18551
|
+
})),
|
18093
18552
|
};
|
18094
18553
|
return this.spotSelection(request);
|
18095
18554
|
}
|
@@ -18127,17 +18586,15 @@ class LiquidCommerceRmnClient {
|
|
18127
18586
|
this.eventService.registerSpot({
|
18128
18587
|
spot,
|
18129
18588
|
placementId: placement.id,
|
18130
|
-
|
18589
|
+
spotElement: content,
|
18131
18590
|
});
|
18132
18591
|
carouselSlides.push(content);
|
18133
18592
|
}
|
18134
18593
|
// Get the max width and height of the spots
|
18135
|
-
const { maxWidth, maxHeight } = spots.reduce((max, spot) => {
|
18136
|
-
|
18137
|
-
|
18138
|
-
|
18139
|
-
};
|
18140
|
-
}, { maxWidth: 0, maxHeight: 0 });
|
18594
|
+
const { maxWidth, maxHeight } = spots.reduce((max, spot) => ({
|
18595
|
+
maxWidth: Math.max(max.maxWidth, spot.width),
|
18596
|
+
maxHeight: Math.max(max.maxHeight, spot.height),
|
18597
|
+
}), { maxWidth: 0, maxHeight: 0 });
|
18141
18598
|
// Create the carousel element
|
18142
18599
|
const carouselElement = this.elementService.createCarouselElement({
|
18143
18600
|
slides: carouselSlides,
|
@@ -18161,7 +18618,7 @@ class LiquidCommerceRmnClient {
|
|
18161
18618
|
placement.replaceChildren(carouselElement);
|
18162
18619
|
this.eventService.handleSpotState(placement.id, {
|
18163
18620
|
dom: {
|
18164
|
-
|
18621
|
+
spotElement: carouselElement,
|
18165
18622
|
},
|
18166
18623
|
state: {
|
18167
18624
|
mounted: true,
|
@@ -18222,12 +18679,12 @@ class LiquidCommerceRmnClient {
|
|
18222
18679
|
this.eventService.registerSpot({
|
18223
18680
|
spot: spotData,
|
18224
18681
|
placementId: injectItem.placementId,
|
18225
|
-
|
18682
|
+
spotElement,
|
18226
18683
|
});
|
18227
18684
|
placement.replaceChildren(spotElement);
|
18228
18685
|
this.eventService.handleSpotState(injectItem.placementId, {
|
18229
18686
|
dom: {
|
18230
|
-
|
18687
|
+
spotElement,
|
18231
18688
|
},
|
18232
18689
|
state: {
|
18233
18690
|
mounted: true,
|
@@ -18288,6 +18745,17 @@ class LiquidCommerceRmnClient {
|
|
18288
18745
|
});
|
18289
18746
|
}
|
18290
18747
|
}
|
18748
|
+
useSpotSelectionExample(inject) {
|
18749
|
+
const examples = RB_SPOTS_SELECTION_EXAMPLE;
|
18750
|
+
const data = {};
|
18751
|
+
inject.map((item) => {
|
18752
|
+
var _a, _b, _c;
|
18753
|
+
data[item.placementId] = (_c = (_a = examples[item.spotType]) === null || _a === void 0 ? void 0 : _a.slice(0, (_b = item.count) !== null && _b !== void 0 ? _b : 1)) !== null && _c !== void 0 ? _c : [];
|
18754
|
+
});
|
18755
|
+
return new Promise((resolve) => {
|
18756
|
+
resolve(data);
|
18757
|
+
});
|
18758
|
+
}
|
18291
18759
|
}
|
18292
18760
|
/**
|
18293
18761
|
* Creates a new instance of the RmnClient.
|
@@ -18302,6 +18770,36 @@ async function RmnClient(apiKey, config) {
|
|
18302
18770
|
const credentials = await authService.initialize();
|
18303
18771
|
return new LiquidCommerceRmnClient(credentials);
|
18304
18772
|
}
|
18773
|
+
/**
|
18774
|
+
* Creates a new instance of the RmnEventManager.
|
18775
|
+
*
|
18776
|
+
* @return {IRmnEventManager} - The RmnEventManager instance.
|
18777
|
+
*/
|
18778
|
+
function RmnEventManager() {
|
18779
|
+
const eventService = EventService.getInstance();
|
18780
|
+
return {
|
18781
|
+
/**
|
18782
|
+
* Subscribes to an event type.
|
18783
|
+
*/
|
18784
|
+
subscribe: (eventType, callback
|
18785
|
+
/* eslint-disable arrow-body-style */
|
18786
|
+
) => {
|
18787
|
+
return eventService.subscribe(eventType, callback);
|
18788
|
+
},
|
18789
|
+
/**
|
18790
|
+
* Publishes an event type.
|
18791
|
+
*/
|
18792
|
+
publish: (eventType, data) => {
|
18793
|
+
eventService.publish(eventType, data);
|
18794
|
+
},
|
18795
|
+
/**
|
18796
|
+
* Destroys a spot element
|
18797
|
+
*/
|
18798
|
+
destroySpot: (placementId) => {
|
18799
|
+
eventService.unregisterSpot(placementId);
|
18800
|
+
},
|
18801
|
+
};
|
18802
|
+
}
|
18305
18803
|
/**
|
18306
18804
|
* Creates the spot html element based on the provided data using shadow dom.
|
18307
18805
|
*
|
@@ -18334,4 +18832,4 @@ function RmnCreateSpotElement(spot, config) {
|
|
18334
18832
|
});
|
18335
18833
|
}
|
18336
18834
|
|
18337
|
-
export { LiquidCommerceRmnClient, RMN_ENV, RMN_FILTER_PROPERTIES, RMN_SPOT_EVENT, RMN_SPOT_TYPE, RmnClient, RmnCreateSpotElement };
|
18835
|
+
export { LiquidCommerceRmnClient, RMN_ENV, RMN_FILTER_PROPERTIES, RMN_SPOT_EVENT, RMN_SPOT_TYPE, RmnClient, RmnCreateSpotElement, RmnEventManager };
|