@surfside/ads-core-web 0.1.22 → 0.3.0-c2d1d13c.0
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/README.md +15 -15
- package/lib/cjs/BuildInfo.js +6 -2
- package/lib/cjs/BuildInfo.js.map +1 -1
- package/lib/cjs/Init.js +92 -0
- package/lib/cjs/Init.js.map +1 -0
- package/lib/cjs/helpers/Dom.js.map +1 -1
- package/lib/cjs/helpers/Trackers.js +1 -1
- package/lib/cjs/helpers/Trackers.js.map +1 -1
- package/lib/cjs/helpers/UserId.js +4 -1
- package/lib/cjs/helpers/UserId.js.map +1 -1
- package/lib/cjs/helpers/WebTelemetryCollector.js +56 -0
- package/lib/cjs/helpers/WebTelemetryCollector.js.map +1 -0
- package/lib/cjs/helpers/index.js +1 -0
- package/lib/cjs/helpers/index.js.map +1 -1
- package/lib/cjs/index.js +29 -5
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/rendering/Banner.js +31 -29
- package/lib/cjs/rendering/Banner.js.map +1 -1
- package/lib/cjs/rendering/Carousel.js +207 -126
- package/lib/cjs/rendering/Carousel.js.map +1 -1
- package/lib/cjs/rendering/Framework.js +4 -2
- package/lib/cjs/rendering/Framework.js.map +1 -1
- package/lib/cjs/rendering/ProductCard.js +25 -20
- package/lib/cjs/rendering/ProductCard.js.map +1 -1
- package/lib/cjs/rendering/Video.js +142 -130
- package/lib/cjs/rendering/Video.js.map +1 -1
- package/lib/cjs/rendering/Watermark.js +34 -34
- package/lib/cjs/rendering/Watermark.js.map +1 -1
- package/lib/cjs/rendering/index.js.map +1 -1
- package/lib/esm/BuildInfo.js +5 -1
- package/lib/esm/BuildInfo.js.map +1 -1
- package/lib/esm/Init.js +85 -0
- package/lib/esm/Init.js.map +1 -0
- package/lib/esm/helpers/Dom.js.map +1 -1
- package/lib/esm/helpers/Trackers.js +1 -1
- package/lib/esm/helpers/Trackers.js.map +1 -1
- package/lib/esm/helpers/UserId.js +4 -1
- package/lib/esm/helpers/UserId.js.map +1 -1
- package/lib/esm/helpers/WebTelemetryCollector.js +52 -0
- package/lib/esm/helpers/WebTelemetryCollector.js.map +1 -0
- package/lib/esm/helpers/index.js +1 -0
- package/lib/esm/helpers/index.js.map +1 -1
- package/lib/esm/index.js +6 -4
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/rendering/Banner.js +31 -29
- package/lib/esm/rendering/Banner.js.map +1 -1
- package/lib/esm/rendering/Carousel.js +207 -126
- package/lib/esm/rendering/Carousel.js.map +1 -1
- package/lib/esm/rendering/Framework.js +4 -2
- package/lib/esm/rendering/Framework.js.map +1 -1
- package/lib/esm/rendering/ProductCard.js +25 -20
- package/lib/esm/rendering/ProductCard.js.map +1 -1
- package/lib/esm/rendering/Video.js +142 -130
- package/lib/esm/rendering/Video.js.map +1 -1
- package/lib/esm/rendering/Watermark.js +34 -34
- package/lib/esm/rendering/Watermark.js.map +1 -1
- package/lib/esm/rendering/index.js.map +1 -1
- package/lib/types/BuildInfo.d.ts +1 -1
- package/lib/types/Init.d.ts +24 -0
- package/lib/types/helpers/WebTelemetryCollector.d.ts +24 -0
- package/lib/types/helpers/index.d.ts +1 -0
- package/lib/types/index.d.ts +3 -1
- package/lib/types/rendering/Video.d.ts +1 -0
- package/package.json +42 -41
- package/lib/cjs/debug/carousel.js +0 -74
- package/lib/cjs/debug/carousel.js.map +0 -1
- package/lib/esm/debug/carousel.js +0 -72
- package/lib/esm/debug/carousel.js.map +0 -1
- package/lib/types/debug/carousel.d.ts +0 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { ITelemetryCollector } from '@surfside/ads-core';
|
|
2
|
+
export class WebTelemetryCollector extends ITelemetryCollector {
|
|
3
|
+
_endpoint;
|
|
4
|
+
_tags;
|
|
5
|
+
_batchIntervalMs;
|
|
6
|
+
_pageUrl;
|
|
7
|
+
_queue = [];
|
|
8
|
+
_flushTimer;
|
|
9
|
+
_device;
|
|
10
|
+
constructor(options) {
|
|
11
|
+
super(options.accountId, options.siteId, options.channelId, options.locationId, options.device);
|
|
12
|
+
this._endpoint = options.endpoint;
|
|
13
|
+
this._tags = { pageSessionId: crypto.randomUUID(), ...(options.tags ?? {}) };
|
|
14
|
+
this._batchIntervalMs = options.batchIntervalMs ?? 1000;
|
|
15
|
+
this._pageUrl = options.url ?? globalThis.location?.href;
|
|
16
|
+
}
|
|
17
|
+
record(entry) {
|
|
18
|
+
this._queue.push({
|
|
19
|
+
device: this.device,
|
|
20
|
+
pageUrl: this._pageUrl ?? globalThis?.window?.location?.href,
|
|
21
|
+
...entry,
|
|
22
|
+
tags: { ...this._tags, ...(entry.tags ?? {}) },
|
|
23
|
+
});
|
|
24
|
+
if (this._batchIntervalMs === 0) {
|
|
25
|
+
this.flush();
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
clearTimeout(this._flushTimer);
|
|
29
|
+
this._flushTimer = setTimeout(() => this.flush(), this._batchIntervalMs);
|
|
30
|
+
if (this._queue.length >= 100) {
|
|
31
|
+
this.flush();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
flush() {
|
|
35
|
+
if (this._queue.length === 0) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const payload = JSON.stringify(this._queue.splice(0));
|
|
39
|
+
clearTimeout(this._flushTimer);
|
|
40
|
+
this._flushTimer = undefined;
|
|
41
|
+
const sent = globalThis.navigator.sendBeacon(this._endpoint, new Blob([payload], { type: 'application/json' }));
|
|
42
|
+
if (!sent) {
|
|
43
|
+
fetch(this._endpoint, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
headers: { 'Content-Type': 'application/json' },
|
|
46
|
+
body: payload,
|
|
47
|
+
keepalive: true,
|
|
48
|
+
}).catch(() => { });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=WebTelemetryCollector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebTelemetryCollector.js","sourceRoot":"../@surfside-ads-core-web/","sources":["helpers/WebTelemetryCollector.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,mBAAmB,EAGtB,MAAM,oBAAoB,CAAC;AAc5B,MAAM,OAAO,qBAAsB,SAAQ,mBAAmB;IACzC,SAAS,CAAS;IAClB,KAAK,CAAyB;IAC9B,gBAAgB,CAAS;IACzB,QAAQ,CAAqB;IACtC,MAAM,GAAsB,EAAE,CAAC;IAC/B,WAAW,CAA4C;IACvD,OAAO,CAA+B;IAE9C,YAAY,OAAsC;QAC9C,KAAK,CACD,OAAO,CAAC,SAAS,EACjB,OAAO,CAAC,MAAM,EACd,OAAO,CAAC,SAAS,EACjB,OAAO,CAAC,UAAU,EAClB,OAAO,CAAC,MAAM,CACjB,CAAC;QACF,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC;QAClC,IAAI,CAAC,KAAK,GAAG,EAAE,aAAa,EAAE,MAAM,CAAC,UAAU,EAAE,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;QAC7E,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,eAAe,IAAI,IAAI,CAAC;QACxD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,GAAG,IAAI,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC;IAC7D,CAAC;IAED,MAAM,CAAC,KAAsB;QACzB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YACb,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,IAAI,CAAC,QAAQ,IAAI,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI;YAC5D,GAAG,KAAK;YACR,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE;SACjD,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,gBAAgB,KAAK,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,OAAO;QACX,CAAC;QACD,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC/B,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACzE,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC;IACL,CAAC;IAED,KAAK;QACD,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO;QACX,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACtD,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC/B,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;QAC7B,MAAM,IAAI,GAAG,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC;QAChH,IAAI,CAAC,IAAI,EAAE,CAAC;YACR,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE;gBAClB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,OAAO;gBACb,SAAS,EAAE,IAAI;aAClB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACvB,CAAC;IACL,CAAC;CACJ"}
|
package/lib/esm/helpers/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"../@surfside-ads-core-web/","sources":["helpers/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC;AACtB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,yBAAyB,CAAC"}
|
package/lib/esm/index.js
CHANGED
|
@@ -3,17 +3,19 @@ import { RenderCarousel } from './rendering/Carousel';
|
|
|
3
3
|
import { RenderBanner } from './rendering';
|
|
4
4
|
import { RenderProductCard } from './rendering/ProductCard';
|
|
5
5
|
import { RenderVideo } from './rendering/Video';
|
|
6
|
+
import { GetSurfUserIdCookie } from './helpers';
|
|
7
|
+
export const PROD_TELEMETRY_SERVICE = '//telemetry.surfside.io/v1/ingest';
|
|
6
8
|
export * from './rendering';
|
|
7
9
|
export * from './helpers';
|
|
8
|
-
export * from './BuildInfo';
|
|
10
|
+
export * as SurfsideAdsCoreWebVersionInfo from './BuildInfo';
|
|
11
|
+
export * from './Init';
|
|
9
12
|
export const InitSurfAdsWebInternal = async (apiResAsync) => {
|
|
10
13
|
const apiRes = await apiResAsync;
|
|
11
14
|
if (!apiRes.ok) {
|
|
12
15
|
return apiRes;
|
|
13
16
|
}
|
|
14
17
|
const { logger, configuration, device, geo, evaluateProductCardTemplate, navigator } = apiRes.value;
|
|
15
|
-
|
|
16
|
-
const isMobile = () => typeof window !== 'undefined' ? (window.ontouchstart !== undefined) : false;
|
|
18
|
+
const isMobile = () => typeof globalThis.window !== 'undefined' ? (globalThis.ontouchstart !== undefined) : false;
|
|
17
19
|
const renderBanner = RenderBanner.bind(undefined, logger, isMobile());
|
|
18
20
|
const renderProductCard = RenderProductCard.bind(undefined, logger, configuration.templates.productCardStylesheet, configuration.templates.javascriptCallbacks, evaluateProductCardTemplate);
|
|
19
21
|
const renderCarousel = RenderCarousel.bind(undefined, logger, evaluateProductCardTemplate, configuration.settings.sponsoredByEnabled === true, configuration.templates.productCardStylesheet, configuration.templates.carouselStylesheet, configuration.templates.javascriptCallbacks);
|
|
@@ -27,6 +29,6 @@ export const InitSurfAdsWebInternal = async (apiResAsync) => {
|
|
|
27
29
|
});
|
|
28
30
|
};
|
|
29
31
|
export const InitSurfAdsWeb = async (accountId, siteId, channelId, locationId, userId, logger) => {
|
|
30
|
-
return InitSurfAdsWebInternal(InitSurfAdsCoreClient(accountId, siteId, channelId, locationId, userId, logger));
|
|
32
|
+
return await InitSurfAdsWebInternal(InitSurfAdsCoreClient(accountId, siteId, channelId, locationId, userId ?? await GetSurfUserIdCookie(logger), logger));
|
|
31
33
|
};
|
|
32
34
|
//# sourceMappingURL=index.js.map
|
package/lib/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"../@surfside-ads-core-web/","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,qBAAqB,EACrB,EAAE,GAIL,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAyB,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAuB,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAA4B,MAAM,yBAAyB,CAAC;AACtF,OAAO,EAAE,WAAW,EAAsB,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEhD,MAAM,CAAC,MAAM,sBAAsB,GAAG,mCAAmC,CAAC;AAE1E,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,OAAO,KAAK,6BAA6B,MAAM,aAAa,CAAC;AAC7D,cAAc,QAAQ,CAAC;AASvB,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,EACvC,WAA4C,EAChB,EAAE;IAC9B,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC;IACjC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACb,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,MAAM,EACF,MAAM,EACN,aAAa,EACb,MAAM,EACN,GAAG,EACH,2BAA2B,EAC3B,SAAS,EACZ,GAAG,MAAM,CAAC,KAAK,CAAC;IAEjB,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,OAAO,UAAU,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAElH,MAAM,YAAY,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IACtE,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EAC9D,aAAa,CAAC,SAAS,CAAC,qBAAqB,EAC7C,aAAa,CAAC,SAAS,CAAC,mBAAmB,EAC3C,2BAA2B,CAC9B,CAAC;IACF,MAAM,cAAc,GAAG,cAAc,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EACxD,2BAA2B,EAC3B,aAAa,CAAC,QAAQ,CAAC,kBAAkB,KAAK,IAAI,EAClD,aAAa,CAAC,SAAS,CAAC,qBAAqB,EAC7C,aAAa,CAAC,SAAS,CAAC,kBAAkB,EAC1C,aAAa,CAAC,SAAS,CAAC,mBAAmB,CAC9C,CAAC;IAEF,MAAM,WAAW,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAE1F,OAAO,EAAE,CAAC;QACN,GAAG,MAAM,CAAC,KAAK;QACf,YAAY;QACZ,iBAAiB;QACjB,cAAc;QACd,WAAW;KACd,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAC/B,SAAiB,EACjB,MAAc,EACd,SAAiB,EACjB,UAAkB,EAClB,MAA0B,EAC1B,MAAgB,EACY,EAAE;IAC9B,OAAO,MAAM,sBAAsB,CAAC,qBAAqB,CACrD,SAAS,EACT,MAAM,EACN,SAAS,EACT,UAAU,EACV,MAAM,IAAI,MAAM,mBAAmB,CAAC,MAAM,CAAC,EAC3C,MAAM,CACT,CAAC,CAAC;AACP,CAAC,CAAC"}
|
|
@@ -6,8 +6,9 @@ export const RenderBanner = (logger, isMobile, builtBanner) => {
|
|
|
6
6
|
const log = Ctx(logger)?.with('RenderBanner');
|
|
7
7
|
log?.info('Rendering banner');
|
|
8
8
|
log?.debug(builtBanner);
|
|
9
|
+
const stopTimer = log?.time?.('render banner');
|
|
9
10
|
/* Create container dom element */
|
|
10
|
-
const bannerContainer = document.createElement('div');
|
|
11
|
+
const bannerContainer = globalThis.document.createElement('div');
|
|
11
12
|
const shadow = bannerContainer.attachShadow({ mode: 'open' });
|
|
12
13
|
const creativeContainerRes = Template(log, 'surfside-banner', template, style);
|
|
13
14
|
if (!creativeContainerRes.ok) {
|
|
@@ -47,6 +48,7 @@ export const RenderBanner = (logger, isMobile, builtBanner) => {
|
|
|
47
48
|
}
|
|
48
49
|
log?.debug('Appending banner win pixel', tracker);
|
|
49
50
|
creativeContainer.appendChild(PixelTracker(tracker));
|
|
51
|
+
stopTimer?.();
|
|
50
52
|
return Ok(bannerContainer);
|
|
51
53
|
};
|
|
52
54
|
export class MissingNurlError extends Error {
|
|
@@ -57,34 +59,34 @@ export class MissingNurlError extends Error {
|
|
|
57
59
|
}
|
|
58
60
|
}
|
|
59
61
|
;
|
|
60
|
-
const template = `<div>
|
|
61
|
-
<div class="surfside-banner-adm">
|
|
62
|
-
|
|
63
|
-
</div>
|
|
64
|
-
<div class="surfside-banner-watermark">
|
|
65
|
-
|
|
66
|
-
</div>
|
|
67
|
-
</div>
|
|
62
|
+
const template = `<div>
|
|
63
|
+
<div class="surfside-banner-adm">
|
|
64
|
+
|
|
65
|
+
</div>
|
|
66
|
+
<div class="surfside-banner-watermark">
|
|
67
|
+
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
68
70
|
`;
|
|
69
|
-
const style = `.surfside-banner {
|
|
70
|
-
position: relative;
|
|
71
|
-
display: inline-block;
|
|
72
|
-
overflow: hidden;
|
|
73
|
-
max-width: 100%;
|
|
74
|
-
height: auto;
|
|
75
|
-
width: 100%;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
.surfside-banner-adm {
|
|
79
|
-
display: flex;
|
|
80
|
-
|
|
81
|
-
a {
|
|
82
|
-
width: 100%;
|
|
83
|
-
|
|
84
|
-
img {
|
|
85
|
-
width: 100%;
|
|
86
|
-
height: auto;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
71
|
+
const style = `.surfside-banner {
|
|
72
|
+
position: relative;
|
|
73
|
+
display: inline-block;
|
|
74
|
+
overflow: hidden;
|
|
75
|
+
max-width: 100%;
|
|
76
|
+
height: auto;
|
|
77
|
+
width: 100%;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.surfside-banner-adm {
|
|
81
|
+
display: flex;
|
|
82
|
+
|
|
83
|
+
a {
|
|
84
|
+
width: 100%;
|
|
85
|
+
|
|
86
|
+
img {
|
|
87
|
+
width: 100%;
|
|
88
|
+
height: auto;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
89
91
|
}`;
|
|
90
92
|
//# sourceMappingURL=Banner.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Banner.js","sourceRoot":"
|
|
1
|
+
{"version":3,"file":"Banner.js","sourceRoot":"../@surfside-ads-core-web/","sources":["rendering/Banner.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,12 +2,15 @@ import { ConsumeNAsync, Ctx, Err, Ok, } from '@surfside/ads-core-client';
|
|
|
2
2
|
import { RenderProductCard } from './ProductCard';
|
|
3
3
|
import { GetNumberAttributeOr } from '../helpers/Dom';
|
|
4
4
|
import { MissingTemplateElementError, Template } from './Framework';
|
|
5
|
+
const SURF_CARD_SIZE = '--surf-card-size';
|
|
5
6
|
;
|
|
6
7
|
;
|
|
7
8
|
;
|
|
9
|
+
const smoothStop3 = (t) => 1 - ((1 - t) * (1 - t) * (1 - t));
|
|
8
10
|
export const RenderCarousel = async (logger, evaluateProductCardTemplate, sponsoredByEnabled, productCardStylesheet, carouselStylesheet, callbacks, carousel, cardMinWidth, carouselLimits, nextType, cardMaxWidth) => {
|
|
9
11
|
const log = Ctx(logger)?.with('RenderCarousel');
|
|
10
12
|
log?.info('Rendering Carousel', cardMinWidth, cardMaxWidth, carouselLimits);
|
|
13
|
+
const stopTimer = log?.time?.('render banner');
|
|
11
14
|
const container = Template(log, 'surf-carousel', template, style + '\n' + carouselStylesheet);
|
|
12
15
|
if (!container.ok) {
|
|
13
16
|
return container;
|
|
@@ -15,7 +18,7 @@ export const RenderCarousel = async (logger, evaluateProductCardTemplate, sponso
|
|
|
15
18
|
log?.debug(container.value.outerHTML);
|
|
16
19
|
const rightArrow = container.value.querySelector('.arrow.right') ?? null;
|
|
17
20
|
const leftArrow = container.value.querySelector('.arrow.left') ?? null;
|
|
18
|
-
const items = container.value.querySelector('.items')
|
|
21
|
+
const items = container.value.querySelector('.items');
|
|
19
22
|
if (rightArrow === null || leftArrow === null || items === null) {
|
|
20
23
|
return Err(new MalformedCarouselError(container.value));
|
|
21
24
|
}
|
|
@@ -47,11 +50,60 @@ export const RenderCarousel = async (logger, evaluateProductCardTemplate, sponso
|
|
|
47
50
|
}
|
|
48
51
|
handleBackPage(log, sponsoredByEnabled, container.value, items, cardMinWidth, cardMaxWidth);
|
|
49
52
|
});
|
|
53
|
+
let touchStart;
|
|
54
|
+
let lastTouch;
|
|
55
|
+
items.addEventListener('touchstart', (e) => {
|
|
56
|
+
log?.debug('touchstart');
|
|
57
|
+
const touch = e.touches[0];
|
|
58
|
+
if (touch === undefined) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
touchStart = touch.clientX;
|
|
62
|
+
});
|
|
63
|
+
items.addEventListener('touchmove', e => {
|
|
64
|
+
const touch = e.touches[0];
|
|
65
|
+
if (touch === undefined || touchStart === undefined) {
|
|
66
|
+
touchStart = undefined;
|
|
67
|
+
lastTouch = undefined;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
lastTouch = touch.clientX;
|
|
71
|
+
const maxSwipe = items.children[0]?.clientWidth ?? cardMaxWidth;
|
|
72
|
+
const sign = Math.sign(lastTouch - touchStart);
|
|
73
|
+
const distance = Math.min(maxSwipe, Math.abs(lastTouch - touchStart));
|
|
74
|
+
const smooth = smoothStop3(Math.min(distance / maxSwipe, 1));
|
|
75
|
+
const diff = smooth * distance * sign;
|
|
76
|
+
items.style.marginLeft = `${diff}px`;
|
|
77
|
+
log?.debug(`${diff}px`);
|
|
78
|
+
});
|
|
79
|
+
items.addEventListener('touchend', () => {
|
|
80
|
+
log?.debug('touchend');
|
|
81
|
+
items.style.marginLeft = '0px';
|
|
82
|
+
if (lastTouch !== undefined && touchStart !== undefined) {
|
|
83
|
+
const diff = lastTouch - touchStart;
|
|
84
|
+
log?.info('Touch Diff', diff);
|
|
85
|
+
if (diff < -16) {
|
|
86
|
+
handleNextPage(log, evaluateProductCardTemplate, sponsoredByEnabled, productCardStylesheet, callbacks, container.value, items, cardMinWidth, cardMaxWidth, carouselLimits, nextType, generator);
|
|
87
|
+
}
|
|
88
|
+
else if (diff > 16) {
|
|
89
|
+
handleBackPage(log, sponsoredByEnabled, container.value, items, cardMinWidth, cardMaxWidth);
|
|
90
|
+
}
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
touchStart = undefined;
|
|
94
|
+
lastTouch = undefined;
|
|
95
|
+
});
|
|
96
|
+
stopTimer?.();
|
|
50
97
|
return Ok(carouselState);
|
|
51
98
|
};
|
|
52
99
|
const addItems = (logger, stylesheet, sponsoredByEnabled, callbacks, evaluateProductCardTemplate, items, itemsDiv, availableSlots, minWidth, maxWidth) => {
|
|
53
100
|
const log = Ctx(logger)?.with('addItems');
|
|
54
101
|
log?.info('Adding items to carousel', items.length);
|
|
102
|
+
const cardSizeRes = getCardSizeOverride(itemsDiv);
|
|
103
|
+
log?.debug('Item mobile scale', cardSizeRes);
|
|
104
|
+
const cardSize = cardSizeRes.ok
|
|
105
|
+
? cardSizeRes.value
|
|
106
|
+
: maxWidth ?? minWidth;
|
|
55
107
|
const renderedCards = [];
|
|
56
108
|
for (const item of items) {
|
|
57
109
|
const productCard = RenderProductCard(log, stylesheet, callbacks, evaluateProductCardTemplate, item);
|
|
@@ -73,7 +125,8 @@ const addItems = (logger, stylesheet, sponsoredByEnabled, callbacks, evaluatePro
|
|
|
73
125
|
const cardIndex = itemsDiv.children.length;
|
|
74
126
|
productCard.value.classList.add(`card-${cardIndex}`);
|
|
75
127
|
productCard.value.classList.add('surf-product-card');
|
|
76
|
-
productCard.value.style.
|
|
128
|
+
productCard.value.style.minWidth = `${cardSize}px`;
|
|
129
|
+
productCard.value.style.maxWidth = `${cardSize}px`;
|
|
77
130
|
log?.debug('Flex value', `1 0 ${Math.ceil((1 / availableSlots) * 100000) / 1000}%`);
|
|
78
131
|
productCard.value.style.flex = `1 0 ${Math.ceil((1 / availableSlots) * 100000) / 1000}%`;
|
|
79
132
|
itemsDiv.appendChild(productCard.value);
|
|
@@ -81,19 +134,34 @@ const addItems = (logger, stylesheet, sponsoredByEnabled, callbacks, evaluatePro
|
|
|
81
134
|
}
|
|
82
135
|
return renderedCards;
|
|
83
136
|
};
|
|
137
|
+
const getCardSizeOverride = (element) => {
|
|
138
|
+
const windowStyle = globalThis.getComputedStyle(element);
|
|
139
|
+
const cardSizeRes = Number(windowStyle.getPropertyValue(SURF_CARD_SIZE));
|
|
140
|
+
const cardSize = Number.isNaN(cardSizeRes) || cardSizeRes === 0
|
|
141
|
+
? Err(new Error('Not a valid card size'))
|
|
142
|
+
: Ok(cardSizeRes);
|
|
143
|
+
return cardSize;
|
|
144
|
+
};
|
|
84
145
|
const handleNextPage = async (logger, evaluateProductCardTemplate, sponsoredByEnabled, stylesheet, callbacks, rootElement, itemsDiv, cardMinWidth, cardMaxWidth, carouselLimits, nextType, carouselGenerator) => {
|
|
85
146
|
const log = Ctx(logger)?.with('handleNextPage');
|
|
86
147
|
log?.info('Handling next page request');
|
|
87
148
|
log?.debug(cardMinWidth, carouselLimits);
|
|
149
|
+
log?.debug('root', rootElement);
|
|
88
150
|
/* Get the card which the carousel is currently scrolled to (i.e, the left-most card) */
|
|
89
151
|
const currentIndex = GetNumberAttributeOr(itemsDiv, 'current-index', 0);
|
|
90
152
|
/* Get the total number of cards which have been rendered so far */
|
|
91
153
|
const totalRendered = itemsDiv.childElementCount;
|
|
92
154
|
log?.debug('currentIndex', currentIndex);
|
|
93
155
|
log?.debug('totalRendered', totalRendered);
|
|
156
|
+
const cardSizeRes = getCardSizeOverride(rootElement);
|
|
157
|
+
log?.debug('Card Size Result', cardSizeRes);
|
|
158
|
+
const cardSize = cardSizeRes.ok
|
|
159
|
+
? cardSizeRes.value
|
|
160
|
+
: (cardMaxWidth ?? cardMinWidth);
|
|
94
161
|
/* Calculate how many cards fit into view currently */
|
|
95
162
|
log?.debug('Root clientWidth: ', rootElement.clientWidth);
|
|
96
|
-
|
|
163
|
+
log?.debug('Card size', cardSize);
|
|
164
|
+
const slotsAvailable = Math.floor(rootElement.clientWidth / cardSize);
|
|
97
165
|
log?.debug('slotsAvailable', slotsAvailable);
|
|
98
166
|
/* Calculate the total number of cards which have already been rendered to the RIGHT of the current page */
|
|
99
167
|
const totalSlotsRenderedAfterThisPage = Math.max(0, Math.min(totalRendered, totalRendered - (currentIndex + slotsAvailable)));
|
|
@@ -127,7 +195,7 @@ const handleNextPage = async (logger, evaluateProductCardTemplate, sponsoredByEn
|
|
|
127
195
|
})() - totalSlotsRenderedAfterThisPage); /* Finally, remove the slots which have already been rendered within the
|
|
128
196
|
* next visible page scroll */
|
|
129
197
|
log?.debug('numberOfCardsToAdd', numberOfCardsToAdd);
|
|
130
|
-
const slotsVisible = Math.floor(rootElement.clientWidth /
|
|
198
|
+
const slotsVisible = Math.floor(rootElement.clientWidth / cardSize);
|
|
131
199
|
if (numberOfCardsToAdd === 0) {
|
|
132
200
|
/* Scroll either to the calculated next page index, or to the last page, depending on which is smaller */
|
|
133
201
|
log?.info('No new cards requested');
|
|
@@ -139,7 +207,9 @@ const handleNextPage = async (logger, evaluateProductCardTemplate, sponsoredByEn
|
|
|
139
207
|
return Ok([]);
|
|
140
208
|
}
|
|
141
209
|
log?.debug('nextCardToScrollTo, either', currentIndex + slotsVisible, itemsDiv.childElementCount);
|
|
210
|
+
const stopTimer = log?.time?.('fetch n products');
|
|
142
211
|
const [builtProducts, finished] = await ConsumeNAsync(carouselGenerator, numberOfCardsToAdd);
|
|
212
|
+
stopTimer?.();
|
|
143
213
|
if (finished) {
|
|
144
214
|
log?.debug('Finished with generator - no more products available');
|
|
145
215
|
}
|
|
@@ -156,7 +226,12 @@ const handleBackPage = (logger, sponsoredByEnabled, rootElement, itemsDiv, cardM
|
|
|
156
226
|
const log = Ctx(logger)?.with('handleBackPage');
|
|
157
227
|
log?.info('scrolling back');
|
|
158
228
|
const currentIndex = GetNumberAttributeOr(itemsDiv, 'current-index', 0);
|
|
159
|
-
const
|
|
229
|
+
const cardSizeRes = getCardSizeOverride(rootElement);
|
|
230
|
+
log?.debug('Card Size Result', cardSizeRes);
|
|
231
|
+
const cardSize = cardSizeRes.ok
|
|
232
|
+
? cardSizeRes.value
|
|
233
|
+
: (cardMaxWidth ?? cardMinWidth);
|
|
234
|
+
const slotsInView = Math.floor(rootElement.clientWidth / cardSize);
|
|
160
235
|
const nextIndex = Math.max(0, currentIndex - slotsInView);
|
|
161
236
|
const arrowsDiv = rootElement.querySelector('div.arrows');
|
|
162
237
|
if (arrowsDiv === null) {
|
|
@@ -198,7 +273,12 @@ const scrollTo = (logger, itemsDiv, arrowsDiv, index, slotsVisible, finished) =>
|
|
|
198
273
|
const checkSponsored = (logger, sponsoredByEnabled, root, itemsDiv, index, cardMinWidth, cardMaxWidth) => {
|
|
199
274
|
const log = Ctx(logger)?.with('checkSponsored');
|
|
200
275
|
log?.info('Checking sponsored tags');
|
|
201
|
-
const
|
|
276
|
+
const cardSizeRes = getCardSizeOverride(root);
|
|
277
|
+
log?.debug('Card Size Result', cardSizeRes);
|
|
278
|
+
const cardSize = cardSizeRes.ok
|
|
279
|
+
? cardSizeRes.value
|
|
280
|
+
: (cardMaxWidth ?? cardMinWidth);
|
|
281
|
+
const totalVisibleCards = Math.floor(root.clientWidth / cardSize);
|
|
202
282
|
const visibleCards = [];
|
|
203
283
|
for (let i = index; i < index + totalVisibleCards; i++) {
|
|
204
284
|
const card = itemsDiv.querySelector(`.card-${i}`);
|
|
@@ -279,126 +359,127 @@ export class EmptyFirstPageError extends Error {
|
|
|
279
359
|
}
|
|
280
360
|
}
|
|
281
361
|
;
|
|
282
|
-
const template = `<div class="carousel-wrapper">
|
|
283
|
-
<div class="sponsored-carousel"></div>
|
|
284
|
-
<div class="surf-carousel">
|
|
285
|
-
<div class="items"></div>
|
|
286
|
-
<div class="arrows">
|
|
287
|
-
<div class="arrow left"></div>
|
|
288
|
-
<div class="arrow right"></div>
|
|
289
|
-
</div>
|
|
290
|
-
</div>
|
|
362
|
+
const template = `<div class="carousel-wrapper surf-v3">
|
|
363
|
+
<div class="sponsored-carousel"></div>
|
|
364
|
+
<div class="surf-carousel">
|
|
365
|
+
<div class="items"></div>
|
|
366
|
+
<div class="arrows">
|
|
367
|
+
<div class="arrow left"></div>
|
|
368
|
+
<div class="arrow right"></div>
|
|
369
|
+
</div>
|
|
370
|
+
</div>
|
|
291
371
|
</div>`;
|
|
292
|
-
const style = `
|
|
293
|
-
.surf-carousel {
|
|
294
|
-
display: flex;
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
flex-
|
|
331
|
-
flex-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
372
|
+
const style = `
|
|
373
|
+
.surf-carousel {
|
|
374
|
+
display: flex;
|
|
375
|
+
flex-direction: column;
|
|
376
|
+
position: relative;
|
|
377
|
+
flex-grow: 1;
|
|
378
|
+
|
|
379
|
+
.sponsored-carousel {
|
|
380
|
+
font-family: 'Helvetica', Verdana, Geneva, Tahoma, sans-serif;
|
|
381
|
+
margin: 10px 0;
|
|
382
|
+
font-size: 24px;
|
|
383
|
+
|
|
384
|
+
&::before {
|
|
385
|
+
content: 'For you';
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
&.sponsoredByOne::before {
|
|
389
|
+
content: 'Sponsored by ';
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
&.recommended::before {
|
|
393
|
+
content: 'Recommended';
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
&.sponsoredByMany::before {
|
|
397
|
+
content: 'Sponsored';
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
.carousel-wrapper {
|
|
402
|
+
width: 100%;
|
|
403
|
+
overflow-x: clip;
|
|
404
|
+
position: relative;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
.items {
|
|
408
|
+
z-index: 1;
|
|
409
|
+
display: flex;
|
|
410
|
+
flex-direction: row;
|
|
411
|
+
flex-grow: 1;
|
|
412
|
+
flex-wrap: nowrap;
|
|
413
|
+
align-items: stretch;
|
|
414
|
+
padding: 0 37px;
|
|
415
|
+
box-sizing: border-box;
|
|
416
|
+
transition: transform 0.4s ease-out, margin-left 0.3s ease;
|
|
417
|
+
width: 100%;
|
|
418
|
+
|
|
419
|
+
.surf-product-card {
|
|
420
|
+
flex: 1;
|
|
421
|
+
display: flex;
|
|
422
|
+
padding: 5px;
|
|
423
|
+
box-sizing: border-box;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
.arrows {
|
|
431
|
+
|
|
432
|
+
.arrow {
|
|
433
|
+
z-index: 2;
|
|
434
|
+
position: absolute;
|
|
435
|
+
top: 50%;
|
|
436
|
+
transform: translateY(-50%);
|
|
437
|
+
width: 40px;
|
|
438
|
+
height: 40px;
|
|
439
|
+
display: flex;
|
|
440
|
+
background-color: rgba(0, 0, 0, 0.5);
|
|
441
|
+
margin: 0 1rem;
|
|
442
|
+
justify-content: center;
|
|
443
|
+
align-items: center;
|
|
444
|
+
border-radius: 50%;
|
|
445
|
+
cursor: pointer;
|
|
446
|
+
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.2),
|
|
447
|
+
0 2px 8px 0 rgba(0, 0, 0, 0.2);
|
|
448
|
+
|
|
449
|
+
&:hover {
|
|
450
|
+
background-color: rgba(0, 0, 0, 0.6);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
&.disabled {
|
|
454
|
+
cursor: not-allowed;
|
|
455
|
+
filter: grayscale(100%);
|
|
456
|
+
opacity: 0.2;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
&.left {
|
|
460
|
+
left: -10px;
|
|
461
|
+
|
|
462
|
+
&:before {
|
|
463
|
+
content: "";
|
|
464
|
+
background: url('//cdn.surfside.io/icons/left-arrow.svg')
|
|
465
|
+
no-repeat center;
|
|
466
|
+
width: 40px;
|
|
467
|
+
height: 40px;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
&.right {
|
|
472
|
+
right: 0;
|
|
473
|
+
|
|
474
|
+
&:before {
|
|
475
|
+
content: "";
|
|
476
|
+
background: url('//cdn.surfside.io/icons/right-arrow.svg')
|
|
477
|
+
no-repeat center;
|
|
478
|
+
width: 40px;
|
|
479
|
+
height: 40px;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
}
|
|
483
|
+
}
|
|
403
484
|
}`;
|
|
404
485
|
//# sourceMappingURL=Carousel.js.map
|