@liquidcommercedev/rmn-sdk 1.4.6 → 1.5.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +3234 -746
- package/dist/index.esm.js +3234 -747
- package/dist/types/common/helpers/utils.helper.d.ts +50 -0
- package/dist/types/common/helpers/uuid.helper.d.ts +49 -0
- package/dist/types/enums.d.ts +64 -1
- package/dist/types/example.constant.d.ts +4 -0
- package/dist/types/index.umd.d.ts +2 -2
- package/dist/types/modules/element/component/carousel/carousel.component.d.ts +3 -0
- package/dist/types/modules/element/component/carousel/carousel.interface.d.ts +35 -0
- package/dist/types/modules/element/component/carousel/carousel.style.d.ts +2 -0
- package/dist/types/modules/element/component/carousel/index.d.ts +3 -0
- package/dist/types/modules/element/component/spot/index.d.ts +2 -0
- package/dist/types/modules/element/component/spot/spot.component.d.ts +3 -0
- package/dist/types/modules/element/component/spot/spot.interface.d.ts +10 -0
- package/dist/types/modules/{spot/html/constants/html.constant.d.ts → element/element.constant.d.ts} +2 -5
- package/dist/types/modules/element/element.interface.d.ts +55 -0
- package/dist/types/modules/element/element.service.d.ts +40 -0
- package/dist/types/modules/element/index.d.ts +3 -0
- package/dist/types/modules/element/template/helper.d.ts +4 -0
- package/dist/types/modules/element/template/index.d.ts +1 -0
- package/dist/types/modules/element/template/reservebar/collection-banner-without-text-block.template.d.ts +3 -0
- package/dist/types/modules/element/template/reservebar/homepage-hero-full-image.template.d.ts +3 -0
- package/dist/types/modules/element/template/reservebar/homepage-hero-three-tile.template.d.ts +3 -0
- package/dist/types/modules/element/template/reservebar/homepage-hero-two-tile.template.d.ts +3 -0
- package/dist/types/modules/element/template/reservebar/large-category-image-tout.template.d.ts +3 -0
- package/dist/types/modules/element/template/reservebar/navigation-banner.template.d.ts +3 -0
- package/dist/types/modules/element/template/reservebar/small-category-image-tout.template.d.ts +3 -0
- package/dist/types/modules/element/template/reservebar/small-discover-tout.template.d.ts +3 -0
- package/dist/types/modules/element/template/template.service.d.ts +11 -0
- package/dist/types/modules/element/template/template.type.d.ts +11 -0
- package/dist/types/modules/event/event.constant.d.ts +1 -0
- package/dist/types/modules/event/event.interface.d.ts +46 -0
- package/dist/types/modules/event/event.service.d.ts +30 -0
- package/dist/types/modules/event/index.d.ts +3 -0
- package/dist/types/modules/helper-service/index.d.ts +4 -0
- package/dist/types/modules/helper-service/intersection.service.d.ts +8 -0
- package/dist/types/modules/helper-service/localstorage.service.d.ts +56 -0
- package/dist/types/modules/helper-service/pubsub.service.d.ts +69 -0
- package/dist/types/modules/helper-service/resize.service.d.ts +30 -0
- package/dist/types/modules/monitor/index.d.ts +2 -0
- package/dist/types/modules/monitor/monitor.enums.d.ts +4 -0
- package/dist/types/modules/monitor/monitor.interface.d.ts +11 -0
- package/dist/types/modules/monitor/monitor.service.d.ts +12 -0
- package/dist/types/modules/monitor/monitors/datalayer.monitor.d.ts +12 -0
- package/dist/types/modules/selection/index.d.ts +4 -0
- package/dist/types/modules/selection/selection.constant.d.ts +1 -0
- package/dist/types/modules/{spot/spot.interface.d.ts → selection/selection.interface.d.ts} +13 -14
- package/dist/types/modules/selection/selection.service.d.ts +18 -0
- package/dist/types/modules/{spot/spot.type.d.ts → selection/selection.type.d.ts} +4 -3
- package/dist/types/rmn-client.d.ts +66 -23
- package/dist/types/types.d.ts +18 -6
- package/package.json +2 -2
- package/umd/liquidcommerce-rmn-sdk.min.js +1 -1
- package/dist/types/modules/spot/html/constants/index.d.ts +0 -1
- package/dist/types/modules/spot/html/index.d.ts +0 -1
- package/dist/types/modules/spot/html/spot.element.service.d.ts +0 -7
- package/dist/types/modules/spot/html/templates/index.d.ts +0 -1
- package/dist/types/modules/spot/html/templates/reservebar/collection-banner-without-text-block.template.d.ts +0 -2
- package/dist/types/modules/spot/html/templates/reservebar/homepage-hero-full-image.template.d.ts +0 -2
- package/dist/types/modules/spot/html/templates/reservebar/homepage-hero-three-tile.template.d.ts +0 -2
- package/dist/types/modules/spot/html/templates/reservebar/homepage-hero-two-tile.template.d.ts +0 -2
- package/dist/types/modules/spot/html/templates/reservebar/large-category-image-tout.template.d.ts +0 -2
- package/dist/types/modules/spot/html/templates/reservebar/navigation-banner.template.d.ts +0 -2
- package/dist/types/modules/spot/html/templates/reservebar/small-category-image-tout.template.d.ts +0 -2
- package/dist/types/modules/spot/html/templates/reservebar/small-discover-tout.template.d.ts +0 -2
- package/dist/types/modules/spot/html/templates/spot.template.d.ts +0 -21
- package/dist/types/modules/spot/index.d.ts +0 -6
- package/dist/types/modules/spot/spot.constant.d.ts +0 -4
- package/dist/types/modules/spot/spot.enum.d.ts +0 -57
- package/dist/types/modules/spot/spot.html.service.d.ts +0 -22
- package/dist/types/modules/spot/spot.selection.service.d.ts +0 -15
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/billboard/billboard-v1.template.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/billboard/billboard-v2.template.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/billboard/billboard-v3.template.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/billboard/index.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/in-text/in-text-v1.template.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/in-text/index.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/index.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/large-leaderboard/index.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/large-leaderboard/large-leaderboard-v1.template.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/large-leaderboard/large-leaderboard-v2.template.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/large-rectangle/index.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/large-rectangle/large-rectangle-v1.template.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/square/index.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/square/square-v1.template.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/square/square-v2.template.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/vertical-rectangle/index.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/vertical-rectangle/vertical-rectangle-v1.template.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/wide-skyscraper/index.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/iab/wide-skyscraper/wide-skyscraper-v1.template.d.ts +0 -0
- /package/dist/types/modules/{spot/html/templates → element/template}/reservebar/index.d.ts +0 -0
package/dist/index.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
exports.RMN_SPOT_TYPE = void 0;
|
|
4
4
|
(function (RMN_SPOT_TYPE) {
|
|
5
5
|
// Reserve Bar Spot Types
|
|
6
|
+
RMN_SPOT_TYPE["RB_HOMEPAGE_HERO"] = "rbHomepageHero";
|
|
6
7
|
RMN_SPOT_TYPE["RB_HOMEPAGE_HERO_THREE_TILE"] = "rbHomepageHeroThreeTile";
|
|
7
8
|
RMN_SPOT_TYPE["RB_HOMEPAGE_HERO_TWO_TILE"] = "rbHomepageHeroTwoTile";
|
|
8
9
|
RMN_SPOT_TYPE["RB_HOMEPAGE_HERO_FULL_IMAGE"] = "rbHomepageHeroFullImage";
|
|
@@ -44,6 +45,7 @@ exports.RMN_SPOT_TYPE = void 0;
|
|
|
44
45
|
exports.RMN_FILTER_PROPERTIES = void 0;
|
|
45
46
|
(function (RMN_FILTER_PROPERTIES) {
|
|
46
47
|
RMN_FILTER_PROPERTIES["KEYWORDS"] = "keywords";
|
|
48
|
+
RMN_FILTER_PROPERTIES["PAGE_LOCATION"] = "pageLocation";
|
|
47
49
|
RMN_FILTER_PROPERTIES["PARENTCO"] = "parentCo";
|
|
48
50
|
RMN_FILTER_PROPERTIES["BRAND"] = "brand";
|
|
49
51
|
RMN_FILTER_PROPERTIES["CATEGORY"] = "category";
|
|
@@ -53,16 +55,21 @@ exports.RMN_FILTER_PROPERTIES = void 0;
|
|
|
53
55
|
RMN_FILTER_PROPERTIES["PUBLISHERS"] = "publishers";
|
|
54
56
|
RMN_FILTER_PROPERTIES["SECTION"] = "section";
|
|
55
57
|
})(exports.RMN_FILTER_PROPERTIES || (exports.RMN_FILTER_PROPERTIES = {}));
|
|
58
|
+
exports.RMN_EVENT = void 0;
|
|
59
|
+
(function (RMN_EVENT) {
|
|
60
|
+
RMN_EVENT["LIFECYCLE_STATE"] = "LIFECYCLE_STATE";
|
|
61
|
+
RMN_EVENT["SPOT_EVENT"] = "SPOT_EVENT";
|
|
62
|
+
})(exports.RMN_EVENT || (exports.RMN_EVENT = {}));
|
|
56
63
|
exports.RMN_SPOT_EVENT = void 0;
|
|
57
64
|
(function (RMN_SPOT_EVENT) {
|
|
58
65
|
RMN_SPOT_EVENT["IMPRESSION"] = "IMPRESSION";
|
|
59
66
|
RMN_SPOT_EVENT["CLICK"] = "CLICK";
|
|
60
67
|
RMN_SPOT_EVENT["PURCHASE"] = "PURCHASE";
|
|
61
68
|
RMN_SPOT_EVENT["ADD_TO_CART"] = "ADD_TO_CART";
|
|
69
|
+
RMN_SPOT_EVENT["REMOVE_FROM_CART"] = "REMOVE_FROM_CART";
|
|
62
70
|
RMN_SPOT_EVENT["ADD_TO_WISHLIST"] = "ADD_TO_WISHLIST";
|
|
63
71
|
RMN_SPOT_EVENT["BUY_NOW"] = "BUY_NOW";
|
|
64
72
|
})(exports.RMN_SPOT_EVENT || (exports.RMN_SPOT_EVENT = {}));
|
|
65
|
-
|
|
66
73
|
exports.RMN_ENV = void 0;
|
|
67
74
|
(function (RMN_ENV) {
|
|
68
75
|
RMN_ENV["LOCAL"] = "local";
|
|
@@ -71,6 +78,511 @@ exports.RMN_ENV = void 0;
|
|
|
71
78
|
RMN_ENV["PRODUCTION"] = "production";
|
|
72
79
|
})(exports.RMN_ENV || (exports.RMN_ENV = {}));
|
|
73
80
|
|
|
81
|
+
const SPOT_EVENTS_EXAMPLE = [
|
|
82
|
+
{
|
|
83
|
+
event: exports.RMN_SPOT_EVENT.CLICK,
|
|
84
|
+
url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwidXIiOm51bGx9&s=hWz37kbxi_u95EVNn2aoQhc5Aas',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
event: exports.RMN_SPOT_EVENT.IMPRESSION,
|
|
88
|
+
url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiYmEiOjEsImZxIjowfQ&s=djoysjCimurf-5T11AlNAwwLSS8',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
event: exports.RMN_SPOT_EVENT.PURCHASE,
|
|
92
|
+
url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiZXQiOjU5fQ&s=AAPAw-3SfZ0JMzjEGFSwt9L-2S4',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
event: exports.RMN_SPOT_EVENT.ADD_TO_CART,
|
|
96
|
+
url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiZXQiOjYwfQ&s=uzQFcjgL7m9XqUG8FvTPVN5YkZY',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
event: exports.RMN_SPOT_EVENT.ADD_TO_WISHLIST,
|
|
100
|
+
url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiZXQiOjYzfQ&s=m3ISU_iIy-OFtXrTKpI6cJAEC0k',
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
event: exports.RMN_SPOT_EVENT.BUY_NOW,
|
|
104
|
+
url: 'https://dev.rmn.liquidcommerce.cloud/api/spots/event?e=eyJ2IjoiMS4xMiIsImF2IjozMDY1NzgzLCJhdCI6MTYzLCJidCI6MCwiY20iOjQ0MDE5MjQxOCwiY2giOjYzMTg0LCJjayI6e30sImNyIjo0ODE4NTUzNzUsImRpIjoiOWMxNGFhMGI3NWY4NDMxNTllMTAwYWQzNzA1NzQyYzMiLCJkaiI6MCwiaWkiOiIxZjU0MGM5NmQ1N2M0YmZjODFlZjRkNjhkMzFjNDVkOSIsImRtIjozLCJmYyI6NjU2NjgyNTQ5LCJmbCI6NjQzOTMxODIxLCJpcCI6IjM1LjIyMy4xOTguOTUiLCJudyI6MTE1MDAsInBjIjo1MDAwLCJvcCI6NTAwMCwibXAiOjUwMDAsImVjIjowLCJnbSI6MCwiZXAiOm51bGwsInByIjoyNDkzMTYsInJ0IjoxLCJycyI6NTAwLCJzYSI6IjU1Iiwic2IiOiJpLTA0MDI0ODg4ZDlkMWRjZWQ3Iiwic3AiOjI3MjI3Miwic3QiOjEyODcyOTYsInRyIjp0cnVlLCJ1ayI6IjNhZWRhMWMxLTZhYjItNDUwNy04Mzg5LTEwZTJmNDMxYjM5MSIsInRzIjoxNzI5MzU5MDU0OTI3LCJiZiI6dHJ1ZSwicG4iOiJyYlByb2R1Y3RVcGNzIiwiZ2MiOnRydWUsImdDIjp0cnVlLCJncyI6Im5vbmUiLCJkYyI6MSwidHoiOiJBbWVyaWNhL05ld19Zb3JrIiwiZXQiOjY5fQ&s=l6MOscQC-q-FkC2Ksd7w6jjySCQ',
|
|
105
|
+
},
|
|
106
|
+
];
|
|
107
|
+
const RB_SPOTS_SELECTION_EXAMPLE = {
|
|
108
|
+
rbHomepageHero: [
|
|
109
|
+
{
|
|
110
|
+
id: 'abc123',
|
|
111
|
+
spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
|
|
112
|
+
variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
|
|
113
|
+
width: 1140,
|
|
114
|
+
height: 640,
|
|
115
|
+
header: 'Premium Wine Collection',
|
|
116
|
+
description: 'Discover our exclusive selection of vintage wines',
|
|
117
|
+
ctaText: 'Shop Wines',
|
|
118
|
+
textColor: '#ffffff',
|
|
119
|
+
ctaTextColor: '#ffffff',
|
|
120
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Wine+Collection',
|
|
121
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Wine',
|
|
122
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
123
|
+
productIds: [1, 2, 3],
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
id: 'jkl012',
|
|
127
|
+
spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
|
|
128
|
+
variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
|
|
129
|
+
width: 1140,
|
|
130
|
+
height: 640,
|
|
131
|
+
header: 'Whiskey Collection',
|
|
132
|
+
description: 'Premium whiskeys from around the world',
|
|
133
|
+
ctaText: 'Shop Whiskeys',
|
|
134
|
+
textColor: '#ffffff',
|
|
135
|
+
backgroundColor: '#2c1810',
|
|
136
|
+
ctaTextColor: '#2c1810',
|
|
137
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Whiskey',
|
|
138
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Whiskey',
|
|
139
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
140
|
+
productIds: [10, 11],
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
id: 'stu901',
|
|
144
|
+
spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
|
|
145
|
+
variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
|
|
146
|
+
width: 1140,
|
|
147
|
+
height: 640,
|
|
148
|
+
header: 'Summer Cocktails',
|
|
149
|
+
description: 'Essential spirits for summer mixing',
|
|
150
|
+
ctaText: 'Mix It Up',
|
|
151
|
+
textColor: '#ffffff',
|
|
152
|
+
backgroundColor: '#4d3a0a',
|
|
153
|
+
ctaTextColor: '#4d3a0a',
|
|
154
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Cocktails',
|
|
155
|
+
secondaryImage: 'https://placehold.co/1140x640/png?text=Mixers',
|
|
156
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Cocktails',
|
|
157
|
+
mobileSecondaryImage: 'https://placehold.co/640x320/png?text=Mobile+Mixers',
|
|
158
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
159
|
+
productIds: [16, 17, 18],
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
id: 'def456',
|
|
163
|
+
spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
|
|
164
|
+
variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
|
|
165
|
+
width: 1140,
|
|
166
|
+
height: 640,
|
|
167
|
+
header: 'Craft Beer Festival',
|
|
168
|
+
description: 'Local breweries and exclusive releases',
|
|
169
|
+
ctaText: 'Explore Beers',
|
|
170
|
+
textColor: '#ffffff',
|
|
171
|
+
ctaTextColor: '#ffffff',
|
|
172
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Beer+Festival',
|
|
173
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Beer',
|
|
174
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
175
|
+
productIds: [4, 5, 6],
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
id: 'mno345',
|
|
179
|
+
spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
|
|
180
|
+
variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
|
|
181
|
+
width: 1140,
|
|
182
|
+
height: 640,
|
|
183
|
+
header: 'Champagne Selection',
|
|
184
|
+
description: 'Finest champagnes for every occasion',
|
|
185
|
+
ctaText: 'View Champagnes',
|
|
186
|
+
textColor: '#ffffff',
|
|
187
|
+
backgroundColor: '#1a1a1a',
|
|
188
|
+
ctaTextColor: '#1a1a1a',
|
|
189
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Champagne',
|
|
190
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Champagne',
|
|
191
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
192
|
+
productIds: [12, 13],
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
id: 'vwx234',
|
|
196
|
+
spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
|
|
197
|
+
variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
|
|
198
|
+
width: 1140,
|
|
199
|
+
height: 640,
|
|
200
|
+
header: 'Wine Regions',
|
|
201
|
+
description: 'Explore wines from top regions',
|
|
202
|
+
ctaText: 'Tour Regions',
|
|
203
|
+
textColor: '#ffffff',
|
|
204
|
+
backgroundColor: '#4d0a0a',
|
|
205
|
+
ctaTextColor: '#4d0a0a',
|
|
206
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Wine+Regions',
|
|
207
|
+
secondaryImage: 'https://placehold.co/1140x640/png?text=Vineyards',
|
|
208
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Regions',
|
|
209
|
+
mobileSecondaryImage: 'https://placehold.co/640x320/png?text=Mobile+Vineyards',
|
|
210
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
211
|
+
productIds: [19, 20, 21],
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
id: 'ghi789',
|
|
215
|
+
spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
|
|
216
|
+
variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
|
|
217
|
+
width: 1140,
|
|
218
|
+
height: 640,
|
|
219
|
+
header: 'Rare Spirits',
|
|
220
|
+
description: 'Limited edition spirits collection',
|
|
221
|
+
ctaText: 'View Collection',
|
|
222
|
+
textColor: '#ffffff',
|
|
223
|
+
ctaTextColor: '#ffffff',
|
|
224
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Rare+Spirits',
|
|
225
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Spirits',
|
|
226
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
227
|
+
productIds: [7, 8, 9],
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
id: 'pqr678',
|
|
231
|
+
spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
|
|
232
|
+
variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
|
|
233
|
+
width: 1140,
|
|
234
|
+
height: 640,
|
|
235
|
+
header: 'Gin Collection',
|
|
236
|
+
description: 'Artisanal gins and botanicals',
|
|
237
|
+
ctaText: 'Explore Gins',
|
|
238
|
+
textColor: '#ffffff',
|
|
239
|
+
backgroundColor: '#0a4d4d',
|
|
240
|
+
ctaTextColor: '#0a4d4d',
|
|
241
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Gin',
|
|
242
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Gin',
|
|
243
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
244
|
+
productIds: [14, 15],
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
id: 'yz5678',
|
|
248
|
+
spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
|
|
249
|
+
variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
|
|
250
|
+
width: 1140,
|
|
251
|
+
height: 640,
|
|
252
|
+
header: 'Tequila Collection',
|
|
253
|
+
description: 'Premium tequilas and mezcals',
|
|
254
|
+
ctaText: 'Shop Tequila',
|
|
255
|
+
textColor: '#ffffff',
|
|
256
|
+
backgroundColor: '#0a4d2b',
|
|
257
|
+
ctaTextColor: '#0a4d2b',
|
|
258
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Tequila',
|
|
259
|
+
secondaryImage: 'https://placehold.co/1140x640/png?text=Mezcal',
|
|
260
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Tequila',
|
|
261
|
+
mobileSecondaryImage: 'https://placehold.co/640x320/png?text=Mobile+Mezcal',
|
|
262
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
263
|
+
productIds: [22, 23, 24],
|
|
264
|
+
},
|
|
265
|
+
],
|
|
266
|
+
rbHomepageHeroFullImage: [
|
|
267
|
+
{
|
|
268
|
+
id: 'hjk567',
|
|
269
|
+
spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
|
|
270
|
+
variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
|
|
271
|
+
width: 1140,
|
|
272
|
+
height: 640,
|
|
273
|
+
header: 'Holiday Gift Guide',
|
|
274
|
+
description: 'Perfect spirits for every occasion',
|
|
275
|
+
ctaText: 'Shop Gifts',
|
|
276
|
+
textColor: '#ffffff',
|
|
277
|
+
ctaTextColor: '#ffffff',
|
|
278
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Gift+Guide',
|
|
279
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Gifts',
|
|
280
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
281
|
+
productIds: [25, 26],
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
id: 'qwe890',
|
|
285
|
+
spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
|
|
286
|
+
variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_FULL_IMAGE,
|
|
287
|
+
width: 1140,
|
|
288
|
+
height: 640,
|
|
289
|
+
header: 'Summer Wine Festival',
|
|
290
|
+
description: 'Refreshing wines for summer',
|
|
291
|
+
ctaText: 'Shop Festival',
|
|
292
|
+
textColor: '#ffffff',
|
|
293
|
+
ctaTextColor: '#ffffff',
|
|
294
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Wine+Festival',
|
|
295
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Festival',
|
|
296
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
297
|
+
productIds: [27, 28],
|
|
298
|
+
},
|
|
299
|
+
],
|
|
300
|
+
rbHomepageHeroTwoTile: [
|
|
301
|
+
{
|
|
302
|
+
id: 'iop987',
|
|
303
|
+
spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
|
|
304
|
+
variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
|
|
305
|
+
width: 1140,
|
|
306
|
+
height: 640,
|
|
307
|
+
header: 'Bourbon Selection',
|
|
308
|
+
description: "Kentucky's finest bourbons",
|
|
309
|
+
ctaText: 'Shop Bourbon',
|
|
310
|
+
textColor: '#ffffff',
|
|
311
|
+
backgroundColor: '#2c1810',
|
|
312
|
+
ctaTextColor: '#2c1810',
|
|
313
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Bourbon',
|
|
314
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Bourbon',
|
|
315
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
316
|
+
productIds: [29, 30],
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
id: 'lkj012',
|
|
320
|
+
spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
|
|
321
|
+
variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_TWO_TILE,
|
|
322
|
+
width: 1140,
|
|
323
|
+
height: 640,
|
|
324
|
+
header: 'Vodka Collection',
|
|
325
|
+
description: 'Premium vodkas from around the world',
|
|
326
|
+
ctaText: 'Shop Vodka',
|
|
327
|
+
textColor: '#ffffff',
|
|
328
|
+
backgroundColor: '#1a1a1a',
|
|
329
|
+
ctaTextColor: '#1a1a1a',
|
|
330
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Vodka',
|
|
331
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Vodka',
|
|
332
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
333
|
+
productIds: [31, 32],
|
|
334
|
+
},
|
|
335
|
+
],
|
|
336
|
+
rbHomepageHeroThreeTile: [
|
|
337
|
+
{
|
|
338
|
+
id: 'bnm345',
|
|
339
|
+
spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
|
|
340
|
+
variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
|
|
341
|
+
width: 1140,
|
|
342
|
+
height: 640,
|
|
343
|
+
header: 'Rum Collection',
|
|
344
|
+
description: 'Caribbean and craft rums',
|
|
345
|
+
ctaText: 'Shop Rum',
|
|
346
|
+
textColor: '#ffffff',
|
|
347
|
+
backgroundColor: '#4d3a0a',
|
|
348
|
+
ctaTextColor: '#4d3a0a',
|
|
349
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Rum',
|
|
350
|
+
secondaryImage: 'https://placehold.co/1140x640/png?text=Craft+Rum',
|
|
351
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Rum',
|
|
352
|
+
mobileSecondaryImage: 'https://placehold.co/640x320/png?text=Mobile+Craft',
|
|
353
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
354
|
+
productIds: [33, 34],
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
id: 'fgh678',
|
|
358
|
+
spot: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
|
|
359
|
+
variant: exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE,
|
|
360
|
+
width: 1140,
|
|
361
|
+
height: 640,
|
|
362
|
+
header: 'Scotch Selection',
|
|
363
|
+
description: 'Single malts and blends',
|
|
364
|
+
ctaText: 'Shop Scotch',
|
|
365
|
+
textColor: '#ffffff',
|
|
366
|
+
backgroundColor: '#4d0a0a',
|
|
367
|
+
ctaTextColor: '#4d0a0a',
|
|
368
|
+
primaryImage: 'https://placehold.co/1140x640/png?text=Scotch',
|
|
369
|
+
secondaryImage: 'https://placehold.co/1140x640/png?text=Single+Malts',
|
|
370
|
+
mobilePrimaryImage: 'https://placehold.co/640x640/png?text=Mobile+Scotch',
|
|
371
|
+
mobileSecondaryImage: 'https://placehold.co/640x320/png?text=Mobile+Malts',
|
|
372
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
373
|
+
productIds: [35, 36],
|
|
374
|
+
},
|
|
375
|
+
],
|
|
376
|
+
rbLargeCategoryImageTout: [
|
|
377
|
+
{
|
|
378
|
+
id: 'cde567',
|
|
379
|
+
spot: exports.RMN_SPOT_TYPE.RB_LARGE_CATEGORY_IMAGE_TOUT,
|
|
380
|
+
variant: exports.RMN_SPOT_TYPE.RB_LARGE_CATEGORY_IMAGE_TOUT,
|
|
381
|
+
width: 468,
|
|
382
|
+
height: 410,
|
|
383
|
+
header: 'Rare & Limited Edition',
|
|
384
|
+
description: 'Discover our collection of hard-to-find and limited release spirits.',
|
|
385
|
+
textColor: '#ffffff',
|
|
386
|
+
ctaTextColor: '#ffffff',
|
|
387
|
+
primaryImage: 'https://placehold.co/468x410/png?text=Rare+Spirits',
|
|
388
|
+
mobilePrimaryImage: 'https://placehold.co/468x410/png?text=Mobile+Rare+Spirits',
|
|
389
|
+
ctaText: 'Shop Rare Spirits',
|
|
390
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
391
|
+
productIds: [37, 38, 39, 40, 41],
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
id: 'efg789',
|
|
395
|
+
spot: exports.RMN_SPOT_TYPE.RB_LARGE_CATEGORY_IMAGE_TOUT,
|
|
396
|
+
variant: exports.RMN_SPOT_TYPE.RB_LARGE_CATEGORY_IMAGE_TOUT,
|
|
397
|
+
width: 468,
|
|
398
|
+
height: 410,
|
|
399
|
+
header: 'Vintage Champagnes',
|
|
400
|
+
description: 'Explore our prestigious collection of aged champagnes.',
|
|
401
|
+
textColor: '#ffffff',
|
|
402
|
+
ctaTextColor: '#ffffff',
|
|
403
|
+
primaryImage: 'https://placehold.co/468x410/png?text=Vintage+Champagne',
|
|
404
|
+
mobilePrimaryImage: 'https://placehold.co/468x410/png?text=Mobile+Champagne',
|
|
405
|
+
ctaText: 'View Collection',
|
|
406
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
407
|
+
productIds: [42, 43, 44, 45, 46],
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
id: 'ghi012',
|
|
411
|
+
spot: exports.RMN_SPOT_TYPE.RB_LARGE_CATEGORY_IMAGE_TOUT,
|
|
412
|
+
variant: exports.RMN_SPOT_TYPE.RB_LARGE_CATEGORY_IMAGE_TOUT,
|
|
413
|
+
width: 468,
|
|
414
|
+
height: 410,
|
|
415
|
+
header: 'Small Batch Bourbon',
|
|
416
|
+
description: 'Hand-selected premium bourbon from craft distilleries.',
|
|
417
|
+
textColor: '#ffffff',
|
|
418
|
+
ctaTextColor: '#ffffff',
|
|
419
|
+
primaryImage: 'https://placehold.co/468x410/png?text=Craft+Bourbon',
|
|
420
|
+
mobilePrimaryImage: 'https://placehold.co/468x410/png?text=Mobile+Bourbon',
|
|
421
|
+
ctaText: 'Explore Bourbon',
|
|
422
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
423
|
+
productIds: [47, 48, 49, 50, 51],
|
|
424
|
+
},
|
|
425
|
+
],
|
|
426
|
+
rbSmallDiscoverTout: [
|
|
427
|
+
{
|
|
428
|
+
id: 'jkl345',
|
|
429
|
+
spot: exports.RMN_SPOT_TYPE.RB_SMALL_DISCOVER_TOUT,
|
|
430
|
+
variant: exports.RMN_SPOT_TYPE.RB_SMALL_DISCOVER_TOUT,
|
|
431
|
+
width: 224,
|
|
432
|
+
height: 378,
|
|
433
|
+
header: 'Château Margaux 2015 Bordeaux',
|
|
434
|
+
textColor: '#ffffff',
|
|
435
|
+
primaryImage: 'https://placehold.co/224x378/png?text=Château+Margaux',
|
|
436
|
+
mobilePrimaryImage: 'https://placehold.co/224x378/png?text=Mobile+Château+Margaux',
|
|
437
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
438
|
+
productIds: [52, 53, 54, 55, 56],
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
id: 'lmn678',
|
|
442
|
+
spot: exports.RMN_SPOT_TYPE.RB_SMALL_DISCOVER_TOUT,
|
|
443
|
+
variant: exports.RMN_SPOT_TYPE.RB_SMALL_DISCOVER_TOUT,
|
|
444
|
+
width: 224,
|
|
445
|
+
height: 378,
|
|
446
|
+
header: 'Macallan 25 Year',
|
|
447
|
+
textColor: '#ffffff',
|
|
448
|
+
primaryImage: 'https://placehold.co/224x378/png?text=Macallan+25',
|
|
449
|
+
mobilePrimaryImage: 'https://placehold.co/224x378/png?text=Mobile+Macallan',
|
|
450
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
451
|
+
productIds: [57, 58, 59, 60, 61],
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
id: 'nop901',
|
|
455
|
+
spot: exports.RMN_SPOT_TYPE.RB_SMALL_DISCOVER_TOUT,
|
|
456
|
+
variant: exports.RMN_SPOT_TYPE.RB_SMALL_DISCOVER_TOUT,
|
|
457
|
+
width: 224,
|
|
458
|
+
height: 378,
|
|
459
|
+
header: 'Louis XIII Cognac',
|
|
460
|
+
textColor: '#ffffff',
|
|
461
|
+
primaryImage: 'https://placehold.co/224x378/png?text=Louis+XIII',
|
|
462
|
+
mobilePrimaryImage: 'https://placehold.co/224x378/png?text=Mobile+Louis+XIII',
|
|
463
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
464
|
+
productIds: [62, 63, 64, 65, 66],
|
|
465
|
+
},
|
|
466
|
+
],
|
|
467
|
+
rbSmallCategoryImageTout: [
|
|
468
|
+
{
|
|
469
|
+
id: 'qrs234',
|
|
470
|
+
spot: exports.RMN_SPOT_TYPE.RB_SMALL_CATEGORY_IMAGE_TOUT,
|
|
471
|
+
variant: exports.RMN_SPOT_TYPE.RB_SMALL_CATEGORY_IMAGE_TOUT,
|
|
472
|
+
width: 224,
|
|
473
|
+
height: 410,
|
|
474
|
+
header: 'Japanese Sake',
|
|
475
|
+
textColor: '#ffffff',
|
|
476
|
+
primaryImage: 'https://placehold.co/224x410/png?text=Japanese+Sake',
|
|
477
|
+
mobilePrimaryImage: 'https://placehold.co/224x410/png?text=Mobile+Japanese+Sake',
|
|
478
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
479
|
+
productIds: [67, 68, 69, 70, 71],
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
id: 'stu567',
|
|
483
|
+
spot: exports.RMN_SPOT_TYPE.RB_SMALL_CATEGORY_IMAGE_TOUT,
|
|
484
|
+
variant: exports.RMN_SPOT_TYPE.RB_SMALL_CATEGORY_IMAGE_TOUT,
|
|
485
|
+
width: 224,
|
|
486
|
+
height: 410,
|
|
487
|
+
header: 'Craft Vermouth',
|
|
488
|
+
textColor: '#ffffff',
|
|
489
|
+
primaryImage: 'https://placehold.co/224x410/png?text=Craft+Vermouth',
|
|
490
|
+
mobilePrimaryImage: 'https://placehold.co/224x410/png?text=Mobile+Vermouth',
|
|
491
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
492
|
+
productIds: [72, 73, 74, 75, 76],
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
id: 'vwx890',
|
|
496
|
+
spot: exports.RMN_SPOT_TYPE.RB_SMALL_CATEGORY_IMAGE_TOUT,
|
|
497
|
+
variant: exports.RMN_SPOT_TYPE.RB_SMALL_CATEGORY_IMAGE_TOUT,
|
|
498
|
+
width: 224,
|
|
499
|
+
height: 410,
|
|
500
|
+
header: 'Premium Mezcal',
|
|
501
|
+
textColor: '#ffffff',
|
|
502
|
+
primaryImage: 'https://placehold.co/224x410/png?text=Premium+Mezcal',
|
|
503
|
+
mobilePrimaryImage: 'https://placehold.co/224x410/png?text=Mobile+Mezcal',
|
|
504
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
505
|
+
productIds: [77, 78, 79, 80, 81],
|
|
506
|
+
},
|
|
507
|
+
],
|
|
508
|
+
rbCollectionBannerWithoutTextBlock: [
|
|
509
|
+
{
|
|
510
|
+
id: 'yz1234',
|
|
511
|
+
spot: exports.RMN_SPOT_TYPE.RB_COLLECTION_BANNER_WITHOUT_TEXT_BLOCK,
|
|
512
|
+
variant: exports.RMN_SPOT_TYPE.RB_COLLECTION_BANNER_WITHOUT_TEXT_BLOCK,
|
|
513
|
+
width: 887,
|
|
514
|
+
height: 344,
|
|
515
|
+
primaryImage: 'https://placehold.co/887x344/png?text=Summer+Cocktails',
|
|
516
|
+
mobilePrimaryImage: 'https://placehold.co/887x344/png?text=Mobile+Summer+Cocktails',
|
|
517
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
518
|
+
productIds: [82, 83, 84, 85, 86],
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
id: 'abc567',
|
|
522
|
+
spot: exports.RMN_SPOT_TYPE.RB_COLLECTION_BANNER_WITHOUT_TEXT_BLOCK,
|
|
523
|
+
variant: exports.RMN_SPOT_TYPE.RB_COLLECTION_BANNER_WITHOUT_TEXT_BLOCK,
|
|
524
|
+
width: 887,
|
|
525
|
+
height: 344,
|
|
526
|
+
primaryImage: 'https://placehold.co/887x344/png?text=Holiday+Spirits',
|
|
527
|
+
mobilePrimaryImage: 'https://placehold.co/887x344/png?text=Mobile+Holiday+Spirits',
|
|
528
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
529
|
+
productIds: [87, 88, 89, 90, 91],
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
id: 'def901',
|
|
533
|
+
spot: exports.RMN_SPOT_TYPE.RB_COLLECTION_BANNER_WITHOUT_TEXT_BLOCK,
|
|
534
|
+
variant: exports.RMN_SPOT_TYPE.RB_COLLECTION_BANNER_WITHOUT_TEXT_BLOCK,
|
|
535
|
+
width: 887,
|
|
536
|
+
height: 344,
|
|
537
|
+
primaryImage: 'https://placehold.co/887x344/png?text=Wine+Essentials',
|
|
538
|
+
mobilePrimaryImage: 'https://placehold.co/887x344/png?text=Mobile+Wine+Essentials',
|
|
539
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
540
|
+
productIds: [92, 93, 94, 95, 96],
|
|
541
|
+
},
|
|
542
|
+
],
|
|
543
|
+
rbNavigationBanner: [
|
|
544
|
+
{
|
|
545
|
+
id: 'ghi234',
|
|
546
|
+
spot: exports.RMN_SPOT_TYPE.RB_NAVIGATION_BANNER,
|
|
547
|
+
variant: exports.RMN_SPOT_TYPE.RB_NAVIGATION_BANNER,
|
|
548
|
+
width: 440,
|
|
549
|
+
height: 220,
|
|
550
|
+
header: 'Explore Tequilas',
|
|
551
|
+
textColor: '#ffffff',
|
|
552
|
+
primaryImage: 'https://placehold.co/440x220/png?text=Tequila+Collection',
|
|
553
|
+
mobilePrimaryImage: 'https://placehold.co/440x220/png?text=Mobile+Tequila+Collection',
|
|
554
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
555
|
+
productIds: [97, 98, 99, 100, 101],
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
id: 'jkl678',
|
|
559
|
+
spot: exports.RMN_SPOT_TYPE.RB_NAVIGATION_BANNER,
|
|
560
|
+
variant: exports.RMN_SPOT_TYPE.RB_NAVIGATION_BANNER,
|
|
561
|
+
width: 440,
|
|
562
|
+
height: 220,
|
|
563
|
+
header: 'Craft Gin Selection',
|
|
564
|
+
textColor: '#ffffff',
|
|
565
|
+
primaryImage: 'https://placehold.co/440x220/png?text=Gin+Selection',
|
|
566
|
+
mobilePrimaryImage: 'https://placehold.co/440x220/png?text=Mobile+Gin+Selection',
|
|
567
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
568
|
+
productIds: [102, 103, 104, 105, 106],
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
id: 'mno012',
|
|
572
|
+
spot: exports.RMN_SPOT_TYPE.RB_NAVIGATION_BANNER,
|
|
573
|
+
variant: exports.RMN_SPOT_TYPE.RB_NAVIGATION_BANNER,
|
|
574
|
+
width: 440,
|
|
575
|
+
height: 220,
|
|
576
|
+
header: 'Premium Vodka',
|
|
577
|
+
textColor: '#ffffff',
|
|
578
|
+
primaryImage: 'https://placehold.co/440x220/png?text=Vodka+Premium',
|
|
579
|
+
mobilePrimaryImage: 'https://placehold.co/440x220/png?text=Mobile+Vodka+Premium',
|
|
580
|
+
events: SPOT_EVENTS_EXAMPLE,
|
|
581
|
+
productIds: [107, 108, 109, 110, 111],
|
|
582
|
+
},
|
|
583
|
+
],
|
|
584
|
+
};
|
|
585
|
+
|
|
74
586
|
const REQUEST_CLOUD_PARTNER_SITE = 'X-Liquid-Partner-Site';
|
|
75
587
|
const REQUEST_CLOUD_PROTECTED_KEY = 'X-Liquid-Protected';
|
|
76
588
|
const REQUEST_CLOUD_PROTECTED_TIMESTAMP = 'X-Liquid-Timestamp';
|
|
@@ -14999,7 +15511,7 @@ class BaseApi extends BaseApiAbstract {
|
|
|
14999
15511
|
*/
|
|
15000
15512
|
async post(path, data, configOverrides) {
|
|
15001
15513
|
let requestData = data;
|
|
15002
|
-
if (
|
|
15514
|
+
if (![exports.RMN_ENV.LOCAL, exports.RMN_ENV.DEVELOPMENT].includes(this.authInfo.env)) {
|
|
15003
15515
|
const timestamp = new Date().getTime();
|
|
15004
15516
|
configOverrides = {
|
|
15005
15517
|
...configOverrides,
|
|
@@ -15152,9 +15664,7 @@ class AuthService extends BaseApi {
|
|
|
15152
15664
|
}
|
|
15153
15665
|
|
|
15154
15666
|
const SPOT_ELEMENT_TAG = 'spot-element';
|
|
15155
|
-
const
|
|
15156
|
-
const SPOTS_SELECTION_API_PATH = '/spots/selection';
|
|
15157
|
-
|
|
15667
|
+
const CAROUSEL_ELEMENT_TAG = 'spot-carousel-element';
|
|
15158
15668
|
const GFONT_PRECONNECT = `
|
|
15159
15669
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
15160
15670
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
@@ -15165,163 +15675,1501 @@ const GFONT_SOURCE_SANS_3 = `
|
|
|
15165
15675
|
const GFONT_CORMORANT = `
|
|
15166
15676
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Cormorant:ital,wght@0,300..700;1,300..700&family=Source+Sans+3:ital,wght@0,200..900;1,200..900&display=swap">
|
|
15167
15677
|
`;
|
|
15168
|
-
|
|
15169
|
-
|
|
15170
|
-
|
|
15171
|
-
|
|
15172
|
-
|
|
15173
|
-
|
|
15174
|
-
|
|
15175
|
-
|
|
15678
|
+
|
|
15679
|
+
/**
|
|
15680
|
+
* Determines the event type from a raw event string.
|
|
15681
|
+
*
|
|
15682
|
+
* @param {string} [event] - The raw event string to evaluate.
|
|
15683
|
+
* @returns {RMN_SPOT_EVENT | null} - The corresponding RMN_SPOT_EVENT or null if no match is found.
|
|
15684
|
+
*/
|
|
15685
|
+
function getEventTypeFromRawEvent(event) {
|
|
15686
|
+
if (!event) {
|
|
15687
|
+
return null;
|
|
15176
15688
|
}
|
|
15177
|
-
|
|
15178
|
-
|
|
15179
|
-
|
|
15689
|
+
if (event.includes('cart')) {
|
|
15690
|
+
if (event.includes('add')) {
|
|
15691
|
+
return exports.RMN_SPOT_EVENT.ADD_TO_CART;
|
|
15692
|
+
}
|
|
15693
|
+
if (event.includes('remove')) {
|
|
15694
|
+
return exports.RMN_SPOT_EVENT.REMOVE_FROM_CART;
|
|
15695
|
+
}
|
|
15180
15696
|
}
|
|
15181
|
-
|
|
15182
|
-
|
|
15183
|
-
height: ${height}px;
|
|
15697
|
+
if (event.includes('purchase')) {
|
|
15698
|
+
return exports.RMN_SPOT_EVENT.PURCHASE;
|
|
15184
15699
|
}
|
|
15185
|
-
|
|
15186
|
-
|
|
15187
|
-
|
|
15188
|
-
|
|
15189
|
-
|
|
15190
|
-
if (!hasCustomContent) {
|
|
15191
|
-
style.textContent += `
|
|
15192
|
-
:host .wrapper {
|
|
15193
|
-
position: absolute;
|
|
15194
|
-
top: 0;
|
|
15195
|
-
left: 0;
|
|
15196
|
-
width: 100%;
|
|
15197
|
-
height: 100%;
|
|
15198
|
-
overflow: hidden;
|
|
15199
|
-
}
|
|
15200
|
-
`;
|
|
15700
|
+
// if(event.includes('refund')) {
|
|
15701
|
+
// return RMN_SPOT_EVENT.REFUND;
|
|
15702
|
+
// }
|
|
15703
|
+
if (event.includes('wishlist') && event.includes('add')) {
|
|
15704
|
+
return exports.RMN_SPOT_EVENT.ADD_TO_WISHLIST;
|
|
15201
15705
|
}
|
|
15202
|
-
return
|
|
15203
|
-
}
|
|
15204
|
-
|
|
15205
|
-
|
|
15206
|
-
|
|
15207
|
-
|
|
15208
|
-
|
|
15209
|
-
|
|
15210
|
-
|
|
15211
|
-
|
|
15212
|
-
|
|
15213
|
-
|
|
15214
|
-
|
|
15215
|
-
|
|
15706
|
+
return null;
|
|
15707
|
+
}
|
|
15708
|
+
/**
|
|
15709
|
+
* Recursively extracts ID values from a nested data structure.
|
|
15710
|
+
* Searches for specified property names and collects their primitive values (strings/numbers).
|
|
15711
|
+
*
|
|
15712
|
+
* @param data - The data structure to search through (can be nested objects/arrays)
|
|
15713
|
+
* @param propertyNames - Array of property names to look for
|
|
15714
|
+
* @returns Array of extracted ID values (strings/numbers only)
|
|
15715
|
+
*
|
|
15716
|
+
* @example
|
|
15717
|
+
* const data = {
|
|
15718
|
+
* id: [1, 2, 3],
|
|
15719
|
+
* nested: { id: 'abc' },
|
|
15720
|
+
* items: [{ id: 456 }]
|
|
15721
|
+
* };
|
|
15722
|
+
* extractDeepIds(data); // Returns [1, 2, 3, 'abc', 456]
|
|
15723
|
+
*/
|
|
15724
|
+
function extractDeepIds(data, propertyNames) {
|
|
15725
|
+
const ids = [];
|
|
15726
|
+
const defaulPropertyNames = [
|
|
15727
|
+
'id',
|
|
15728
|
+
'upc',
|
|
15729
|
+
'groupingId',
|
|
15730
|
+
'sku',
|
|
15731
|
+
'productId',
|
|
15732
|
+
'item_id',
|
|
15733
|
+
'isbn',
|
|
15734
|
+
'asin',
|
|
15735
|
+
'mpn',
|
|
15736
|
+
'model_number',
|
|
15737
|
+
'article_number',
|
|
15738
|
+
'variant_id',
|
|
15739
|
+
'item_number',
|
|
15740
|
+
'catalog_id',
|
|
15741
|
+
'reference_id',
|
|
15742
|
+
];
|
|
15743
|
+
// Set for faster property name lookups
|
|
15744
|
+
const propertySet = new Set(defaulPropertyNames);
|
|
15745
|
+
/**
|
|
15746
|
+
* Processes a value and extracts IDs if it matches criteria
|
|
15747
|
+
* @param value - The value to process
|
|
15748
|
+
* @param currentKey - The property name of the current value
|
|
15749
|
+
*/
|
|
15750
|
+
const processValue = (value, currentKey) => {
|
|
15751
|
+
// Early exit for null/undefined values
|
|
15752
|
+
if (value == null)
|
|
15753
|
+
return;
|
|
15754
|
+
// If current key matches our target properties
|
|
15755
|
+
if (currentKey && propertySet.has(currentKey)) {
|
|
15756
|
+
if (Array.isArray(value)) {
|
|
15757
|
+
// Filter and push valid array values in one pass
|
|
15758
|
+
ids.push(...value.filter((item) => typeof item === 'string' || typeof item === 'number'));
|
|
15759
|
+
}
|
|
15760
|
+
else if (typeof value === 'string' || typeof value === 'number') {
|
|
15761
|
+
ids.push(value);
|
|
15762
|
+
}
|
|
15763
|
+
return; // Stop processing this branch after handling the ID
|
|
15216
15764
|
}
|
|
15217
|
-
|
|
15218
|
-
|
|
15219
|
-
|
|
15220
|
-
background-image: url("${primaryImage}");
|
|
15221
|
-
background-position: center;
|
|
15222
|
-
background-repeat: no-repeat;
|
|
15223
|
-
background-size: cover;
|
|
15765
|
+
// Recursively process nested structures
|
|
15766
|
+
if (Array.isArray(value)) {
|
|
15767
|
+
value.forEach((item) => processValue(item));
|
|
15224
15768
|
}
|
|
15225
|
-
|
|
15226
|
-
|
|
15227
|
-
|
|
15228
|
-
|
|
15229
|
-
|
|
15230
|
-
gap: 0.5cqw;
|
|
15769
|
+
else if (typeof value === 'object') {
|
|
15770
|
+
// Process all enumerable properties
|
|
15771
|
+
for (const [key, val] of Object.entries(value)) {
|
|
15772
|
+
processValue(val, key);
|
|
15773
|
+
}
|
|
15231
15774
|
}
|
|
15232
|
-
|
|
15233
|
-
|
|
15234
|
-
|
|
15235
|
-
|
|
15236
|
-
|
|
15237
|
-
|
|
15238
|
-
|
|
15775
|
+
};
|
|
15776
|
+
processValue(data);
|
|
15777
|
+
return ids; // No need to filter nulls as we handle that during collection
|
|
15778
|
+
}
|
|
15779
|
+
// Fallback method using fetch if sendBeacon isn't available
|
|
15780
|
+
async function fallbackEventFire(url) {
|
|
15781
|
+
try {
|
|
15782
|
+
const racePromise = Promise.race([
|
|
15783
|
+
// Promise #1: The fetch request
|
|
15784
|
+
fetch(url, {
|
|
15785
|
+
method: 'POST',
|
|
15786
|
+
keepalive: true,
|
|
15787
|
+
}),
|
|
15788
|
+
// Promise #2: The timeout
|
|
15789
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('Request timeout')), 2000)),
|
|
15790
|
+
]);
|
|
15791
|
+
/**
|
|
15792
|
+
* Prevent requests from hanging indefinitely
|
|
15793
|
+
* Improve user experience by failing fast
|
|
15794
|
+
* Handle slow network conditions gracefully
|
|
15795
|
+
* Ensure resources are freed up in a timely manner
|
|
15796
|
+
*/
|
|
15797
|
+
const response = await racePromise;
|
|
15798
|
+
return response.ok;
|
|
15799
|
+
}
|
|
15800
|
+
catch (_a) {
|
|
15801
|
+
return false;
|
|
15802
|
+
}
|
|
15803
|
+
}
|
|
15804
|
+
/**
|
|
15805
|
+
* Extracts and decodes a URL from a base64-encoded query parameter.
|
|
15806
|
+
*
|
|
15807
|
+
* @param {string} url - The URL containing the base64-encoded query parameter.
|
|
15808
|
+
* @returns {string | null} - The decoded URL or null if not found or invalid.
|
|
15809
|
+
*/
|
|
15810
|
+
function getRedirectUrlFromPayload(url) {
|
|
15811
|
+
try {
|
|
15812
|
+
const base64String = new URL(url).searchParams.get('e');
|
|
15813
|
+
if (!base64String) {
|
|
15814
|
+
return null;
|
|
15239
15815
|
}
|
|
15240
|
-
.
|
|
15241
|
-
|
|
15242
|
-
|
|
15243
|
-
|
|
15244
|
-
|
|
15245
|
-
|
|
15246
|
-
|
|
15247
|
-
|
|
15248
|
-
|
|
15249
|
-
|
|
15250
|
-
|
|
15251
|
-
|
|
15816
|
+
const data = JSON.parse(atob(base64String));
|
|
15817
|
+
return data.ur || null;
|
|
15818
|
+
}
|
|
15819
|
+
catch (_a) {
|
|
15820
|
+
return null;
|
|
15821
|
+
}
|
|
15822
|
+
}
|
|
15823
|
+
/**
|
|
15824
|
+
* Fires an event using the navigator.sendBeacon method or a fallback method if sendBeacon is not available.
|
|
15825
|
+
* If the event is a click event and a redirect URL is found, it redirects the user to that URL.
|
|
15826
|
+
*
|
|
15827
|
+
* @param {IFireEventParams} params - The parameters for firing the event.
|
|
15828
|
+
* @param {RMN_SPOT_EVENT} params.event - The event type.
|
|
15829
|
+
* @param {string} params.eventUrl - The URL to which the event is sent.
|
|
15830
|
+
* @returns {Promise<void>} - A promise that resolves when the event is fired.
|
|
15831
|
+
*/
|
|
15832
|
+
async function fireEvent({ event, eventUrl }) {
|
|
15833
|
+
var _a;
|
|
15834
|
+
try {
|
|
15835
|
+
const didFireEvent = ((_a = navigator === null || navigator === void 0 ? void 0 : navigator.sendBeacon) === null || _a === void 0 ? void 0 : _a.call(navigator, eventUrl)) || (await fallbackEventFire(eventUrl));
|
|
15836
|
+
if (!didFireEvent) {
|
|
15837
|
+
return;
|
|
15252
15838
|
}
|
|
15253
|
-
.
|
|
15254
|
-
|
|
15255
|
-
|
|
15256
|
-
|
|
15257
|
-
|
|
15258
|
-
font-family: "Cormorant", serif;
|
|
15259
|
-
margin: 0;
|
|
15839
|
+
if (event === exports.RMN_SPOT_EVENT.CLICK) {
|
|
15840
|
+
const redirectUrl = getRedirectUrlFromPayload(eventUrl);
|
|
15841
|
+
if (redirectUrl) {
|
|
15842
|
+
window.location.href = redirectUrl;
|
|
15843
|
+
}
|
|
15260
15844
|
}
|
|
15261
|
-
|
|
15262
|
-
|
|
15263
|
-
|
|
15264
|
-
|
|
15265
|
-
|
|
15266
|
-
|
|
15845
|
+
}
|
|
15846
|
+
catch (_b) {
|
|
15847
|
+
// Handle errors silently
|
|
15848
|
+
}
|
|
15849
|
+
}
|
|
15850
|
+
function calculateScaleFactor(elementScale) {
|
|
15851
|
+
// Step 1: Apply square root for non-linear scaling
|
|
15852
|
+
// This creates a more gradual scaling effect, especially for larger changes
|
|
15853
|
+
// For example:
|
|
15854
|
+
// - elementScale of 0.25 (1/4 size) becomes 0.5
|
|
15855
|
+
// - elementScale of 1 (unchanged) remains 1
|
|
15856
|
+
// - elementScale of 4 (4x size) becomes 2
|
|
15857
|
+
const baseFactor = Math.sqrt(elementScale);
|
|
15858
|
+
// Step 2: Apply additional dampening to further soften the scaling effect
|
|
15859
|
+
// The dampening factor (0.5) can be adjusted:
|
|
15860
|
+
// - Lower values (closer to 0) make scaling more subtle
|
|
15861
|
+
// - Higher values (closer to 1) make scaling more pronounced
|
|
15862
|
+
const dampening = 0.35;
|
|
15863
|
+
// Calculate the scaleFactor:
|
|
15864
|
+
// 1. (baseFactor - 1) represents the change from the original size
|
|
15865
|
+
// 2. Multiply by dampening to reduce the effect
|
|
15866
|
+
// 3. Add 1 to center the scaling around the original size
|
|
15867
|
+
// For example, if baseFactor is 2:
|
|
15868
|
+
// scaleFactor = 1 + (2 - 1) * 0.5 = 1.5
|
|
15869
|
+
const scaleFactor = 1 + (baseFactor - 1) * dampening;
|
|
15870
|
+
// Step 3: Define the allowed range for the scale factor
|
|
15871
|
+
// This ensures that the font size never changes too drastically
|
|
15872
|
+
const minScale = 0.35; // Font will never be smaller than 50% of original
|
|
15873
|
+
const maxScale = 1.5; // Font will never be larger than 150% of original
|
|
15874
|
+
// Step 4: Clamp the scale factor to the defined range
|
|
15875
|
+
// Math.min ensures the value doesn't exceed maxScale
|
|
15876
|
+
// Math.max ensures the value isn't less than minScale
|
|
15877
|
+
return Math.max(minScale, Math.min(maxScale, scaleFactor));
|
|
15878
|
+
}
|
|
15879
|
+
|
|
15880
|
+
class IntersectionObserverService {
|
|
15881
|
+
constructor(defaultOptions = {}) {
|
|
15882
|
+
this.observers = new Map();
|
|
15883
|
+
this.defaultOptions = {
|
|
15884
|
+
root: null,
|
|
15885
|
+
rootMargin: '0px',
|
|
15886
|
+
threshold: 0.5,
|
|
15887
|
+
...defaultOptions,
|
|
15888
|
+
};
|
|
15889
|
+
}
|
|
15890
|
+
observe(element, callback, options = {}) {
|
|
15891
|
+
const mergedOptions = { ...this.defaultOptions, ...options };
|
|
15892
|
+
const ioCallback = (entries) => {
|
|
15893
|
+
entries.forEach((entry) => {
|
|
15894
|
+
if (entry.isIntersecting) {
|
|
15895
|
+
callback(entry);
|
|
15896
|
+
}
|
|
15897
|
+
});
|
|
15898
|
+
};
|
|
15899
|
+
const observer = new IntersectionObserver(ioCallback, mergedOptions);
|
|
15900
|
+
this.observers.set(element, observer);
|
|
15901
|
+
observer.observe(element);
|
|
15902
|
+
}
|
|
15903
|
+
unobserve(element) {
|
|
15904
|
+
const observer = this.observers.get(element);
|
|
15905
|
+
if (observer) {
|
|
15906
|
+
observer.unobserve(element);
|
|
15907
|
+
observer.disconnect();
|
|
15908
|
+
this.observers.delete(element);
|
|
15267
15909
|
}
|
|
15268
|
-
|
|
15269
|
-
|
|
15270
|
-
|
|
15271
|
-
|
|
15272
|
-
|
|
15273
|
-
|
|
15274
|
-
|
|
15275
|
-
|
|
15276
|
-
|
|
15277
|
-
|
|
15278
|
-
|
|
15279
|
-
|
|
15910
|
+
}
|
|
15911
|
+
unobserveAll() {
|
|
15912
|
+
this.observers.forEach((observer, element) => {
|
|
15913
|
+
observer.unobserve(element);
|
|
15914
|
+
observer.disconnect();
|
|
15915
|
+
});
|
|
15916
|
+
this.observers.clear();
|
|
15917
|
+
}
|
|
15918
|
+
}
|
|
15919
|
+
|
|
15920
|
+
var ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX;
|
|
15921
|
+
(function (ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX) {
|
|
15922
|
+
ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["PLACEMENT_ID"] = 0] = "PLACEMENT_ID";
|
|
15923
|
+
ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["SPOT_ID"] = 1] = "SPOT_ID";
|
|
15924
|
+
ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["SPOT_TYPE"] = 2] = "SPOT_TYPE";
|
|
15925
|
+
ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["EVENTS"] = 3] = "EVENTS";
|
|
15926
|
+
ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["PRODUCT_IDS"] = 4] = "PRODUCT_IDS";
|
|
15927
|
+
ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["CREATED_AT"] = 5] = "CREATED_AT";
|
|
15928
|
+
})(ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX || (ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX = {}));
|
|
15929
|
+
class LocalStorageService {
|
|
15930
|
+
constructor() {
|
|
15931
|
+
if (typeof window.localStorage === 'undefined') {
|
|
15932
|
+
console.warn('Local storage is not supported in this environment');
|
|
15933
|
+
return;
|
|
15280
15934
|
}
|
|
15281
|
-
.
|
|
15282
|
-
|
|
15935
|
+
this.spots = new Map();
|
|
15936
|
+
// Sync local storage with the current state
|
|
15937
|
+
this.syncLocalStorage();
|
|
15938
|
+
// Remove expired spots
|
|
15939
|
+
this.removeExpiredSpots();
|
|
15940
|
+
}
|
|
15941
|
+
static getInstance() {
|
|
15942
|
+
if (!LocalStorageService.instance) {
|
|
15943
|
+
LocalStorageService.instance = new LocalStorageService();
|
|
15283
15944
|
}
|
|
15284
|
-
|
|
15285
|
-
|
|
15286
|
-
|
|
15287
|
-
|
|
15288
|
-
|
|
15289
|
-
|
|
15290
|
-
|
|
15945
|
+
return LocalStorageService.instance;
|
|
15946
|
+
}
|
|
15947
|
+
syncLocalStorage() {
|
|
15948
|
+
const localStorageData = window.localStorage.getItem(LocalStorageService.localStorageKey);
|
|
15949
|
+
if (localStorageData) {
|
|
15950
|
+
try {
|
|
15951
|
+
const decryptedData = this.decryptData(localStorageData);
|
|
15952
|
+
const parsedData = JSON.parse(decryptedData);
|
|
15953
|
+
if (parsedData && typeof parsedData === 'object') {
|
|
15954
|
+
const data = {};
|
|
15955
|
+
for (const [key, value] of Object.entries(parsedData)) {
|
|
15956
|
+
data[key] = this.arrayToObject(value);
|
|
15957
|
+
}
|
|
15958
|
+
this.spots = this.objectToMap(data);
|
|
15959
|
+
}
|
|
15960
|
+
else {
|
|
15961
|
+
this.clearLocalStorage();
|
|
15962
|
+
}
|
|
15291
15963
|
}
|
|
15292
|
-
|
|
15293
|
-
|
|
15964
|
+
catch (_a) {
|
|
15965
|
+
// If there is an error parsing the data, clear the local storage to prevent any issues
|
|
15966
|
+
this.clearLocalStorage();
|
|
15294
15967
|
}
|
|
15295
15968
|
}
|
|
15296
|
-
|
|
15297
|
-
|
|
15298
|
-
|
|
15299
|
-
|
|
15300
|
-
|
|
15301
|
-
|
|
15302
|
-
|
|
15303
|
-
|
|
15304
|
-
|
|
15305
|
-
|
|
15306
|
-
|
|
15307
|
-
|
|
15308
|
-
|
|
15309
|
-
|
|
15310
|
-
|
|
15311
|
-
|
|
15312
|
-
|
|
15313
|
-
|
|
15314
|
-
|
|
15315
|
-
|
|
15316
|
-
}
|
|
15317
|
-
|
|
15318
|
-
|
|
15319
|
-
|
|
15320
|
-
.
|
|
15321
|
-
|
|
15322
|
-
|
|
15323
|
-
|
|
15324
|
-
|
|
15969
|
+
}
|
|
15970
|
+
setSpot(spotId, data) {
|
|
15971
|
+
var _a;
|
|
15972
|
+
data.createdAt = Date.now();
|
|
15973
|
+
(_a = this.spots) === null || _a === void 0 ? void 0 : _a.set(spotId, data);
|
|
15974
|
+
this.updateLocalStorage();
|
|
15975
|
+
}
|
|
15976
|
+
removeSpot(spotId) {
|
|
15977
|
+
var _a;
|
|
15978
|
+
(_a = this.spots) === null || _a === void 0 ? void 0 : _a.delete(spotId);
|
|
15979
|
+
this.updateLocalStorage();
|
|
15980
|
+
}
|
|
15981
|
+
getSpot(spotId) {
|
|
15982
|
+
var _a;
|
|
15983
|
+
return (_a = this.spots) === null || _a === void 0 ? void 0 : _a.get(spotId);
|
|
15984
|
+
}
|
|
15985
|
+
getSpots() {
|
|
15986
|
+
if (!this.spots)
|
|
15987
|
+
return undefined;
|
|
15988
|
+
return this.mapToObject(this.spots);
|
|
15989
|
+
}
|
|
15990
|
+
updateLocalStorage() {
|
|
15991
|
+
if (!this.spots)
|
|
15992
|
+
return undefined;
|
|
15993
|
+
const data = this.mapToObject(this.spots);
|
|
15994
|
+
const dataArray = {};
|
|
15995
|
+
for (const [key, value] of Object.entries(data)) {
|
|
15996
|
+
dataArray[key] = this.objectToArray(value);
|
|
15997
|
+
}
|
|
15998
|
+
try {
|
|
15999
|
+
const encryptedData = this.encryptData(JSON.stringify(dataArray));
|
|
16000
|
+
window.localStorage.setItem(LocalStorageService.localStorageKey, encryptedData);
|
|
16001
|
+
}
|
|
16002
|
+
catch (_a) {
|
|
16003
|
+
// If there is an error parsing the data, clear the local storage to prevent any issues
|
|
16004
|
+
this.clearLocalStorage();
|
|
16005
|
+
}
|
|
16006
|
+
}
|
|
16007
|
+
clearLocalStorage() {
|
|
16008
|
+
window.localStorage.removeItem(LocalStorageService.localStorageKey);
|
|
16009
|
+
}
|
|
16010
|
+
removeExpiredSpots() {
|
|
16011
|
+
var _a;
|
|
16012
|
+
const currentTime = Date.now();
|
|
16013
|
+
(_a = this.spots) === null || _a === void 0 ? void 0 : _a.forEach((spot, spotId) => {
|
|
16014
|
+
var _a, _b;
|
|
16015
|
+
if (currentTime - ((_a = spot.createdAt) !== null && _a !== void 0 ? _a : 0) > LocalStorageService.spotExpirationTime) {
|
|
16016
|
+
(_b = this.spots) === null || _b === void 0 ? void 0 : _b.delete(spotId);
|
|
16017
|
+
}
|
|
16018
|
+
});
|
|
16019
|
+
this.updateLocalStorage();
|
|
16020
|
+
}
|
|
16021
|
+
mapToObject(map) {
|
|
16022
|
+
return Object.fromEntries(map);
|
|
16023
|
+
}
|
|
16024
|
+
objectToMap(obj) {
|
|
16025
|
+
return new Map(Object.entries(obj));
|
|
16026
|
+
}
|
|
16027
|
+
objectToArray(obj) {
|
|
16028
|
+
return [obj.placementId, obj.spotId, obj.spotType, obj.events, obj.productIds, obj.createdAt];
|
|
16029
|
+
}
|
|
16030
|
+
arrayToObject(arr) {
|
|
16031
|
+
return {
|
|
16032
|
+
placementId: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.PLACEMENT_ID],
|
|
16033
|
+
spotId: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.SPOT_ID],
|
|
16034
|
+
spotType: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.SPOT_TYPE],
|
|
16035
|
+
events: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.EVENTS],
|
|
16036
|
+
productIds: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.PRODUCT_IDS],
|
|
16037
|
+
createdAt: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.CREATED_AT],
|
|
16038
|
+
};
|
|
16039
|
+
}
|
|
16040
|
+
encryptData(data) {
|
|
16041
|
+
if (!LocalStorageService.encryptData)
|
|
16042
|
+
return data;
|
|
16043
|
+
// For now, we are using base64 encoding to encrypt the data
|
|
16044
|
+
// Later we will use Jose encryption
|
|
16045
|
+
const encryptedData = btoa(data);
|
|
16046
|
+
return encryptedData;
|
|
16047
|
+
}
|
|
16048
|
+
decryptData(data) {
|
|
16049
|
+
if (!LocalStorageService.encryptData)
|
|
16050
|
+
return data;
|
|
16051
|
+
// For now, we are using base64 encoding to encrypt
|
|
16052
|
+
// Later we will use Jose encryption
|
|
16053
|
+
const decryptedData = atob(data);
|
|
16054
|
+
return decryptedData;
|
|
16055
|
+
}
|
|
16056
|
+
}
|
|
16057
|
+
LocalStorageService.localStorageKey = 'lc_rmn';
|
|
16058
|
+
LocalStorageService.spotExpirationTime = 1000 * 60 * 60 * 24 * 7; // 7 days
|
|
16059
|
+
LocalStorageService.encryptData = true;
|
|
16060
|
+
|
|
16061
|
+
/**
|
|
16062
|
+
* PubsubService class
|
|
16063
|
+
* Manages event subscriptions and publications
|
|
16064
|
+
* @template IRmnEventMap A record type defining the structure of events and their data
|
|
16065
|
+
*/
|
|
16066
|
+
class PubsubService {
|
|
16067
|
+
constructor() {
|
|
16068
|
+
/**
|
|
16069
|
+
* Object to store subscribers for each event type
|
|
16070
|
+
*/
|
|
16071
|
+
this.subscribers = {};
|
|
16072
|
+
}
|
|
16073
|
+
static getInstance() {
|
|
16074
|
+
if (!PubsubService.instance) {
|
|
16075
|
+
PubsubService.instance = new PubsubService();
|
|
16076
|
+
}
|
|
16077
|
+
return PubsubService.instance;
|
|
16078
|
+
}
|
|
16079
|
+
/**
|
|
16080
|
+
* Subscribe to an event
|
|
16081
|
+
* @param eventType - The type of event to subscribe to
|
|
16082
|
+
* @param callback - The function to be called when the event is published
|
|
16083
|
+
* @returns A function to unsubscribe from the event
|
|
16084
|
+
*
|
|
16085
|
+
* @Example:
|
|
16086
|
+
* const unsubscribe = pubSub.subscribe('userLogin', (data) => {
|
|
16087
|
+
* console.log(`User ${data.username} logged in`);
|
|
16088
|
+
* });
|
|
16089
|
+
*/
|
|
16090
|
+
subscribe(eventType, callback) {
|
|
16091
|
+
if (!this.subscribers[eventType]) {
|
|
16092
|
+
this.subscribers[eventType] = [];
|
|
16093
|
+
}
|
|
16094
|
+
this.subscribers[eventType].push(callback);
|
|
16095
|
+
// Return an unsubscribe function
|
|
16096
|
+
return () => {
|
|
16097
|
+
this.subscribers[eventType] = this.subscribers[eventType].filter((cb) => cb !== callback);
|
|
16098
|
+
};
|
|
16099
|
+
}
|
|
16100
|
+
/**
|
|
16101
|
+
* Publish an event
|
|
16102
|
+
* @param eventType - The type of event to publish
|
|
16103
|
+
* @param data - The data to be passed to the event subscribers
|
|
16104
|
+
*
|
|
16105
|
+
* @Example:
|
|
16106
|
+
* pubSub.publish('userLogin', { username: 'john_doe', timestamp: Date.now() });
|
|
16107
|
+
*/
|
|
16108
|
+
publish(eventType, data) {
|
|
16109
|
+
if (!this.subscribers[eventType]) {
|
|
16110
|
+
return;
|
|
16111
|
+
}
|
|
16112
|
+
this.subscribers[eventType].forEach((callback) => callback(data));
|
|
16113
|
+
}
|
|
16114
|
+
}
|
|
16115
|
+
/**
|
|
16116
|
+
* Usage Example:
|
|
16117
|
+
*
|
|
16118
|
+
* interface IRmnEventMap {
|
|
16119
|
+
* userLogin: { username: string; timestamp: number };
|
|
16120
|
+
* pageView: { url: string; timestamp: number };
|
|
16121
|
+
* }
|
|
16122
|
+
*
|
|
16123
|
+
* const pubSub = new PubsubService<IRmnEventMap>();
|
|
16124
|
+
*
|
|
16125
|
+
* // Subscribe to events
|
|
16126
|
+
* const unsubscribeLogin = pubSub.subscribe('userLogin', (data) => {
|
|
16127
|
+
* console.log(`User ${data.username} logged in at ${new Date(data.timestamp)}`);
|
|
16128
|
+
* });
|
|
16129
|
+
*
|
|
16130
|
+
* pubSub.subscribe('pageView', (data) => {
|
|
16131
|
+
* console.log(`Page ${data.url} viewed at ${new Date(data.timestamp)}`);
|
|
16132
|
+
* });
|
|
16133
|
+
*
|
|
16134
|
+
* // Publish events
|
|
16135
|
+
* pubSub.publish('userLogin', { username: 'john_doe', timestamp: Date.now() });
|
|
16136
|
+
* pubSub.publish('pageView', { url: '/home', timestamp: Date.now() });
|
|
16137
|
+
*
|
|
16138
|
+
* // Unsubscribe from an event
|
|
16139
|
+
* unsubscribeLogin();
|
|
16140
|
+
*/
|
|
16141
|
+
|
|
16142
|
+
class ResizeObserverService {
|
|
16143
|
+
constructor({ element, maxSize, minScale }) {
|
|
16144
|
+
this.element = element;
|
|
16145
|
+
if (!element.parentElement) {
|
|
16146
|
+
throw new Error('RmnSdk: Spot element must have a parent container.');
|
|
16147
|
+
}
|
|
16148
|
+
this.container = element.parentElement;
|
|
16149
|
+
this.setDimensions(maxSize, minScale);
|
|
16150
|
+
this.resizeObserver = new ResizeObserver(() => this.updateElementSize());
|
|
16151
|
+
this.resizeObserver.observe(this.container);
|
|
16152
|
+
// Initial size update
|
|
16153
|
+
this.updateElementSize();
|
|
16154
|
+
}
|
|
16155
|
+
setDimensions(maxSize, minScale) {
|
|
16156
|
+
if (minScale <= 0 || minScale > 1) {
|
|
16157
|
+
throw new Error('RmnSdk: Invalid minScale value');
|
|
16158
|
+
}
|
|
16159
|
+
const minSize = {
|
|
16160
|
+
width: maxSize.width * minScale,
|
|
16161
|
+
height: maxSize.height * minScale,
|
|
16162
|
+
};
|
|
16163
|
+
if (maxSize.width <= 0 || maxSize.height <= 0 || minSize.width <= 0 || minSize.height <= 0) {
|
|
16164
|
+
throw new Error('RmnSdk: Invalid dimensions');
|
|
16165
|
+
}
|
|
16166
|
+
if (minSize.width > maxSize.width || minSize.height > maxSize.height) {
|
|
16167
|
+
throw new Error('RmnSdk: Minimum size cannot be greater than maximum size');
|
|
16168
|
+
}
|
|
16169
|
+
this.maxSize = maxSize;
|
|
16170
|
+
this.minSize = minSize;
|
|
16171
|
+
this.aspectRatio = this.maxSize.width / this.maxSize.height;
|
|
16172
|
+
}
|
|
16173
|
+
updateElementSize() {
|
|
16174
|
+
const { clientWidth: containerWidth, clientHeight: containerHeight } = this.container;
|
|
16175
|
+
let newWidth;
|
|
16176
|
+
let newHeight;
|
|
16177
|
+
// First, try to fit the maximum width
|
|
16178
|
+
newWidth = Math.min(containerWidth, this.maxSize.width);
|
|
16179
|
+
newHeight = newWidth / this.aspectRatio;
|
|
16180
|
+
// If the height exceeds the container, adjust based on height
|
|
16181
|
+
if (newWidth > containerWidth) {
|
|
16182
|
+
newWidth = containerWidth;
|
|
16183
|
+
newHeight = containerHeight * this.aspectRatio;
|
|
16184
|
+
}
|
|
16185
|
+
// Ensure we're not going below minimum dimensions
|
|
16186
|
+
newWidth = Math.max(newWidth, this.minSize.width);
|
|
16187
|
+
newHeight = Math.max(newHeight, this.minSize.height);
|
|
16188
|
+
this.element.style.width = `${newWidth}px`;
|
|
16189
|
+
this.element.style.height = `${newHeight}px`;
|
|
16190
|
+
// Calculate the scale percentage
|
|
16191
|
+
const scaleWidth = newWidth / this.maxSize.width;
|
|
16192
|
+
const scaleHeight = newHeight / this.maxSize.height;
|
|
16193
|
+
const scale = Math.min(scaleWidth, scaleHeight);
|
|
16194
|
+
// Dispatch a custom event
|
|
16195
|
+
this.element.dispatchEvent(new CustomEvent('spotSizeChanged', {
|
|
16196
|
+
detail: {
|
|
16197
|
+
width: this.maxSize.width,
|
|
16198
|
+
height: this.maxSize.height,
|
|
16199
|
+
newWidth,
|
|
16200
|
+
newHeight,
|
|
16201
|
+
scale,
|
|
16202
|
+
},
|
|
16203
|
+
}));
|
|
16204
|
+
}
|
|
16205
|
+
disconnect() {
|
|
16206
|
+
this.resizeObserver.disconnect();
|
|
16207
|
+
}
|
|
16208
|
+
}
|
|
16209
|
+
|
|
16210
|
+
const CAROUSEL_COMPONENT_STYLE = ({ width, height, fluid }) => `
|
|
16211
|
+
:host {
|
|
16212
|
+
position: relative;
|
|
16213
|
+
display: inline-block;
|
|
16214
|
+
margin: 0;
|
|
16215
|
+
overflow: hidden;
|
|
16216
|
+
width: ${fluid ? '100%' : `${width}px`};
|
|
16217
|
+
height: ${fluid ? '100%' : `${height}px`};
|
|
16218
|
+
}
|
|
16219
|
+
|
|
16220
|
+
.slides {
|
|
16221
|
+
position: relative;
|
|
16222
|
+
height: 100%;
|
|
16223
|
+
width: 100%;
|
|
16224
|
+
display: flex;
|
|
16225
|
+
transition: transform 0.5s ease-in-out;
|
|
16226
|
+
}
|
|
16227
|
+
|
|
16228
|
+
.slide {
|
|
16229
|
+
flex: 0 0 100%;
|
|
16230
|
+
display: flex;
|
|
16231
|
+
justify-content: center;
|
|
16232
|
+
align-items: center;
|
|
16233
|
+
height: 100%;
|
|
16234
|
+
width: 100%;
|
|
16235
|
+
}
|
|
16236
|
+
|
|
16237
|
+
.slide.active {
|
|
16238
|
+
display: flex;
|
|
16239
|
+
}
|
|
16240
|
+
|
|
16241
|
+
.dots {
|
|
16242
|
+
position: absolute;
|
|
16243
|
+
display: flex;
|
|
16244
|
+
align-items: center;
|
|
16245
|
+
gap: 8px;
|
|
16246
|
+
opacity: var(--opacity, 1);
|
|
16247
|
+
}
|
|
16248
|
+
|
|
16249
|
+
.dots.small .dot {
|
|
16250
|
+
width: 8px;
|
|
16251
|
+
height: 8px;
|
|
16252
|
+
}
|
|
16253
|
+
|
|
16254
|
+
.dots.base .dot {
|
|
16255
|
+
width: 12px;
|
|
16256
|
+
height: 12px;
|
|
16257
|
+
}
|
|
16258
|
+
|
|
16259
|
+
.dots.large .dot {
|
|
16260
|
+
width: 16px;
|
|
16261
|
+
height: 16px;
|
|
16262
|
+
}
|
|
16263
|
+
|
|
16264
|
+
.dots .dot {
|
|
16265
|
+
border-radius: 50%;
|
|
16266
|
+
cursor: pointer;
|
|
16267
|
+
transition: all 0.3s ease;
|
|
16268
|
+
}
|
|
16269
|
+
|
|
16270
|
+
.dots.top-left,
|
|
16271
|
+
.dots.bottom-left {
|
|
16272
|
+
left: 10px;
|
|
16273
|
+
}
|
|
16274
|
+
|
|
16275
|
+
.dots.top-center,
|
|
16276
|
+
.dots.bottom-center {
|
|
16277
|
+
left: 50%;
|
|
16278
|
+
transform: translateX(-50%);
|
|
16279
|
+
}
|
|
16280
|
+
|
|
16281
|
+
.dots.top-right,
|
|
16282
|
+
.dots.bottom-right {
|
|
16283
|
+
right: 10px;
|
|
16284
|
+
}
|
|
16285
|
+
|
|
16286
|
+
.dots.top-left,
|
|
16287
|
+
.dots.top-center,
|
|
16288
|
+
.dots.top-right {
|
|
16289
|
+
top: 10px;
|
|
16290
|
+
}
|
|
16291
|
+
|
|
16292
|
+
.dots.bottom-left,
|
|
16293
|
+
.dots.bottom-center,
|
|
16294
|
+
.dots.bottom-right {
|
|
16295
|
+
bottom: 10px;
|
|
16296
|
+
}
|
|
16297
|
+
|
|
16298
|
+
.dots.middle-left {
|
|
16299
|
+
left: 10px;
|
|
16300
|
+
top: 50%;
|
|
16301
|
+
transform: translateY(-50%);
|
|
16302
|
+
flex-direction: column;
|
|
16303
|
+
}
|
|
16304
|
+
|
|
16305
|
+
.dots.middle-right {
|
|
16306
|
+
right: 10px;
|
|
16307
|
+
top: 50%;
|
|
16308
|
+
transform: translateY(-50%);
|
|
16309
|
+
flex-direction: column;
|
|
16310
|
+
}
|
|
16311
|
+
|
|
16312
|
+
.buttons {
|
|
16313
|
+
opacity: var(--opacity, 1);
|
|
16314
|
+
}
|
|
16315
|
+
|
|
16316
|
+
.buttons button {
|
|
16317
|
+
background-color: #00000080;
|
|
16318
|
+
color: #fff;
|
|
16319
|
+
border: none;
|
|
16320
|
+
padding: 10px;
|
|
16321
|
+
cursor: pointer;
|
|
16322
|
+
transition: background-color 0.3s ease;
|
|
16323
|
+
}
|
|
16324
|
+
|
|
16325
|
+
.buttons.small button {
|
|
16326
|
+
padding: 6px;
|
|
16327
|
+
}
|
|
16328
|
+
|
|
16329
|
+
.buttons.base button {
|
|
16330
|
+
padding: 10px;
|
|
16331
|
+
}
|
|
16332
|
+
|
|
16333
|
+
.buttons.large button {
|
|
16334
|
+
padding: 14px;
|
|
16335
|
+
}
|
|
16336
|
+
|
|
16337
|
+
.buttons button:hover {
|
|
16338
|
+
background-color: #000000b3;
|
|
16339
|
+
}
|
|
16340
|
+
|
|
16341
|
+
.buttons.buttons-separate button {
|
|
16342
|
+
position: absolute;
|
|
16343
|
+
top: 50%;
|
|
16344
|
+
transform: translateY(-50%);
|
|
16345
|
+
}
|
|
16346
|
+
|
|
16347
|
+
.buttons.buttons-separate .prev-button {
|
|
16348
|
+
left: 10px;
|
|
16349
|
+
}
|
|
16350
|
+
|
|
16351
|
+
.buttons.buttons-separate .next-button {
|
|
16352
|
+
right: 10px;
|
|
16353
|
+
}
|
|
16354
|
+
|
|
16355
|
+
.buttons.buttons-together {
|
|
16356
|
+
position: absolute;
|
|
16357
|
+
display: flex;
|
|
16358
|
+
gap: 10px;
|
|
16359
|
+
}
|
|
16360
|
+
|
|
16361
|
+
.buttons.buttons-together.top-left,
|
|
16362
|
+
.buttons.buttons-together.bottom-left {
|
|
16363
|
+
left: 10px;
|
|
16364
|
+
}
|
|
16365
|
+
|
|
16366
|
+
.buttons.buttons-together.top-center,
|
|
16367
|
+
.buttons.buttons-together.bottom-center {
|
|
16368
|
+
left: 50%;
|
|
16369
|
+
transform: translateX(-50%);
|
|
16370
|
+
}
|
|
16371
|
+
|
|
16372
|
+
.buttons.buttons-together.top-right,
|
|
16373
|
+
.buttons.buttons-together.bottom-right {
|
|
16374
|
+
right: 10px;
|
|
16375
|
+
}
|
|
16376
|
+
|
|
16377
|
+
.buttons.buttons-together.top-left,
|
|
16378
|
+
.buttons.buttons-together.top-center,
|
|
16379
|
+
.buttons.buttons-together.top-right {
|
|
16380
|
+
top: 10px;
|
|
16381
|
+
}
|
|
16382
|
+
|
|
16383
|
+
.buttons.buttons-together.bottom-left,
|
|
16384
|
+
.buttons.buttons-together.bottom-center,
|
|
16385
|
+
.buttons.buttons-together.bottom-right {
|
|
16386
|
+
bottom: 10px;
|
|
16387
|
+
}
|
|
16388
|
+
|
|
16389
|
+
.buttons.buttons-together.middle-left,
|
|
16390
|
+
.buttons.buttons-together.middle-right {
|
|
16391
|
+
top: 50%;
|
|
16392
|
+
transform: translateY(-50%);
|
|
16393
|
+
flex-direction: column;
|
|
16394
|
+
}
|
|
16395
|
+
|
|
16396
|
+
.buttons.buttons-together.middle-left {
|
|
16397
|
+
left: 10px;
|
|
16398
|
+
}
|
|
16399
|
+
|
|
16400
|
+
.buttons.buttons-together.middle-right {
|
|
16401
|
+
right: 10px;
|
|
16402
|
+
}
|
|
16403
|
+
|
|
16404
|
+
@media (max-width: 768px) {
|
|
16405
|
+
.buttons button {
|
|
16406
|
+
padding: 8px 12px;
|
|
16407
|
+
font-size: 14px;
|
|
16408
|
+
}
|
|
16409
|
+
}
|
|
16410
|
+
`;
|
|
16411
|
+
|
|
16412
|
+
let CarouselElement;
|
|
16413
|
+
if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined') {
|
|
16414
|
+
class CustomCarouselElement extends HTMLElement {
|
|
16415
|
+
constructor() {
|
|
16416
|
+
super();
|
|
16417
|
+
this.currentSlide = 0;
|
|
16418
|
+
this.dotElements = [];
|
|
16419
|
+
this.prevButton = null;
|
|
16420
|
+
this.nextButton = null;
|
|
16421
|
+
this.autoplayInterval = null;
|
|
16422
|
+
this.useDots = false;
|
|
16423
|
+
this.useButtons = false;
|
|
16424
|
+
this.originalFontSizes = new Map();
|
|
16425
|
+
this.attachShadow({ mode: 'open' });
|
|
16426
|
+
}
|
|
16427
|
+
connectedCallback() {
|
|
16428
|
+
this.initializeOptions();
|
|
16429
|
+
this.setupResizeObserver();
|
|
16430
|
+
this.render();
|
|
16431
|
+
this.setupCarousel();
|
|
16432
|
+
}
|
|
16433
|
+
disconnectedCallback() {
|
|
16434
|
+
var _a;
|
|
16435
|
+
this.stopAutoplay();
|
|
16436
|
+
(_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
16437
|
+
}
|
|
16438
|
+
initializeOptions() {
|
|
16439
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
16440
|
+
this.useDots = ((_a = this.data) === null || _a === void 0 ? void 0 : _a.useDots) === true || typeof ((_b = this.data) === null || _b === void 0 ? void 0 : _b.useDots) === 'object';
|
|
16441
|
+
this.useButtons = ((_c = this.data) === null || _c === void 0 ? void 0 : _c.useButtons) === true || typeof ((_d = this.data) === null || _d === void 0 ? void 0 : _d.useButtons) === 'object';
|
|
16442
|
+
this.autoplay = (_f = (_e = this.data) === null || _e === void 0 ? void 0 : _e.autoplay) !== null && _f !== void 0 ? _f : true;
|
|
16443
|
+
this.interval = (_h = (_g = this.data) === null || _g === void 0 ? void 0 : _g.interval) !== null && _h !== void 0 ? _h : CustomCarouselElement.defaultInterval;
|
|
16444
|
+
this.dotsOptions = {
|
|
16445
|
+
position: 'bottom-center',
|
|
16446
|
+
color: '#d9d9d9',
|
|
16447
|
+
activeColor: '#b5914a',
|
|
16448
|
+
size: 'base',
|
|
16449
|
+
opacity: 1,
|
|
16450
|
+
...(typeof ((_j = this.data) === null || _j === void 0 ? void 0 : _j.useDots) === 'object' ? this.data.useDots : {}),
|
|
16451
|
+
};
|
|
16452
|
+
this.buttonsOptions = {
|
|
16453
|
+
together: false,
|
|
16454
|
+
position: 'middle-sides',
|
|
16455
|
+
textColor: '#000000',
|
|
16456
|
+
backgroundColor: '#ffffff',
|
|
16457
|
+
borderRadius: '50%',
|
|
16458
|
+
prev: 'Prev',
|
|
16459
|
+
next: 'Next',
|
|
16460
|
+
size: 'base',
|
|
16461
|
+
opacity: 1,
|
|
16462
|
+
...(typeof ((_k = this.data) === null || _k === void 0 ? void 0 : _k.useButtons) === 'object' ? this.data.useButtons : {}),
|
|
16463
|
+
};
|
|
16464
|
+
this.validateOptions();
|
|
16465
|
+
}
|
|
16466
|
+
setupResizeObserver() {
|
|
16467
|
+
if (this.data && !this.data.fluid) {
|
|
16468
|
+
this.resizeObserver = new ResizeObserverService({
|
|
16469
|
+
element: this,
|
|
16470
|
+
maxSize: {
|
|
16471
|
+
width: this.data.width,
|
|
16472
|
+
height: this.data.height,
|
|
16473
|
+
},
|
|
16474
|
+
minScale: this.data.minScale,
|
|
16475
|
+
});
|
|
16476
|
+
this.addEventListener('spotSizeChanged', this.handleCarouselSizeChanged.bind(this));
|
|
16477
|
+
}
|
|
16478
|
+
}
|
|
16479
|
+
handleCarouselSizeChanged(event) {
|
|
16480
|
+
const isRBSpot = 'rbHeroadaksda'.startsWith('rb');
|
|
16481
|
+
if (!isRBSpot) {
|
|
16482
|
+
// Adjust text elements font size based on the scale factor
|
|
16483
|
+
this.adjustFontSize(event.detail.scale);
|
|
16484
|
+
}
|
|
16485
|
+
}
|
|
16486
|
+
adjustFontSize(elementScale) {
|
|
16487
|
+
var _a;
|
|
16488
|
+
const scaleFactor = calculateScaleFactor(elementScale);
|
|
16489
|
+
// Find all text elements within the shadow root
|
|
16490
|
+
const elements = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('h1, h2, h3, h4, p, span');
|
|
16491
|
+
elements === null || elements === void 0 ? void 0 : elements.forEach((element) => {
|
|
16492
|
+
if (element instanceof HTMLElement) {
|
|
16493
|
+
if (!this.originalFontSizes.has(element)) {
|
|
16494
|
+
const originalSize = parseFloat(window.getComputedStyle(element).fontSize);
|
|
16495
|
+
this.originalFontSizes.set(element, originalSize);
|
|
16496
|
+
}
|
|
16497
|
+
const originalSize = this.originalFontSizes.get(element);
|
|
16498
|
+
const newFontSize = originalSize * scaleFactor;
|
|
16499
|
+
element.style.fontSize = `${newFontSize}px`;
|
|
16500
|
+
}
|
|
16501
|
+
});
|
|
16502
|
+
}
|
|
16503
|
+
render() {
|
|
16504
|
+
var _a;
|
|
16505
|
+
if (!this.shadowRoot)
|
|
16506
|
+
return;
|
|
16507
|
+
const style = document.createElement('style');
|
|
16508
|
+
style.textContent = CAROUSEL_COMPONENT_STYLE(this.data);
|
|
16509
|
+
this.shadowRoot.appendChild(style);
|
|
16510
|
+
const slides = this.renderSlides();
|
|
16511
|
+
this.shadowRoot.appendChild(slides);
|
|
16512
|
+
this.slidesContainer = (_a = this.shadowRoot.querySelector('.slides')) !== null && _a !== void 0 ? _a : undefined;
|
|
16513
|
+
if (this.useDots) {
|
|
16514
|
+
const dots = this.renderDots();
|
|
16515
|
+
if (dots)
|
|
16516
|
+
this.shadowRoot.appendChild(dots);
|
|
16517
|
+
}
|
|
16518
|
+
if (this.useButtons) {
|
|
16519
|
+
const buttons = this.renderButtons();
|
|
16520
|
+
if (buttons)
|
|
16521
|
+
this.shadowRoot.appendChild(buttons);
|
|
16522
|
+
}
|
|
16523
|
+
}
|
|
16524
|
+
setupCarousel() {
|
|
16525
|
+
this.setupDots();
|
|
16526
|
+
this.setupButtons();
|
|
16527
|
+
if (this.autoplay) {
|
|
16528
|
+
this.startAutoplay();
|
|
16529
|
+
}
|
|
16530
|
+
this.updateCarousel();
|
|
16531
|
+
}
|
|
16532
|
+
renderSlides() {
|
|
16533
|
+
const slidesContainer = document.createElement('div');
|
|
16534
|
+
slidesContainer.className = 'slides';
|
|
16535
|
+
this.slides.forEach((slide) => {
|
|
16536
|
+
const slideElement = document.createElement('div');
|
|
16537
|
+
slideElement.className = 'slide';
|
|
16538
|
+
if (slide instanceof HTMLElement) {
|
|
16539
|
+
slideElement.appendChild(slide);
|
|
16540
|
+
}
|
|
16541
|
+
slidesContainer.appendChild(slideElement);
|
|
16542
|
+
});
|
|
16543
|
+
return slidesContainer;
|
|
16544
|
+
}
|
|
16545
|
+
renderDots() {
|
|
16546
|
+
const dotsContainer = document.createElement('div');
|
|
16547
|
+
dotsContainer.className = `dots ${this.dotsOptions.position} ${this.dotsOptions.size}`;
|
|
16548
|
+
dotsContainer.style.cssText = `--opacity: ${this.dotsOptions.opacity}`;
|
|
16549
|
+
this.slides.forEach((_, index) => {
|
|
16550
|
+
const dot = document.createElement('span');
|
|
16551
|
+
dot.className = `dot ${index === this.currentSlide ? 'active' : ''}`;
|
|
16552
|
+
dot.style.backgroundColor = this.dotsOptions.color;
|
|
16553
|
+
dotsContainer.appendChild(dot);
|
|
16554
|
+
});
|
|
16555
|
+
return dotsContainer;
|
|
16556
|
+
}
|
|
16557
|
+
renderButtons() {
|
|
16558
|
+
const buttonsContainer = document.createElement('div');
|
|
16559
|
+
const buttonsClass = this.buttonsOptions.together
|
|
16560
|
+
? `buttons-together ${this.buttonsOptions.position}`
|
|
16561
|
+
: 'buttons-separate';
|
|
16562
|
+
buttonsContainer.className = `buttons ${buttonsClass} ${this.buttonsOptions.size}`;
|
|
16563
|
+
buttonsContainer.style.cssText = `--opacity: ${this.buttonsOptions.opacity}`;
|
|
16564
|
+
this.prevButton = this.createButton('prev-button', this.buttonsOptions.prev);
|
|
16565
|
+
this.nextButton = this.createButton('next-button', this.buttonsOptions.next);
|
|
16566
|
+
buttonsContainer.appendChild(this.prevButton);
|
|
16567
|
+
buttonsContainer.appendChild(this.nextButton);
|
|
16568
|
+
return buttonsContainer;
|
|
16569
|
+
}
|
|
16570
|
+
createButton(className, text) {
|
|
16571
|
+
const button = document.createElement('button');
|
|
16572
|
+
button.className = className;
|
|
16573
|
+
button.textContent = text;
|
|
16574
|
+
button.style.color = this.buttonsOptions.textColor;
|
|
16575
|
+
button.style.backgroundColor = this.buttonsOptions.backgroundColor;
|
|
16576
|
+
button.style.borderRadius = this.buttonsOptions.borderRadius;
|
|
16577
|
+
return button;
|
|
16578
|
+
}
|
|
16579
|
+
setupDots() {
|
|
16580
|
+
if (!this.shadowRoot || !this.useDots)
|
|
16581
|
+
return;
|
|
16582
|
+
this.dotElements = Array.from(this.shadowRoot.querySelectorAll('.dot'));
|
|
16583
|
+
this.dotElements.forEach((dot, index) => {
|
|
16584
|
+
dot.addEventListener('click', () => {
|
|
16585
|
+
this.goToSlide(index);
|
|
16586
|
+
this.resetAutoplay();
|
|
16587
|
+
});
|
|
16588
|
+
});
|
|
16589
|
+
}
|
|
16590
|
+
setupButtons() {
|
|
16591
|
+
var _a, _b;
|
|
16592
|
+
if (!this.useButtons)
|
|
16593
|
+
return;
|
|
16594
|
+
(_a = this.prevButton) === null || _a === void 0 ? void 0 : _a.addEventListener('click', () => {
|
|
16595
|
+
this.prevSlide();
|
|
16596
|
+
this.resetAutoplay();
|
|
16597
|
+
});
|
|
16598
|
+
(_b = this.nextButton) === null || _b === void 0 ? void 0 : _b.addEventListener('click', () => {
|
|
16599
|
+
this.nextSlide();
|
|
16600
|
+
this.resetAutoplay();
|
|
16601
|
+
});
|
|
16602
|
+
}
|
|
16603
|
+
nextSlide() {
|
|
16604
|
+
this.goToSlide((this.currentSlide + 1) % this.slides.length);
|
|
16605
|
+
}
|
|
16606
|
+
prevSlide() {
|
|
16607
|
+
this.goToSlide((this.currentSlide - 1 + this.slides.length) % this.slides.length);
|
|
16608
|
+
}
|
|
16609
|
+
goToSlide(index) {
|
|
16610
|
+
this.currentSlide = index;
|
|
16611
|
+
this.updateCarousel();
|
|
16612
|
+
}
|
|
16613
|
+
updateCarousel() {
|
|
16614
|
+
if (!this.slidesContainer)
|
|
16615
|
+
return;
|
|
16616
|
+
// Calculate the translation distance based on current slide
|
|
16617
|
+
const translateX = -this.currentSlide * 100;
|
|
16618
|
+
this.slidesContainer.style.transform = `translateX(${translateX}%)`;
|
|
16619
|
+
this.updateDots();
|
|
16620
|
+
}
|
|
16621
|
+
updateDots() {
|
|
16622
|
+
if (!this.useDots)
|
|
16623
|
+
return;
|
|
16624
|
+
this.dotElements.forEach((dot, index) => {
|
|
16625
|
+
const isActive = index === this.currentSlide;
|
|
16626
|
+
dot.classList.toggle('active', isActive);
|
|
16627
|
+
dot.style.backgroundColor = isActive
|
|
16628
|
+
? this.dotsOptions.activeColor
|
|
16629
|
+
: this.dotsOptions.color;
|
|
16630
|
+
});
|
|
16631
|
+
}
|
|
16632
|
+
startAutoplay() {
|
|
16633
|
+
this.autoplayInterval = window.setInterval(() => this.nextSlide(), this.interval);
|
|
16634
|
+
}
|
|
16635
|
+
stopAutoplay() {
|
|
16636
|
+
if (this.autoplayInterval !== null) {
|
|
16637
|
+
window.clearInterval(this.autoplayInterval);
|
|
16638
|
+
this.autoplayInterval = null;
|
|
16639
|
+
}
|
|
16640
|
+
}
|
|
16641
|
+
resetAutoplay() {
|
|
16642
|
+
if (this.autoplay) {
|
|
16643
|
+
this.stopAutoplay();
|
|
16644
|
+
this.startAutoplay();
|
|
16645
|
+
}
|
|
16646
|
+
}
|
|
16647
|
+
validateOptions() {
|
|
16648
|
+
this.validatePosition(this.dotsOptions.position, 'dotsPosition', 'bottom-center');
|
|
16649
|
+
this.validateButtonsPosition();
|
|
16650
|
+
}
|
|
16651
|
+
validatePosition(position, optionName, defaultValue) {
|
|
16652
|
+
if (!CustomCarouselElement.validPositions.includes(position)) {
|
|
16653
|
+
console.warn(`Invalid ${optionName}: ${position}. Defaulting to '${defaultValue}'.`);
|
|
16654
|
+
if (optionName === 'dotsPosition') {
|
|
16655
|
+
this.dotsOptions.position = defaultValue;
|
|
16656
|
+
}
|
|
16657
|
+
else if (optionName === 'buttonsPosition') {
|
|
16658
|
+
this.buttonsOptions.position = defaultValue;
|
|
16659
|
+
}
|
|
16660
|
+
}
|
|
16661
|
+
}
|
|
16662
|
+
validateButtonsPosition() {
|
|
16663
|
+
if (this.useButtons) {
|
|
16664
|
+
if (this.buttonsOptions.together) {
|
|
16665
|
+
this.validatePosition(this.buttonsOptions.position, 'buttonsPosition', 'bottom-center');
|
|
16666
|
+
}
|
|
16667
|
+
else if (this.buttonsOptions.position !== 'middle-sides') {
|
|
16668
|
+
console.warn(`Invalid buttonsPosition: ${this.buttonsOptions.position}. When buttons are not together, only 'middle-sides' is allowed. Defaulting to 'middle-sides'.`);
|
|
16669
|
+
this.buttonsOptions.position = 'middle-sides';
|
|
16670
|
+
}
|
|
16671
|
+
}
|
|
16672
|
+
}
|
|
16673
|
+
}
|
|
16674
|
+
CustomCarouselElement.defaultInterval = 5000;
|
|
16675
|
+
CustomCarouselElement.validPositions = [
|
|
16676
|
+
'top-left',
|
|
16677
|
+
'top-center',
|
|
16678
|
+
'top-right',
|
|
16679
|
+
'bottom-left',
|
|
16680
|
+
'bottom-center',
|
|
16681
|
+
'bottom-right',
|
|
16682
|
+
'middle-left',
|
|
16683
|
+
'middle-right',
|
|
16684
|
+
'middle-sides',
|
|
16685
|
+
];
|
|
16686
|
+
CarouselElement = CustomCarouselElement;
|
|
16687
|
+
}
|
|
16688
|
+
|
|
16689
|
+
let SpotElement;
|
|
16690
|
+
if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined') {
|
|
16691
|
+
class CustomSpotElement extends HTMLElement {
|
|
16692
|
+
constructor() {
|
|
16693
|
+
super();
|
|
16694
|
+
this.originalFontSizes = new Map();
|
|
16695
|
+
this.attachShadow({ mode: 'open' });
|
|
16696
|
+
}
|
|
16697
|
+
connectedCallback() {
|
|
16698
|
+
this.setupResizeObserver();
|
|
16699
|
+
this.render();
|
|
16700
|
+
}
|
|
16701
|
+
disconnectedCallback() {
|
|
16702
|
+
var _a;
|
|
16703
|
+
this.removeEventListener('spotSizeChanged', this.handleSpotSizeChanged);
|
|
16704
|
+
(_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
16705
|
+
}
|
|
16706
|
+
/**
|
|
16707
|
+
* Setup observers for the spot element
|
|
16708
|
+
* #########################################################
|
|
16709
|
+
*/
|
|
16710
|
+
setupResizeObserver() {
|
|
16711
|
+
if (this.data && !this.data.fluid) {
|
|
16712
|
+
this.resizeObserver = new ResizeObserverService({
|
|
16713
|
+
element: this,
|
|
16714
|
+
maxSize: {
|
|
16715
|
+
width: this.data.width,
|
|
16716
|
+
height: this.data.height,
|
|
16717
|
+
},
|
|
16718
|
+
minScale: this.data.minScale,
|
|
16719
|
+
});
|
|
16720
|
+
this.addEventListener('spotSizeChanged', this.handleSpotSizeChanged.bind(this));
|
|
16721
|
+
}
|
|
16722
|
+
}
|
|
16723
|
+
/**
|
|
16724
|
+
* Observer additional event handlers
|
|
16725
|
+
* #########################################################
|
|
16726
|
+
*/
|
|
16727
|
+
handleSpotSizeChanged(event) {
|
|
16728
|
+
var _a, _b, _c;
|
|
16729
|
+
const isRBSpot = (_c = (_b = (_a = this.data) === null || _a === void 0 ? void 0 : _a.spot) === null || _b === void 0 ? void 0 : _b.startsWith('rb')) !== null && _c !== void 0 ? _c : false;
|
|
16730
|
+
if (!isRBSpot) {
|
|
16731
|
+
// Adjust text elements font size based on the scale factor
|
|
16732
|
+
this.adjustFontSize(event.detail.scale);
|
|
16733
|
+
}
|
|
16734
|
+
}
|
|
16735
|
+
adjustFontSize(elementScale) {
|
|
16736
|
+
var _a;
|
|
16737
|
+
const scaleFactor = calculateScaleFactor(elementScale);
|
|
16738
|
+
// Find all text elements within the shadow root
|
|
16739
|
+
const elements = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelectorAll('h1, h2, h3, h4, p, span');
|
|
16740
|
+
elements === null || elements === void 0 ? void 0 : elements.forEach((element) => {
|
|
16741
|
+
if (element instanceof HTMLElement) {
|
|
16742
|
+
if (!this.originalFontSizes.has(element)) {
|
|
16743
|
+
const originalSize = parseFloat(window.getComputedStyle(element).fontSize);
|
|
16744
|
+
this.originalFontSizes.set(element, originalSize);
|
|
16745
|
+
}
|
|
16746
|
+
const originalSize = this.originalFontSizes.get(element);
|
|
16747
|
+
const newFontSize = originalSize * scaleFactor;
|
|
16748
|
+
element.style.fontSize = `${newFontSize}px`;
|
|
16749
|
+
}
|
|
16750
|
+
});
|
|
16751
|
+
}
|
|
16752
|
+
/**
|
|
16753
|
+
* Spot element rendering
|
|
16754
|
+
* #########################################################
|
|
16755
|
+
*/
|
|
16756
|
+
render() {
|
|
16757
|
+
if (!this.shadowRoot || !this.data || !this.content)
|
|
16758
|
+
return;
|
|
16759
|
+
const style = this.getTemplateStyle(this.data.width, this.data.height);
|
|
16760
|
+
if (this.content instanceof HTMLElement) {
|
|
16761
|
+
this.shadowRoot.replaceChildren(style, this.content);
|
|
16762
|
+
}
|
|
16763
|
+
}
|
|
16764
|
+
getTemplateStyle(width, height) {
|
|
16765
|
+
const style = document.createElement('style');
|
|
16766
|
+
style.textContent = `
|
|
16767
|
+
:host {
|
|
16768
|
+
display: block;
|
|
16769
|
+
position: relative;
|
|
16770
|
+
box-sizing: border-box;
|
|
16771
|
+
overflow: hidden;
|
|
16772
|
+
width: ${this.data.fluid ? '100%' : `${width}px`};
|
|
16773
|
+
height: ${this.data.fluid ? '100%' : `${height}px`};
|
|
16774
|
+
}
|
|
16775
|
+
`;
|
|
16776
|
+
return style;
|
|
16777
|
+
}
|
|
16778
|
+
}
|
|
16779
|
+
SpotElement = CustomSpotElement;
|
|
16780
|
+
}
|
|
16781
|
+
|
|
16782
|
+
class ElementService {
|
|
16783
|
+
static getInstance() {
|
|
16784
|
+
return SingletonManager.getInstance('ElementService', () => new ElementService());
|
|
16785
|
+
}
|
|
16786
|
+
/**
|
|
16787
|
+
* Creates the html element based on the provided data, content and configs using shadow dom.
|
|
16788
|
+
*
|
|
16789
|
+
* This method is only available in browser environments.
|
|
16790
|
+
*
|
|
16791
|
+
* @param {ICreateSpotElementParams} params - The parameters to create the final element.
|
|
16792
|
+
*
|
|
16793
|
+
* @return {HTMLElement | null} - The html element or null if the browser environment is not available.
|
|
16794
|
+
*/
|
|
16795
|
+
createSpotElement({ content, config }) {
|
|
16796
|
+
var _a, _b;
|
|
16797
|
+
if (!this.ensureBrowserEnvironmentAndDefineElement()) {
|
|
16798
|
+
return null;
|
|
16799
|
+
}
|
|
16800
|
+
const spot = document.createElement(SPOT_ELEMENT_TAG);
|
|
16801
|
+
spot.setAttribute('type', (_a = config === null || config === void 0 ? void 0 : config.spot) !== null && _a !== void 0 ? _a : '');
|
|
16802
|
+
spot.data = {
|
|
16803
|
+
spot: config === null || config === void 0 ? void 0 : config.spot,
|
|
16804
|
+
fluid: (_b = config === null || config === void 0 ? void 0 : config.fluid) !== null && _b !== void 0 ? _b : false,
|
|
16805
|
+
...config,
|
|
16806
|
+
};
|
|
16807
|
+
spot.content = content;
|
|
16808
|
+
return spot;
|
|
16809
|
+
}
|
|
16810
|
+
/**
|
|
16811
|
+
* Creates the carousel html element based on the provided slides and configs using shadow dom.
|
|
16812
|
+
*
|
|
16813
|
+
* This method is only available in browser environments.
|
|
16814
|
+
*
|
|
16815
|
+
* @param {ICreateCarouselElementParams} params - The parameters to create the final element.
|
|
16816
|
+
*
|
|
16817
|
+
* @return {HTMLElement | null} - The html element or null if the browser environment is not available.
|
|
16818
|
+
*/
|
|
16819
|
+
createCarouselElement({ slides, config, }) {
|
|
16820
|
+
if (!this.ensureBrowserEnvironmentAndDefineElement()) {
|
|
16821
|
+
return null;
|
|
16822
|
+
}
|
|
16823
|
+
const carousel = document.createElement(CAROUSEL_ELEMENT_TAG);
|
|
16824
|
+
carousel.data = {
|
|
16825
|
+
spot: config === null || config === void 0 ? void 0 : config.spot,
|
|
16826
|
+
fluid: false,
|
|
16827
|
+
...config,
|
|
16828
|
+
};
|
|
16829
|
+
carousel.slides = slides;
|
|
16830
|
+
return carousel;
|
|
16831
|
+
}
|
|
16832
|
+
/**
|
|
16833
|
+
* Overrides the spot colors with the provided colors.
|
|
16834
|
+
*
|
|
16835
|
+
* @param {ISpot} spot - The spot data.
|
|
16836
|
+
* @param {ISpotColors} colors - The colors to override.
|
|
16837
|
+
*
|
|
16838
|
+
* @return {ISpot} - The spot data with the colors overridden.
|
|
16839
|
+
*/
|
|
16840
|
+
overrideSpotColors(spot, colors) {
|
|
16841
|
+
if (!colors)
|
|
16842
|
+
return spot;
|
|
16843
|
+
const { textColor, backgroundColor, ctaTextColor, ctaBorderColor } = colors;
|
|
16844
|
+
return {
|
|
16845
|
+
...spot,
|
|
16846
|
+
textColor: textColor !== null && textColor !== void 0 ? textColor : spot.textColor,
|
|
16847
|
+
backgroundColor: backgroundColor !== null && backgroundColor !== void 0 ? backgroundColor : spot.backgroundColor,
|
|
16848
|
+
ctaTextColor: ctaTextColor !== null && ctaTextColor !== void 0 ? ctaTextColor : spot.ctaTextColor,
|
|
16849
|
+
ctaBorderColor: ctaBorderColor !== null && ctaBorderColor !== void 0 ? ctaBorderColor : spot.ctaBorderColor,
|
|
16850
|
+
};
|
|
16851
|
+
}
|
|
16852
|
+
/**
|
|
16853
|
+
* @returns {boolean} - True if the browser environment is available and the element is defined.
|
|
16854
|
+
*/
|
|
16855
|
+
ensureBrowserEnvironmentAndDefineElement() {
|
|
16856
|
+
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
16857
|
+
console.warn('LiquidCommerce Rmn Sdk: Methods which create elements are only available in browser environments.');
|
|
16858
|
+
return false;
|
|
16859
|
+
}
|
|
16860
|
+
if (!window.customElements.get(SPOT_ELEMENT_TAG)) {
|
|
16861
|
+
window.customElements.define(SPOT_ELEMENT_TAG, SpotElement);
|
|
16862
|
+
}
|
|
16863
|
+
if (!window.customElements.get(CAROUSEL_ELEMENT_TAG)) {
|
|
16864
|
+
window.customElements.define(CAROUSEL_ELEMENT_TAG, CarouselElement);
|
|
16865
|
+
}
|
|
16866
|
+
return true;
|
|
16867
|
+
}
|
|
16868
|
+
}
|
|
16869
|
+
|
|
16870
|
+
class UniqueIdGenerator {
|
|
16871
|
+
/**
|
|
16872
|
+
* Initialize the generator with a node ID
|
|
16873
|
+
* @param nodeId Number between 0-1023 to identify this instance
|
|
16874
|
+
*/
|
|
16875
|
+
static initialize(nodeId = Math.floor(Math.random() * 1024)) {
|
|
16876
|
+
if (nodeId < 0 || nodeId >= 1 << this.nodeBits) {
|
|
16877
|
+
throw new Error(`Node ID must be between 0 and ${(1 << this.nodeBits) - 1}`);
|
|
16878
|
+
}
|
|
16879
|
+
this.nodeId = nodeId;
|
|
16880
|
+
}
|
|
16881
|
+
/**
|
|
16882
|
+
* Convert a number to base32 string with specified length
|
|
16883
|
+
*/
|
|
16884
|
+
static toBase32(num, length) {
|
|
16885
|
+
let result = '';
|
|
16886
|
+
while (num > 0) {
|
|
16887
|
+
result = this.base32Chars[Number(num % BigInt(32))] + result;
|
|
16888
|
+
// @ts-expect-error - TS doesn't support bigint division
|
|
16889
|
+
num = num / 32n;
|
|
16890
|
+
}
|
|
16891
|
+
return result.padStart(length, '0');
|
|
16892
|
+
}
|
|
16893
|
+
/**
|
|
16894
|
+
* Generate a cryptographically secure random number
|
|
16895
|
+
*/
|
|
16896
|
+
static getSecureRandom() {
|
|
16897
|
+
if (typeof crypto !== 'undefined') {
|
|
16898
|
+
const buffer = new Uint32Array(1);
|
|
16899
|
+
crypto.getRandomValues(buffer);
|
|
16900
|
+
return buffer[0];
|
|
16901
|
+
}
|
|
16902
|
+
return Math.floor(Math.random() * 0xffffffff);
|
|
16903
|
+
}
|
|
16904
|
+
/**
|
|
16905
|
+
* Wait until next millisecond
|
|
16906
|
+
*/
|
|
16907
|
+
static waitNextMillis(lastTimestamp) {
|
|
16908
|
+
let timestamp = Date.now();
|
|
16909
|
+
while (timestamp <= lastTimestamp) {
|
|
16910
|
+
timestamp = Date.now();
|
|
16911
|
+
}
|
|
16912
|
+
return timestamp;
|
|
16913
|
+
}
|
|
16914
|
+
/**
|
|
16915
|
+
* Generates a highly unique ID with the following format:
|
|
16916
|
+
* TTTTTTTTTTCCCCNNNNNRRRR
|
|
16917
|
+
* T: Timestamp (10 chars)
|
|
16918
|
+
* C: Counter (4 chars)
|
|
16919
|
+
* N: Node ID (5 chars)
|
|
16920
|
+
* R: Random (4 chars)
|
|
16921
|
+
*
|
|
16922
|
+
* Total length: 23 characters, always uppercase alphanumeric
|
|
16923
|
+
*/
|
|
16924
|
+
static generate() {
|
|
16925
|
+
if (this.nodeId === undefined) {
|
|
16926
|
+
this.initialize();
|
|
16927
|
+
}
|
|
16928
|
+
let timestamp = Date.now() - this.epoch;
|
|
16929
|
+
// Handle clock moving backwards or same millisecond
|
|
16930
|
+
if (timestamp < this.lastTimestamp) {
|
|
16931
|
+
throw new Error('Clock moved backwards. Refusing to generate ID.');
|
|
16932
|
+
}
|
|
16933
|
+
if (timestamp === this.lastTimestamp) {
|
|
16934
|
+
this.sequence = (this.sequence + 1) & ((1 << this.sequenceBits) - 1);
|
|
16935
|
+
if (this.sequence === 0) {
|
|
16936
|
+
timestamp = this.waitNextMillis(this.lastTimestamp);
|
|
16937
|
+
}
|
|
16938
|
+
}
|
|
16939
|
+
else {
|
|
16940
|
+
this.sequence = 0;
|
|
16941
|
+
}
|
|
16942
|
+
this.lastTimestamp = timestamp;
|
|
16943
|
+
// Generate random component
|
|
16944
|
+
const random = this.getSecureRandom() & 0xffff; // 16 bits of randomness
|
|
16945
|
+
// Combine all components into a BigInt
|
|
16946
|
+
// const id =
|
|
16947
|
+
// (BigInt(timestamp) << BigInt(this.nodeBits + this.sequenceBits + 16)) |
|
|
16948
|
+
// (BigInt(this.nodeId) << BigInt(this.sequenceBits + 16)) |
|
|
16949
|
+
// (BigInt(this.sequence) << BigInt(16)) |
|
|
16950
|
+
// BigInt(random);
|
|
16951
|
+
// Convert to base32 representation
|
|
16952
|
+
const timeComponent = this.toBase32(BigInt(timestamp), 10);
|
|
16953
|
+
const counterComponent = this.toBase32(BigInt(this.sequence), 4);
|
|
16954
|
+
const nodeComponent = this.toBase32(BigInt(this.nodeId), 5);
|
|
16955
|
+
const randomComponent = this.toBase32(BigInt(random), 4);
|
|
16956
|
+
return `${timeComponent}${counterComponent}${nodeComponent}${randomComponent}`;
|
|
16957
|
+
}
|
|
16958
|
+
/**
|
|
16959
|
+
* Validates if a string matches the expected ID format
|
|
16960
|
+
*/
|
|
16961
|
+
static isValid(id) {
|
|
16962
|
+
if (!/^[0-9A-HJ-NP-Z]{23}$/.test(id))
|
|
16963
|
+
return false;
|
|
16964
|
+
try {
|
|
16965
|
+
const timeComponent = id.slice(0, 10);
|
|
16966
|
+
const timestamp = this.decodeBase32(timeComponent);
|
|
16967
|
+
const now = Date.now() - this.epoch;
|
|
16968
|
+
return timestamp >= 0 && timestamp <= now;
|
|
16969
|
+
}
|
|
16970
|
+
catch (_a) {
|
|
16971
|
+
return false;
|
|
16972
|
+
}
|
|
16973
|
+
}
|
|
16974
|
+
/**
|
|
16975
|
+
* Decode base32 string to number
|
|
16976
|
+
*/
|
|
16977
|
+
static decodeBase32(str) {
|
|
16978
|
+
let result = 0;
|
|
16979
|
+
for (const char of str) {
|
|
16980
|
+
result = result * 32 + this.base32Chars.indexOf(char);
|
|
16981
|
+
}
|
|
16982
|
+
return result;
|
|
16983
|
+
}
|
|
16984
|
+
/**
|
|
16985
|
+
* Extract timestamp from ID
|
|
16986
|
+
*/
|
|
16987
|
+
static getTimestamp(id) {
|
|
16988
|
+
if (!this.isValid(id))
|
|
16989
|
+
throw new Error('Invalid ID format');
|
|
16990
|
+
const timeComponent = id.slice(0, 10);
|
|
16991
|
+
const timestamp = this.decodeBase32(timeComponent);
|
|
16992
|
+
return new Date(timestamp + this.epoch);
|
|
16993
|
+
}
|
|
16994
|
+
}
|
|
16995
|
+
// Constants for bit manipulation
|
|
16996
|
+
UniqueIdGenerator.epoch = 1577836800000; // 2020-01-01 as epoch
|
|
16997
|
+
UniqueIdGenerator.nodeBits = 10;
|
|
16998
|
+
UniqueIdGenerator.sequenceBits = 12;
|
|
16999
|
+
// Instance variables
|
|
17000
|
+
UniqueIdGenerator.lastTimestamp = -1;
|
|
17001
|
+
UniqueIdGenerator.sequence = 0;
|
|
17002
|
+
// Character set for base32 encoding (excluding similar looking characters)
|
|
17003
|
+
UniqueIdGenerator.base32Chars = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
|
|
17004
|
+
|
|
17005
|
+
function convertHexToRgba(hex, opacity = 1) {
|
|
17006
|
+
// Remove # if present
|
|
17007
|
+
const cleanHex = hex.replace('#', '');
|
|
17008
|
+
// Convert hex to RGB
|
|
17009
|
+
const r = parseInt(cleanHex.substring(0, 2), 16);
|
|
17010
|
+
const g = parseInt(cleanHex.substring(2, 4), 16);
|
|
17011
|
+
const b = parseInt(cleanHex.substring(4, 6), 16);
|
|
17012
|
+
// Return rgba string
|
|
17013
|
+
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
|
17014
|
+
}
|
|
17015
|
+
function generateGradientColor(overlay, fallback = '') {
|
|
17016
|
+
if (!overlay) {
|
|
17017
|
+
return fallback;
|
|
17018
|
+
}
|
|
17019
|
+
const OVERLAY_SIZE = {
|
|
17020
|
+
small: 10,
|
|
17021
|
+
base: 30,
|
|
17022
|
+
large: 50,
|
|
17023
|
+
};
|
|
17024
|
+
const OVERLAY_OPACITY = {
|
|
17025
|
+
light: 0.1,
|
|
17026
|
+
medium: 0.4,
|
|
17027
|
+
dark: 0.6,
|
|
17028
|
+
};
|
|
17029
|
+
const { size, opacity, color } = overlay;
|
|
17030
|
+
const goTo = OVERLAY_SIZE[size];
|
|
17031
|
+
const overlayOpacity = OVERLAY_OPACITY[opacity];
|
|
17032
|
+
const fullColor = convertHexToRgba(color, 1);
|
|
17033
|
+
const transparentColor = convertHexToRgba(color, 0);
|
|
17034
|
+
const gradientColor = convertHexToRgba(color, overlayOpacity);
|
|
17035
|
+
return `${fullColor} 0%, ${gradientColor} ${goTo}%, ${transparentColor} 100%`;
|
|
17036
|
+
}
|
|
17037
|
+
function spotHtmlStringToElement(htmlString) {
|
|
17038
|
+
const spot = document.createElement('div');
|
|
17039
|
+
spot.className = 'spot';
|
|
17040
|
+
spot.innerHTML = htmlString;
|
|
17041
|
+
Object.assign(spot.style, {
|
|
17042
|
+
display: 'block',
|
|
17043
|
+
width: '100%',
|
|
17044
|
+
height: '100%',
|
|
17045
|
+
margin: '0',
|
|
17046
|
+
padding: '0',
|
|
17047
|
+
containerType: 'inline-size',
|
|
17048
|
+
position: 'relative',
|
|
17049
|
+
});
|
|
17050
|
+
return spot;
|
|
17051
|
+
}
|
|
17052
|
+
|
|
17053
|
+
const STYLES$i = ({ primaryImage, secondaryImage }) => `
|
|
17054
|
+
<style>
|
|
17055
|
+
.content {
|
|
17056
|
+
width: 100%;
|
|
17057
|
+
height: 100%;
|
|
17058
|
+
display: flex;
|
|
17059
|
+
flex-direction: row;
|
|
17060
|
+
background-color: #FFFFFF;
|
|
17061
|
+
gap: 0.5cqw;
|
|
17062
|
+
cursor: pointer;
|
|
17063
|
+
color: inherit;
|
|
17064
|
+
}
|
|
17065
|
+
.big-image {
|
|
17066
|
+
width: 65%;
|
|
17067
|
+
height: 100%;
|
|
17068
|
+
background-image: url("${primaryImage}");
|
|
17069
|
+
background-position: center;
|
|
17070
|
+
background-repeat: no-repeat;
|
|
17071
|
+
background-size: cover;
|
|
17072
|
+
}
|
|
17073
|
+
.main {
|
|
17074
|
+
width: 35%;
|
|
17075
|
+
height: 100%;
|
|
17076
|
+
display: flex;
|
|
17077
|
+
flex-direction: column;
|
|
17078
|
+
gap: 0.5cqw;
|
|
17079
|
+
}
|
|
17080
|
+
.small-image {
|
|
17081
|
+
width: 100%;
|
|
17082
|
+
height: 50%;
|
|
17083
|
+
background-image: url("${secondaryImage}");
|
|
17084
|
+
background-position: center;
|
|
17085
|
+
background-repeat: no-repeat;
|
|
17086
|
+
background-size: cover;
|
|
17087
|
+
}
|
|
17088
|
+
.text {
|
|
17089
|
+
background: #E8E6DE;
|
|
17090
|
+
text-align: center;
|
|
17091
|
+
display: flex;
|
|
17092
|
+
flex-direction: column;
|
|
17093
|
+
justify-content: center;
|
|
17094
|
+
align-items: center;
|
|
17095
|
+
height: 50%;
|
|
17096
|
+
width: 100%;
|
|
17097
|
+
padding: 5% 10%;
|
|
17098
|
+
box-sizing: border-box;
|
|
17099
|
+
font-family: "Source Sans 3", sans-serif;
|
|
17100
|
+
}
|
|
17101
|
+
.header {
|
|
17102
|
+
font-size: 2.2cqw;
|
|
17103
|
+
color: #000000;
|
|
17104
|
+
font-style: normal;
|
|
17105
|
+
font-weight: 400;
|
|
17106
|
+
font-family: "Cormorant", serif;
|
|
17107
|
+
margin: 0;
|
|
17108
|
+
}
|
|
17109
|
+
.description {
|
|
17110
|
+
font-size: 1.2cqw;
|
|
17111
|
+
color: #000000;
|
|
17112
|
+
font-style: normal;
|
|
17113
|
+
font-weight: 400;
|
|
17114
|
+
margin: 1cqh 0;
|
|
17115
|
+
}
|
|
17116
|
+
.button {
|
|
17117
|
+
font-size: 1cqw;
|
|
17118
|
+
color: #000000;
|
|
17119
|
+
background-color: transparent;
|
|
17120
|
+
font-style: normal;
|
|
17121
|
+
font-weight: 700;
|
|
17122
|
+
text-decoration: underline;
|
|
17123
|
+
text-transform: uppercase;
|
|
17124
|
+
border: none;
|
|
17125
|
+
cursor: pointer;
|
|
17126
|
+
padding: 0;
|
|
17127
|
+
transition: opacity 0.3s ease;
|
|
17128
|
+
}
|
|
17129
|
+
.content:hover .button {
|
|
17130
|
+
opacity: 0.7;
|
|
17131
|
+
}
|
|
17132
|
+
@container (max-width: 600px) {
|
|
17133
|
+
.header {
|
|
17134
|
+
font-size: 3cqw;
|
|
17135
|
+
}
|
|
17136
|
+
.description {
|
|
17137
|
+
font-size: 1.6cqw;
|
|
17138
|
+
margin: 0;
|
|
17139
|
+
}
|
|
17140
|
+
.button {
|
|
17141
|
+
font-size: 1.4cqw;
|
|
17142
|
+
}
|
|
17143
|
+
}
|
|
17144
|
+
</style>
|
|
17145
|
+
`;
|
|
17146
|
+
function billboardV1Template(spot) {
|
|
17147
|
+
return `
|
|
17148
|
+
${GFONT_PRECONNECT}
|
|
17149
|
+
${GFONT_SOURCE_SANS_3}
|
|
17150
|
+
${GFONT_CORMORANT}
|
|
17151
|
+
${STYLES$i(spot)}
|
|
17152
|
+
<div class="content">
|
|
17153
|
+
<div class="big-image"></div>
|
|
17154
|
+
<div class="main">
|
|
17155
|
+
<div class="small-image"></div>
|
|
17156
|
+
<div class="text">
|
|
17157
|
+
<h2 class="header">${spot.header}</h2>
|
|
17158
|
+
<p class="description">${spot.description}</p>
|
|
17159
|
+
<span class="button">${spot.ctaText}</span>
|
|
17160
|
+
</div>
|
|
17161
|
+
</div>
|
|
17162
|
+
</div>
|
|
17163
|
+
`;
|
|
17164
|
+
}
|
|
17165
|
+
|
|
17166
|
+
const STYLES$h = ({ primaryImage }) => `
|
|
17167
|
+
<style>
|
|
17168
|
+
.content {
|
|
17169
|
+
display: flex;
|
|
17170
|
+
flex-direction: column;
|
|
17171
|
+
justify-content: flex-end;
|
|
17172
|
+
align-items: flex-start;
|
|
15325
17173
|
width: 100%;
|
|
15326
17174
|
height: 100%;
|
|
15327
17175
|
font-family: "Source Sans 3", sans-serif;
|
|
@@ -16019,185 +17867,202 @@ function wideSkyscraperV1Template(spot) {
|
|
|
16019
17867
|
`;
|
|
16020
17868
|
}
|
|
16021
17869
|
|
|
16022
|
-
const STYLES$7 = ({ primaryImage, mobilePrimaryImage = primaryImage }) => `
|
|
16023
|
-
|
|
16024
|
-
|
|
16025
|
-
|
|
16026
|
-
|
|
16027
|
-
|
|
16028
|
-
|
|
16029
|
-
|
|
16030
|
-
|
|
16031
|
-
|
|
16032
|
-
|
|
16033
|
-
|
|
16034
|
-
|
|
16035
|
-
|
|
16036
|
-
|
|
16037
|
-
}
|
|
16038
|
-
|
|
16039
|
-
.content {
|
|
16040
|
-
background-image: url("${primaryImage}");
|
|
16041
|
-
}
|
|
17870
|
+
const STYLES$7 = ({ primaryImage, mobilePrimaryImage = primaryImage }, { prefix }) => `
|
|
17871
|
+
<style>
|
|
17872
|
+
.${prefix} {
|
|
17873
|
+
display: block;
|
|
17874
|
+
width: 100%;
|
|
17875
|
+
height: 100%;
|
|
17876
|
+
background-image: url("${mobilePrimaryImage}");
|
|
17877
|
+
background-size: cover;
|
|
17878
|
+
background-repeat: no-repeat;
|
|
17879
|
+
background-position: center;
|
|
17880
|
+
cursor: pointer;
|
|
17881
|
+
container-type: inline-size;
|
|
17882
|
+
}
|
|
17883
|
+
|
|
17884
|
+
@container (min-width: 640px) {
|
|
17885
|
+
.${prefix} {
|
|
17886
|
+
background-image: url("${primaryImage}");
|
|
16042
17887
|
}
|
|
16043
|
-
|
|
17888
|
+
}
|
|
17889
|
+
</style>
|
|
16044
17890
|
`;
|
|
16045
|
-
function rbCollectionBannerWithoutTextBlockTemplate(spot) {
|
|
17891
|
+
function rbCollectionBannerWithoutTextBlockTemplate(spot, config) {
|
|
17892
|
+
const { prefix = '' } = config;
|
|
16046
17893
|
return `
|
|
16047
|
-
${STYLES$7(spot)}
|
|
16048
|
-
<div class="
|
|
17894
|
+
${STYLES$7(spot, config)}
|
|
17895
|
+
<div class="${prefix}"></div>
|
|
16049
17896
|
`;
|
|
16050
17897
|
}
|
|
16051
17898
|
|
|
16052
|
-
const STYLES$6 = ({ textColor = '#ffffff', ctaTextColor = textColor, ctaBorderColor = ctaTextColor, primaryImage, mobilePrimaryImage = primaryImage, }) =>
|
|
16053
|
-
|
|
16054
|
-
|
|
16055
|
-
|
|
16056
|
-
|
|
16057
|
-
|
|
16058
|
-
.content {
|
|
16059
|
-
display: flex;
|
|
16060
|
-
flex-direction: column;
|
|
16061
|
-
justify-content: flex-end;
|
|
16062
|
-
align-items: flex-start;
|
|
16063
|
-
width: 100%;
|
|
16064
|
-
height: 100%;
|
|
16065
|
-
background-image: url("${mobilePrimaryImage}");
|
|
16066
|
-
background-size: cover;
|
|
16067
|
-
background-repeat: no-repeat;
|
|
16068
|
-
background-position: center;
|
|
16069
|
-
padding: 3%;
|
|
16070
|
-
box-sizing: border-box;
|
|
16071
|
-
color: ${textColor};
|
|
16072
|
-
cursor: pointer;
|
|
16073
|
-
}
|
|
16074
|
-
.text {
|
|
16075
|
-
display: flex;
|
|
16076
|
-
flex-direction: column;
|
|
16077
|
-
justify-content: flex-start;
|
|
16078
|
-
align-items: flex-start;
|
|
16079
|
-
width: 100%;
|
|
16080
|
-
height: fit-content;
|
|
16081
|
-
gap: 5px;
|
|
16082
|
-
}
|
|
16083
|
-
.header {
|
|
16084
|
-
font-size: 18px;
|
|
16085
|
-
margin: 0;
|
|
16086
|
-
font-family: "Cormorant";
|
|
16087
|
-
font-style: normal;
|
|
16088
|
-
font-weight: 300;
|
|
16089
|
-
line-height: normal;
|
|
16090
|
-
}
|
|
16091
|
-
.description {
|
|
16092
|
-
font-size: 10px;
|
|
16093
|
-
font-family: "Source Sans 3", system-ui;
|
|
16094
|
-
font-style: normal;
|
|
16095
|
-
font-weight: 400;
|
|
16096
|
-
line-height: 20px;
|
|
16097
|
-
margin: 0;
|
|
16098
|
-
}
|
|
16099
|
-
.cta-button {
|
|
16100
|
-
font-size: 8px;
|
|
16101
|
-
font-family: "Source Sans 3", system-ui;
|
|
16102
|
-
font-style: normal;
|
|
16103
|
-
font-weight: 400;
|
|
16104
|
-
line-height: 18px;
|
|
16105
|
-
border-radius: 5px;
|
|
16106
|
-
border: 0.5px solid ${ctaBorderColor};
|
|
16107
|
-
display: inline-block;
|
|
16108
|
-
padding: 7px 20px;
|
|
16109
|
-
color: ${ctaTextColor};
|
|
16110
|
-
transition: background-color 0.3s ease;
|
|
16111
|
-
}
|
|
16112
|
-
.content:hover .cta-button {
|
|
16113
|
-
background-color: ${ctaBorderColor.length === 7 ? `${ctaBorderColor}15` : `${ctaBorderColor}`};
|
|
16114
|
-
}
|
|
16115
|
-
@media (min-width: 640px) {
|
|
16116
|
-
.content {
|
|
16117
|
-
background-image: url("${primaryImage}");
|
|
16118
|
-
}
|
|
16119
|
-
}
|
|
16120
|
-
@media (min-width: 768px) {
|
|
16121
|
-
.primary-image {
|
|
16122
|
-
width: 66.66666%;
|
|
16123
|
-
height: 100%;
|
|
16124
|
-
}
|
|
16125
|
-
.main {
|
|
17899
|
+
const STYLES$6 = ({ textColor = '#ffffff', ctaTextColor = textColor, ctaBorderColor = ctaTextColor, primaryImage, mobilePrimaryImage = primaryImage, }, { prefix, overlay }) => {
|
|
17900
|
+
const linearGradient = generateGradientColor(overlay, 'rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 40%');
|
|
17901
|
+
return `
|
|
17902
|
+
<style>
|
|
17903
|
+
.${prefix} {
|
|
17904
|
+
display: flex;
|
|
16126
17905
|
flex-direction: column;
|
|
17906
|
+
justify-content: flex-end;
|
|
17907
|
+
align-items: flex-start;
|
|
17908
|
+
width: 100%;
|
|
16127
17909
|
height: 100%;
|
|
16128
|
-
|
|
17910
|
+
background-image: linear-gradient(to top, ${linearGradient}), url("${mobilePrimaryImage}");
|
|
17911
|
+
background-size: cover;
|
|
17912
|
+
background-repeat: no-repeat;
|
|
17913
|
+
background-position: center;
|
|
17914
|
+
padding: 3%;
|
|
17915
|
+
box-sizing: border-box;
|
|
17916
|
+
color: ${textColor};
|
|
17917
|
+
cursor: pointer;
|
|
16129
17918
|
}
|
|
16130
|
-
|
|
17919
|
+
|
|
17920
|
+
.${prefix}__text {
|
|
17921
|
+
display: flex;
|
|
17922
|
+
flex-direction: column;
|
|
17923
|
+
justify-content: flex-start;
|
|
17924
|
+
align-items: flex-start;
|
|
16131
17925
|
width: 100%;
|
|
16132
|
-
height:
|
|
17926
|
+
height: fit-content;
|
|
17927
|
+
gap: 8px;
|
|
16133
17928
|
}
|
|
16134
|
-
|
|
16135
|
-
|
|
16136
|
-
|
|
16137
|
-
|
|
16138
|
-
font-
|
|
17929
|
+
|
|
17930
|
+
.${prefix}__header {
|
|
17931
|
+
font-size: 24px;
|
|
17932
|
+
margin: 0;
|
|
17933
|
+
font-family: "Cormorant", system-ui;
|
|
17934
|
+
font-style: normal;
|
|
17935
|
+
font-weight: 300;
|
|
17936
|
+
line-height: normal;
|
|
16139
17937
|
}
|
|
16140
|
-
|
|
16141
|
-
|
|
17938
|
+
|
|
17939
|
+
.${prefix}__description {
|
|
17940
|
+
font-size: 10px;
|
|
17941
|
+
font-family: "Source Sans 3", system-ui;
|
|
17942
|
+
font-style: normal;
|
|
17943
|
+
font-weight: 400;
|
|
17944
|
+
line-height: 20px;
|
|
17945
|
+
margin: 0;
|
|
16142
17946
|
}
|
|
16143
|
-
|
|
16144
|
-
|
|
16145
|
-
|
|
16146
|
-
font-
|
|
17947
|
+
|
|
17948
|
+
.${prefix}__cta-button {
|
|
17949
|
+
font-size: 8px;
|
|
17950
|
+
font-family: "Source Sans 3", system-ui;
|
|
17951
|
+
font-style: normal;
|
|
17952
|
+
font-weight: 400;
|
|
17953
|
+
line-height: 18px;
|
|
17954
|
+
border-radius: 5px;
|
|
17955
|
+
border: 0.5px solid ${ctaBorderColor};
|
|
17956
|
+
display: inline-block;
|
|
17957
|
+
padding: 7px 20px;
|
|
17958
|
+
color: ${ctaTextColor};
|
|
17959
|
+
transition: background-color 0.3s ease;
|
|
16147
17960
|
}
|
|
16148
|
-
|
|
16149
|
-
|
|
17961
|
+
|
|
17962
|
+
.${prefix}:hover .cta-button {
|
|
17963
|
+
background-color: ${ctaBorderColor.length === 7 ? `${ctaBorderColor}15` : `${ctaBorderColor}`};
|
|
16150
17964
|
}
|
|
16151
|
-
|
|
16152
|
-
|
|
17965
|
+
|
|
17966
|
+
@container (min-width: 640px) {
|
|
17967
|
+
.${prefix} {
|
|
17968
|
+
background-image: linear-gradient(to top, ${linearGradient}), url("${primaryImage}");
|
|
17969
|
+
}
|
|
16153
17970
|
}
|
|
16154
|
-
|
|
16155
|
-
|
|
16156
|
-
|
|
16157
|
-
|
|
17971
|
+
|
|
17972
|
+
@container (min-width: 768px) {
|
|
17973
|
+
.${prefix}__primary-image {
|
|
17974
|
+
width: 66.66666%;
|
|
17975
|
+
height: 100%;
|
|
17976
|
+
}
|
|
17977
|
+
|
|
17978
|
+
.${prefix}__main {
|
|
17979
|
+
flex-direction: column;
|
|
17980
|
+
height: 100%;
|
|
17981
|
+
width: 33.33333%;
|
|
17982
|
+
}
|
|
17983
|
+
|
|
17984
|
+
.${prefix}__secondary-image {
|
|
17985
|
+
width: 100%;
|
|
17986
|
+
height: 50%;
|
|
17987
|
+
}
|
|
17988
|
+
|
|
17989
|
+
.${prefix}__description {
|
|
17990
|
+
font-size: 12px;
|
|
17991
|
+
}
|
|
17992
|
+
|
|
17993
|
+
.${prefix}__cta-button {
|
|
17994
|
+
font-size: 12px;
|
|
17995
|
+
}
|
|
16158
17996
|
}
|
|
16159
|
-
|
|
16160
|
-
|
|
17997
|
+
|
|
17998
|
+
@container (min-width: 1024px) {
|
|
17999
|
+
.${prefix}__header {
|
|
18000
|
+
font-size: 26px;
|
|
18001
|
+
}
|
|
18002
|
+
|
|
18003
|
+
.${prefix}__description {
|
|
18004
|
+
font-size: 13px;
|
|
18005
|
+
}
|
|
18006
|
+
|
|
18007
|
+
.${prefix}__cta-button {
|
|
18008
|
+
font-size: 13px;
|
|
18009
|
+
}
|
|
16161
18010
|
}
|
|
16162
|
-
|
|
16163
|
-
|
|
18011
|
+
|
|
18012
|
+
@container (min-width: 1280px) {
|
|
18013
|
+
.${prefix}__header {
|
|
18014
|
+
font-size: 28px;
|
|
18015
|
+
}
|
|
18016
|
+
|
|
18017
|
+
.${prefix}__description {
|
|
18018
|
+
font-size: 14px;
|
|
18019
|
+
}
|
|
18020
|
+
|
|
18021
|
+
.${prefix}__cta-button {
|
|
18022
|
+
font-size: 14px;
|
|
18023
|
+
}
|
|
16164
18024
|
}
|
|
16165
|
-
|
|
16166
|
-
|
|
16167
|
-
|
|
16168
|
-
function rbHomepageHeroFullImageTemplate(spot) {
|
|
18025
|
+
</style>
|
|
18026
|
+
`;
|
|
18027
|
+
};
|
|
18028
|
+
function rbHomepageHeroFullImageTemplate(spot, config) {
|
|
18029
|
+
const { prefix = '' } = config;
|
|
16169
18030
|
return `
|
|
16170
18031
|
${GFONT_PRECONNECT}
|
|
16171
18032
|
${GFONT_SOURCE_SANS_3}
|
|
16172
18033
|
${GFONT_CORMORANT}
|
|
16173
|
-
${STYLES$6(spot)}
|
|
16174
|
-
<div class="
|
|
16175
|
-
|
|
16176
|
-
|
|
16177
|
-
|
|
16178
|
-
|
|
16179
|
-
|
|
18034
|
+
${STYLES$6(spot, config)}
|
|
18035
|
+
<div class="${prefix}">
|
|
18036
|
+
<div class="${prefix}__text">
|
|
18037
|
+
${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
|
|
18038
|
+
${spot.description ? `<p class="${prefix}__description">${spot.description}</p>` : ''}
|
|
18039
|
+
${spot.ctaText ? `<span class="${prefix}__cta-button">${spot.ctaText}</span>` : ''}
|
|
18040
|
+
</div>
|
|
16180
18041
|
</div>
|
|
16181
18042
|
`;
|
|
16182
18043
|
}
|
|
16183
18044
|
|
|
16184
|
-
const STYLES$5 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextColor = textColor, primaryImage, mobilePrimaryImage = primaryImage, secondaryImage, mobileSecondaryImage = secondaryImage, }) => `
|
|
16185
|
-
|
|
16186
|
-
|
|
16187
|
-
|
|
16188
|
-
|
|
18045
|
+
const STYLES$5 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextColor = textColor, primaryImage, mobilePrimaryImage = primaryImage, secondaryImage, mobileSecondaryImage = secondaryImage, }, { prefix }) => `
|
|
18046
|
+
<style>
|
|
18047
|
+
.${prefix} {
|
|
18048
|
+
width: 100%;
|
|
18049
|
+
height: 100%;
|
|
18050
|
+
display: block;
|
|
18051
|
+
position: relative;
|
|
16189
18052
|
}
|
|
16190
|
-
|
|
18053
|
+
|
|
18054
|
+
.${prefix}__content {
|
|
16191
18055
|
width: 100%;
|
|
16192
18056
|
height: 100%;
|
|
16193
18057
|
display: flex;
|
|
16194
|
-
flex-direction: column;
|
|
18058
|
+
flex-direction: column;
|
|
16195
18059
|
background-color: transparent;
|
|
16196
|
-
gap:
|
|
18060
|
+
gap: 6px;
|
|
16197
18061
|
color: inherit;
|
|
16198
18062
|
cursor: pointer;
|
|
16199
18063
|
}
|
|
16200
|
-
|
|
18064
|
+
|
|
18065
|
+
.${prefix}__primary-image {
|
|
16201
18066
|
width: 100%;
|
|
16202
18067
|
height: 60%;
|
|
16203
18068
|
background-image: url("${mobilePrimaryImage}");
|
|
@@ -16205,14 +18070,16 @@ const STYLES$5 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
|
|
|
16205
18070
|
background-repeat: no-repeat;
|
|
16206
18071
|
background-size: cover;
|
|
16207
18072
|
}
|
|
16208
|
-
|
|
18073
|
+
|
|
18074
|
+
.${prefix}__main {
|
|
16209
18075
|
width: 100%;
|
|
16210
18076
|
height: 40%;
|
|
16211
18077
|
display: flex;
|
|
16212
18078
|
flex-direction: row;
|
|
16213
|
-
|
|
18079
|
+
gap: 6px;
|
|
16214
18080
|
}
|
|
16215
|
-
|
|
18081
|
+
|
|
18082
|
+
.${prefix}__secondary-image {
|
|
16216
18083
|
width: 50%;
|
|
16217
18084
|
height: 100%;
|
|
16218
18085
|
background-image: url("${mobileSecondaryImage}");
|
|
@@ -16220,7 +18087,8 @@ const STYLES$5 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
|
|
|
16220
18087
|
background-repeat: no-repeat;
|
|
16221
18088
|
background-size: cover;
|
|
16222
18089
|
}
|
|
16223
|
-
|
|
18090
|
+
|
|
18091
|
+
.${prefix}__text {
|
|
16224
18092
|
color: ${textColor};
|
|
16225
18093
|
background-color: ${backgroundColor};
|
|
16226
18094
|
text-align: center;
|
|
@@ -16230,11 +18098,12 @@ const STYLES$5 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
|
|
|
16230
18098
|
align-items: center;
|
|
16231
18099
|
width: 50%;
|
|
16232
18100
|
height: 100%;
|
|
16233
|
-
gap:
|
|
18101
|
+
gap: 10px;
|
|
16234
18102
|
padding: 0 10px;
|
|
16235
18103
|
box-sizing: border-box;
|
|
16236
18104
|
}
|
|
16237
|
-
|
|
18105
|
+
|
|
18106
|
+
.${prefix}__header {
|
|
16238
18107
|
color: inherit;
|
|
16239
18108
|
margin: 0;
|
|
16240
18109
|
font-size: 18px;
|
|
@@ -16243,7 +18112,8 @@ const STYLES$5 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
|
|
|
16243
18112
|
font-weight: 700;
|
|
16244
18113
|
line-height: normal;
|
|
16245
18114
|
}
|
|
16246
|
-
|
|
18115
|
+
|
|
18116
|
+
.${prefix}__description {
|
|
16247
18117
|
color: inherit;
|
|
16248
18118
|
margin: 0;
|
|
16249
18119
|
font-size: 10px;
|
|
@@ -16251,7 +18121,8 @@ const STYLES$5 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
|
|
|
16251
18121
|
font-style: normal;
|
|
16252
18122
|
font-weight: 400;
|
|
16253
18123
|
}
|
|
16254
|
-
|
|
18124
|
+
|
|
18125
|
+
.${prefix}__cta-button {
|
|
16255
18126
|
color: ${ctaTextColor};
|
|
16256
18127
|
background-color: transparent;
|
|
16257
18128
|
font-size: 8px;
|
|
@@ -16266,108 +18137,125 @@ const STYLES$5 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
|
|
|
16266
18137
|
padding: 0;
|
|
16267
18138
|
transition: opacity 0.3s ease;
|
|
16268
18139
|
}
|
|
16269
|
-
|
|
18140
|
+
|
|
18141
|
+
.${prefix}__content:hover .${prefix}__cta-button {
|
|
16270
18142
|
opacity: 0.8;
|
|
16271
18143
|
}
|
|
16272
|
-
|
|
16273
|
-
|
|
18144
|
+
|
|
18145
|
+
@container (min-width: 640px) {
|
|
18146
|
+
.${prefix}__primary-image {
|
|
16274
18147
|
background-image: url("${primaryImage}");
|
|
16275
18148
|
}
|
|
16276
|
-
|
|
18149
|
+
|
|
18150
|
+
.${prefix}__secondary-image {
|
|
16277
18151
|
background-image: url("${secondaryImage}");
|
|
16278
18152
|
}
|
|
16279
18153
|
}
|
|
16280
|
-
|
|
16281
|
-
|
|
18154
|
+
|
|
18155
|
+
@container (min-width: 768px) {
|
|
18156
|
+
.${prefix}__content {
|
|
16282
18157
|
flex-direction: row;
|
|
16283
18158
|
}
|
|
16284
|
-
|
|
18159
|
+
|
|
18160
|
+
.${prefix}__primary-image {
|
|
16285
18161
|
width: 66.66666%;
|
|
16286
18162
|
height: 100%;
|
|
16287
18163
|
}
|
|
16288
|
-
|
|
18164
|
+
|
|
18165
|
+
.${prefix}__main {
|
|
16289
18166
|
flex-direction: column;
|
|
16290
18167
|
height: 100%;
|
|
16291
18168
|
width: 33.33333%;
|
|
16292
18169
|
}
|
|
16293
|
-
|
|
18170
|
+
|
|
18171
|
+
.${prefix}__secondary-image {
|
|
16294
18172
|
width: 100%;
|
|
16295
18173
|
height: 50%;
|
|
16296
18174
|
}
|
|
16297
|
-
|
|
18175
|
+
|
|
18176
|
+
.${prefix}__text {
|
|
16298
18177
|
width: 100%;
|
|
16299
18178
|
height: 50%;
|
|
16300
18179
|
}
|
|
16301
|
-
|
|
18180
|
+
.${prefix}__header {
|
|
16302
18181
|
font-size: 22px;
|
|
16303
18182
|
}
|
|
16304
|
-
|
|
18183
|
+
.${prefix}__description {
|
|
16305
18184
|
font-size: 12px;
|
|
16306
18185
|
}
|
|
16307
|
-
|
|
18186
|
+
.${prefix}__cta-button {
|
|
16308
18187
|
font-size: 12px;
|
|
16309
18188
|
}
|
|
16310
18189
|
}
|
|
16311
|
-
|
|
16312
|
-
|
|
18190
|
+
|
|
18191
|
+
@container (min-width: 1024px) {
|
|
18192
|
+
.${prefix}__header {
|
|
16313
18193
|
font-size: 24px;
|
|
16314
18194
|
}
|
|
16315
|
-
|
|
18195
|
+
.${prefix}__description {
|
|
16316
18196
|
font-size: 13px;
|
|
16317
|
-
|
|
16318
|
-
|
|
16319
|
-
|
|
16320
|
-
|
|
18197
|
+
}
|
|
18198
|
+
.${prefix}__cta-button {
|
|
18199
|
+
font-size: 13px;
|
|
18200
|
+
}
|
|
16321
18201
|
}
|
|
16322
|
-
|
|
16323
|
-
|
|
18202
|
+
|
|
18203
|
+
@container (min-width: 1280px) {
|
|
18204
|
+
.${prefix}__header {
|
|
16324
18205
|
font-size: 28px;
|
|
16325
18206
|
}
|
|
16326
|
-
|
|
18207
|
+
.${prefix}__description {
|
|
16327
18208
|
font-size: 14px;
|
|
16328
18209
|
}
|
|
16329
|
-
|
|
18210
|
+
.${prefix}__cta-button {
|
|
16330
18211
|
font-size: 14px;
|
|
16331
18212
|
}
|
|
16332
18213
|
}
|
|
16333
|
-
|
|
18214
|
+
</style>
|
|
16334
18215
|
`;
|
|
16335
|
-
function rbHomepageHeroThreeTileTemplate(spot) {
|
|
18216
|
+
function rbHomepageHeroThreeTileTemplate(spot, config) {
|
|
18217
|
+
const { prefix = '' } = config;
|
|
16336
18218
|
return `
|
|
16337
18219
|
${GFONT_PRECONNECT}
|
|
16338
18220
|
${GFONT_SOURCE_SANS_3}
|
|
16339
18221
|
${GFONT_CORMORANT}
|
|
16340
|
-
${STYLES$5(spot)}
|
|
16341
|
-
<div class="
|
|
16342
|
-
<div class="
|
|
16343
|
-
|
|
16344
|
-
<div class="
|
|
16345
|
-
|
|
16346
|
-
|
|
16347
|
-
|
|
16348
|
-
|
|
18222
|
+
${STYLES$5(spot, config)}
|
|
18223
|
+
<div class="${prefix}">
|
|
18224
|
+
<div class="${prefix}__content">
|
|
18225
|
+
<div class="${prefix}__primary-image"></div>
|
|
18226
|
+
<div class="${prefix}__main">
|
|
18227
|
+
<div class="${prefix}__secondary-image"></div>
|
|
18228
|
+
<div class="${prefix}__text">
|
|
18229
|
+
${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
|
|
18230
|
+
${spot.description ? `<p class="${prefix}__description">${spot.description}</p>` : ''}
|
|
18231
|
+
${spot.ctaText ? `<span class="${prefix}__cta-button">${spot.ctaText}</span>` : ''}
|
|
18232
|
+
</div>
|
|
16349
18233
|
</div>
|
|
16350
18234
|
</div>
|
|
16351
18235
|
</div>
|
|
16352
18236
|
`;
|
|
16353
18237
|
}
|
|
16354
18238
|
|
|
16355
|
-
const STYLES$4 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextColor = textColor, primaryImage, mobilePrimaryImage = primaryImage, }) => `
|
|
18239
|
+
const STYLES$4 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextColor = textColor, primaryImage, mobilePrimaryImage = primaryImage, }, { prefix }) => `
|
|
16356
18240
|
<style>
|
|
16357
|
-
|
|
16358
|
-
|
|
16359
|
-
|
|
18241
|
+
.${prefix} {
|
|
18242
|
+
width: 100%;
|
|
18243
|
+
height: 100%;
|
|
18244
|
+
background-color: transparent;
|
|
18245
|
+
cursor: pointer;
|
|
18246
|
+
position: relative;
|
|
16360
18247
|
}
|
|
16361
|
-
|
|
18248
|
+
|
|
18249
|
+
.${prefix}__content {
|
|
16362
18250
|
width: 100%;
|
|
16363
18251
|
height: 100%;
|
|
16364
18252
|
display: flex;
|
|
16365
|
-
flex-direction: column-reverse;
|
|
18253
|
+
flex-direction: column-reverse;
|
|
16366
18254
|
background-color: transparent;
|
|
16367
|
-
gap:
|
|
16368
|
-
cursor: pointer;
|
|
18255
|
+
gap: 6px;
|
|
16369
18256
|
}
|
|
16370
|
-
|
|
18257
|
+
|
|
18258
|
+
.${prefix}__image {
|
|
16371
18259
|
width: 100%;
|
|
16372
18260
|
height: 100%;
|
|
16373
18261
|
background-image: url("${mobilePrimaryImage}");
|
|
@@ -16375,7 +18263,8 @@ const STYLES$4 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
|
|
|
16375
18263
|
background-repeat: no-repeat;
|
|
16376
18264
|
background-size: cover;
|
|
16377
18265
|
}
|
|
16378
|
-
|
|
18266
|
+
|
|
18267
|
+
.${prefix}__text {
|
|
16379
18268
|
color: ${textColor};
|
|
16380
18269
|
background-color: ${backgroundColor};
|
|
16381
18270
|
text-align: center;
|
|
@@ -16385,20 +18274,22 @@ const STYLES$4 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
|
|
|
16385
18274
|
align-items: center;
|
|
16386
18275
|
width: 100%;
|
|
16387
18276
|
height: 100%;
|
|
16388
|
-
gap:
|
|
18277
|
+
gap: 10px;
|
|
16389
18278
|
padding: 0 10px;
|
|
16390
18279
|
box-sizing: border-box;
|
|
16391
18280
|
}
|
|
16392
|
-
|
|
18281
|
+
|
|
18282
|
+
.${prefix}__header {
|
|
16393
18283
|
font-size: 18px;
|
|
16394
18284
|
margin: 0;
|
|
16395
18285
|
color: inherit;
|
|
16396
|
-
font-family: "Cormorant";
|
|
18286
|
+
font-family: "Cormorant", system-ui;
|
|
16397
18287
|
font-style: normal;
|
|
16398
18288
|
font-weight: 700;
|
|
16399
18289
|
line-height: normal;
|
|
16400
18290
|
}
|
|
16401
|
-
|
|
18291
|
+
|
|
18292
|
+
.${prefix}__description {
|
|
16402
18293
|
color: inherit;
|
|
16403
18294
|
margin: 0;
|
|
16404
18295
|
font-size: 10px;
|
|
@@ -16406,7 +18297,8 @@ const STYLES$4 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
|
|
|
16406
18297
|
font-style: normal;
|
|
16407
18298
|
font-weight: 400;
|
|
16408
18299
|
}
|
|
16409
|
-
|
|
18300
|
+
|
|
18301
|
+
.${prefix}__cta-button {
|
|
16410
18302
|
color: ${ctaTextColor};
|
|
16411
18303
|
background-color: transparent;
|
|
16412
18304
|
font-size: 8px;
|
|
@@ -16421,205 +18313,225 @@ const STYLES$4 = ({ textColor = '#212121', backgroundColor = '#e8e6de', ctaTextC
|
|
|
16421
18313
|
padding: 0;
|
|
16422
18314
|
transition: opacity 0.3s ease;
|
|
16423
18315
|
}
|
|
16424
|
-
|
|
18316
|
+
|
|
18317
|
+
.${prefix}__content:hover .${prefix}__cta-button {
|
|
16425
18318
|
opacity: 0.8;
|
|
16426
18319
|
}
|
|
16427
|
-
|
|
16428
|
-
|
|
18320
|
+
|
|
18321
|
+
@container (min-width: 640px) {
|
|
18322
|
+
.${prefix}__image {
|
|
16429
18323
|
background-image: url("${primaryImage}");
|
|
16430
18324
|
}
|
|
16431
18325
|
}
|
|
16432
|
-
|
|
16433
|
-
|
|
18326
|
+
|
|
18327
|
+
@container (min-width: 768px) {
|
|
18328
|
+
.${prefix}__content {
|
|
16434
18329
|
flex-direction: row;
|
|
16435
18330
|
}
|
|
16436
|
-
|
|
18331
|
+
.${prefix}__image {
|
|
16437
18332
|
width: 66.66666%;
|
|
16438
18333
|
height: 100%;
|
|
16439
18334
|
}
|
|
16440
|
-
|
|
16441
|
-
width: 33.
|
|
18335
|
+
.${prefix}__text {
|
|
18336
|
+
width: 33.33333%;
|
|
16442
18337
|
height: 100%;
|
|
16443
18338
|
}
|
|
16444
|
-
|
|
18339
|
+
.${prefix}__header {
|
|
16445
18340
|
font-size: 22px;
|
|
16446
18341
|
}
|
|
16447
|
-
|
|
18342
|
+
.${prefix}__description {
|
|
16448
18343
|
font-size: 12px;
|
|
16449
18344
|
}
|
|
16450
|
-
|
|
18345
|
+
.${prefix}__cta-button {
|
|
16451
18346
|
font-size: 12px;
|
|
16452
18347
|
}
|
|
16453
18348
|
}
|
|
16454
|
-
|
|
16455
|
-
|
|
18349
|
+
|
|
18350
|
+
@container (min-width: 1024px) {
|
|
18351
|
+
.${prefix}__header {
|
|
16456
18352
|
font-size: 24px;
|
|
16457
18353
|
}
|
|
16458
|
-
|
|
18354
|
+
.${prefix}__description {
|
|
16459
18355
|
font-size: 13px;
|
|
16460
|
-
|
|
16461
|
-
|
|
16462
|
-
|
|
16463
|
-
|
|
18356
|
+
}
|
|
18357
|
+
.${prefix}__cta-button {
|
|
18358
|
+
font-size: 13px;
|
|
18359
|
+
}
|
|
16464
18360
|
}
|
|
16465
|
-
|
|
16466
|
-
|
|
18361
|
+
|
|
18362
|
+
@container (min-width: 1280px) {
|
|
18363
|
+
.${prefix}__header {
|
|
16467
18364
|
font-size: 28px;
|
|
16468
18365
|
}
|
|
16469
|
-
|
|
18366
|
+
.${prefix}__description {
|
|
16470
18367
|
font-size: 14px;
|
|
16471
18368
|
}
|
|
16472
|
-
|
|
18369
|
+
.${prefix}__cta-button {
|
|
16473
18370
|
font-size: 14px;
|
|
16474
18371
|
}
|
|
16475
18372
|
}
|
|
16476
18373
|
</style>
|
|
16477
18374
|
`;
|
|
16478
|
-
function rbHomepageHeroTwoTileTemplate(spot) {
|
|
18375
|
+
function rbHomepageHeroTwoTileTemplate(spot, config) {
|
|
18376
|
+
const { prefix = '' } = config;
|
|
16479
18377
|
return `
|
|
16480
18378
|
${GFONT_PRECONNECT}
|
|
16481
18379
|
${GFONT_SOURCE_SANS_3}
|
|
16482
18380
|
${GFONT_CORMORANT}
|
|
16483
|
-
${STYLES$4(spot)}
|
|
16484
|
-
<div class="
|
|
16485
|
-
|
|
16486
|
-
|
|
16487
|
-
|
|
16488
|
-
|
|
16489
|
-
|
|
16490
|
-
|
|
18381
|
+
${STYLES$4(spot, config)}
|
|
18382
|
+
<div class="${prefix}">
|
|
18383
|
+
<div class="${prefix}__content">
|
|
18384
|
+
<div class="${prefix}__text">
|
|
18385
|
+
${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
|
|
18386
|
+
${spot.description ? `<p class="${prefix}__description">${spot.description}</p>` : ''}
|
|
18387
|
+
${spot.ctaText ? `<span class="${prefix}__cta-button">${spot.ctaText}</span>` : ''}
|
|
18388
|
+
</div>
|
|
18389
|
+
<div class="${prefix}__image"></div>
|
|
18390
|
+
</div>
|
|
16491
18391
|
</div>
|
|
16492
18392
|
`;
|
|
16493
18393
|
}
|
|
16494
18394
|
|
|
16495
|
-
const STYLES$3 = ({ textColor = '#ffffff', ctaTextColor = textColor, ctaBorderColor = ctaTextColor, primaryImage, mobilePrimaryImage = primaryImage, }) =>
|
|
16496
|
-
|
|
16497
|
-
|
|
16498
|
-
|
|
16499
|
-
|
|
16500
|
-
|
|
16501
|
-
|
|
16502
|
-
|
|
16503
|
-
|
|
16504
|
-
|
|
16505
|
-
|
|
16506
|
-
|
|
16507
|
-
|
|
16508
|
-
|
|
16509
|
-
|
|
16510
|
-
|
|
16511
|
-
|
|
16512
|
-
|
|
16513
|
-
cursor: pointer;
|
|
16514
|
-
color: ${textColor};
|
|
16515
|
-
}
|
|
16516
|
-
.text {
|
|
16517
|
-
padding: 20px;
|
|
16518
|
-
width: 70%;
|
|
16519
|
-
display: flex;
|
|
16520
|
-
flex-direction: column;
|
|
16521
|
-
justify-content: center;
|
|
16522
|
-
align-items: flex-start;
|
|
16523
|
-
gap: 10px;
|
|
16524
|
-
}
|
|
16525
|
-
.header {
|
|
16526
|
-
color: inherit;
|
|
16527
|
-
margin: 0;
|
|
16528
|
-
font-size: 20px;
|
|
16529
|
-
font-family: "Cormorant";
|
|
16530
|
-
font-style: normal;
|
|
16531
|
-
font-weight: 300;
|
|
16532
|
-
line-height: normal;
|
|
16533
|
-
}
|
|
16534
|
-
.description {
|
|
16535
|
-
color: inherit;
|
|
16536
|
-
font-size: 12px;
|
|
16537
|
-
line-height: 16px;
|
|
16538
|
-
font-family: "Source Sans 3", system-ui;
|
|
16539
|
-
font-style: normal;
|
|
16540
|
-
font-weight: 400;
|
|
16541
|
-
margin: 0;
|
|
16542
|
-
}
|
|
16543
|
-
.cta-button {
|
|
16544
|
-
width: fit-content;
|
|
16545
|
-
display: inline-block;
|
|
16546
|
-
padding: 7px 20px;
|
|
16547
|
-
border: 0.5px solid ${ctaBorderColor};
|
|
16548
|
-
border-radius: 5px;
|
|
16549
|
-
color: ${ctaTextColor};
|
|
16550
|
-
font-size: 8px;
|
|
16551
|
-
transition: background-color 0.3s ease;
|
|
16552
|
-
font-family: "Source Sans 3", system-ui;
|
|
16553
|
-
font-style: normal;
|
|
16554
|
-
font-weight: 400;
|
|
16555
|
-
}
|
|
16556
|
-
.content:hover .cta-button {
|
|
16557
|
-
background-color: ${ctaBorderColor.length === 7 ? `${ctaBorderColor}15` : `${ctaBorderColor}`};
|
|
16558
|
-
}
|
|
16559
|
-
@media (min-width: 640px) {
|
|
16560
|
-
.content {
|
|
16561
|
-
background-image: url("${primaryImage}");
|
|
16562
|
-
}
|
|
16563
|
-
}
|
|
16564
|
-
@media (min-width: 768px) {
|
|
16565
|
-
.text {
|
|
16566
|
-
padding: 25px;
|
|
18395
|
+
const STYLES$3 = ({ textColor = '#ffffff', ctaTextColor = textColor, ctaBorderColor = ctaTextColor, primaryImage, mobilePrimaryImage = primaryImage, }, { prefix, overlay }) => {
|
|
18396
|
+
const linearGradient = generateGradientColor(overlay, 'rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 30%');
|
|
18397
|
+
return `
|
|
18398
|
+
<style>
|
|
18399
|
+
.${prefix} {
|
|
18400
|
+
width: 100%;
|
|
18401
|
+
height: 100%;
|
|
18402
|
+
display: flex;
|
|
18403
|
+
flex-direction: column;
|
|
18404
|
+
justify-content: flex-end;
|
|
18405
|
+
background-image: linear-gradient(to top, ${linearGradient}), url("${mobilePrimaryImage}");
|
|
18406
|
+
background-size: cover;
|
|
18407
|
+
background-repeat: no-repeat;
|
|
18408
|
+
background-position: center;
|
|
18409
|
+
border-radius: 5px;
|
|
18410
|
+
overflow: hidden;
|
|
18411
|
+
cursor: pointer;
|
|
18412
|
+
color: ${textColor};
|
|
16567
18413
|
}
|
|
16568
|
-
|
|
16569
|
-
|
|
18414
|
+
|
|
18415
|
+
.${prefix}__text {
|
|
18416
|
+
padding: 20px;
|
|
18417
|
+
display: flex;
|
|
18418
|
+
flex-direction: column;
|
|
18419
|
+
justify-content: center;
|
|
18420
|
+
align-items: flex-start;
|
|
18421
|
+
gap: 10px;
|
|
16570
18422
|
}
|
|
16571
|
-
|
|
16572
|
-
|
|
16573
|
-
|
|
18423
|
+
|
|
18424
|
+
.${prefix}__header {
|
|
18425
|
+
color: inherit;
|
|
18426
|
+
margin: 0;
|
|
18427
|
+
font-size: 20px;
|
|
18428
|
+
font-family: "Cormorant", system-ui;
|
|
18429
|
+
font-style: normal;
|
|
18430
|
+
font-weight: 300;
|
|
18431
|
+
line-height: normal;
|
|
16574
18432
|
}
|
|
16575
|
-
|
|
18433
|
+
|
|
18434
|
+
.${prefix}__description {
|
|
18435
|
+
color: inherit;
|
|
16576
18436
|
font-size: 12px;
|
|
18437
|
+
line-height: 16px;
|
|
18438
|
+
font-family: "Source Sans 3", system-ui;
|
|
18439
|
+
font-style: normal;
|
|
18440
|
+
font-weight: 400;
|
|
18441
|
+
margin: 0;
|
|
16577
18442
|
}
|
|
16578
|
-
|
|
16579
|
-
|
|
16580
|
-
|
|
16581
|
-
|
|
18443
|
+
|
|
18444
|
+
.${prefix}__cta-button {
|
|
18445
|
+
width: fit-content;
|
|
18446
|
+
display: inline-block;
|
|
18447
|
+
padding: 7px 20px;
|
|
18448
|
+
border: 0.5px solid ${ctaBorderColor};
|
|
18449
|
+
border-radius: 5px;
|
|
18450
|
+
color: ${ctaTextColor};
|
|
18451
|
+
font-size: 8px;
|
|
18452
|
+
transition: background-color 0.3s ease;
|
|
18453
|
+
font-family: "Source Sans 3", system-ui;
|
|
18454
|
+
font-style: normal;
|
|
18455
|
+
font-weight: 400;
|
|
16582
18456
|
}
|
|
16583
|
-
|
|
16584
|
-
|
|
18457
|
+
|
|
18458
|
+
.${prefix}:hover .${prefix}__cta-button {
|
|
18459
|
+
background-color: ${ctaBorderColor.length === 7 ? `${ctaBorderColor}15` : `${ctaBorderColor}`};
|
|
18460
|
+
}
|
|
18461
|
+
|
|
18462
|
+
@container (min-width: 640px) {
|
|
18463
|
+
.${prefix} {
|
|
18464
|
+
background-image: linear-gradient(to top, ${linearGradient}), url("${primaryImage}");
|
|
18465
|
+
}
|
|
16585
18466
|
}
|
|
16586
|
-
|
|
16587
|
-
|
|
18467
|
+
|
|
18468
|
+
@container (min-width: 768px) {
|
|
18469
|
+
.${prefix}__text {
|
|
18470
|
+
padding: 25px;
|
|
18471
|
+
}
|
|
18472
|
+
|
|
18473
|
+
.${prefix}__header {
|
|
18474
|
+
font-size: 24px;
|
|
18475
|
+
}
|
|
18476
|
+
|
|
18477
|
+
.${prefix}__description {
|
|
18478
|
+
font-size: 13px;
|
|
18479
|
+
line-height: 18px;
|
|
18480
|
+
}
|
|
18481
|
+
|
|
18482
|
+
.${prefix}__cta-button {
|
|
18483
|
+
font-size: 12px;
|
|
18484
|
+
}
|
|
16588
18485
|
}
|
|
16589
|
-
|
|
16590
|
-
|
|
18486
|
+
|
|
18487
|
+
@container (min-width: 1024px) {
|
|
18488
|
+
.${prefix}__text {
|
|
18489
|
+
padding: 30px;
|
|
18490
|
+
}
|
|
18491
|
+
|
|
18492
|
+
.${prefix}__header {
|
|
18493
|
+
font-size: 28px;
|
|
18494
|
+
}
|
|
18495
|
+
|
|
18496
|
+
.${prefix}__description {
|
|
18497
|
+
font-size: 14px;
|
|
18498
|
+
}
|
|
18499
|
+
|
|
18500
|
+
.${prefix}__cta-button {
|
|
18501
|
+
font-size: 13px;
|
|
18502
|
+
}
|
|
16591
18503
|
}
|
|
16592
|
-
|
|
16593
|
-
|
|
16594
|
-
|
|
16595
|
-
|
|
18504
|
+
|
|
18505
|
+
@container (min-width: 1280px) {
|
|
18506
|
+
.${prefix}__cta-button {
|
|
18507
|
+
font-size: 14px;
|
|
18508
|
+
}
|
|
16596
18509
|
}
|
|
16597
|
-
|
|
16598
|
-
|
|
16599
|
-
|
|
16600
|
-
function rbLargeCategoryImageToutTemplate(spot) {
|
|
18510
|
+
</style>
|
|
18511
|
+
`;
|
|
18512
|
+
};
|
|
18513
|
+
function rbLargeCategoryImageToutTemplate(spot, config) {
|
|
18514
|
+
const { prefix = '' } = config;
|
|
16601
18515
|
return `
|
|
16602
18516
|
${GFONT_PRECONNECT}
|
|
16603
18517
|
${GFONT_SOURCE_SANS_3}
|
|
16604
18518
|
${GFONT_CORMORANT}
|
|
16605
|
-
${STYLES$3(spot)}
|
|
16606
|
-
<div class="
|
|
16607
|
-
<div class="
|
|
16608
|
-
${spot.header ? `<h2 class="
|
|
16609
|
-
${spot.description ? `<p class="
|
|
16610
|
-
${spot.ctaText ? `<span class="
|
|
18519
|
+
${STYLES$3(spot, config)}
|
|
18520
|
+
<div class="${prefix}">
|
|
18521
|
+
<div class="${prefix}__text">
|
|
18522
|
+
${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
|
|
18523
|
+
${spot.description ? `<p class="${prefix}__description">${spot.description}</p>` : ''}
|
|
18524
|
+
${spot.ctaText ? `<span class="${prefix}__cta-button">${spot.ctaText}</span>` : ''}
|
|
16611
18525
|
</div>
|
|
16612
18526
|
</div>
|
|
16613
18527
|
`;
|
|
16614
18528
|
}
|
|
16615
18529
|
|
|
16616
|
-
const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = primaryImage, }) =>
|
|
18530
|
+
const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = primaryImage }, { prefix, overlay }) => {
|
|
18531
|
+
const linearGradient = generateGradientColor(overlay, 'rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 30%');
|
|
18532
|
+
return `
|
|
16617
18533
|
<style>
|
|
16618
|
-
|
|
16619
|
-
min-width: 320px;
|
|
16620
|
-
min-height: 150px;
|
|
16621
|
-
}
|
|
16622
|
-
.content {
|
|
18534
|
+
.${prefix} {
|
|
16623
18535
|
width: 100%;
|
|
16624
18536
|
height: 100%;
|
|
16625
18537
|
display: flex;
|
|
@@ -16628,17 +18540,14 @@ const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = pr
|
|
|
16628
18540
|
border-radius: 5px;
|
|
16629
18541
|
overflow: hidden;
|
|
16630
18542
|
cursor: pointer;
|
|
16631
|
-
background-image: url("${mobilePrimaryImage}");
|
|
18543
|
+
background-image: linear-gradient(to top, ${linearGradient}), url("${mobilePrimaryImage}");
|
|
16632
18544
|
background-size: cover;
|
|
16633
18545
|
background-position: center;
|
|
16634
|
-
background-blend-mode: overlay;
|
|
16635
18546
|
background-repeat: no-repeat;
|
|
18547
|
+
position: relative;
|
|
16636
18548
|
}
|
|
16637
|
-
|
|
16638
|
-
|
|
16639
|
-
width: fit-content;
|
|
16640
|
-
}
|
|
16641
|
-
.header {
|
|
18549
|
+
|
|
18550
|
+
.${prefix}__header {
|
|
16642
18551
|
font-size: 16px;
|
|
16643
18552
|
color: ${textColor};
|
|
16644
18553
|
line-height: 20px;
|
|
@@ -16646,103 +18555,101 @@ const STYLES$2 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = pr
|
|
|
16646
18555
|
font-family: "Source Sans 3", system-ui;
|
|
16647
18556
|
font-style: normal;
|
|
16648
18557
|
margin: 0;
|
|
18558
|
+
padding: 15px 10%;
|
|
16649
18559
|
}
|
|
16650
|
-
|
|
16651
|
-
|
|
16652
|
-
|
|
18560
|
+
|
|
18561
|
+
@container (min-width: 640px) {
|
|
18562
|
+
.${prefix} {
|
|
18563
|
+
background-image: linear-gradient(to top, ${linearGradient}), url("${primaryImage}");
|
|
16653
18564
|
}
|
|
16654
18565
|
}
|
|
16655
|
-
|
|
16656
|
-
|
|
18566
|
+
|
|
18567
|
+
@container (min-width: 768px) {
|
|
18568
|
+
.${prefix}__header {
|
|
16657
18569
|
font-size: 22px;
|
|
16658
18570
|
}
|
|
16659
18571
|
}
|
|
16660
|
-
|
|
16661
|
-
|
|
18572
|
+
|
|
18573
|
+
@container (min-width: 1024px) {
|
|
18574
|
+
.${prefix}__header {
|
|
16662
18575
|
font-size: 24px;
|
|
16663
18576
|
}
|
|
16664
18577
|
}
|
|
16665
|
-
|
|
16666
|
-
|
|
18578
|
+
|
|
18579
|
+
@container (min-width: 1280px) {
|
|
18580
|
+
.${prefix}__header {
|
|
16667
18581
|
font-size: 28px;
|
|
16668
18582
|
}
|
|
16669
18583
|
}
|
|
16670
18584
|
</style>
|
|
16671
18585
|
`;
|
|
16672
|
-
|
|
18586
|
+
};
|
|
18587
|
+
function rbNavigationBannerTemplate(spot, config) {
|
|
18588
|
+
const { prefix = '' } = config;
|
|
16673
18589
|
return `
|
|
16674
18590
|
${GFONT_PRECONNECT}
|
|
16675
18591
|
${GFONT_SOURCE_SANS_3}
|
|
16676
|
-
${STYLES$2(spot)}
|
|
16677
|
-
<div class="
|
|
16678
|
-
|
|
16679
|
-
${spot.header ? `<h2 class="header">${spot.header}</h2>` : ''}
|
|
16680
|
-
</div>
|
|
18592
|
+
${STYLES$2(spot, config)}
|
|
18593
|
+
<div class="${prefix}">
|
|
18594
|
+
${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
|
|
16681
18595
|
</div>
|
|
16682
18596
|
`;
|
|
16683
18597
|
}
|
|
16684
18598
|
|
|
16685
|
-
const STYLES$1 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = primaryImage, }) =>
|
|
16686
|
-
|
|
16687
|
-
|
|
16688
|
-
|
|
16689
|
-
|
|
16690
|
-
|
|
16691
|
-
|
|
16692
|
-
|
|
16693
|
-
|
|
16694
|
-
|
|
16695
|
-
|
|
16696
|
-
|
|
16697
|
-
|
|
16698
|
-
|
|
16699
|
-
|
|
16700
|
-
|
|
16701
|
-
|
|
16702
|
-
|
|
16703
|
-
cursor: pointer;
|
|
16704
|
-
}
|
|
16705
|
-
.text {
|
|
16706
|
-
padding: 10px;
|
|
16707
|
-
width: 70%;
|
|
16708
|
-
}
|
|
16709
|
-
.header {
|
|
16710
|
-
font-size: 12px;
|
|
16711
|
-
color: ${textColor};
|
|
16712
|
-
line-height: 16px;
|
|
16713
|
-
font-family: "Source Sans 3", system-ui;
|
|
16714
|
-
font-style: normal;
|
|
16715
|
-
font-weight: 400;
|
|
16716
|
-
line-height: normal;
|
|
16717
|
-
margin: 0;
|
|
16718
|
-
}
|
|
16719
|
-
@media (min-width: 640px) {
|
|
16720
|
-
.content {
|
|
16721
|
-
background-image: url("${primaryImage}");
|
|
18599
|
+
const STYLES$1 = ({ textColor = '#ffffff', primaryImage, mobilePrimaryImage = primaryImage }, { prefix, overlay }) => {
|
|
18600
|
+
const linearGradient = generateGradientColor(overlay, 'rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0) 30%');
|
|
18601
|
+
return `
|
|
18602
|
+
<style>
|
|
18603
|
+
.${prefix} {
|
|
18604
|
+
width: 100%;
|
|
18605
|
+
height: 100%;
|
|
18606
|
+
display: flex;
|
|
18607
|
+
flex-direction: column;
|
|
18608
|
+
justify-content: flex-end;
|
|
18609
|
+
background-image: linear-gradient(to top, ${linearGradient}), url("${mobilePrimaryImage}");
|
|
18610
|
+
background-size: cover;
|
|
18611
|
+
background-repeat: no-repeat;
|
|
18612
|
+
background-position: center;
|
|
18613
|
+
border-radius: 5px;
|
|
18614
|
+
overflow: hidden;
|
|
18615
|
+
cursor: pointer;
|
|
18616
|
+
position: relative;
|
|
16722
18617
|
}
|
|
16723
|
-
|
|
16724
|
-
|
|
16725
|
-
|
|
16726
|
-
|
|
18618
|
+
|
|
18619
|
+
.${prefix}__header {
|
|
18620
|
+
font-size: 12px;
|
|
18621
|
+
color: ${textColor};
|
|
18622
|
+
line-height: 16px;
|
|
18623
|
+
font-family: "Source Sans 3", system-ui;
|
|
18624
|
+
font-style: normal;
|
|
18625
|
+
font-weight: 400;
|
|
18626
|
+
margin: 0;
|
|
18627
|
+
padding: 10px;
|
|
18628
|
+
}
|
|
18629
|
+
|
|
18630
|
+
@container (min-width: 640px) {
|
|
18631
|
+
.${prefix} {
|
|
18632
|
+
background-image: linear-gradient(to top, ${linearGradient}), url("${primaryImage}");
|
|
18633
|
+
}
|
|
18634
|
+
}
|
|
18635
|
+
</style>
|
|
18636
|
+
`;
|
|
18637
|
+
};
|
|
18638
|
+
function rbSmallCategoryImageToutTemplate(spot, config) {
|
|
18639
|
+
const { prefix = '' } = config;
|
|
16727
18640
|
return `
|
|
16728
18641
|
${GFONT_PRECONNECT}
|
|
16729
18642
|
${GFONT_CORMORANT}
|
|
16730
|
-
${STYLES$1(spot)}
|
|
16731
|
-
<div class="
|
|
16732
|
-
|
|
16733
|
-
${spot.header ? `<h2 class="header">${spot.header}</h2>` : ''}
|
|
16734
|
-
</div>
|
|
18643
|
+
${STYLES$1(spot, config)}
|
|
18644
|
+
<div class="${prefix}">
|
|
18645
|
+
${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
|
|
16735
18646
|
</div>
|
|
16736
18647
|
`;
|
|
16737
18648
|
}
|
|
16738
18649
|
|
|
16739
|
-
const STYLES = ({ textColor = '#000000', backgroundColor = 'transparent', primaryImage, mobilePrimaryImage = primaryImage, }) => `
|
|
18650
|
+
const STYLES = ({ textColor = '#000000', backgroundColor = 'transparent', primaryImage, mobilePrimaryImage = primaryImage, }, { prefix }) => `
|
|
16740
18651
|
<style>
|
|
16741
|
-
|
|
16742
|
-
min-width: 165px;
|
|
16743
|
-
min-height: 250px;
|
|
16744
|
-
}
|
|
16745
|
-
.content {
|
|
18652
|
+
.${prefix} {
|
|
16746
18653
|
width: 100%;
|
|
16747
18654
|
height: 100%;
|
|
16748
18655
|
background-color: ${backgroundColor};
|
|
@@ -16751,7 +18658,8 @@ const STYLES = ({ textColor = '#000000', backgroundColor = 'transparent', primar
|
|
|
16751
18658
|
flex-direction: column;
|
|
16752
18659
|
border-radius: 5px;
|
|
16753
18660
|
}
|
|
16754
|
-
|
|
18661
|
+
|
|
18662
|
+
.${prefix}__image {
|
|
16755
18663
|
width: 100%;
|
|
16756
18664
|
height: 100%;
|
|
16757
18665
|
background-image: url("${mobilePrimaryImage}");
|
|
@@ -16760,7 +18668,8 @@ const STYLES = ({ textColor = '#000000', backgroundColor = 'transparent', primar
|
|
|
16760
18668
|
background-position: center;
|
|
16761
18669
|
border-radius: 5px;
|
|
16762
18670
|
}
|
|
16763
|
-
|
|
18671
|
+
|
|
18672
|
+
.${prefix}__text {
|
|
16764
18673
|
text-align: left;
|
|
16765
18674
|
display: flex;
|
|
16766
18675
|
flex-direction: row;
|
|
@@ -16770,7 +18679,8 @@ const STYLES = ({ textColor = '#000000', backgroundColor = 'transparent', primar
|
|
|
16770
18679
|
height: fit-content;
|
|
16771
18680
|
position: relative;
|
|
16772
18681
|
}
|
|
16773
|
-
|
|
18682
|
+
|
|
18683
|
+
.${prefix}__header {
|
|
16774
18684
|
font-size: 12px;
|
|
16775
18685
|
color: ${textColor};
|
|
16776
18686
|
padding-top: 5px;
|
|
@@ -16778,46 +18688,42 @@ const STYLES = ({ textColor = '#000000', backgroundColor = 'transparent', primar
|
|
|
16778
18688
|
font-family: "Source Sans 3", system-ui;
|
|
16779
18689
|
font-style: normal;
|
|
16780
18690
|
font-weight: 400;
|
|
16781
|
-
line-height: normal;
|
|
16782
18691
|
margin: 0;
|
|
16783
18692
|
}
|
|
16784
|
-
|
|
16785
|
-
|
|
18693
|
+
|
|
18694
|
+
@container (min-width: 640px) {
|
|
18695
|
+
.${prefix}__image {
|
|
16786
18696
|
background-image: url("${primaryImage}");
|
|
16787
18697
|
}
|
|
16788
18698
|
}
|
|
16789
18699
|
</style>
|
|
16790
18700
|
`;
|
|
16791
|
-
function rbSmallDiscoverToutTemplate(spot) {
|
|
18701
|
+
function rbSmallDiscoverToutTemplate(spot, config) {
|
|
18702
|
+
const { prefix = '' } = config;
|
|
16792
18703
|
return `
|
|
16793
18704
|
${GFONT_PRECONNECT}
|
|
16794
18705
|
${GFONT_CORMORANT}
|
|
16795
|
-
${STYLES(spot)}
|
|
16796
|
-
<div class="
|
|
16797
|
-
<div class="
|
|
16798
|
-
<div class="
|
|
16799
|
-
${spot.header ? `<h2 class="
|
|
18706
|
+
${STYLES(spot, config)}
|
|
18707
|
+
<div class="${prefix}">
|
|
18708
|
+
<div class="${prefix}__image"></div>
|
|
18709
|
+
<div class="${prefix}__text">
|
|
18710
|
+
${spot.header ? `<h2 class="${prefix}__header">${spot.header}</h2>` : ''}
|
|
16800
18711
|
</div>
|
|
16801
18712
|
</div>
|
|
16802
18713
|
`;
|
|
16803
18714
|
}
|
|
16804
18715
|
|
|
16805
|
-
var ENUM_SPOT_ELEMENT_ATTRIBUTE;
|
|
16806
|
-
(function (ENUM_SPOT_ELEMENT_ATTRIBUTE) {
|
|
16807
|
-
ENUM_SPOT_ELEMENT_ATTRIBUTE["WIDTH"] = "width";
|
|
16808
|
-
ENUM_SPOT_ELEMENT_ATTRIBUTE["HEIGHT"] = "height";
|
|
16809
|
-
ENUM_SPOT_ELEMENT_ATTRIBUTE["FLUID"] = "fluid";
|
|
16810
|
-
ENUM_SPOT_ELEMENT_ATTRIBUTE["REDIRECT_ON_CLICK"] = "redirect-on-click";
|
|
16811
|
-
})(ENUM_SPOT_ELEMENT_ATTRIBUTE || (ENUM_SPOT_ELEMENT_ATTRIBUTE = {}));
|
|
16812
18716
|
/**
|
|
16813
|
-
*
|
|
18717
|
+
* Returns the HTML element for the given spot.
|
|
16814
18718
|
*
|
|
16815
|
-
* @param {ISpot}
|
|
18719
|
+
* @param {ISpot} spot - The spot object.
|
|
18720
|
+
* @param {ISpotTemplateConfig} config - The spot template configuration.
|
|
16816
18721
|
*
|
|
16817
|
-
* @return {
|
|
18722
|
+
* @return {HTMLElement | null} - The HTML element for the given spot or null if the spot template is not found.
|
|
16818
18723
|
*/
|
|
16819
|
-
const
|
|
18724
|
+
const SPOT_TEMPLATE_HTML_ELEMENT = (spot, config) => {
|
|
16820
18725
|
const templates = {
|
|
18726
|
+
// Reserve Bar Spot Templates
|
|
16821
18727
|
[exports.RMN_SPOT_TYPE.RB_HOMEPAGE_HERO_THREE_TILE]: {
|
|
16822
18728
|
rbHomepageHeroThreeTile: rbHomepageHeroThreeTileTemplate,
|
|
16823
18729
|
},
|
|
@@ -16845,6 +18751,7 @@ const GET_SPOT_TEMPLATE_HTML_STRING = (data) => {
|
|
|
16845
18751
|
[exports.RMN_SPOT_TYPE.RB_PRODUCT_UPCS]: {
|
|
16846
18752
|
rbProductUpcs: () => '', // No template for this spot type, it will be handled by ReserveBar App.
|
|
16847
18753
|
},
|
|
18754
|
+
// IAB Standard Spot Templates
|
|
16848
18755
|
[exports.RMN_SPOT_TYPE.BILLBOARD]: {
|
|
16849
18756
|
billboardV1: billboardV1Template,
|
|
16850
18757
|
billboardV2: billboardV2Template,
|
|
@@ -16871,232 +18778,770 @@ const GET_SPOT_TEMPLATE_HTML_STRING = (data) => {
|
|
|
16871
18778
|
inTextV1: inTextV1Template,
|
|
16872
18779
|
},
|
|
16873
18780
|
};
|
|
16874
|
-
const spotVariants = templates[
|
|
18781
|
+
const spotVariants = templates[spot.spot];
|
|
16875
18782
|
if (!spotVariants) {
|
|
16876
|
-
return
|
|
18783
|
+
return null;
|
|
16877
18784
|
}
|
|
16878
|
-
const variantTemplate = spotVariants[
|
|
18785
|
+
const variantTemplate = spotVariants[spot.variant];
|
|
16879
18786
|
if (!variantTemplate) {
|
|
16880
|
-
return
|
|
18787
|
+
return null;
|
|
16881
18788
|
}
|
|
16882
|
-
|
|
18789
|
+
// Generate a highly unique prefix to avoid conflicts with other elements.
|
|
18790
|
+
const prefix = 's' + UniqueIdGenerator.generate().toLowerCase();
|
|
18791
|
+
const spotHtmlString = variantTemplate(spot, { ...config, prefix });
|
|
18792
|
+
return spotHtmlStringToElement(spotHtmlString);
|
|
16883
18793
|
};
|
|
16884
18794
|
|
|
16885
|
-
|
|
16886
|
-
|
|
16887
|
-
|
|
16888
|
-
|
|
16889
|
-
|
|
16890
|
-
|
|
16891
|
-
|
|
16892
|
-
|
|
16893
|
-
|
|
16894
|
-
|
|
16895
|
-
|
|
16896
|
-
|
|
16897
|
-
this.setupIntersectionObserver();
|
|
16898
|
-
this.render();
|
|
18795
|
+
// For the moment, we will only focus on sites that use Google Analytics,
|
|
18796
|
+
// but we will add support for other analytics tools in the future.
|
|
18797
|
+
var AnalyticsTool;
|
|
18798
|
+
(function (AnalyticsTool) {
|
|
18799
|
+
AnalyticsTool["GoogleAnalytics"] = "google-analytics";
|
|
18800
|
+
AnalyticsTool["Other"] = "Other";
|
|
18801
|
+
})(AnalyticsTool || (AnalyticsTool = {}));
|
|
18802
|
+
|
|
18803
|
+
class DataLayerMonitor {
|
|
18804
|
+
constructor() {
|
|
18805
|
+
if (!window.dataLayer) {
|
|
18806
|
+
return;
|
|
16899
18807
|
}
|
|
16900
|
-
|
|
16901
|
-
|
|
16902
|
-
|
|
16903
|
-
|
|
18808
|
+
this.originalPush = window.dataLayer.push;
|
|
18809
|
+
}
|
|
18810
|
+
static getInstance() {
|
|
18811
|
+
if (!DataLayerMonitor.instance) {
|
|
18812
|
+
DataLayerMonitor.instance = new DataLayerMonitor();
|
|
16904
18813
|
}
|
|
16905
|
-
|
|
16906
|
-
|
|
16907
|
-
|
|
18814
|
+
return DataLayerMonitor.instance;
|
|
18815
|
+
}
|
|
18816
|
+
setListener(listener) {
|
|
18817
|
+
this.listener = listener;
|
|
18818
|
+
}
|
|
18819
|
+
start() {
|
|
18820
|
+
window.dataLayer.push = (...args) => {
|
|
18821
|
+
const result = this.originalPush.apply(window.dataLayer, args);
|
|
18822
|
+
const pushedEvent = args[0];
|
|
18823
|
+
if (this.listener) {
|
|
18824
|
+
const normalizedData = this.cleanEventData(pushedEvent);
|
|
18825
|
+
if (normalizedData) {
|
|
18826
|
+
this.listener(normalizedData);
|
|
18827
|
+
}
|
|
16908
18828
|
}
|
|
18829
|
+
return result;
|
|
18830
|
+
};
|
|
18831
|
+
}
|
|
18832
|
+
cleanEventData(data) {
|
|
18833
|
+
const eventName = getEventTypeFromRawEvent(data.event);
|
|
18834
|
+
if (!eventName) {
|
|
18835
|
+
return null;
|
|
16909
18836
|
}
|
|
16910
|
-
|
|
16911
|
-
|
|
16912
|
-
|
|
16913
|
-
|
|
16914
|
-
|
|
16915
|
-
|
|
16916
|
-
|
|
16917
|
-
|
|
16918
|
-
|
|
16919
|
-
wrapper.innerHTML = GET_SPOT_TEMPLATE_HTML_STRING(this.data);
|
|
16920
|
-
this.shadowRoot.appendChild(wrapper);
|
|
16921
|
-
}
|
|
18837
|
+
const productIds = extractDeepIds(data.value);
|
|
18838
|
+
return {
|
|
18839
|
+
event: eventName,
|
|
18840
|
+
productIds,
|
|
18841
|
+
};
|
|
18842
|
+
}
|
|
18843
|
+
stop() {
|
|
18844
|
+
if (this.originalPush) {
|
|
18845
|
+
window.dataLayer.push = this.originalPush;
|
|
16922
18846
|
}
|
|
16923
|
-
|
|
16924
|
-
|
|
16925
|
-
|
|
16926
|
-
|
|
16927
|
-
|
|
16928
|
-
|
|
16929
|
-
|
|
16930
|
-
|
|
16931
|
-
|
|
16932
|
-
|
|
18847
|
+
this.listener = undefined;
|
|
18848
|
+
}
|
|
18849
|
+
}
|
|
18850
|
+
|
|
18851
|
+
// @TODO: Add support for user to push events to our own data layer, if they don't use any analytics tool.
|
|
18852
|
+
// window.rmnDataLayer = window.rmnDataLayer || [];
|
|
18853
|
+
class MonitorService {
|
|
18854
|
+
constructor() {
|
|
18855
|
+
const analyticsTool = this.detectAnalyticsTool();
|
|
18856
|
+
switch (analyticsTool) {
|
|
18857
|
+
case AnalyticsTool.GoogleAnalytics:
|
|
18858
|
+
this.implementedMonitor = DataLayerMonitor.getInstance();
|
|
18859
|
+
break;
|
|
18860
|
+
case AnalyticsTool.Other:
|
|
18861
|
+
default:
|
|
18862
|
+
console.warn('This site uses an unsupported analytics tool.');
|
|
18863
|
+
break;
|
|
16933
18864
|
}
|
|
16934
|
-
|
|
16935
|
-
|
|
16936
|
-
root: null,
|
|
16937
|
-
rootMargin: '0px',
|
|
16938
|
-
threshold: 0.5, // The element is considered visible when 50% of it is visible
|
|
16939
|
-
};
|
|
16940
|
-
this.observer = new IntersectionObserver((entries) => {
|
|
16941
|
-
var _a;
|
|
16942
|
-
if (entries[0].isIntersecting) {
|
|
16943
|
-
this.registerEvent(exports.RMN_SPOT_EVENT.IMPRESSION);
|
|
16944
|
-
(_a = this.observer) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
16945
|
-
}
|
|
16946
|
-
}, options);
|
|
16947
|
-
this.observer.observe(this);
|
|
18865
|
+
if (analyticsTool === AnalyticsTool.Other) {
|
|
18866
|
+
return;
|
|
16948
18867
|
}
|
|
16949
|
-
|
|
16950
|
-
|
|
18868
|
+
this.pubSubService = PubsubService.getInstance();
|
|
18869
|
+
this.localStorageService = LocalStorageService.getInstance();
|
|
18870
|
+
}
|
|
18871
|
+
static getInstance() {
|
|
18872
|
+
if (!MonitorService.instance) {
|
|
18873
|
+
MonitorService.instance = new MonitorService();
|
|
16951
18874
|
}
|
|
16952
|
-
|
|
16953
|
-
|
|
16954
|
-
|
|
16955
|
-
|
|
16956
|
-
|
|
16957
|
-
|
|
16958
|
-
|
|
16959
|
-
|
|
16960
|
-
|
|
16961
|
-
|
|
16962
|
-
|
|
16963
|
-
|
|
16964
|
-
|
|
16965
|
-
|
|
18875
|
+
return MonitorService.instance;
|
|
18876
|
+
}
|
|
18877
|
+
start() {
|
|
18878
|
+
if (!this.implementedMonitor)
|
|
18879
|
+
return;
|
|
18880
|
+
this.implementedMonitor.setListener(async (eventData) => {
|
|
18881
|
+
var _a;
|
|
18882
|
+
await this.matchAndFireEvent(eventData, (_a = this.localStorageService) === null || _a === void 0 ? void 0 : _a.getSpots());
|
|
18883
|
+
});
|
|
18884
|
+
this.implementedMonitor.start();
|
|
18885
|
+
}
|
|
18886
|
+
async matchAndFireEvent(eventData, spots) {
|
|
18887
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
18888
|
+
if (!spots)
|
|
18889
|
+
return;
|
|
18890
|
+
const eventProductIds = new Set(eventData.productIds);
|
|
18891
|
+
for (const spot of Object.values(spots)) {
|
|
18892
|
+
if (!spot.productIds.length)
|
|
18893
|
+
continue;
|
|
18894
|
+
const hasCommonProductIds = spot.productIds.find((productId) => eventProductIds.has(productId));
|
|
18895
|
+
if (hasCommonProductIds) {
|
|
18896
|
+
switch (eventData.event) {
|
|
18897
|
+
case exports.RMN_SPOT_EVENT.ADD_TO_CART:
|
|
18898
|
+
await this.fireAndPublishSpotEvent({
|
|
18899
|
+
spotEvent: exports.RMN_SPOT_EVENT.ADD_TO_CART,
|
|
18900
|
+
eventUrl: (_b = (_a = spot.events.find((event) => event.event === exports.RMN_SPOT_EVENT.ADD_TO_CART)) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : '',
|
|
18901
|
+
placementId: spot.placementId,
|
|
18902
|
+
spotId: spot.spotId,
|
|
18903
|
+
});
|
|
18904
|
+
break;
|
|
18905
|
+
case exports.RMN_SPOT_EVENT.REMOVE_FROM_CART:
|
|
18906
|
+
await this.fireAndPublishSpotEvent({
|
|
18907
|
+
spotEvent: exports.RMN_SPOT_EVENT.REMOVE_FROM_CART,
|
|
18908
|
+
eventUrl: (_d = (_c = spot.events.find((event) => event.event === exports.RMN_SPOT_EVENT.REMOVE_FROM_CART)) === null || _c === void 0 ? void 0 : _c.url) !== null && _d !== void 0 ? _d : '',
|
|
18909
|
+
placementId: spot.placementId,
|
|
18910
|
+
spotId: spot.spotId,
|
|
18911
|
+
});
|
|
18912
|
+
break;
|
|
18913
|
+
case exports.RMN_SPOT_EVENT.PURCHASE:
|
|
18914
|
+
await this.fireAndPublishSpotEvent({
|
|
18915
|
+
spotEvent: exports.RMN_SPOT_EVENT.PURCHASE,
|
|
18916
|
+
eventUrl: (_f = (_e = spot.events.find((event) => event.event === exports.RMN_SPOT_EVENT.PURCHASE)) === null || _e === void 0 ? void 0 : _e.url) !== null && _f !== void 0 ? _f : '',
|
|
18917
|
+
placementId: spot.placementId,
|
|
18918
|
+
spotId: spot.spotId,
|
|
18919
|
+
});
|
|
18920
|
+
break;
|
|
18921
|
+
case exports.RMN_SPOT_EVENT.ADD_TO_WISHLIST:
|
|
18922
|
+
await this.fireAndPublishSpotEvent({
|
|
18923
|
+
spotEvent: exports.RMN_SPOT_EVENT.ADD_TO_WISHLIST,
|
|
18924
|
+
eventUrl: (_h = (_g = spot.events.find((event) => event.event === exports.RMN_SPOT_EVENT.ADD_TO_WISHLIST)) === null || _g === void 0 ? void 0 : _g.url) !== null && _h !== void 0 ? _h : '',
|
|
18925
|
+
placementId: spot.placementId,
|
|
18926
|
+
spotId: spot.spotId,
|
|
18927
|
+
});
|
|
18928
|
+
break;
|
|
18929
|
+
case exports.RMN_SPOT_EVENT.BUY_NOW:
|
|
18930
|
+
await this.fireAndPublishSpotEvent({
|
|
18931
|
+
spotEvent: exports.RMN_SPOT_EVENT.BUY_NOW,
|
|
18932
|
+
eventUrl: (_k = (_j = spot.events.find((event) => event.event === exports.RMN_SPOT_EVENT.BUY_NOW)) === null || _j === void 0 ? void 0 : _j.url) !== null && _k !== void 0 ? _k : '',
|
|
18933
|
+
placementId: spot.placementId,
|
|
18934
|
+
spotId: spot.spotId,
|
|
18935
|
+
});
|
|
18936
|
+
break;
|
|
16966
18937
|
}
|
|
16967
18938
|
}
|
|
16968
|
-
catch (error) {
|
|
16969
|
-
console.error(`Rmn error sending ${event} event:`, error);
|
|
16970
|
-
}
|
|
16971
18939
|
}
|
|
16972
|
-
|
|
16973
|
-
|
|
16974
|
-
|
|
16975
|
-
|
|
16976
|
-
|
|
16977
|
-
|
|
16978
|
-
|
|
16979
|
-
|
|
16980
|
-
|
|
16981
|
-
|
|
18940
|
+
}
|
|
18941
|
+
async fireAndPublishSpotEvent({ spotEvent, eventUrl, placementId, spotId, }) {
|
|
18942
|
+
await fireEvent({
|
|
18943
|
+
event: spotEvent,
|
|
18944
|
+
eventUrl,
|
|
18945
|
+
});
|
|
18946
|
+
if (!this.pubSubService)
|
|
18947
|
+
return;
|
|
18948
|
+
this.pubSubService.publish(exports.RMN_EVENT.SPOT_EVENT, {
|
|
18949
|
+
eventType: spotEvent,
|
|
18950
|
+
placementId,
|
|
18951
|
+
spotId,
|
|
18952
|
+
});
|
|
18953
|
+
}
|
|
18954
|
+
detectAnalyticsTool() {
|
|
18955
|
+
let analyticsTool = AnalyticsTool.Other;
|
|
18956
|
+
// Check for Google Analytics
|
|
18957
|
+
if (typeof window.ga !== 'undefined') {
|
|
18958
|
+
analyticsTool = AnalyticsTool.GoogleAnalytics;
|
|
18959
|
+
}
|
|
18960
|
+
// Check for Google Analytics 4
|
|
18961
|
+
if (typeof window.gtag !== 'undefined') {
|
|
18962
|
+
analyticsTool = AnalyticsTool.GoogleAnalytics;
|
|
18963
|
+
}
|
|
18964
|
+
// Check for Google Tag Manager
|
|
18965
|
+
if (typeof window.google_tag_manager !== 'undefined') {
|
|
18966
|
+
analyticsTool = AnalyticsTool.GoogleAnalytics;
|
|
16982
18967
|
}
|
|
18968
|
+
// @TODO: Add support for other analytics tools
|
|
18969
|
+
// Check for Heap Analytics
|
|
18970
|
+
// Check for Mixpanel
|
|
18971
|
+
// Check for Woopra
|
|
18972
|
+
// Check for Segment
|
|
18973
|
+
// Check for Amplitude
|
|
18974
|
+
return analyticsTool;
|
|
16983
18975
|
}
|
|
16984
|
-
CustomSpotElement.observedAttributes = Object.values(ENUM_SPOT_ELEMENT_ATTRIBUTE);
|
|
16985
|
-
SpotElement = CustomSpotElement;
|
|
16986
18976
|
}
|
|
16987
18977
|
|
|
16988
|
-
class
|
|
18978
|
+
class EventService {
|
|
18979
|
+
constructor() {
|
|
18980
|
+
this.pubSubService = PubsubService.getInstance();
|
|
18981
|
+
this.localStorageService = LocalStorageService.getInstance();
|
|
18982
|
+
this.activeSpots = new Map();
|
|
18983
|
+
this.spotStates = new Map();
|
|
18984
|
+
this.intersectionObserver = new IntersectionObserverService();
|
|
18985
|
+
// Start the user monitor, which will track and check user interactions
|
|
18986
|
+
MonitorService.getInstance().start();
|
|
18987
|
+
}
|
|
16989
18988
|
static getInstance() {
|
|
16990
|
-
|
|
18989
|
+
if (!EventService.instance) {
|
|
18990
|
+
EventService.instance = new EventService();
|
|
18991
|
+
}
|
|
18992
|
+
return EventService.instance;
|
|
18993
|
+
}
|
|
18994
|
+
subscribe(eventType, callback) {
|
|
18995
|
+
return this.pubSubService.subscribe(eventType, callback);
|
|
18996
|
+
}
|
|
18997
|
+
publish(eventType, data) {
|
|
18998
|
+
this.pubSubService.publish(eventType, data);
|
|
18999
|
+
}
|
|
19000
|
+
registerSpot(params) {
|
|
19001
|
+
const { placementId, spot, spotElement } = params;
|
|
19002
|
+
this.activeSpots.set(placementId, { spotElement });
|
|
19003
|
+
// Fire impression event
|
|
19004
|
+
this.fireImpressionEvent(placementId, spot);
|
|
19005
|
+
// Handle intersection observer
|
|
19006
|
+
this.handleIntersectionObserver(placementId, spot, spotElement);
|
|
19007
|
+
// Attach click event listener
|
|
19008
|
+
spotElement.addEventListener('click', async () => await this.handleClick(params));
|
|
19009
|
+
}
|
|
19010
|
+
unregisterSpot(placementId) {
|
|
19011
|
+
const placementIdClean = placementId.replace('#', '');
|
|
19012
|
+
const spotData = this.activeSpots.get(placementIdClean);
|
|
19013
|
+
if (!spotData) {
|
|
19014
|
+
this.handleSpotState(placementIdClean, {
|
|
19015
|
+
state: {
|
|
19016
|
+
error: `Active spot with placementId ${placementIdClean} not found.`,
|
|
19017
|
+
},
|
|
19018
|
+
});
|
|
19019
|
+
return;
|
|
19020
|
+
}
|
|
19021
|
+
this.intersectionObserver.unobserve(spotData.spotElement);
|
|
19022
|
+
this.handleSpotState(placementIdClean, {
|
|
19023
|
+
dom: {
|
|
19024
|
+
spotElement: undefined,
|
|
19025
|
+
visibleOnViewport: false,
|
|
19026
|
+
},
|
|
19027
|
+
state: {
|
|
19028
|
+
unmounted: true,
|
|
19029
|
+
mounted: false,
|
|
19030
|
+
},
|
|
19031
|
+
});
|
|
19032
|
+
this.activeSpots.delete(placementIdClean);
|
|
19033
|
+
const placementElement = document.getElementById(placementIdClean);
|
|
19034
|
+
if (!placementElement) {
|
|
19035
|
+
this.handleSpotState(placementIdClean, {
|
|
19036
|
+
state: {
|
|
19037
|
+
error: `Placement element with id ${placementIdClean} not found.`,
|
|
19038
|
+
},
|
|
19039
|
+
});
|
|
19040
|
+
return;
|
|
19041
|
+
}
|
|
19042
|
+
placementElement.innerHTML = '';
|
|
16991
19043
|
}
|
|
16992
19044
|
/**
|
|
16993
|
-
*
|
|
16994
|
-
*
|
|
16995
|
-
* This method is only available in browser environments.
|
|
19045
|
+
* Updates the state of a spot.
|
|
16996
19046
|
*
|
|
16997
|
-
* @param {
|
|
16998
|
-
* @param {
|
|
16999
|
-
* @param {
|
|
17000
|
-
* @param {ICreateSpotElementConfig.customContent} config.customContent - Use a custom html element/string.
|
|
17001
|
-
* @param {ICreateSpotElementConfig.redirectOnClick} config.redirectOnClick - If the spot should redirect on click.
|
|
19047
|
+
* @param {string} placementId - The placement ID of the spot.
|
|
19048
|
+
* @param {Partial<ILifecycleState>} updates - The updates to apply to the spot state.
|
|
19049
|
+
* @param {boolean} publish - Whether to publish the updated state.
|
|
17002
19050
|
*
|
|
17003
|
-
* @
|
|
17004
|
-
*/
|
|
17005
|
-
createSpotHtmlElement(spot, config) {
|
|
17006
|
-
var _a, _b;
|
|
17007
|
-
if (!this.ensureBrowserEnvironmentAndDefineElement()) {
|
|
17008
|
-
return null;
|
|
17009
|
-
}
|
|
17010
|
-
const isFluid = (_a = config === null || config === void 0 ? void 0 : config.fluid) !== null && _a !== void 0 ? _a : false;
|
|
17011
|
-
const shouldRedirectOnClick = (_b = config === null || config === void 0 ? void 0 : config.redirectOnClick) !== null && _b !== void 0 ? _b : true;
|
|
17012
|
-
const element = document.createElement(SPOT_ELEMENT_TAG);
|
|
17013
|
-
element.setAttribute(ENUM_SPOT_ELEMENT_ATTRIBUTE.WIDTH, spot.width.toString());
|
|
17014
|
-
element.setAttribute(ENUM_SPOT_ELEMENT_ATTRIBUTE.HEIGHT, spot.height.toString());
|
|
17015
|
-
element.setAttribute(ENUM_SPOT_ELEMENT_ATTRIBUTE.FLUID, isFluid.toString());
|
|
17016
|
-
element.setAttribute(ENUM_SPOT_ELEMENT_ATTRIBUTE.REDIRECT_ON_CLICK, shouldRedirectOnClick.toString());
|
|
17017
|
-
// Share the spot data with the element
|
|
17018
|
-
element.data = spot;
|
|
17019
|
-
// Set custom content
|
|
17020
|
-
if (config === null || config === void 0 ? void 0 : config.customContent) {
|
|
17021
|
-
element.customContent = config.customContent;
|
|
17022
|
-
}
|
|
17023
|
-
return element;
|
|
17024
|
-
}
|
|
17025
|
-
/**
|
|
17026
|
-
* @returns {boolean} - True if the browser environment is available and the element is defined.
|
|
19051
|
+
* @returns {void}
|
|
17027
19052
|
*/
|
|
17028
|
-
|
|
17029
|
-
|
|
17030
|
-
|
|
17031
|
-
|
|
19053
|
+
handleSpotState(placementId, updates, publish = true) {
|
|
19054
|
+
let currentState = this.spotStates.get(placementId);
|
|
19055
|
+
if (!currentState) {
|
|
19056
|
+
currentState = {
|
|
19057
|
+
identifier: {
|
|
19058
|
+
placementId,
|
|
19059
|
+
spotId: '',
|
|
19060
|
+
spotType: '',
|
|
19061
|
+
},
|
|
19062
|
+
dom: {
|
|
19063
|
+
spotElement: undefined,
|
|
19064
|
+
visibleOnViewport: false,
|
|
19065
|
+
},
|
|
19066
|
+
state: {
|
|
19067
|
+
mounted: false,
|
|
19068
|
+
unmounted: false,
|
|
19069
|
+
loading: false,
|
|
19070
|
+
error: undefined,
|
|
19071
|
+
},
|
|
19072
|
+
displayConfig: {
|
|
19073
|
+
isCarousel: false,
|
|
19074
|
+
isCarouselItem: false,
|
|
19075
|
+
isSingleItem: false,
|
|
19076
|
+
},
|
|
19077
|
+
};
|
|
17032
19078
|
}
|
|
17033
|
-
|
|
17034
|
-
|
|
19079
|
+
const merged = this.deepMerge(currentState, updates);
|
|
19080
|
+
this.spotStates.set(placementId, merged);
|
|
19081
|
+
if (publish) {
|
|
19082
|
+
this.pubSubService.publish(exports.RMN_EVENT.LIFECYCLE_STATE, this.spotStates.get(placementId));
|
|
17035
19083
|
}
|
|
17036
|
-
|
|
19084
|
+
}
|
|
19085
|
+
deepMerge(current, updates) {
|
|
19086
|
+
return {
|
|
19087
|
+
identifier: updates.identifier
|
|
19088
|
+
? { ...current.identifier, ...updates.identifier }
|
|
19089
|
+
: current.identifier,
|
|
19090
|
+
dom: updates.dom ? { ...current.dom, ...updates.dom } : current.dom,
|
|
19091
|
+
state: updates.state ? { ...current.state, ...updates.state } : current.state,
|
|
19092
|
+
displayConfig: updates.displayConfig
|
|
19093
|
+
? { ...current.displayConfig, ...updates.displayConfig }
|
|
19094
|
+
: current.displayConfig,
|
|
19095
|
+
};
|
|
19096
|
+
}
|
|
19097
|
+
async handleClick({ placementId, spot }) {
|
|
19098
|
+
var _a, _b, _c;
|
|
19099
|
+
this.pubSubService.publish(exports.RMN_EVENT.SPOT_EVENT, {
|
|
19100
|
+
eventType: exports.RMN_SPOT_EVENT.CLICK,
|
|
19101
|
+
placementId,
|
|
19102
|
+
spotId: spot.id,
|
|
19103
|
+
});
|
|
19104
|
+
await fireEvent({
|
|
19105
|
+
event: exports.RMN_SPOT_EVENT.CLICK,
|
|
19106
|
+
eventUrl: (_b = (_a = spot.events.find((event) => event.event === exports.RMN_SPOT_EVENT.CLICK)) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : '',
|
|
19107
|
+
});
|
|
19108
|
+
// Save spot to local storage for event tracking
|
|
19109
|
+
this.localStorageService.setSpot(spot.id, {
|
|
19110
|
+
placementId,
|
|
19111
|
+
spotId: spot.id,
|
|
19112
|
+
spotType: spot.spot,
|
|
19113
|
+
events: spot.events,
|
|
19114
|
+
productIds: (_c = spot.productIds) !== null && _c !== void 0 ? _c : [],
|
|
19115
|
+
});
|
|
19116
|
+
}
|
|
19117
|
+
handleIntersectionObserver(placementId, _spot, spotElement) {
|
|
19118
|
+
const spotIsVisibleCallback = async () => {
|
|
19119
|
+
this.intersectionObserver.unobserve(spotElement);
|
|
19120
|
+
this.handleSpotState(placementId, {
|
|
19121
|
+
dom: {
|
|
19122
|
+
spotElement,
|
|
19123
|
+
visibleOnViewport: true,
|
|
19124
|
+
},
|
|
19125
|
+
});
|
|
19126
|
+
};
|
|
19127
|
+
this.intersectionObserver.observe(spotElement, spotIsVisibleCallback);
|
|
19128
|
+
}
|
|
19129
|
+
fireImpressionEvent(placementId, spot) {
|
|
19130
|
+
this.pubSubService.publish(exports.RMN_EVENT.SPOT_EVENT, {
|
|
19131
|
+
eventType: exports.RMN_SPOT_EVENT.IMPRESSION,
|
|
19132
|
+
placementId,
|
|
19133
|
+
spotId: spot.id,
|
|
19134
|
+
});
|
|
19135
|
+
(async () => {
|
|
19136
|
+
var _a, _b;
|
|
19137
|
+
await fireEvent({
|
|
19138
|
+
event: exports.RMN_SPOT_EVENT.IMPRESSION,
|
|
19139
|
+
eventUrl: (_b = (_a = spot.events.find((event) => event.event === exports.RMN_SPOT_EVENT.IMPRESSION)) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : '',
|
|
19140
|
+
});
|
|
19141
|
+
})();
|
|
17037
19142
|
}
|
|
17038
19143
|
}
|
|
17039
19144
|
|
|
17040
|
-
|
|
19145
|
+
const SELECTION_API_PATH = '/spots/selection';
|
|
19146
|
+
|
|
19147
|
+
class SelectionService extends BaseApi {
|
|
17041
19148
|
constructor(auth) {
|
|
17042
19149
|
super(auth);
|
|
17043
19150
|
}
|
|
17044
19151
|
static getInstance(auth) {
|
|
17045
|
-
return SingletonManager.getInstance('
|
|
19152
|
+
return SingletonManager.getInstance('SelectionService', () => new SelectionService(auth));
|
|
17046
19153
|
}
|
|
17047
19154
|
/**
|
|
17048
19155
|
* Makes a selection request on our server based on the provided data.
|
|
17049
19156
|
*
|
|
17050
19157
|
* @param {ISpotSelectionParams} data - Spots selection parameters.
|
|
17051
19158
|
*
|
|
17052
|
-
* @return {Promise<ISpots>} - The spots response object.
|
|
19159
|
+
* @return {Promise<ISpots | { error: string }>} - The spots response object.
|
|
17053
19160
|
*/
|
|
17054
19161
|
async spotSelection(data) {
|
|
17055
|
-
const { isOk, val, isErr } = await this.post(
|
|
19162
|
+
const { isOk, val, isErr } = await this.post(SELECTION_API_PATH, data, {});
|
|
17056
19163
|
if (isErr) {
|
|
17057
|
-
|
|
19164
|
+
return { error: `There was an error during spot selection: (${isErr === null || isErr === void 0 ? void 0 : isErr.errorMessage})` };
|
|
17058
19165
|
}
|
|
17059
19166
|
if (isOk && val && val.data && (val === null || val === void 0 ? void 0 : val.refresh.token)) {
|
|
17060
19167
|
this.authInfo.authenticated = true;
|
|
17061
19168
|
this.authInfo.token = val.refresh.token;
|
|
17062
19169
|
return val.data.spots;
|
|
17063
19170
|
}
|
|
17064
|
-
|
|
19171
|
+
return { error: 'Spot selection response was not successful' };
|
|
17065
19172
|
}
|
|
17066
19173
|
}
|
|
17067
19174
|
|
|
17068
19175
|
class LiquidCommerceRmnClient {
|
|
17069
19176
|
constructor(auth) {
|
|
17070
|
-
this.
|
|
17071
|
-
this.
|
|
19177
|
+
this.selectionService = SelectionService.getInstance(auth);
|
|
19178
|
+
this.elementService = ElementService.getInstance();
|
|
19179
|
+
this.eventService = EventService.getInstance();
|
|
17072
19180
|
}
|
|
17073
19181
|
/**
|
|
17074
19182
|
* Makes a selection request on our server based on the provided data.
|
|
17075
19183
|
*
|
|
17076
19184
|
* To create a spot html element, use the RmnCreateSpotElement function.
|
|
17077
19185
|
*
|
|
17078
|
-
* @param {ISpotSelectionParams}
|
|
19186
|
+
* @param {ISpotSelectionParams} params - Spots selection parameters.
|
|
17079
19187
|
*
|
|
17080
|
-
* @return {Promise<ISpots>} - The spots response object.
|
|
19188
|
+
* @return {Promise<ISpots | { error : string }>} - The spots response object.
|
|
17081
19189
|
*/
|
|
17082
|
-
async spotSelection(
|
|
17083
|
-
return this.
|
|
19190
|
+
async spotSelection(params) {
|
|
19191
|
+
return this.selectionService.spotSelection(params);
|
|
19192
|
+
}
|
|
19193
|
+
/**
|
|
19194
|
+
* Injects the spot elements into their provided placement.
|
|
19195
|
+
*
|
|
19196
|
+
* @param {IInjectSpotElementParams} params - Parameters for injecting spot elements.
|
|
19197
|
+
*
|
|
19198
|
+
* @return {Promise<void>} - A promise that resolves when the spot elements are injected.
|
|
19199
|
+
*/
|
|
19200
|
+
async injectSpotElement(params) {
|
|
19201
|
+
var _a;
|
|
19202
|
+
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
19203
|
+
console.warn('LiquidCommerce Rmn Sdk: Methods which create elements are only available in browser environments.');
|
|
19204
|
+
return;
|
|
19205
|
+
}
|
|
19206
|
+
const config = params.config;
|
|
19207
|
+
let inject = params.inject;
|
|
19208
|
+
if (!inject.length) {
|
|
19209
|
+
// Handle no spots error state
|
|
19210
|
+
this.eventService.handleSpotState('all', {
|
|
19211
|
+
state: {
|
|
19212
|
+
error: 'No spot elements provided for injection.',
|
|
19213
|
+
loading: false,
|
|
19214
|
+
mounted: false,
|
|
19215
|
+
},
|
|
19216
|
+
});
|
|
19217
|
+
return;
|
|
19218
|
+
}
|
|
19219
|
+
// Update the state of the spots to loading
|
|
19220
|
+
this.updateSpotsState(inject);
|
|
19221
|
+
// Prevent duplicate placement ids
|
|
19222
|
+
const hasDuplicatePlacementIds = this.preventDuplicateSpotPlacementIds(inject);
|
|
19223
|
+
if (!hasDuplicatePlacementIds) {
|
|
19224
|
+
return;
|
|
19225
|
+
}
|
|
19226
|
+
// Prevent non-existent spot types
|
|
19227
|
+
inject = this.preventNonExistentSpotTypes(inject);
|
|
19228
|
+
// Make the spot selection request
|
|
19229
|
+
const response = await this.spotSelectionRequest({ ...params, inject });
|
|
19230
|
+
// const response = await this.useSpotSelectionExample(inject);
|
|
19231
|
+
// Handle the response
|
|
19232
|
+
if (typeof response === 'object' && 'error' in response) {
|
|
19233
|
+
// Handle request error state
|
|
19234
|
+
this.eventService.handleSpotState('all', {
|
|
19235
|
+
state: {
|
|
19236
|
+
error: response.error,
|
|
19237
|
+
mounted: false,
|
|
19238
|
+
loading: false,
|
|
19239
|
+
},
|
|
19240
|
+
});
|
|
19241
|
+
return;
|
|
19242
|
+
}
|
|
19243
|
+
for (const item of inject) {
|
|
19244
|
+
const itemConfig = (_a = item.config) !== null && _a !== void 0 ? _a : config;
|
|
19245
|
+
const spots = response[item.placementId];
|
|
19246
|
+
if (!(spots === null || spots === void 0 ? void 0 : spots.length)) {
|
|
19247
|
+
// Handle no spots found error state
|
|
19248
|
+
this.eventService.handleSpotState(item.placementId, {
|
|
19249
|
+
state: {
|
|
19250
|
+
error: `No spots found for type "${item.spotType}".`,
|
|
19251
|
+
mounted: false,
|
|
19252
|
+
loading: false,
|
|
19253
|
+
},
|
|
19254
|
+
});
|
|
19255
|
+
continue;
|
|
19256
|
+
}
|
|
19257
|
+
const placementId = item.placementId.replace('#', '');
|
|
19258
|
+
const placement = document.getElementById(placementId);
|
|
19259
|
+
if (!placement) {
|
|
19260
|
+
// Handle placement not found error state
|
|
19261
|
+
this.eventService.handleSpotState(item.placementId, {
|
|
19262
|
+
state: {
|
|
19263
|
+
error: `Placement not found for id "${placementId}".`,
|
|
19264
|
+
mounted: false,
|
|
19265
|
+
loading: false,
|
|
19266
|
+
},
|
|
19267
|
+
});
|
|
19268
|
+
continue;
|
|
19269
|
+
}
|
|
19270
|
+
// Take over placement styles
|
|
19271
|
+
placement.removeAttribute('style');
|
|
19272
|
+
placement.removeAttribute('class');
|
|
19273
|
+
Object.assign(placement.style, {
|
|
19274
|
+
width: '100%',
|
|
19275
|
+
height: '100%',
|
|
19276
|
+
display: 'flex',
|
|
19277
|
+
justifyContent: 'center',
|
|
19278
|
+
});
|
|
19279
|
+
// Handle single spot
|
|
19280
|
+
if (spots.length === 1) {
|
|
19281
|
+
const isInjected = this.injectOneSpotElement(item, placement, spots[0], itemConfig);
|
|
19282
|
+
if (!isInjected) {
|
|
19283
|
+
continue;
|
|
19284
|
+
}
|
|
19285
|
+
}
|
|
19286
|
+
// Handle multiple spots (carousel)
|
|
19287
|
+
if (spots.length > 1) {
|
|
19288
|
+
const isInjected = this.injectCarouselSpotElement(placement, spots, itemConfig);
|
|
19289
|
+
if (!isInjected) {
|
|
19290
|
+
continue;
|
|
19291
|
+
}
|
|
19292
|
+
}
|
|
19293
|
+
}
|
|
17084
19294
|
}
|
|
17085
19295
|
/**
|
|
17086
|
-
*
|
|
19296
|
+
* Makes a selection request on our server based on the provided data.
|
|
19297
|
+
*
|
|
19298
|
+
* @param {IInjectSpotElementParams} params - Parameters for injecting spot elements.
|
|
19299
|
+
*
|
|
19300
|
+
* @return {Promise<ISpots | {error: string}>} - The spots response object.
|
|
19301
|
+
*/
|
|
19302
|
+
async spotSelectionRequest(params) {
|
|
19303
|
+
const { inject, filter, config } = params;
|
|
19304
|
+
const request = {
|
|
19305
|
+
url: config === null || config === void 0 ? void 0 : config.url,
|
|
19306
|
+
filter,
|
|
19307
|
+
spots: inject.map((item) => ({
|
|
19308
|
+
placementId: item.placementId,
|
|
19309
|
+
spot: item.spotType,
|
|
19310
|
+
count: item === null || item === void 0 ? void 0 : item.count,
|
|
19311
|
+
...item === null || item === void 0 ? void 0 : item.filter,
|
|
19312
|
+
})),
|
|
19313
|
+
};
|
|
19314
|
+
return this.spotSelection(request);
|
|
19315
|
+
}
|
|
19316
|
+
/**
|
|
19317
|
+
* Injects a carousel element with the provided spots into the placement.
|
|
19318
|
+
*
|
|
19319
|
+
* @param {HTMLElement} placement - The placement element.
|
|
19320
|
+
* @param {ISpot[]} spots - The spot data.
|
|
19321
|
+
* @param {IInjectSpotElementConfig} config - The configuration object.
|
|
17087
19322
|
*
|
|
17088
|
-
*
|
|
19323
|
+
* @return {void}
|
|
19324
|
+
*/
|
|
19325
|
+
injectCarouselSpotElement(placement, spots, config) {
|
|
19326
|
+
var _a;
|
|
19327
|
+
const carouselSlides = [];
|
|
19328
|
+
for (const spotItem of spots) {
|
|
19329
|
+
this.eventService.handleSpotState(placement.id, {
|
|
19330
|
+
identifier: {
|
|
19331
|
+
placementId: placement.id,
|
|
19332
|
+
spotType: spotItem.spot,
|
|
19333
|
+
spotId: spotItem.id,
|
|
19334
|
+
},
|
|
19335
|
+
displayConfig: {
|
|
19336
|
+
isSingleItem: false,
|
|
19337
|
+
isCarousel: true,
|
|
19338
|
+
isCarouselItem: true,
|
|
19339
|
+
},
|
|
19340
|
+
});
|
|
19341
|
+
const spot = this.elementService.overrideSpotColors(spotItem, config === null || config === void 0 ? void 0 : config.colors);
|
|
19342
|
+
const content = SPOT_TEMPLATE_HTML_ELEMENT(spot, { overlay: config === null || config === void 0 ? void 0 : config.overlay });
|
|
19343
|
+
if (!content) {
|
|
19344
|
+
this.eventService.handleSpotState(placement.id, {
|
|
19345
|
+
state: {
|
|
19346
|
+
error: `Failed to inject carousel spot item element. Could not create element for type "${spot.spot}".`,
|
|
19347
|
+
mounted: false,
|
|
19348
|
+
loading: false,
|
|
19349
|
+
},
|
|
19350
|
+
});
|
|
19351
|
+
continue;
|
|
19352
|
+
}
|
|
19353
|
+
this.eventService.registerSpot({
|
|
19354
|
+
spot,
|
|
19355
|
+
placementId: placement.id,
|
|
19356
|
+
spotElement: content,
|
|
19357
|
+
});
|
|
19358
|
+
carouselSlides.push(content);
|
|
19359
|
+
}
|
|
19360
|
+
// Get the max width and height of the spots
|
|
19361
|
+
const { maxWidth, maxHeight } = spots.reduce((max, spot) => ({
|
|
19362
|
+
maxWidth: Math.max(max.maxWidth, spot.width),
|
|
19363
|
+
maxHeight: Math.max(max.maxHeight, spot.height),
|
|
19364
|
+
}), { maxWidth: 0, maxHeight: 0 });
|
|
19365
|
+
// Create the carousel element
|
|
19366
|
+
const carouselElement = this.elementService.createCarouselElement({
|
|
19367
|
+
slides: carouselSlides,
|
|
19368
|
+
config: {
|
|
19369
|
+
fluid: config === null || config === void 0 ? void 0 : config.fluid,
|
|
19370
|
+
width: maxWidth,
|
|
19371
|
+
height: maxHeight,
|
|
19372
|
+
minScale: (_a = config === null || config === void 0 ? void 0 : config.minScale) !== null && _a !== void 0 ? _a : 0.25, // Scale down to 25% of the original size
|
|
19373
|
+
...config === null || config === void 0 ? void 0 : config.carousel,
|
|
19374
|
+
},
|
|
19375
|
+
});
|
|
19376
|
+
if (!carouselElement) {
|
|
19377
|
+
this.eventService.handleSpotState(placement.id, {
|
|
19378
|
+
state: {
|
|
19379
|
+
error: `Failed to inject spot carousel element. Could not create spot carousel element.`,
|
|
19380
|
+
mounted: false,
|
|
19381
|
+
loading: false,
|
|
19382
|
+
},
|
|
19383
|
+
});
|
|
19384
|
+
return false;
|
|
19385
|
+
}
|
|
19386
|
+
placement.replaceChildren(carouselElement);
|
|
19387
|
+
this.eventService.handleSpotState(placement.id, {
|
|
19388
|
+
dom: {
|
|
19389
|
+
spotElement: carouselElement,
|
|
19390
|
+
visibleOnViewport: false,
|
|
19391
|
+
},
|
|
19392
|
+
state: {
|
|
19393
|
+
mounted: true,
|
|
19394
|
+
loading: false,
|
|
19395
|
+
error: undefined,
|
|
19396
|
+
},
|
|
19397
|
+
});
|
|
19398
|
+
return true;
|
|
19399
|
+
}
|
|
19400
|
+
/**
|
|
19401
|
+
* Injects a single spot element into the provided placement.
|
|
17089
19402
|
*
|
|
19403
|
+
* @param {IInjectSpotElement} injectItem - The inject item data.
|
|
19404
|
+
* @param {HTMLElement} placement - The placement element.
|
|
17090
19405
|
* @param {ISpot} spot - The spot data.
|
|
17091
|
-
* @param {
|
|
17092
|
-
*
|
|
17093
|
-
* @
|
|
17094
|
-
|
|
19406
|
+
* @param {IInjectSpotElementConfig} config - The configuration object.
|
|
19407
|
+
*
|
|
19408
|
+
* @return {void}
|
|
19409
|
+
*/
|
|
19410
|
+
injectOneSpotElement(injectItem, placement, spot, config) {
|
|
19411
|
+
var _a;
|
|
19412
|
+
this.eventService.handleSpotState(injectItem.placementId, {
|
|
19413
|
+
identifier: {
|
|
19414
|
+
placementId: injectItem.placementId,
|
|
19415
|
+
spotType: injectItem.spotType,
|
|
19416
|
+
spotId: spot.id,
|
|
19417
|
+
},
|
|
19418
|
+
displayConfig: {
|
|
19419
|
+
isSingleItem: true,
|
|
19420
|
+
isCarousel: false,
|
|
19421
|
+
isCarouselItem: false,
|
|
19422
|
+
},
|
|
19423
|
+
});
|
|
19424
|
+
const spotData = this.elementService.overrideSpotColors(spot, config === null || config === void 0 ? void 0 : config.colors);
|
|
19425
|
+
const content = SPOT_TEMPLATE_HTML_ELEMENT(spotData, { overlay: config === null || config === void 0 ? void 0 : config.overlay });
|
|
19426
|
+
if (!content) {
|
|
19427
|
+
this.eventService.handleSpotState(injectItem.placementId, {
|
|
19428
|
+
state: {
|
|
19429
|
+
error: `Failed to inject spot element. Could not create element for type "${injectItem.spotType}".`,
|
|
19430
|
+
mounted: false,
|
|
19431
|
+
loading: false,
|
|
19432
|
+
},
|
|
19433
|
+
});
|
|
19434
|
+
return false;
|
|
19435
|
+
}
|
|
19436
|
+
// Create the spot element
|
|
19437
|
+
const spotElement = this.elementService.createSpotElement({
|
|
19438
|
+
content,
|
|
19439
|
+
config: {
|
|
19440
|
+
fluid: config === null || config === void 0 ? void 0 : config.fluid,
|
|
19441
|
+
spot: spot.spot,
|
|
19442
|
+
width: spot.width,
|
|
19443
|
+
height: spot.height,
|
|
19444
|
+
minScale: (_a = config === null || config === void 0 ? void 0 : config.minScale) !== null && _a !== void 0 ? _a : 0.25, // Scale down to 25% of the original size
|
|
19445
|
+
},
|
|
19446
|
+
});
|
|
19447
|
+
if (!spotElement) {
|
|
19448
|
+
this.eventService.handleSpotState(injectItem.placementId, {
|
|
19449
|
+
state: {
|
|
19450
|
+
error: `Failed to inject spot element. Could not create element for type "${injectItem.spotType}".`,
|
|
19451
|
+
mounted: false,
|
|
19452
|
+
loading: false,
|
|
19453
|
+
},
|
|
19454
|
+
});
|
|
19455
|
+
return false;
|
|
19456
|
+
}
|
|
19457
|
+
this.eventService.registerSpot({
|
|
19458
|
+
spot: spotData,
|
|
19459
|
+
placementId: injectItem.placementId,
|
|
19460
|
+
spotElement,
|
|
19461
|
+
});
|
|
19462
|
+
placement.replaceChildren(spotElement);
|
|
19463
|
+
this.eventService.handleSpotState(injectItem.placementId, {
|
|
19464
|
+
dom: {
|
|
19465
|
+
spotElement,
|
|
19466
|
+
visibleOnViewport: false,
|
|
19467
|
+
},
|
|
19468
|
+
state: {
|
|
19469
|
+
mounted: true,
|
|
19470
|
+
loading: false,
|
|
19471
|
+
error: undefined,
|
|
19472
|
+
},
|
|
19473
|
+
});
|
|
19474
|
+
return true;
|
|
19475
|
+
}
|
|
19476
|
+
/**
|
|
19477
|
+
* Prevents duplicate placement ids in the inject data.
|
|
19478
|
+
*
|
|
19479
|
+
* @param {IInjectSpotElement[]} inject - The inject data.
|
|
17095
19480
|
*
|
|
17096
|
-
* @
|
|
19481
|
+
* @throws {Error} - If a duplicate placement id is found.
|
|
19482
|
+
*
|
|
19483
|
+
* @return {void}
|
|
17097
19484
|
*/
|
|
17098
|
-
|
|
17099
|
-
|
|
19485
|
+
preventDuplicateSpotPlacementIds(inject) {
|
|
19486
|
+
const placementIds = new Set();
|
|
19487
|
+
for (const item of inject) {
|
|
19488
|
+
if (placementIds.has(item.placementId)) {
|
|
19489
|
+
this.eventService.handleSpotState(item.placementId, {
|
|
19490
|
+
state: {
|
|
19491
|
+
error: `Duplicate placement id (${item.placementId}) found. Please provide a unique placement id for each spot element.`,
|
|
19492
|
+
mounted: false,
|
|
19493
|
+
loading: false,
|
|
19494
|
+
},
|
|
19495
|
+
});
|
|
19496
|
+
return false;
|
|
19497
|
+
}
|
|
19498
|
+
placementIds.add(item.placementId);
|
|
19499
|
+
}
|
|
19500
|
+
return true;
|
|
19501
|
+
}
|
|
19502
|
+
preventNonExistentSpotTypes(inject) {
|
|
19503
|
+
const newInject = [];
|
|
19504
|
+
for (const item of inject) {
|
|
19505
|
+
if (!Object.values(exports.RMN_SPOT_TYPE).includes(item.spotType)) {
|
|
19506
|
+
this.eventService.handleSpotState(item.placementId, {
|
|
19507
|
+
state: {
|
|
19508
|
+
error: `Invalid spot type (${item.spotType}) found. Please provide a valid spot type for each spot element.`,
|
|
19509
|
+
mounted: false,
|
|
19510
|
+
loading: false,
|
|
19511
|
+
},
|
|
19512
|
+
});
|
|
19513
|
+
continue;
|
|
19514
|
+
}
|
|
19515
|
+
newInject.push(item);
|
|
19516
|
+
}
|
|
19517
|
+
return newInject;
|
|
19518
|
+
}
|
|
19519
|
+
// Initialize spots with loading state and identifiers
|
|
19520
|
+
updateSpotsState(inject) {
|
|
19521
|
+
for (const item of inject) {
|
|
19522
|
+
this.eventService.handleSpotState(item.placementId, {
|
|
19523
|
+
identifier: {
|
|
19524
|
+
placementId: item.placementId,
|
|
19525
|
+
spotType: item.spotType,
|
|
19526
|
+
},
|
|
19527
|
+
state: {
|
|
19528
|
+
loading: true,
|
|
19529
|
+
mounted: false,
|
|
19530
|
+
error: undefined,
|
|
19531
|
+
},
|
|
19532
|
+
});
|
|
19533
|
+
}
|
|
19534
|
+
}
|
|
19535
|
+
useSpotSelectionExample(inject) {
|
|
19536
|
+
const examples = RB_SPOTS_SELECTION_EXAMPLE;
|
|
19537
|
+
const data = {};
|
|
19538
|
+
inject.map((item) => {
|
|
19539
|
+
var _a, _b, _c;
|
|
19540
|
+
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 : [];
|
|
19541
|
+
});
|
|
19542
|
+
return new Promise((resolve) => {
|
|
19543
|
+
resolve(data);
|
|
19544
|
+
});
|
|
17100
19545
|
}
|
|
17101
19546
|
}
|
|
17102
19547
|
/**
|
|
@@ -17112,26 +19557,69 @@ async function RmnClient(apiKey, config) {
|
|
|
17112
19557
|
const credentials = await authService.initialize();
|
|
17113
19558
|
return new LiquidCommerceRmnClient(credentials);
|
|
17114
19559
|
}
|
|
19560
|
+
/**
|
|
19561
|
+
* Creates a new instance of the RmnEventManager.
|
|
19562
|
+
*
|
|
19563
|
+
* @return {IRmnEventManager} - The RmnEventManager instance.
|
|
19564
|
+
*/
|
|
19565
|
+
function RmnEventManager() {
|
|
19566
|
+
const eventService = EventService.getInstance();
|
|
19567
|
+
return {
|
|
19568
|
+
/**
|
|
19569
|
+
* Subscribes to an event type.
|
|
19570
|
+
*/
|
|
19571
|
+
subscribe: (eventType, callback
|
|
19572
|
+
/* eslint-disable arrow-body-style */
|
|
19573
|
+
) => {
|
|
19574
|
+
return eventService.subscribe(eventType, callback);
|
|
19575
|
+
},
|
|
19576
|
+
/**
|
|
19577
|
+
* Publishes an event type.
|
|
19578
|
+
*/
|
|
19579
|
+
publish: (eventType, data) => {
|
|
19580
|
+
eventService.publish(eventType, data);
|
|
19581
|
+
},
|
|
19582
|
+
/**
|
|
19583
|
+
* Destroys a spot element
|
|
19584
|
+
*/
|
|
19585
|
+
destroySpot: (placementId) => {
|
|
19586
|
+
eventService.unregisterSpot(placementId);
|
|
19587
|
+
},
|
|
19588
|
+
};
|
|
19589
|
+
}
|
|
17115
19590
|
/**
|
|
17116
19591
|
* Creates the spot html element based on the provided data using shadow dom.
|
|
17117
19592
|
*
|
|
17118
19593
|
* This method is useful when you are initializing the client in a non-browser environment.
|
|
17119
|
-
* When you request a spot selection, you will receive the spot data in server-side and return them
|
|
19594
|
+
* When you request a spot selection, you will receive the spot data in server-side and return them to the client.
|
|
17120
19595
|
* Then you can use this function to create the spot html element based on the provided data without the need of the RmnClient instance.
|
|
17121
19596
|
*
|
|
17122
19597
|
* @param {ISpot} spot - The spot data.
|
|
17123
|
-
* @param {
|
|
17124
|
-
* @param {ICreateSpotElementConfig.fluid} config.fluid - If the spot should be fluid or not.
|
|
17125
|
-
* @param {ICreateSpotElementConfig.customContent} config.customContent - Use a custom html element/string.
|
|
17126
|
-
* @param {ICreateSpotElementConfig.redirectOnClick} config.redirectOnClick - If the spot should redirect on click.
|
|
19598
|
+
* @param {IRmnCreateSpotElementConfig} config - The configuration object.
|
|
17127
19599
|
*
|
|
17128
19600
|
* @return {HTMLElement | null} - The spot html element or null if the browser environment is not available.
|
|
17129
19601
|
*/
|
|
17130
19602
|
function RmnCreateSpotElement(spot, config) {
|
|
17131
|
-
|
|
17132
|
-
|
|
19603
|
+
var _a;
|
|
19604
|
+
const elementService = ElementService.getInstance();
|
|
19605
|
+
const spotData = elementService.overrideSpotColors(spot, config === null || config === void 0 ? void 0 : config.colors);
|
|
19606
|
+
const content = SPOT_TEMPLATE_HTML_ELEMENT(spotData, { overlay: config === null || config === void 0 ? void 0 : config.overlay });
|
|
19607
|
+
if (!content) {
|
|
19608
|
+
console.warn(`RmnSdk: Failed to create spot element for type "${spotData.spot}".`);
|
|
19609
|
+
return null;
|
|
19610
|
+
}
|
|
19611
|
+
return elementService.createSpotElement({
|
|
19612
|
+
content,
|
|
19613
|
+
config: {
|
|
19614
|
+
fluid: true,
|
|
19615
|
+
width: spot.width,
|
|
19616
|
+
height: spot.height,
|
|
19617
|
+
minScale: (_a = config === null || config === void 0 ? void 0 : config.minScale) !== null && _a !== void 0 ? _a : 0.25, // Scale down to 25% of the original size
|
|
19618
|
+
},
|
|
19619
|
+
});
|
|
17133
19620
|
}
|
|
17134
19621
|
|
|
17135
19622
|
exports.LiquidCommerceRmnClient = LiquidCommerceRmnClient;
|
|
17136
19623
|
exports.RmnClient = RmnClient;
|
|
17137
19624
|
exports.RmnCreateSpotElement = RmnCreateSpotElement;
|
|
19625
|
+
exports.RmnEventManager = RmnEventManager;
|