@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.cjs
CHANGED
@@ -15000,7 +15000,7 @@ class BaseApi extends BaseApiAbstract {
|
|
15000
15000
|
*/
|
15001
15001
|
async post(path, data, configOverrides) {
|
15002
15002
|
let requestData = data;
|
15003
|
-
if (
|
15003
|
+
if (![exports.RMN_ENV.LOCAL, exports.RMN_ENV.DEVELOPMENT].includes(this.authInfo.env)) {
|
15004
15004
|
const timestamp = new Date().getTime();
|
15005
15005
|
configOverrides = {
|
15006
15006
|
...configOverrides,
|
@@ -15205,6 +15205,78 @@ class IntersectionObserverService {
|
|
15205
15205
|
}
|
15206
15206
|
}
|
15207
15207
|
|
15208
|
+
class LocalStorage {
|
15209
|
+
constructor() {
|
15210
|
+
this.spots = new Map();
|
15211
|
+
// Sync local storage with the current state
|
15212
|
+
this.syncLocalStorage();
|
15213
|
+
// Remove expired spots
|
15214
|
+
this.removeExpiredSpots();
|
15215
|
+
}
|
15216
|
+
static getInstance() {
|
15217
|
+
if (!LocalStorage.instance) {
|
15218
|
+
LocalStorage.instance = new LocalStorage();
|
15219
|
+
}
|
15220
|
+
return LocalStorage.instance;
|
15221
|
+
}
|
15222
|
+
syncLocalStorage() {
|
15223
|
+
const localStorageData = localStorage.getItem(LocalStorage.localStorageKey);
|
15224
|
+
// TODO: Encrypt the data before storing it in the local storage
|
15225
|
+
if (localStorageData) {
|
15226
|
+
try {
|
15227
|
+
const parsedData = JSON.parse(localStorageData);
|
15228
|
+
if (parsedData && typeof parsedData === 'object') {
|
15229
|
+
this.spots = this.objToMap(parsedData);
|
15230
|
+
}
|
15231
|
+
else {
|
15232
|
+
this.clearLocalStorage();
|
15233
|
+
}
|
15234
|
+
}
|
15235
|
+
catch (_a) {
|
15236
|
+
// If there is an error parsing the data, clear the local storage to prevent any issues
|
15237
|
+
this.clearLocalStorage();
|
15238
|
+
}
|
15239
|
+
}
|
15240
|
+
}
|
15241
|
+
setSpot(spotId, data) {
|
15242
|
+
data.createdAt = Date.now();
|
15243
|
+
this.spots.set(spotId, data);
|
15244
|
+
this.updateLocalStorage();
|
15245
|
+
}
|
15246
|
+
getSpot(spotId) {
|
15247
|
+
return this.spots.get(spotId);
|
15248
|
+
}
|
15249
|
+
removeSpot(spotId) {
|
15250
|
+
this.spots.delete(spotId);
|
15251
|
+
this.updateLocalStorage();
|
15252
|
+
}
|
15253
|
+
updateLocalStorage() {
|
15254
|
+
const data = this.mapToObj(this.spots);
|
15255
|
+
localStorage.setItem(LocalStorage.localStorageKey, JSON.stringify(data));
|
15256
|
+
}
|
15257
|
+
clearLocalStorage() {
|
15258
|
+
localStorage.removeItem(LocalStorage.localStorageKey);
|
15259
|
+
}
|
15260
|
+
removeExpiredSpots() {
|
15261
|
+
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);
|
15266
|
+
}
|
15267
|
+
});
|
15268
|
+
this.updateLocalStorage();
|
15269
|
+
}
|
15270
|
+
mapToObj(map) {
|
15271
|
+
return Object.fromEntries(map);
|
15272
|
+
}
|
15273
|
+
objToMap(obj) {
|
15274
|
+
return new Map(Object.entries(obj));
|
15275
|
+
}
|
15276
|
+
}
|
15277
|
+
LocalStorage.localStorageKey = 'lc_rmn';
|
15278
|
+
LocalStorage.spotExpirationTime = 1000 * 60 * 60 * 24 * 7; // 7 days
|
15279
|
+
|
15208
15280
|
class ResizeObserverService {
|
15209
15281
|
constructor({ element, maxSize, minScale }) {
|
15210
15282
|
this.element = element;
|
@@ -15337,11 +15409,25 @@ const CAROUSEL_COMPONENT_STYLE = ({ width, height, fluid }) => `
|
|
15337
15409
|
display: flex;
|
15338
15410
|
align-items: center;
|
15339
15411
|
gap: 8px;
|
15412
|
+
opacity: var(--opacity, 1);
|
15340
15413
|
}
|
15341
15414
|
|
15342
|
-
.dots .dot {
|
15415
|
+
.dots.small .dot {
|
15416
|
+
width: 8px;
|
15417
|
+
height: 8px;
|
15418
|
+
}
|
15419
|
+
|
15420
|
+
.dots.base .dot {
|
15343
15421
|
width: 12px;
|
15344
15422
|
height: 12px;
|
15423
|
+
}
|
15424
|
+
|
15425
|
+
.dots.large .dot {
|
15426
|
+
width: 16px;
|
15427
|
+
height: 16px;
|
15428
|
+
}
|
15429
|
+
|
15430
|
+
.dots .dot {
|
15345
15431
|
border-radius: 50%;
|
15346
15432
|
cursor: pointer;
|
15347
15433
|
transition: all 0.3s ease;
|
@@ -15389,6 +15475,10 @@ const CAROUSEL_COMPONENT_STYLE = ({ width, height, fluid }) => `
|
|
15389
15475
|
flex-direction: column;
|
15390
15476
|
}
|
15391
15477
|
|
15478
|
+
.buttons {
|
15479
|
+
opacity: var(--opacity, 1);
|
15480
|
+
}
|
15481
|
+
|
15392
15482
|
.buttons button {
|
15393
15483
|
background-color: #00000080;
|
15394
15484
|
color: #fff;
|
@@ -15398,6 +15488,18 @@ const CAROUSEL_COMPONENT_STYLE = ({ width, height, fluid }) => `
|
|
15398
15488
|
transition: background-color 0.3s ease;
|
15399
15489
|
}
|
15400
15490
|
|
15491
|
+
.buttons.small button {
|
15492
|
+
padding: 6px;
|
15493
|
+
}
|
15494
|
+
|
15495
|
+
.buttons.base button {
|
15496
|
+
padding: 10px;
|
15497
|
+
}
|
15498
|
+
|
15499
|
+
.buttons.large button {
|
15500
|
+
padding: 14px;
|
15501
|
+
}
|
15502
|
+
|
15401
15503
|
.buttons button:hover {
|
15402
15504
|
background-color: #000000b3;
|
15403
15505
|
}
|
@@ -15470,11 +15572,6 @@ const CAROUSEL_COMPONENT_STYLE = ({ width, height, fluid }) => `
|
|
15470
15572
|
padding: 8px 12px;
|
15471
15573
|
font-size: 14px;
|
15472
15574
|
}
|
15473
|
-
|
15474
|
-
.dots .dot {
|
15475
|
-
width: 8px;
|
15476
|
-
height: 8px;
|
15477
|
-
}
|
15478
15575
|
}
|
15479
15576
|
`;
|
15480
15577
|
|
@@ -15514,6 +15611,8 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
|
|
15514
15611
|
position: 'bottom-center',
|
15515
15612
|
color: '#d9d9d9',
|
15516
15613
|
activeColor: '#b5914a',
|
15614
|
+
size: 'base',
|
15615
|
+
opacity: 1,
|
15517
15616
|
...(typeof ((_j = this.data) === null || _j === void 0 ? void 0 : _j.useDots) === 'object' ? this.data.useDots : {}),
|
15518
15617
|
};
|
15519
15618
|
this.buttonsOptions = {
|
@@ -15524,6 +15623,8 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
|
|
15524
15623
|
borderRadius: '50%',
|
15525
15624
|
prev: 'Prev',
|
15526
15625
|
next: 'Next',
|
15626
|
+
size: 'base',
|
15627
|
+
opacity: 1,
|
15527
15628
|
...(typeof ((_k = this.data) === null || _k === void 0 ? void 0 : _k.useButtons) === 'object' ? this.data.useButtons : {}),
|
15528
15629
|
};
|
15529
15630
|
this.validateOptions();
|
@@ -15609,7 +15710,8 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
|
|
15609
15710
|
}
|
15610
15711
|
renderDots() {
|
15611
15712
|
const dotsContainer = document.createElement('div');
|
15612
|
-
dotsContainer.className = `dots ${this.dotsOptions.position}`;
|
15713
|
+
dotsContainer.className = `dots ${this.dotsOptions.position} ${this.dotsOptions.size}`;
|
15714
|
+
dotsContainer.style.cssText = `--opacity: ${this.dotsOptions.opacity}`;
|
15613
15715
|
this.slides.forEach((_, index) => {
|
15614
15716
|
const dot = document.createElement('span');
|
15615
15717
|
dot.className = `dot ${index === this.currentSlide ? 'active' : ''}`;
|
@@ -15623,7 +15725,8 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
|
|
15623
15725
|
const buttonsClass = this.buttonsOptions.together
|
15624
15726
|
? `buttons-together ${this.buttonsOptions.position}`
|
15625
15727
|
: 'buttons-separate';
|
15626
|
-
buttonsContainer.className = `buttons ${buttonsClass}`;
|
15728
|
+
buttonsContainer.className = `buttons ${buttonsClass} ${this.buttonsOptions.size}`;
|
15729
|
+
buttonsContainer.style.cssText = `--opacity: ${this.buttonsOptions.opacity}`;
|
15627
15730
|
this.prevButton = this.createButton('prev-button', this.buttonsOptions.prev);
|
15628
15731
|
this.nextButton = this.createButton('next-button', this.buttonsOptions.next);
|
15629
15732
|
buttonsContainer.appendChild(this.prevButton);
|
@@ -15857,14 +15960,15 @@ class ElementService {
|
|
15857
15960
|
* @return {HTMLElement | null} - The html element or null if the browser environment is not available.
|
15858
15961
|
*/
|
15859
15962
|
createSpotElement({ content, config }) {
|
15860
|
-
var _a;
|
15963
|
+
var _a, _b;
|
15861
15964
|
if (!this.ensureBrowserEnvironmentAndDefineElement()) {
|
15862
15965
|
return null;
|
15863
15966
|
}
|
15864
15967
|
const spot = document.createElement(SPOT_ELEMENT_TAG);
|
15968
|
+
spot.setAttribute('type', (_a = config === null || config === void 0 ? void 0 : config.spot) !== null && _a !== void 0 ? _a : '');
|
15865
15969
|
spot.data = {
|
15866
15970
|
spot: config === null || config === void 0 ? void 0 : config.spot,
|
15867
|
-
fluid: (
|
15971
|
+
fluid: (_b = config === null || config === void 0 ? void 0 : config.fluid) !== null && _b !== void 0 ? _b : false,
|
15868
15972
|
...config,
|
15869
15973
|
};
|
15870
15974
|
spot.content = content;
|
@@ -15930,11 +16034,172 @@ class ElementService {
|
|
15930
16034
|
}
|
15931
16035
|
}
|
15932
16036
|
|
15933
|
-
|
15934
|
-
|
16037
|
+
class UniqueIdGenerator {
|
16038
|
+
/**
|
16039
|
+
* Initialize the generator with a node ID
|
16040
|
+
* @param nodeId Number between 0-1023 to identify this instance
|
16041
|
+
*/
|
16042
|
+
static initialize(nodeId = Math.floor(Math.random() * 1024)) {
|
16043
|
+
if (nodeId < 0 || nodeId >= 1 << this.nodeBits) {
|
16044
|
+
throw new Error(`Node ID must be between 0 and ${(1 << this.nodeBits) - 1}`);
|
16045
|
+
}
|
16046
|
+
this.nodeId = nodeId;
|
16047
|
+
}
|
16048
|
+
/**
|
16049
|
+
* Convert a number to base32 string with specified length
|
16050
|
+
*/
|
16051
|
+
static toBase32(num, length) {
|
16052
|
+
let result = '';
|
16053
|
+
while (num > 0) {
|
16054
|
+
result = this.base32Chars[Number(num % BigInt(32))] + result;
|
16055
|
+
// @ts-expect-error - TS doesn't support bigint division
|
16056
|
+
num = num / 32n;
|
16057
|
+
}
|
16058
|
+
return result.padStart(length, '0');
|
16059
|
+
}
|
16060
|
+
/**
|
16061
|
+
* Generate a cryptographically secure random number
|
16062
|
+
*/
|
16063
|
+
static getSecureRandom() {
|
16064
|
+
if (typeof crypto !== 'undefined') {
|
16065
|
+
const buffer = new Uint32Array(1);
|
16066
|
+
crypto.getRandomValues(buffer);
|
16067
|
+
return buffer[0];
|
16068
|
+
}
|
16069
|
+
return Math.floor(Math.random() * 0xffffffff);
|
16070
|
+
}
|
16071
|
+
/**
|
16072
|
+
* Wait until next millisecond
|
16073
|
+
*/
|
16074
|
+
static waitNextMillis(lastTimestamp) {
|
16075
|
+
let timestamp = Date.now();
|
16076
|
+
while (timestamp <= lastTimestamp) {
|
16077
|
+
timestamp = Date.now();
|
16078
|
+
}
|
16079
|
+
return timestamp;
|
16080
|
+
}
|
16081
|
+
/**
|
16082
|
+
* Generates a highly unique ID with the following format:
|
16083
|
+
* TTTTTTTTTTCCCCNNNNNRRRR
|
16084
|
+
* T: Timestamp (10 chars)
|
16085
|
+
* C: Counter (4 chars)
|
16086
|
+
* N: Node ID (5 chars)
|
16087
|
+
* R: Random (4 chars)
|
16088
|
+
*
|
16089
|
+
* Total length: 23 characters, always uppercase alphanumeric
|
16090
|
+
*/
|
16091
|
+
static generate() {
|
16092
|
+
if (this.nodeId === undefined) {
|
16093
|
+
this.initialize();
|
16094
|
+
}
|
16095
|
+
let timestamp = Date.now() - this.epoch;
|
16096
|
+
// Handle clock moving backwards or same millisecond
|
16097
|
+
if (timestamp < this.lastTimestamp) {
|
16098
|
+
throw new Error('Clock moved backwards. Refusing to generate ID.');
|
16099
|
+
}
|
16100
|
+
if (timestamp === this.lastTimestamp) {
|
16101
|
+
this.sequence = (this.sequence + 1) & ((1 << this.sequenceBits) - 1);
|
16102
|
+
if (this.sequence === 0) {
|
16103
|
+
timestamp = this.waitNextMillis(this.lastTimestamp);
|
16104
|
+
}
|
16105
|
+
}
|
16106
|
+
else {
|
16107
|
+
this.sequence = 0;
|
16108
|
+
}
|
16109
|
+
this.lastTimestamp = timestamp;
|
16110
|
+
// Generate random component
|
16111
|
+
const random = this.getSecureRandom() & 0xffff; // 16 bits of randomness
|
16112
|
+
// Combine all components into a BigInt
|
16113
|
+
// const id =
|
16114
|
+
// (BigInt(timestamp) << BigInt(this.nodeBits + this.sequenceBits + 16)) |
|
16115
|
+
// (BigInt(this.nodeId) << BigInt(this.sequenceBits + 16)) |
|
16116
|
+
// (BigInt(this.sequence) << BigInt(16)) |
|
16117
|
+
// BigInt(random);
|
16118
|
+
// Convert to base32 representation
|
16119
|
+
const timeComponent = this.toBase32(BigInt(timestamp), 10);
|
16120
|
+
const counterComponent = this.toBase32(BigInt(this.sequence), 4);
|
16121
|
+
const nodeComponent = this.toBase32(BigInt(this.nodeId), 5);
|
16122
|
+
const randomComponent = this.toBase32(BigInt(random), 4);
|
16123
|
+
return `${timeComponent}${counterComponent}${nodeComponent}${randomComponent}`;
|
16124
|
+
}
|
16125
|
+
/**
|
16126
|
+
* Validates if a string matches the expected ID format
|
16127
|
+
*/
|
16128
|
+
static isValid(id) {
|
16129
|
+
if (!/^[0-9A-HJ-NP-Z]{23}$/.test(id))
|
16130
|
+
return false;
|
16131
|
+
try {
|
16132
|
+
const timeComponent = id.slice(0, 10);
|
16133
|
+
const timestamp = this.decodeBase32(timeComponent);
|
16134
|
+
const now = Date.now() - this.epoch;
|
16135
|
+
return timestamp >= 0 && timestamp <= now;
|
16136
|
+
}
|
16137
|
+
catch (_a) {
|
16138
|
+
return false;
|
16139
|
+
}
|
16140
|
+
}
|
16141
|
+
/**
|
16142
|
+
* Decode base32 string to number
|
16143
|
+
*/
|
16144
|
+
static decodeBase32(str) {
|
16145
|
+
let result = 0;
|
16146
|
+
for (const char of str) {
|
16147
|
+
result = result * 32 + this.base32Chars.indexOf(char);
|
16148
|
+
}
|
16149
|
+
return result;
|
16150
|
+
}
|
16151
|
+
/**
|
16152
|
+
* Extract timestamp from ID
|
16153
|
+
*/
|
16154
|
+
static getTimestamp(id) {
|
16155
|
+
if (!this.isValid(id))
|
16156
|
+
throw new Error('Invalid ID format');
|
16157
|
+
const timeComponent = id.slice(0, 10);
|
16158
|
+
const timestamp = this.decodeBase32(timeComponent);
|
16159
|
+
return new Date(timestamp + this.epoch);
|
16160
|
+
}
|
16161
|
+
}
|
16162
|
+
// Constants for bit manipulation
|
16163
|
+
UniqueIdGenerator.epoch = 1577836800000; // 2020-01-01 as epoch
|
16164
|
+
UniqueIdGenerator.nodeBits = 10;
|
16165
|
+
UniqueIdGenerator.sequenceBits = 12;
|
16166
|
+
// Instance variables
|
16167
|
+
UniqueIdGenerator.lastTimestamp = -1;
|
16168
|
+
UniqueIdGenerator.sequence = 0;
|
16169
|
+
// Character set for base32 encoding (excluding similar looking characters)
|
16170
|
+
UniqueIdGenerator.base32Chars = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
|
16171
|
+
|
16172
|
+
function convertHexToRgba(hex, opacity = 1) {
|
16173
|
+
// Remove # if present
|
16174
|
+
const cleanHex = hex.replace('#', '');
|
16175
|
+
// Convert hex to RGB
|
16176
|
+
const r = parseInt(cleanHex.substring(0, 2), 16);
|
16177
|
+
const g = parseInt(cleanHex.substring(2, 4), 16);
|
16178
|
+
const b = parseInt(cleanHex.substring(4, 6), 16);
|
16179
|
+
// Return rgba string
|
16180
|
+
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
16181
|
+
}
|
16182
|
+
function generateGradientColor(overlay, fallback = '') {
|
16183
|
+
if (!overlay) {
|
15935
16184
|
return fallback;
|
15936
16185
|
}
|
15937
|
-
|
16186
|
+
const OVERLAY_SIZE = {
|
16187
|
+
small: 10,
|
16188
|
+
base: 30,
|
16189
|
+
large: 50,
|
16190
|
+
};
|
16191
|
+
const OVERLAY_OPACITY = {
|
16192
|
+
light: 0.1,
|
16193
|
+
medium: 0.4,
|
16194
|
+
dark: 0.6,
|
16195
|
+
};
|
16196
|
+
const { size, opacity, color } = overlay;
|
16197
|
+
const goTo = OVERLAY_SIZE[size];
|
16198
|
+
const overlayOpacity = OVERLAY_OPACITY[opacity];
|
16199
|
+
const fullColor = convertHexToRgba(color, 1);
|
16200
|
+
const transparentColor = convertHexToRgba(color, 0);
|
16201
|
+
const gradientColor = convertHexToRgba(color, overlayOpacity);
|
16202
|
+
return `${fullColor} 0%, ${gradientColor} ${goTo}%, ${transparentColor} 100%`;
|
15938
16203
|
}
|
15939
16204
|
function spotHtmlStringToElement(htmlString) {
|
15940
16205
|
const spot = document.createElement('div');
|
@@ -16798,7 +17063,7 @@ function rbCollectionBannerWithoutTextBlockTemplate(spot, config) {
|
|
16798
17063
|
}
|
16799
17064
|
|
16800
17065
|
const STYLES$6 = ({ textColor = '#ffffff', ctaTextColor = textColor, ctaBorderColor = ctaTextColor, primaryImage, mobilePrimaryImage = primaryImage, }, { prefix, overlay }) => {
|
16801
|
-
const linearGradient =
|
17066
|
+
const linearGradient = generateGradientColor(overlay, 'rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 40%');
|
16802
17067
|
return `
|
16803
17068
|
<style>
|
16804
17069
|
.${prefix} {
|
@@ -17289,7 +17554,7 @@ function rbHomepageHeroTwoTileTemplate(spot, config) {
|
|
17289
17554
|
}
|
17290
17555
|
|
17291
17556
|
const STYLES$3 = ({ textColor = '#ffffff', ctaTextColor = textColor, ctaBorderColor = ctaTextColor, primaryImage, mobilePrimaryImage = primaryImage, }, { prefix, overlay }) => {
|
17292
|
-
const linearGradient =
|
17557
|
+
const linearGradient = generateGradientColor(overlay, 'rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 30%');
|
17293
17558
|
return `
|
17294
17559
|
<style>
|
17295
17560
|
.${prefix} {
|
@@ -17426,7 +17691,7 @@ function rbLargeCategoryImageToutTemplate(spot, config) {
|
|
17426
17691
|
}
|
17427
17692
|
|
17428
17693
|
const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = primaryImage }, { prefix, overlay }) => {
|
17429
|
-
const linearGradient =
|
17694
|
+
const linearGradient = generateGradientColor(overlay, 'rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 30%');
|
17430
17695
|
return `
|
17431
17696
|
<style>
|
17432
17697
|
.${prefix} {
|
@@ -17443,11 +17708,7 @@ const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = pr
|
|
17443
17708
|
background-position: center;
|
17444
17709
|
background-repeat: no-repeat;
|
17445
17710
|
container-type: inline-size;
|
17446
|
-
|
17447
|
-
|
17448
|
-
.${prefix}__text {
|
17449
|
-
padding: 15px 10%;
|
17450
|
-
width: fit-content;
|
17711
|
+
position: relative;
|
17451
17712
|
}
|
17452
17713
|
|
17453
17714
|
.${prefix}__header {
|
@@ -17458,6 +17719,7 @@ const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = pr
|
|
17458
17719
|
font-family: "Source Sans 3", system-ui;
|
17459
17720
|
font-style: normal;
|
17460
17721
|
margin: 0;
|
17722
|
+
padding: 15px 10%;
|
17461
17723
|
}
|
17462
17724
|
|
17463
17725
|
@container (min-width: 640px) {
|
@@ -17493,15 +17755,13 @@ function rbNavigationBannerTemplate(spot, config) {
|
|
17493
17755
|
${GFONT_SOURCE_SANS_3}
|
17494
17756
|
${STYLES$2(spot, config)}
|
17495
17757
|
<div class="${prefix}">
|
17496
|
-
<div class="${prefix}__text">
|
17497
17758
|
${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
|
17498
|
-
</div>
|
17499
17759
|
</div>
|
17500
17760
|
`;
|
17501
17761
|
}
|
17502
17762
|
|
17503
17763
|
const STYLES$1 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = primaryImage }, { prefix, overlay }) => {
|
17504
|
-
const linearGradient =
|
17764
|
+
const linearGradient = generateGradientColor(overlay, 'rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 30%');
|
17505
17765
|
return `
|
17506
17766
|
<style>
|
17507
17767
|
.${prefix} {
|
@@ -17697,8 +17957,8 @@ const SPOT_TEMPLATE_HTML_ELEMENT = (spot, config) => {
|
|
17697
17957
|
if (!variantTemplate) {
|
17698
17958
|
return null;
|
17699
17959
|
}
|
17700
|
-
// Generate a
|
17701
|
-
const prefix = 's' +
|
17960
|
+
// Generate a highly unique prefix to avoid conflicts with other elements.
|
17961
|
+
const prefix = 's' + UniqueIdGenerator.generate().toLowerCase();
|
17702
17962
|
const spotHtmlString = variantTemplate(spot, { ...config, prefix });
|
17703
17963
|
return spotHtmlStringToElement(spotHtmlString);
|
17704
17964
|
};
|
@@ -17715,6 +17975,12 @@ class PubSub {
|
|
17715
17975
|
*/
|
17716
17976
|
this.subscribers = {};
|
17717
17977
|
}
|
17978
|
+
static getInstance() {
|
17979
|
+
if (!PubSub.instance) {
|
17980
|
+
PubSub.instance = new PubSub();
|
17981
|
+
}
|
17982
|
+
return PubSub.instance;
|
17983
|
+
}
|
17718
17984
|
/**
|
17719
17985
|
* Subscribe to an event
|
17720
17986
|
* @param eventType - The type of event to subscribe to
|
@@ -17780,7 +18046,8 @@ class PubSub {
|
|
17780
18046
|
|
17781
18047
|
class EventService {
|
17782
18048
|
constructor() {
|
17783
|
-
this.pubSub =
|
18049
|
+
this.pubSub = PubSub.getInstance();
|
18050
|
+
this.localStorage = LocalStorage.getInstance();
|
17784
18051
|
this.activeSpots = new Map();
|
17785
18052
|
this.spotStates = new Map();
|
17786
18053
|
this.intersectionObserver = new IntersectionObserverService();
|
@@ -17797,6 +18064,59 @@ class EventService {
|
|
17797
18064
|
publish(eventType, data) {
|
17798
18065
|
this.pubSub.publish(eventType, data);
|
17799
18066
|
}
|
18067
|
+
registerSpot(params) {
|
18068
|
+
const { placementId, spot, spotElement } = params;
|
18069
|
+
this.activeSpots.set(placementId, { spotElement });
|
18070
|
+
// Fire impression event
|
18071
|
+
this.fireImpressionEvent(placementId, spot, spotElement);
|
18072
|
+
// Handle intersection observer
|
18073
|
+
this.handleIntersectionObserver(placementId, spot, spotElement);
|
18074
|
+
// Attach click event listener
|
18075
|
+
spotElement.addEventListener('click', async () => await this.handleClick(params));
|
18076
|
+
}
|
18077
|
+
unregisterSpot(placementId) {
|
18078
|
+
const placementIdClean = placementId.replace('#', '');
|
18079
|
+
const spotData = this.activeSpots.get(placementIdClean);
|
18080
|
+
if (!spotData) {
|
18081
|
+
this.handleSpotState(placementIdClean, {
|
18082
|
+
state: {
|
18083
|
+
error: `Active spot with placementId ${placementIdClean} not found.`,
|
18084
|
+
},
|
18085
|
+
});
|
18086
|
+
return;
|
18087
|
+
}
|
18088
|
+
this.intersectionObserver.unobserve(spotData.spotElement);
|
18089
|
+
this.handleSpotState(placementIdClean, {
|
18090
|
+
dom: {
|
18091
|
+
spotElement: undefined,
|
18092
|
+
visibleOnViewport: false,
|
18093
|
+
},
|
18094
|
+
state: {
|
18095
|
+
unmounted: true,
|
18096
|
+
mounted: false,
|
18097
|
+
},
|
18098
|
+
});
|
18099
|
+
this.activeSpots.delete(placementIdClean);
|
18100
|
+
const placementElement = document.getElementById(placementIdClean);
|
18101
|
+
if (!placementElement) {
|
18102
|
+
this.handleSpotState(placementIdClean, {
|
18103
|
+
state: {
|
18104
|
+
error: `Placement element with id ${placementIdClean} not found.`,
|
18105
|
+
},
|
18106
|
+
});
|
18107
|
+
return;
|
18108
|
+
}
|
18109
|
+
placementElement.innerHTML = '';
|
18110
|
+
}
|
18111
|
+
/**
|
18112
|
+
* Updates the state of a spot.
|
18113
|
+
*
|
18114
|
+
* @param {string} placementId - The placement ID of the spot.
|
18115
|
+
* @param {Partial<ILifecycleState>} updates - The updates to apply to the spot state.
|
18116
|
+
* @param {boolean} publish - Whether to publish the updated state.
|
18117
|
+
*
|
18118
|
+
* @returns {void}
|
18119
|
+
*/
|
17800
18120
|
handleSpotState(placementId, updates, publish = true) {
|
17801
18121
|
let currentState = this.spotStates.get(placementId);
|
17802
18122
|
if (!currentState) {
|
@@ -17807,8 +18127,8 @@ class EventService {
|
|
17807
18127
|
spotType: '',
|
17808
18128
|
},
|
17809
18129
|
dom: {
|
17810
|
-
|
17811
|
-
|
18130
|
+
spotElement: undefined,
|
18131
|
+
visibleOnViewport: false,
|
17812
18132
|
},
|
17813
18133
|
state: {
|
17814
18134
|
mounted: false,
|
@@ -17823,81 +18143,57 @@ class EventService {
|
|
17823
18143
|
},
|
17824
18144
|
};
|
17825
18145
|
}
|
17826
|
-
this.spotStates.set(placementId, {
|
17827
|
-
...currentState,
|
17828
|
-
...updates,
|
17829
|
-
});
|
18146
|
+
this.spotStates.set(placementId, { ...currentState, ...updates });
|
17830
18147
|
if (publish) {
|
17831
18148
|
this.pubSub.publish(exports.RMN_SPOT_EVENT.LIFECYCLE_STATE, this.spotStates.get(placementId));
|
17832
18149
|
}
|
17833
18150
|
}
|
17834
|
-
|
17835
|
-
|
18151
|
+
async handleClick({ placementId, spot, spotElement, }) {
|
18152
|
+
var _a, _b, _c;
|
18153
|
+
// Publish click event
|
18154
|
+
this.pubSub.publish(exports.RMN_SPOT_EVENT.CLICK, {
|
17836
18155
|
placementId,
|
17837
|
-
|
17838
|
-
|
18156
|
+
spotId: spot.id,
|
18157
|
+
spotElement,
|
17839
18158
|
});
|
17840
|
-
//
|
17841
|
-
this.
|
17842
|
-
|
17843
|
-
|
17844
|
-
|
17845
|
-
|
17846
|
-
|
17847
|
-
|
17848
|
-
|
17849
|
-
|
17850
|
-
|
17851
|
-
await this.fireEvent({
|
17852
|
-
event: exports.RMN_SPOT_EVENT.CLICK,
|
17853
|
-
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 : '',
|
17854
|
-
});
|
18159
|
+
// Fire click event
|
18160
|
+
await this.fireEvent({
|
18161
|
+
event: exports.RMN_SPOT_EVENT.CLICK,
|
18162
|
+
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
|
+
});
|
18164
|
+
// Save spot to local storage for event tracking
|
18165
|
+
this.localStorage.setSpot(spot.id, {
|
18166
|
+
spotId: spot.id,
|
18167
|
+
spotType: spot.spot,
|
18168
|
+
events: spot.events,
|
18169
|
+
productIds: (_c = spot.productIds) !== null && _c !== void 0 ? _c : [1, 'GROUPING-12345', 'DAN-12345', 131398103],
|
17855
18170
|
});
|
17856
18171
|
}
|
17857
|
-
|
17858
|
-
const
|
17859
|
-
|
17860
|
-
this.
|
17861
|
-
this.handleSpotState(spotData.placementId, {
|
18172
|
+
handleIntersectionObserver(placementId, _spot, spotElement) {
|
18173
|
+
const spotIsVisibleCallback = async () => {
|
18174
|
+
this.intersectionObserver.unobserve(spotElement);
|
18175
|
+
this.handleSpotState(placementId, {
|
17862
18176
|
dom: {
|
17863
|
-
|
17864
|
-
|
17865
|
-
},
|
17866
|
-
state: {
|
17867
|
-
unmounted: true,
|
17868
|
-
mounted: false,
|
18177
|
+
spotElement,
|
18178
|
+
visibleOnViewport: true,
|
17869
18179
|
},
|
17870
18180
|
});
|
17871
|
-
|
17872
|
-
|
18181
|
+
};
|
18182
|
+
this.intersectionObserver.observe(spotElement, spotIsVisibleCallback);
|
17873
18183
|
}
|
17874
|
-
|
17875
|
-
|
18184
|
+
fireImpressionEvent(placementId, spot, spotElement) {
|
18185
|
+
this.pubSub.publish(exports.RMN_SPOT_EVENT.IMPRESSION, {
|
18186
|
+
placementId,
|
18187
|
+
spotId: spot.id,
|
18188
|
+
spotElement,
|
18189
|
+
});
|
18190
|
+
(async () => {
|
17876
18191
|
var _a, _b;
|
17877
|
-
this.pubSub.publish(exports.RMN_SPOT_EVENT.IMPRESSION, {
|
17878
|
-
placementId,
|
17879
|
-
spotId: spot.id,
|
17880
|
-
element,
|
17881
|
-
});
|
17882
|
-
this.intersectionObserver.unobserve(element);
|
17883
|
-
this.activeSpots.set(spot.id, {
|
17884
|
-
placementId,
|
17885
|
-
element,
|
17886
|
-
impressionTracked: true,
|
17887
|
-
});
|
17888
|
-
this.handleSpotState(placementId, {
|
17889
|
-
dom: {
|
17890
|
-
element,
|
17891
|
-
visible: true,
|
17892
|
-
},
|
17893
|
-
});
|
17894
|
-
// Fire impression event
|
17895
18192
|
await this.fireEvent({
|
17896
18193
|
event: exports.RMN_SPOT_EVENT.IMPRESSION,
|
17897
18194
|
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 : '',
|
17898
18195
|
});
|
17899
|
-
};
|
17900
|
-
this.intersectionObserver.observe(element, spotIsVisibleCb);
|
18196
|
+
})();
|
17901
18197
|
}
|
17902
18198
|
/**
|
17903
18199
|
* Fires an event using the navigator.sendBeacon method and redirects the user if the event is a click event.
|
@@ -17962,23 +18258,178 @@ class SelectionService extends BaseApi {
|
|
17962
18258
|
}
|
17963
18259
|
}
|
17964
18260
|
|
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
|
+
|
17965
18431
|
class LiquidCommerceRmnClient {
|
17966
18432
|
constructor(auth) {
|
17967
|
-
/**
|
17968
|
-
* Returns the event manager instance.
|
17969
|
-
*
|
17970
|
-
* @return {EventService} - The event manager instance.
|
17971
|
-
*/
|
17972
|
-
this.eventManager = {
|
17973
|
-
subscribe: (eventType, callback
|
17974
|
-
/* eslint-disable arrow-body-style */
|
17975
|
-
) => {
|
17976
|
-
return this.eventService.subscribe(eventType, callback);
|
17977
|
-
},
|
17978
|
-
publish: (eventType, data) => {
|
17979
|
-
this.eventService.publish(eventType, data);
|
17980
|
-
},
|
17981
|
-
};
|
17982
18433
|
this.selectionService = SelectionService.getInstance(auth);
|
17983
18434
|
this.elementService = ElementService.getInstance();
|
17984
18435
|
this.eventService = EventService.getInstance();
|
@@ -18026,6 +18477,7 @@ class LiquidCommerceRmnClient {
|
|
18026
18477
|
inject = this.preventNonExistentSpotTypes(inject);
|
18027
18478
|
// Make the spot selection request
|
18028
18479
|
const response = await this.spotSelectionRequest({ ...params, inject });
|
18480
|
+
// const response = await this.useSpotSelectionExample(inject);
|
18029
18481
|
// Handle the response
|
18030
18482
|
if (typeof response === 'object' && 'error' in response) {
|
18031
18483
|
this.eventService.handleSpotState('all', {
|
@@ -18058,6 +18510,15 @@ class LiquidCommerceRmnClient {
|
|
18058
18510
|
});
|
18059
18511
|
continue;
|
18060
18512
|
}
|
18513
|
+
// Take over placement styles
|
18514
|
+
placement.removeAttribute('style');
|
18515
|
+
placement.removeAttribute('class');
|
18516
|
+
Object.assign(placement.style, {
|
18517
|
+
width: '100%',
|
18518
|
+
height: 'auto',
|
18519
|
+
display: 'flex',
|
18520
|
+
justifyContent: 'center',
|
18521
|
+
});
|
18061
18522
|
if (spots.length === 1) {
|
18062
18523
|
const isInjected = this.injectOneSpotElement(item, placement, spots[0], itemConfig);
|
18063
18524
|
if (!isInjected) {
|
@@ -18084,14 +18545,12 @@ class LiquidCommerceRmnClient {
|
|
18084
18545
|
const request = {
|
18085
18546
|
url: config === null || config === void 0 ? void 0 : config.url,
|
18086
18547
|
filter,
|
18087
|
-
spots: inject.map((item) => {
|
18088
|
-
|
18089
|
-
|
18090
|
-
|
18091
|
-
|
18092
|
-
|
18093
|
-
};
|
18094
|
-
}),
|
18548
|
+
spots: inject.map((item) => ({
|
18549
|
+
placementId: item.placementId,
|
18550
|
+
spot: item.spotType,
|
18551
|
+
count: item === null || item === void 0 ? void 0 : item.count,
|
18552
|
+
...item === null || item === void 0 ? void 0 : item.filter,
|
18553
|
+
})),
|
18095
18554
|
};
|
18096
18555
|
return this.spotSelection(request);
|
18097
18556
|
}
|
@@ -18129,17 +18588,15 @@ class LiquidCommerceRmnClient {
|
|
18129
18588
|
this.eventService.registerSpot({
|
18130
18589
|
spot,
|
18131
18590
|
placementId: placement.id,
|
18132
|
-
|
18591
|
+
spotElement: content,
|
18133
18592
|
});
|
18134
18593
|
carouselSlides.push(content);
|
18135
18594
|
}
|
18136
18595
|
// Get the max width and height of the spots
|
18137
|
-
const { maxWidth, maxHeight } = spots.reduce((max, spot) => {
|
18138
|
-
|
18139
|
-
|
18140
|
-
|
18141
|
-
};
|
18142
|
-
}, { maxWidth: 0, maxHeight: 0 });
|
18596
|
+
const { maxWidth, maxHeight } = spots.reduce((max, spot) => ({
|
18597
|
+
maxWidth: Math.max(max.maxWidth, spot.width),
|
18598
|
+
maxHeight: Math.max(max.maxHeight, spot.height),
|
18599
|
+
}), { maxWidth: 0, maxHeight: 0 });
|
18143
18600
|
// Create the carousel element
|
18144
18601
|
const carouselElement = this.elementService.createCarouselElement({
|
18145
18602
|
slides: carouselSlides,
|
@@ -18163,7 +18620,7 @@ class LiquidCommerceRmnClient {
|
|
18163
18620
|
placement.replaceChildren(carouselElement);
|
18164
18621
|
this.eventService.handleSpotState(placement.id, {
|
18165
18622
|
dom: {
|
18166
|
-
|
18623
|
+
spotElement: carouselElement,
|
18167
18624
|
},
|
18168
18625
|
state: {
|
18169
18626
|
mounted: true,
|
@@ -18224,12 +18681,12 @@ class LiquidCommerceRmnClient {
|
|
18224
18681
|
this.eventService.registerSpot({
|
18225
18682
|
spot: spotData,
|
18226
18683
|
placementId: injectItem.placementId,
|
18227
|
-
|
18684
|
+
spotElement,
|
18228
18685
|
});
|
18229
18686
|
placement.replaceChildren(spotElement);
|
18230
18687
|
this.eventService.handleSpotState(injectItem.placementId, {
|
18231
18688
|
dom: {
|
18232
|
-
|
18689
|
+
spotElement,
|
18233
18690
|
},
|
18234
18691
|
state: {
|
18235
18692
|
mounted: true,
|
@@ -18290,6 +18747,17 @@ class LiquidCommerceRmnClient {
|
|
18290
18747
|
});
|
18291
18748
|
}
|
18292
18749
|
}
|
18750
|
+
useSpotSelectionExample(inject) {
|
18751
|
+
const examples = RB_SPOTS_SELECTION_EXAMPLE;
|
18752
|
+
const data = {};
|
18753
|
+
inject.map((item) => {
|
18754
|
+
var _a, _b, _c;
|
18755
|
+
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 : [];
|
18756
|
+
});
|
18757
|
+
return new Promise((resolve) => {
|
18758
|
+
resolve(data);
|
18759
|
+
});
|
18760
|
+
}
|
18293
18761
|
}
|
18294
18762
|
/**
|
18295
18763
|
* Creates a new instance of the RmnClient.
|
@@ -18304,6 +18772,36 @@ async function RmnClient(apiKey, config) {
|
|
18304
18772
|
const credentials = await authService.initialize();
|
18305
18773
|
return new LiquidCommerceRmnClient(credentials);
|
18306
18774
|
}
|
18775
|
+
/**
|
18776
|
+
* Creates a new instance of the RmnEventManager.
|
18777
|
+
*
|
18778
|
+
* @return {IRmnEventManager} - The RmnEventManager instance.
|
18779
|
+
*/
|
18780
|
+
function RmnEventManager() {
|
18781
|
+
const eventService = EventService.getInstance();
|
18782
|
+
return {
|
18783
|
+
/**
|
18784
|
+
* Subscribes to an event type.
|
18785
|
+
*/
|
18786
|
+
subscribe: (eventType, callback
|
18787
|
+
/* eslint-disable arrow-body-style */
|
18788
|
+
) => {
|
18789
|
+
return eventService.subscribe(eventType, callback);
|
18790
|
+
},
|
18791
|
+
/**
|
18792
|
+
* Publishes an event type.
|
18793
|
+
*/
|
18794
|
+
publish: (eventType, data) => {
|
18795
|
+
eventService.publish(eventType, data);
|
18796
|
+
},
|
18797
|
+
/**
|
18798
|
+
* Destroys a spot element
|
18799
|
+
*/
|
18800
|
+
destroySpot: (placementId) => {
|
18801
|
+
eventService.unregisterSpot(placementId);
|
18802
|
+
},
|
18803
|
+
};
|
18804
|
+
}
|
18307
18805
|
/**
|
18308
18806
|
* Creates the spot html element based on the provided data using shadow dom.
|
18309
18807
|
*
|
@@ -18339,3 +18837,4 @@ function RmnCreateSpotElement(spot, config) {
|
|
18339
18837
|
exports.LiquidCommerceRmnClient = LiquidCommerceRmnClient;
|
18340
18838
|
exports.RmnClient = RmnClient;
|
18341
18839
|
exports.RmnCreateSpotElement = RmnCreateSpotElement;
|
18840
|
+
exports.RmnEventManager = RmnEventManager;
|