@inappstory/slide-api 0.1.37 → 0.1.39
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 +400 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +47 -1
- package/dist/index.d.ts +47 -1
- package/dist/index.js +400 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1011,6 +1011,47 @@ declare class WidgetVote extends WidgetBase<WidgetVoteOptions> {
|
|
|
1011
1011
|
};
|
|
1012
1012
|
}
|
|
1013
1013
|
|
|
1014
|
+
type WidgetReactionsOptions = WidgetOptionsBase & {};
|
|
1015
|
+
type WidgetReactionsSharedData = Record<string, number[]> & {
|
|
1016
|
+
ts: number;
|
|
1017
|
+
};
|
|
1018
|
+
|
|
1019
|
+
declare class WidgetReactions extends WidgetBase<WidgetReactionsOptions> {
|
|
1020
|
+
static DEFAULTS: WidgetReactionsOptions;
|
|
1021
|
+
static widgetClassName: string;
|
|
1022
|
+
private readonly model;
|
|
1023
|
+
private readonly reactions;
|
|
1024
|
+
constructor(element: HTMLElement, options: Partial<WidgetReactionsOptions>, widgetCallbacks: WidgetCallbacks, widgetDeps: WidgetDeps);
|
|
1025
|
+
onRefreshUserData(localData: Record<string, any>): void;
|
|
1026
|
+
resetWidget(): void;
|
|
1027
|
+
select(reaction: HTMLElement): void;
|
|
1028
|
+
isDone(): boolean;
|
|
1029
|
+
private showAnimationAfterSelection;
|
|
1030
|
+
private initFromLocalData;
|
|
1031
|
+
private createReactionsModel;
|
|
1032
|
+
private displayResults;
|
|
1033
|
+
private displayPercentageResults;
|
|
1034
|
+
private displayTotalResults;
|
|
1035
|
+
private renderResults;
|
|
1036
|
+
private markWidgetAsDone;
|
|
1037
|
+
private getReactionsSummary;
|
|
1038
|
+
private hasValidSharedData;
|
|
1039
|
+
private completeWidget;
|
|
1040
|
+
private sendStatEvent;
|
|
1041
|
+
private getLocalDataKeys;
|
|
1042
|
+
private getFromLocalData;
|
|
1043
|
+
private saveToLocalData;
|
|
1044
|
+
private incrementAllocationByIndex;
|
|
1045
|
+
static api: {
|
|
1046
|
+
widgetClassName: string;
|
|
1047
|
+
onRefreshUserData: typeof WidgetBase.onRefreshUserData;
|
|
1048
|
+
init: (element: HTMLElement, localData: Record<string, any>, widgetCallbacks: WidgetCallbacks, widgetDeps: WidgetDeps) => void;
|
|
1049
|
+
onStart: (element: HTMLElement) => void;
|
|
1050
|
+
onStop: (element: HTMLElement) => void;
|
|
1051
|
+
select: (element: HTMLElement) => boolean;
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1014
1055
|
interface ILayoutApi {
|
|
1015
1056
|
get widgetCopyApi(): typeof WidgetCopy.api | undefined;
|
|
1016
1057
|
get widgetBarcodeApi(): typeof WidgetBarcode.api | undefined;
|
|
@@ -1030,6 +1071,7 @@ interface ILayoutApi {
|
|
|
1030
1071
|
get widgetProductsApi(): typeof WidgetProducts.api | undefined;
|
|
1031
1072
|
get widgetTooltipApi(): typeof WidgetTooltip.api | undefined;
|
|
1032
1073
|
get widgetTimerApi(): typeof WidgetTimer.api | undefined;
|
|
1074
|
+
get widgetReactionsApi(): typeof WidgetReactions.api | undefined;
|
|
1033
1075
|
get VideoPlayer(): typeof Player | undefined;
|
|
1034
1076
|
}
|
|
1035
1077
|
|
|
@@ -1053,6 +1095,7 @@ declare global {
|
|
|
1053
1095
|
_narrative_range_slider_data: Record<number, WidgetRangeSliderSharedData>;
|
|
1054
1096
|
_narrative_poll_data: Record<number, WidgetPollSharedData>;
|
|
1055
1097
|
_narrative_vote_data: Record<number, WidgetVoteSharedData>;
|
|
1098
|
+
_narrative_reactions_data: Record<number, WidgetReactionsSharedData>;
|
|
1056
1099
|
_showNarrativeNextSlide(duration: number): void;
|
|
1057
1100
|
_sendStatisticEvent(name: string, data: Record<string, string | number | Array<string | number>>, devPayload?: Record<string, string | number | Array<string | number>>, forceEnableStatisticV2?: boolean): void;
|
|
1058
1101
|
_getNarrativeLocalData(): Promise<Record<string, any>>;
|
|
@@ -1396,12 +1439,15 @@ declare const enum Widgets {
|
|
|
1396
1439
|
Copy = "copy",
|
|
1397
1440
|
Share = "share",
|
|
1398
1441
|
DateCountdown = "dateCountdown",
|
|
1399
|
-
Quest = "quest"
|
|
1442
|
+
Quest = "quest",
|
|
1443
|
+
Timer = "timer",
|
|
1444
|
+
Reactions = "reactions"
|
|
1400
1445
|
}
|
|
1401
1446
|
interface WidgetsSharedDataMap {
|
|
1402
1447
|
rangeSlider: WidgetRangeSliderSharedData;
|
|
1403
1448
|
poll: WidgetPollSharedData;
|
|
1404
1449
|
vote: WidgetVoteSharedData;
|
|
1450
|
+
reactions: WidgetReactionsSharedData;
|
|
1405
1451
|
}
|
|
1406
1452
|
|
|
1407
1453
|
type OnWidgetComplete = (cardId: number, slideIndex: number) => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -1011,6 +1011,47 @@ declare class WidgetVote extends WidgetBase<WidgetVoteOptions> {
|
|
|
1011
1011
|
};
|
|
1012
1012
|
}
|
|
1013
1013
|
|
|
1014
|
+
type WidgetReactionsOptions = WidgetOptionsBase & {};
|
|
1015
|
+
type WidgetReactionsSharedData = Record<string, number[]> & {
|
|
1016
|
+
ts: number;
|
|
1017
|
+
};
|
|
1018
|
+
|
|
1019
|
+
declare class WidgetReactions extends WidgetBase<WidgetReactionsOptions> {
|
|
1020
|
+
static DEFAULTS: WidgetReactionsOptions;
|
|
1021
|
+
static widgetClassName: string;
|
|
1022
|
+
private readonly model;
|
|
1023
|
+
private readonly reactions;
|
|
1024
|
+
constructor(element: HTMLElement, options: Partial<WidgetReactionsOptions>, widgetCallbacks: WidgetCallbacks, widgetDeps: WidgetDeps);
|
|
1025
|
+
onRefreshUserData(localData: Record<string, any>): void;
|
|
1026
|
+
resetWidget(): void;
|
|
1027
|
+
select(reaction: HTMLElement): void;
|
|
1028
|
+
isDone(): boolean;
|
|
1029
|
+
private showAnimationAfterSelection;
|
|
1030
|
+
private initFromLocalData;
|
|
1031
|
+
private createReactionsModel;
|
|
1032
|
+
private displayResults;
|
|
1033
|
+
private displayPercentageResults;
|
|
1034
|
+
private displayTotalResults;
|
|
1035
|
+
private renderResults;
|
|
1036
|
+
private markWidgetAsDone;
|
|
1037
|
+
private getReactionsSummary;
|
|
1038
|
+
private hasValidSharedData;
|
|
1039
|
+
private completeWidget;
|
|
1040
|
+
private sendStatEvent;
|
|
1041
|
+
private getLocalDataKeys;
|
|
1042
|
+
private getFromLocalData;
|
|
1043
|
+
private saveToLocalData;
|
|
1044
|
+
private incrementAllocationByIndex;
|
|
1045
|
+
static api: {
|
|
1046
|
+
widgetClassName: string;
|
|
1047
|
+
onRefreshUserData: typeof WidgetBase.onRefreshUserData;
|
|
1048
|
+
init: (element: HTMLElement, localData: Record<string, any>, widgetCallbacks: WidgetCallbacks, widgetDeps: WidgetDeps) => void;
|
|
1049
|
+
onStart: (element: HTMLElement) => void;
|
|
1050
|
+
onStop: (element: HTMLElement) => void;
|
|
1051
|
+
select: (element: HTMLElement) => boolean;
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1014
1055
|
interface ILayoutApi {
|
|
1015
1056
|
get widgetCopyApi(): typeof WidgetCopy.api | undefined;
|
|
1016
1057
|
get widgetBarcodeApi(): typeof WidgetBarcode.api | undefined;
|
|
@@ -1030,6 +1071,7 @@ interface ILayoutApi {
|
|
|
1030
1071
|
get widgetProductsApi(): typeof WidgetProducts.api | undefined;
|
|
1031
1072
|
get widgetTooltipApi(): typeof WidgetTooltip.api | undefined;
|
|
1032
1073
|
get widgetTimerApi(): typeof WidgetTimer.api | undefined;
|
|
1074
|
+
get widgetReactionsApi(): typeof WidgetReactions.api | undefined;
|
|
1033
1075
|
get VideoPlayer(): typeof Player | undefined;
|
|
1034
1076
|
}
|
|
1035
1077
|
|
|
@@ -1053,6 +1095,7 @@ declare global {
|
|
|
1053
1095
|
_narrative_range_slider_data: Record<number, WidgetRangeSliderSharedData>;
|
|
1054
1096
|
_narrative_poll_data: Record<number, WidgetPollSharedData>;
|
|
1055
1097
|
_narrative_vote_data: Record<number, WidgetVoteSharedData>;
|
|
1098
|
+
_narrative_reactions_data: Record<number, WidgetReactionsSharedData>;
|
|
1056
1099
|
_showNarrativeNextSlide(duration: number): void;
|
|
1057
1100
|
_sendStatisticEvent(name: string, data: Record<string, string | number | Array<string | number>>, devPayload?: Record<string, string | number | Array<string | number>>, forceEnableStatisticV2?: boolean): void;
|
|
1058
1101
|
_getNarrativeLocalData(): Promise<Record<string, any>>;
|
|
@@ -1396,12 +1439,15 @@ declare const enum Widgets {
|
|
|
1396
1439
|
Copy = "copy",
|
|
1397
1440
|
Share = "share",
|
|
1398
1441
|
DateCountdown = "dateCountdown",
|
|
1399
|
-
Quest = "quest"
|
|
1442
|
+
Quest = "quest",
|
|
1443
|
+
Timer = "timer",
|
|
1444
|
+
Reactions = "reactions"
|
|
1400
1445
|
}
|
|
1401
1446
|
interface WidgetsSharedDataMap {
|
|
1402
1447
|
rangeSlider: WidgetRangeSliderSharedData;
|
|
1403
1448
|
poll: WidgetPollSharedData;
|
|
1404
1449
|
vote: WidgetVoteSharedData;
|
|
1450
|
+
reactions: WidgetReactionsSharedData;
|
|
1405
1451
|
}
|
|
1406
1452
|
|
|
1407
1453
|
type OnWidgetComplete = (cardId: number, slideIndex: number) => void;
|
package/dist/index.js
CHANGED
|
@@ -3357,6 +3357,57 @@ class Timer {
|
|
|
3357
3357
|
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Layer`, `Array`, `typeof WidgetTimer.api`, `WidgetCallbacks`, `WidgetDeps`]; }
|
|
3358
3358
|
}
|
|
3359
3359
|
|
|
3360
|
+
class Reactions {
|
|
3361
|
+
_elementNodeRef;
|
|
3362
|
+
_widgetApi;
|
|
3363
|
+
_widgetCallbacks;
|
|
3364
|
+
_widgetDeps;
|
|
3365
|
+
static _className = "narrative-element-reactions";
|
|
3366
|
+
static className() {
|
|
3367
|
+
return Reactions._className;
|
|
3368
|
+
}
|
|
3369
|
+
constructor(_elementNodeRef, _widgetApi, _widgetCallbacks, _widgetDeps) {
|
|
3370
|
+
this._elementNodeRef = _elementNodeRef;
|
|
3371
|
+
this._widgetApi = _widgetApi;
|
|
3372
|
+
this._widgetCallbacks = _widgetCallbacks;
|
|
3373
|
+
this._widgetDeps = _widgetDeps;
|
|
3374
|
+
}
|
|
3375
|
+
static isTypeOf(element) {
|
|
3376
|
+
return element instanceof Reactions;
|
|
3377
|
+
}
|
|
3378
|
+
mediaElementsLoadingPromises = [];
|
|
3379
|
+
get nodeRef() {
|
|
3380
|
+
return this._elementNodeRef;
|
|
3381
|
+
}
|
|
3382
|
+
init(localData) {
|
|
3383
|
+
try {
|
|
3384
|
+
this._widgetApi.init(this._elementNodeRef, localData, this._widgetCallbacks, this._widgetDeps);
|
|
3385
|
+
}
|
|
3386
|
+
catch (e) {
|
|
3387
|
+
console.error(e);
|
|
3388
|
+
}
|
|
3389
|
+
return Promise.resolve(true);
|
|
3390
|
+
}
|
|
3391
|
+
onPause() { }
|
|
3392
|
+
onResume() { }
|
|
3393
|
+
onStart() {
|
|
3394
|
+
this._widgetApi.onStart(this._elementNodeRef);
|
|
3395
|
+
}
|
|
3396
|
+
onStop() {
|
|
3397
|
+
this._widgetApi.onStop(this._elementNodeRef);
|
|
3398
|
+
}
|
|
3399
|
+
onBeforeUnmount() {
|
|
3400
|
+
return Promise.resolve();
|
|
3401
|
+
}
|
|
3402
|
+
handleClick() {
|
|
3403
|
+
return false;
|
|
3404
|
+
}
|
|
3405
|
+
get isLayerForcePaused() {
|
|
3406
|
+
return false;
|
|
3407
|
+
}
|
|
3408
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `typeof WidgetReactions.api`, `WidgetCallbacks`, `WidgetDeps`]; }
|
|
3409
|
+
}
|
|
3410
|
+
|
|
3360
3411
|
// export const tryCreateAtLayer = (layerNodeRef: HTMLElement): IElement {
|
|
3361
3412
|
// const
|
|
3362
3413
|
// }
|
|
@@ -3419,6 +3470,8 @@ const tryCreateFromHtmlElement = (nodeRef, layer, widgetCallbacks, widgetDeps) =
|
|
|
3419
3470
|
return layoutApi.widgetTooltipApi ? new Tooltip(nodeRef, layer, layoutApi.widgetTooltipApi, widgetCallbacks, widgetDeps) : null;
|
|
3420
3471
|
case Timer.className():
|
|
3421
3472
|
return layoutApi.widgetTimerApi ? new Timer(nodeRef, layer, layersNodesRefs, layoutApi.widgetTimerApi, widgetCallbacks, widgetDeps) : null;
|
|
3473
|
+
case Reactions.className():
|
|
3474
|
+
return layoutApi.widgetReactionsApi ? new Reactions(nodeRef, layoutApi.widgetReactionsApi, widgetCallbacks, widgetDeps) : null;
|
|
3422
3475
|
}
|
|
3423
3476
|
}
|
|
3424
3477
|
return null;
|
|
@@ -5198,6 +5251,19 @@ let SlideApi$1 = class SlideApi {
|
|
|
5198
5251
|
propagation = false; // по клику на варианты ответа(даже на законченной викторине) не делаем клик на слайде
|
|
5199
5252
|
}
|
|
5200
5253
|
}
|
|
5254
|
+
/** reactions */
|
|
5255
|
+
if (target?.classList.contains("narrative-element-reaction")) {
|
|
5256
|
+
element = target;
|
|
5257
|
+
}
|
|
5258
|
+
else {
|
|
5259
|
+
element = target?.closest(".narrative-element-reaction");
|
|
5260
|
+
}
|
|
5261
|
+
if (element) {
|
|
5262
|
+
if (this.layoutService.layoutApi.widgetReactionsApi) {
|
|
5263
|
+
propagation = this.layoutService.layoutApi.widgetReactionsApi.select(element);
|
|
5264
|
+
propagation = false;
|
|
5265
|
+
}
|
|
5266
|
+
}
|
|
5201
5267
|
/** test */
|
|
5202
5268
|
if (target?.classList.contains("narrative-element-test-answer")) {
|
|
5203
5269
|
element = target;
|
|
@@ -6315,7 +6381,7 @@ class Slider {
|
|
|
6315
6381
|
timer.classList.add("cards-slider__timer--reverse-direction");
|
|
6316
6382
|
}
|
|
6317
6383
|
const timeline = document.createElement("div");
|
|
6318
|
-
timeline.classList.add("cards-slider__timer_timeline"
|
|
6384
|
+
timeline.classList.add("cards-slider__timer_timeline");
|
|
6319
6385
|
const timelineFill = document.createElement("div");
|
|
6320
6386
|
timelineFill.classList.add("cards-slider__timer_timeline-fill");
|
|
6321
6387
|
timeline.append(timelineFill);
|
|
@@ -6481,6 +6547,8 @@ class Slider {
|
|
|
6481
6547
|
}
|
|
6482
6548
|
}
|
|
6483
6549
|
async updateTimeline(slideIndex, action, currentTime, duration, showLoader, showError) {
|
|
6550
|
+
// Don't use <activeSlide> and <activeIndex>, as <slideIndex> may differ from <activeIndex>
|
|
6551
|
+
const slide = this.slides[slideIndex];
|
|
6484
6552
|
switch (action) {
|
|
6485
6553
|
case "before_start" /* TIMELINE_ACTION.BEFORE_START */: {
|
|
6486
6554
|
// switch timeline to active slide and wait for start (wait VOD loading)
|
|
@@ -6512,7 +6580,7 @@ class Slider {
|
|
|
6512
6580
|
// we must resume timer - for trigger done callback and hide Card (SingleSlideTimer business logic)
|
|
6513
6581
|
}
|
|
6514
6582
|
if (resumeTimer) {
|
|
6515
|
-
|
|
6583
|
+
slide?.timer.resume(currentTime, duration);
|
|
6516
6584
|
}
|
|
6517
6585
|
break;
|
|
6518
6586
|
}
|
|
@@ -6520,7 +6588,7 @@ class Slider {
|
|
|
6520
6588
|
if (showLoader) {
|
|
6521
6589
|
this.config.onSlideDataWaiting();
|
|
6522
6590
|
}
|
|
6523
|
-
|
|
6591
|
+
slide?.timer.pause();
|
|
6524
6592
|
if (this.isSingleSlideTimerActive) {
|
|
6525
6593
|
this.pausedAt = new Date().getTime();
|
|
6526
6594
|
}
|
|
@@ -6532,7 +6600,7 @@ class Slider {
|
|
|
6532
6600
|
if (showError) {
|
|
6533
6601
|
this.config.onSlideDataError();
|
|
6534
6602
|
}
|
|
6535
|
-
|
|
6603
|
+
slide?.timer.stop();
|
|
6536
6604
|
// todo нужен STOP когда вручную переключаем слайд на другой
|
|
6537
6605
|
// console.log("TIMELINE_ACTION.STOP", { activeSlide: this.activeSlide, duration });
|
|
6538
6606
|
break;
|
|
@@ -6607,6 +6675,22 @@ class CardApi {
|
|
|
6607
6675
|
this._overlappingActionBarHeight = config.overlappingActionBarHeight ?? 0;
|
|
6608
6676
|
this._separateUserAndAppPause = config.separateUserAndAppPause;
|
|
6609
6677
|
this._useSdkCacheForMultislideMode = config.useSdkCacheForMultislideMode;
|
|
6678
|
+
let isSafari = false;
|
|
6679
|
+
if (this.config.sdkApi.isIOS) {
|
|
6680
|
+
isSafari = true;
|
|
6681
|
+
}
|
|
6682
|
+
else {
|
|
6683
|
+
if (navigator.vendor &&
|
|
6684
|
+
navigator.vendor.indexOf("Apple") > -1 &&
|
|
6685
|
+
navigator.userAgent &&
|
|
6686
|
+
navigator.userAgent.indexOf("CriOS") == -1 &&
|
|
6687
|
+
navigator.userAgent.indexOf("FxiOS") == -1) {
|
|
6688
|
+
isSafari = true;
|
|
6689
|
+
}
|
|
6690
|
+
}
|
|
6691
|
+
if (isSafari) {
|
|
6692
|
+
this.config.root.classList.add("_isSafari");
|
|
6693
|
+
}
|
|
6610
6694
|
this.refreshSizes = proxy(this.refreshSizes, this);
|
|
6611
6695
|
this.getSdkClientVariables = proxy(this.getSdkClientVariables, this);
|
|
6612
6696
|
this.refreshSizes();
|
|
@@ -24123,6 +24207,315 @@ class WidgetVote extends WidgetBase {
|
|
|
24123
24207
|
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Partial`, `WidgetCallbacks`, `WidgetDeps`]; }
|
|
24124
24208
|
}
|
|
24125
24209
|
|
|
24210
|
+
var ResultDisplayMode;
|
|
24211
|
+
(function (ResultDisplayMode) {
|
|
24212
|
+
ResultDisplayMode["Hide"] = "hide";
|
|
24213
|
+
ResultDisplayMode["Always"] = "always";
|
|
24214
|
+
ResultDisplayMode["AfterSelection"] = "afterSelection";
|
|
24215
|
+
})(ResultDisplayMode || (ResultDisplayMode = {}));
|
|
24216
|
+
var ResultDisplayFormat;
|
|
24217
|
+
(function (ResultDisplayFormat) {
|
|
24218
|
+
ResultDisplayFormat["Total"] = "total";
|
|
24219
|
+
ResultDisplayFormat["Percentage"] = "percentage";
|
|
24220
|
+
})(ResultDisplayFormat || (ResultDisplayFormat = {}));
|
|
24221
|
+
|
|
24222
|
+
const MIN_DURATION = 2000;
|
|
24223
|
+
const MAX_EXTRA_DURATION = 1500;
|
|
24224
|
+
const MIN_SCALE = 0.8;
|
|
24225
|
+
const SCALE_VARIATION = 0.4;
|
|
24226
|
+
const MAX_DRIFT_X = 40; // [-40, 40]
|
|
24227
|
+
const MAX_DELAY = 300;
|
|
24228
|
+
class ReactionFloatEffect {
|
|
24229
|
+
container;
|
|
24230
|
+
emoji;
|
|
24231
|
+
count;
|
|
24232
|
+
constructor(options) {
|
|
24233
|
+
this.container = options.container;
|
|
24234
|
+
this.emoji = options.emoji;
|
|
24235
|
+
this.count = options.count ?? 6;
|
|
24236
|
+
}
|
|
24237
|
+
animate() {
|
|
24238
|
+
for (let i = 0; i < this.count; i++) {
|
|
24239
|
+
const delay = Math.random() * MAX_DELAY;
|
|
24240
|
+
setTimeout(() => {
|
|
24241
|
+
this.spawnReaction();
|
|
24242
|
+
}, delay);
|
|
24243
|
+
}
|
|
24244
|
+
}
|
|
24245
|
+
spawnReaction() {
|
|
24246
|
+
const el = document.createElement("span");
|
|
24247
|
+
el.className = "narrative-element-reaction--float-effect";
|
|
24248
|
+
el.textContent = this.emoji;
|
|
24249
|
+
const containerWidth = this.container.clientWidth;
|
|
24250
|
+
const thresholdY = this.container.clientHeight / 2;
|
|
24251
|
+
const startX = Math.random() * containerWidth;
|
|
24252
|
+
const driftX = Math.random() * MAX_DRIFT_X * 2 - MAX_DRIFT_X;
|
|
24253
|
+
const duration = MIN_DURATION + Math.random() * MAX_EXTRA_DURATION;
|
|
24254
|
+
const randomScale = MIN_SCALE + Math.random() * SCALE_VARIATION;
|
|
24255
|
+
el.style.left = `${startX}px`;
|
|
24256
|
+
el.style.setProperty("--drift", `${driftX}px`);
|
|
24257
|
+
el.style.setProperty("--y-threshold", `${thresholdY}px`);
|
|
24258
|
+
el.style.setProperty("--duration", `${duration}ms`);
|
|
24259
|
+
el.style.setProperty("--scale", `${randomScale}`);
|
|
24260
|
+
this.container.appendChild(el);
|
|
24261
|
+
setTimeout(() => {
|
|
24262
|
+
el.remove();
|
|
24263
|
+
}, duration);
|
|
24264
|
+
}
|
|
24265
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`ReactionFloatEffectOptions`]; }
|
|
24266
|
+
}
|
|
24267
|
+
|
|
24268
|
+
class WidgetReactions extends WidgetBase {
|
|
24269
|
+
static DEFAULTS = {
|
|
24270
|
+
slide: null,
|
|
24271
|
+
activateAfterCreate: false,
|
|
24272
|
+
create: false,
|
|
24273
|
+
localData: {},
|
|
24274
|
+
layers: [],
|
|
24275
|
+
};
|
|
24276
|
+
static widgetClassName = "narrative-element-reactions";
|
|
24277
|
+
model;
|
|
24278
|
+
reactions;
|
|
24279
|
+
constructor(element, options, widgetCallbacks, widgetDeps) {
|
|
24280
|
+
super(element, options, widgetCallbacks, widgetDeps);
|
|
24281
|
+
this.model = this.createReactionsModel();
|
|
24282
|
+
this.reactions = Array.from(this.element.querySelectorAll(".narrative-element-reaction"));
|
|
24283
|
+
}
|
|
24284
|
+
onRefreshUserData(localData) {
|
|
24285
|
+
super.onRefreshUserData(localData);
|
|
24286
|
+
const data = this.getFromLocalData();
|
|
24287
|
+
if (data.selectedIndex == null || data.widgetDoneAt == null || this.reactions[data.selectedIndex] === undefined) {
|
|
24288
|
+
this.resetWidget();
|
|
24289
|
+
}
|
|
24290
|
+
else {
|
|
24291
|
+
const reaction = this.reactions[data.selectedIndex];
|
|
24292
|
+
this.initFromLocalData({ reaction, selectedIndex: data.selectedIndex, widgetDoneAt: data.widgetDoneAt });
|
|
24293
|
+
}
|
|
24294
|
+
this.firstOpenTime = new Date().getTime();
|
|
24295
|
+
}
|
|
24296
|
+
resetWidget() {
|
|
24297
|
+
for (const reaction of this.reactions) {
|
|
24298
|
+
reaction.classList.remove("narrative-element-reaction--selected");
|
|
24299
|
+
}
|
|
24300
|
+
this.element.classList.remove("narrative-element-reactions--done", "narrative-element-reactions--reacted");
|
|
24301
|
+
if (this.model.resultDisplayMode === ResultDisplayMode.Always) {
|
|
24302
|
+
const summary = this.getReactionsSummary();
|
|
24303
|
+
this.displayResults(summary.allocation);
|
|
24304
|
+
}
|
|
24305
|
+
}
|
|
24306
|
+
select(reaction) {
|
|
24307
|
+
try {
|
|
24308
|
+
if (this.isDone())
|
|
24309
|
+
return;
|
|
24310
|
+
const index = this.reactions.indexOf(reaction);
|
|
24311
|
+
if (index === -1)
|
|
24312
|
+
return;
|
|
24313
|
+
reaction.classList.add("narrative-element-reaction--selected");
|
|
24314
|
+
this.element.classList.add("narrative-element-reactions--reacted");
|
|
24315
|
+
this.completeWidget(index);
|
|
24316
|
+
}
|
|
24317
|
+
catch (error) {
|
|
24318
|
+
console.error(error);
|
|
24319
|
+
}
|
|
24320
|
+
}
|
|
24321
|
+
isDone() {
|
|
24322
|
+
return this.getFromLocalData().selectedIndex != null;
|
|
24323
|
+
}
|
|
24324
|
+
showAnimationAfterSelection(emoji) {
|
|
24325
|
+
if (!this.model.showAnimationAfterSelection)
|
|
24326
|
+
return;
|
|
24327
|
+
const geometryParent = this.element.closest(".narrative-slide-elements");
|
|
24328
|
+
if (!geometryParent)
|
|
24329
|
+
return;
|
|
24330
|
+
new ReactionFloatEffect({ container: geometryParent, emoji, count: 15 /* fontSize: getComputedStyle(this.reactions[0]).fontSize */ }).animate();
|
|
24331
|
+
}
|
|
24332
|
+
initFromLocalData({ selectedIndex, widgetDoneAt, reaction }) {
|
|
24333
|
+
try {
|
|
24334
|
+
const summary = this.getReactionsSummary();
|
|
24335
|
+
let allocation = summary.allocation;
|
|
24336
|
+
if (summary.serverTimestamp == null || widgetDoneAt > summary.serverTimestamp) {
|
|
24337
|
+
allocation = this.incrementAllocationByIndex(selectedIndex);
|
|
24338
|
+
}
|
|
24339
|
+
this.markWidgetAsDone(reaction);
|
|
24340
|
+
this.displayResults(allocation);
|
|
24341
|
+
this.startReadyPromise.then(() => {
|
|
24342
|
+
if (this.disableTimer) {
|
|
24343
|
+
this.onWidgetComplete();
|
|
24344
|
+
}
|
|
24345
|
+
});
|
|
24346
|
+
}
|
|
24347
|
+
catch (error) {
|
|
24348
|
+
console.error(error);
|
|
24349
|
+
}
|
|
24350
|
+
}
|
|
24351
|
+
createReactionsModel() {
|
|
24352
|
+
return {
|
|
24353
|
+
icons: getTagData(this.element, "icons")?.split(",") ?? [],
|
|
24354
|
+
showAnimationAfterSelection: getTagData(this.element, "showAnimationAfterSelection") === "true",
|
|
24355
|
+
resultDisplayMode: getTagData(this.element, "resultDisplayMode"),
|
|
24356
|
+
resultDisplayFormat: getTagData(this.element, "resultDisplayFormat"),
|
|
24357
|
+
};
|
|
24358
|
+
}
|
|
24359
|
+
displayResults(results) {
|
|
24360
|
+
try {
|
|
24361
|
+
switch (this.model.resultDisplayFormat) {
|
|
24362
|
+
case ResultDisplayFormat.Total:
|
|
24363
|
+
this.displayTotalResults(results);
|
|
24364
|
+
break;
|
|
24365
|
+
case ResultDisplayFormat.Percentage:
|
|
24366
|
+
this.displayPercentageResults(results);
|
|
24367
|
+
break;
|
|
24368
|
+
}
|
|
24369
|
+
}
|
|
24370
|
+
catch (error) {
|
|
24371
|
+
console.error(error);
|
|
24372
|
+
}
|
|
24373
|
+
}
|
|
24374
|
+
displayPercentageResults(counts) {
|
|
24375
|
+
const totalCount = counts.reduce((sum, value) => sum + value, 0);
|
|
24376
|
+
if (totalCount === 0)
|
|
24377
|
+
return;
|
|
24378
|
+
const formattedResults = counts.map(count => {
|
|
24379
|
+
const percent = Math.min(Math.round((count / totalCount) * 1000) / 10, 100);
|
|
24380
|
+
return `${percent}%`;
|
|
24381
|
+
});
|
|
24382
|
+
this.renderResults(formattedResults);
|
|
24383
|
+
}
|
|
24384
|
+
displayTotalResults(counts) {
|
|
24385
|
+
const formattedResults = counts.map(count => {
|
|
24386
|
+
if (count >= 1000000) {
|
|
24387
|
+
const value = count / 1000000;
|
|
24388
|
+
return `${+value.toPrecision(3)}M`;
|
|
24389
|
+
}
|
|
24390
|
+
if (count >= 1000) {
|
|
24391
|
+
const value = count / 1000;
|
|
24392
|
+
return `${+value.toPrecision(3)}K`;
|
|
24393
|
+
}
|
|
24394
|
+
return count.toString();
|
|
24395
|
+
});
|
|
24396
|
+
this.renderResults(formattedResults);
|
|
24397
|
+
}
|
|
24398
|
+
renderResults(results) {
|
|
24399
|
+
if (this.model.resultDisplayMode === ResultDisplayMode.Hide)
|
|
24400
|
+
return;
|
|
24401
|
+
this.reactions.forEach((reaction, index) => {
|
|
24402
|
+
const resultEl = reaction.querySelector(".narrative-element-reaction__result");
|
|
24403
|
+
if (!resultEl)
|
|
24404
|
+
return;
|
|
24405
|
+
resultEl.textContent = results[index];
|
|
24406
|
+
});
|
|
24407
|
+
}
|
|
24408
|
+
markWidgetAsDone(reaction) {
|
|
24409
|
+
reaction.classList.add("narrative-element-reaction--selected");
|
|
24410
|
+
this.element.classList.add("narrative-element-reactions--done");
|
|
24411
|
+
}
|
|
24412
|
+
getReactionsSummary() {
|
|
24413
|
+
const sharedData = this.widgetDeps.slideApiDeps.getWidgetsSharedData(this.cardId, "reactions" /* Widgets.Reactions */);
|
|
24414
|
+
let allocation = [];
|
|
24415
|
+
let timestamp = null;
|
|
24416
|
+
if (this.hasValidSharedData(sharedData)) {
|
|
24417
|
+
allocation = sharedData[this.elementId].slice();
|
|
24418
|
+
timestamp = sharedData.ts;
|
|
24419
|
+
}
|
|
24420
|
+
this.reactions.forEach((reaction, index) => {
|
|
24421
|
+
if (allocation[index] == null || !isNumber(allocation[index]))
|
|
24422
|
+
allocation[index] = 0;
|
|
24423
|
+
});
|
|
24424
|
+
return {
|
|
24425
|
+
allocation,
|
|
24426
|
+
serverTimestamp: timestamp,
|
|
24427
|
+
};
|
|
24428
|
+
}
|
|
24429
|
+
hasValidSharedData(sharedData) {
|
|
24430
|
+
if (!sharedData || sharedData[this.elementId] == null) {
|
|
24431
|
+
return false;
|
|
24432
|
+
}
|
|
24433
|
+
const elementData = sharedData[this.elementId];
|
|
24434
|
+
return isArray(elementData);
|
|
24435
|
+
}
|
|
24436
|
+
completeWidget(index) {
|
|
24437
|
+
this.saveToLocalData(index);
|
|
24438
|
+
this.sendStatEvent(index);
|
|
24439
|
+
this.showAnimationAfterSelection(this.model.icons[index]);
|
|
24440
|
+
const results = this.incrementAllocationByIndex(index);
|
|
24441
|
+
this.displayResults(results);
|
|
24442
|
+
this.markWidgetAsDone(this.reactions[index]);
|
|
24443
|
+
if (this.disableTimer) {
|
|
24444
|
+
this.onWidgetComplete();
|
|
24445
|
+
}
|
|
24446
|
+
}
|
|
24447
|
+
sendStatEvent(selectedIndex) {
|
|
24448
|
+
try {
|
|
24449
|
+
const duration = new Date().getTime() - this.firstOpenTime;
|
|
24450
|
+
this.sendStatisticEventToApp("w-reactions-answer", {
|
|
24451
|
+
...this.statisticEventBaseFieldsShortForm,
|
|
24452
|
+
wi: this.elementId,
|
|
24453
|
+
wa: selectedIndex,
|
|
24454
|
+
d: duration,
|
|
24455
|
+
}, {
|
|
24456
|
+
...this.statisticEventBaseFieldsFullForm,
|
|
24457
|
+
widget_id: this.elementId,
|
|
24458
|
+
widget_answer: selectedIndex,
|
|
24459
|
+
duration_ms: duration,
|
|
24460
|
+
});
|
|
24461
|
+
}
|
|
24462
|
+
catch (error) {
|
|
24463
|
+
console.error(error);
|
|
24464
|
+
}
|
|
24465
|
+
}
|
|
24466
|
+
getLocalDataKeys() {
|
|
24467
|
+
return {
|
|
24468
|
+
selectedIndex: "_re_g_" + this.elementId + "_r",
|
|
24469
|
+
widgetDoneAt: "_re_g_" + this.elementId + "_done_at",
|
|
24470
|
+
selectedAt: "_&ts_re_g_" + this.elementId + "_a_at",
|
|
24471
|
+
};
|
|
24472
|
+
}
|
|
24473
|
+
getFromLocalData() {
|
|
24474
|
+
const keys = this.getLocalDataKeys();
|
|
24475
|
+
return {
|
|
24476
|
+
selectedIndex: this.localData[keys.selectedIndex],
|
|
24477
|
+
widgetDoneAt: this.localData[keys.widgetDoneAt],
|
|
24478
|
+
};
|
|
24479
|
+
}
|
|
24480
|
+
saveToLocalData(selectedIndex) {
|
|
24481
|
+
const keys = this.getLocalDataKeys();
|
|
24482
|
+
const time = Math.round(new Date().getTime() / 1000);
|
|
24483
|
+
this.localData[keys.selectedIndex] = selectedIndex;
|
|
24484
|
+
this.localData[keys.widgetDoneAt] = time;
|
|
24485
|
+
this.localData[keys.selectedAt] = time;
|
|
24486
|
+
this.setLocalData(this.localData, true);
|
|
24487
|
+
}
|
|
24488
|
+
incrementAllocationByIndex(index) {
|
|
24489
|
+
const reactionsSummary = this.getReactionsSummary();
|
|
24490
|
+
if (reactionsSummary.allocation[index] == null)
|
|
24491
|
+
throw new Error(`No reaction allocation for the index <${index}>. Allocation: ${reactionsSummary.allocation.join(",")}`);
|
|
24492
|
+
reactionsSummary.allocation[index]++;
|
|
24493
|
+
return reactionsSummary.allocation;
|
|
24494
|
+
}
|
|
24495
|
+
static api = {
|
|
24496
|
+
widgetClassName: WidgetReactions.widgetClassName,
|
|
24497
|
+
onRefreshUserData: WidgetReactions.onRefreshUserData,
|
|
24498
|
+
init: function (element, localData, widgetCallbacks, widgetDeps) {
|
|
24499
|
+
WidgetReactions.initWidget(element, localData, (element, options) => new WidgetReactions(element, { ...options }, widgetCallbacks, widgetDeps));
|
|
24500
|
+
},
|
|
24501
|
+
onStart: function (element) {
|
|
24502
|
+
WidgetReactions.getInstance(element)?.onStart();
|
|
24503
|
+
},
|
|
24504
|
+
onStop: function (element) {
|
|
24505
|
+
WidgetReactions.getInstance(element)?.onStop();
|
|
24506
|
+
},
|
|
24507
|
+
select: function (element) {
|
|
24508
|
+
const widgetElement = element.closest(`.${WidgetReactions.widgetClassName}`);
|
|
24509
|
+
if (widgetElement) {
|
|
24510
|
+
const widget = WidgetReactions.getInstance(widgetElement);
|
|
24511
|
+
widget?.select(element);
|
|
24512
|
+
}
|
|
24513
|
+
return false;
|
|
24514
|
+
},
|
|
24515
|
+
};
|
|
24516
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Partial`, `WidgetCallbacks`, `WidgetDeps`]; }
|
|
24517
|
+
}
|
|
24518
|
+
|
|
24126
24519
|
class EsModuleLayoutApi {
|
|
24127
24520
|
slideApiPeerDeps;
|
|
24128
24521
|
constructor(slideApiPeerDeps) {
|
|
@@ -24182,6 +24575,9 @@ class EsModuleLayoutApi {
|
|
|
24182
24575
|
get widgetTimerApi() {
|
|
24183
24576
|
return WidgetTimer.api;
|
|
24184
24577
|
}
|
|
24578
|
+
get widgetReactionsApi() {
|
|
24579
|
+
return WidgetReactions.api;
|
|
24580
|
+
}
|
|
24185
24581
|
get VideoPlayer() {
|
|
24186
24582
|
return this.slideApiPeerDeps().VODPlayer;
|
|
24187
24583
|
}
|