lido-player 0.0.2-beta-16-dev → 0.0.2-beta-17-dev
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/cjs/{decode-C08Ujimj.js → decode-DUZYNXIv.js} +1 -1
- package/dist/cjs/{index-BkBqiwe8.js → index-BEjUmVtH.js} +189 -53
- package/dist/cjs/{index-Dy19zuTX.js → index-DnqQXD5x.js} +53 -12
- package/dist/cjs/index.cjs.js +2 -2
- package/dist/cjs/lido-avatar_22.cjs.entry.js +60 -54
- package/dist/cjs/lido-player.cjs.js +3 -3
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/collection/collection-manifest.json +1 -1
- package/dist/collection/components/calculator/lido-calculator.js +3 -3
- package/dist/collection/components/mathMatrix/lido-math-matrix.js +12 -2
- package/dist/collection/components/scale/assets/Shadow.svg +9 -0
- package/dist/collection/components/scale/lido-balance.css +1 -1
- package/dist/collection/components/scale/lido-balance.js +13 -11
- package/dist/collection/components/text/lido-text.js +28 -2
- package/dist/collection/components/trace/assets/Tracing-hand.svg +8 -0
- package/dist/collection/components/trace/lido-trace.js +25 -38
- package/dist/collection/css/index.css +7 -4
- package/dist/collection/stories/Templates/blender/blender.stories.js +9 -5
- package/dist/collection/utils/audioPlayer.js +31 -9
- package/dist/collection/utils/utils.js +20 -10
- package/dist/collection/utils/utilsHandlers/animationHandler.js +9 -2
- package/dist/collection/utils/utilsHandlers/clickHandler.js +8 -0
- package/dist/collection/utils/utilsHandlers/dragDropHandler.js +28 -8
- package/dist/collection/utils/utilsHandlers/lidoCalculatorHandler.js +12 -15
- package/dist/collection/utils/utilsHandlers/slideHandler.js +76 -17
- package/dist/components/index.js +1 -1
- package/dist/components/lido-balance.js +1 -1
- package/dist/components/lido-calculator.js +1 -1
- package/dist/components/lido-container.js +1 -1
- package/dist/components/lido-home.js +1 -1
- package/dist/components/lido-keyboard.js +1 -1
- package/dist/components/lido-math-matrix.js +1 -1
- package/dist/components/lido-root.js +1 -1
- package/dist/components/lido-text.js +1 -1
- package/dist/components/lido-trace.js +1 -1
- package/dist/components/p-BNNX1Pew.js +12 -0
- package/dist/components/p-CTlwn9r7.js +1 -0
- package/dist/components/{p-C2p0KZh4.js → p-Cj-6tqzU.js} +1 -1
- package/dist/components/p-CjdDpXfk.js +1 -0
- package/dist/components/{p-Uluc7jQ7.js → p-D54c-ybm.js} +1 -1
- package/dist/components/p-DdQ1eqJr.js +1 -0
- package/dist/components/{p-D-IYWSAa.js → p-SPZTb5fI.js} +1 -1
- package/dist/components/p-yT7udDfd.js +1 -0
- package/dist/esm/{decode-CGJIPA4t.js → decode-BgBfbPZu.js} +1 -1
- package/dist/esm/{index-Dq-Z8Dx0.js → index-BeHFCsWf.js} +54 -13
- package/dist/esm/{index-C854B63S.js → index-D-29PaRa.js} +189 -53
- package/dist/esm/index.js +2 -2
- package/dist/esm/lido-avatar_22.entry.js +60 -54
- package/dist/esm/lido-player.js +4 -4
- package/dist/esm/loader.js +3 -3
- package/dist/lido-player/assets/Shadow.svg +9 -0
- package/dist/lido-player/assets/Tracing-hand.svg +8 -0
- package/dist/lido-player/index.esm.js +1 -1
- package/dist/lido-player/lido-player.css +1 -1
- package/dist/lido-player/lido-player.esm.js +1 -1
- package/dist/lido-player/p-856e1956.entry.js +12 -0
- package/dist/lido-player/{p-Bg5mBsd9.js → p-BA2X6O7O.js} +1 -1
- package/dist/lido-player/p-BeHFCsWf.js +3 -0
- package/dist/lido-player/p-TuBmCgtK.js +1 -0
- package/dist/types/components/scale/lido-balance.d.ts +2 -2
- package/dist/types/components/text/lido-text.d.ts +6 -1
- package/dist/types/components/trace/lido-trace.d.ts +1 -1
- package/dist/types/components.d.ts +21 -10
- package/dist/types/stencil-public-runtime.d.ts +12 -0
- package/dist/types/utils/audioPlayer.d.ts +2 -0
- package/dist/types/utils/utilsHandlers/slideHandler.d.ts +5 -0
- package/loader/index.d.ts +1 -1
- package/package.json +1 -1
- package/dist/components/p-C7U1h9gI.js +0 -1
- package/dist/components/p-CS6iRQJh.js +0 -1
- package/dist/components/p-DGvzMlyn.js +0 -12
- package/dist/components/p-DPAlnts-.js +0 -1
- package/dist/components/p-DYs8s-uh.js +0 -1
- package/dist/lido-player/p-C4OTDhbr.js +0 -1
- package/dist/lido-player/p-Dq-Z8Dx0.js +0 -2
- package/dist/lido-player/p-f0e333c6.entry.js +0 -12
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { h, Host } from "@stencil/core";
|
|
1
|
+
import { h, Host, getAssetPath } from "@stencil/core";
|
|
2
2
|
import { convertUrlToRelative, executeActions, triggerNextContainer, speakIcon, setVisibilityWithDelay, parseProp, storingEachActivityScore, calculateScore, } from "../../utils/utils";
|
|
3
3
|
import { fingerUrl, LidoContainer, TraceMode } from "../../utils/constants";
|
|
4
4
|
// Enum for different tracing modes
|
|
@@ -88,7 +88,7 @@ export class LidoTrace {
|
|
|
88
88
|
/**
|
|
89
89
|
* URL for the finger hint image
|
|
90
90
|
*/
|
|
91
|
-
this.fingerHintUrl = '
|
|
91
|
+
this.fingerHintUrl = getAssetPath('assets/Tracing-hand.svg');
|
|
92
92
|
/**
|
|
93
93
|
* Indicates whether to highlight the text associated with the SVG when the trace is completed.
|
|
94
94
|
*/
|
|
@@ -112,6 +112,8 @@ export class LidoTrace {
|
|
|
112
112
|
this.isDragging = false;
|
|
113
113
|
this.activePointerId = null;
|
|
114
114
|
// Counter for throttling free trace updates
|
|
115
|
+
// This is only an internal counter. Keeping it out of @State prevents a
|
|
116
|
+
// Stencil component re-render while the user is dragging.
|
|
115
117
|
this.freeTraceUpdateCounter = 0;
|
|
116
118
|
/** ───────────────────────────────────────────────────────────
|
|
117
119
|
* NEW: idle‑timer + finger‑hint state
|
|
@@ -144,6 +146,7 @@ export class LidoTrace {
|
|
|
144
146
|
lastPointerPos: null,
|
|
145
147
|
dragOffset: null,
|
|
146
148
|
isCompletingPath: false,
|
|
149
|
+
touchProximityThreshold: null,
|
|
147
150
|
};
|
|
148
151
|
const url = this.svgUrls[this.currentSvgIndex];
|
|
149
152
|
if (!url || url.trim() === '') {
|
|
@@ -363,6 +366,12 @@ export class LidoTrace {
|
|
|
363
366
|
setupDrawingPath(state) {
|
|
364
367
|
state.paths.forEach((path, index) => {
|
|
365
368
|
const pathLength = path.getTotalLength();
|
|
369
|
+
// Geometry calls are expensive on slower SVG implementations. Cache
|
|
370
|
+
// the length once and reuse it during pointer movement.
|
|
371
|
+
path._lidoTraceLength = pathLength;
|
|
372
|
+
path._lidoTraceStart = path.getPointAtLength(0);
|
|
373
|
+
path._lidoTraceEnd = path.getPointAtLength(pathLength);
|
|
374
|
+
path._lidoTraceIsClosed = this.getDistanceSquared(path._lidoTraceStart, path._lidoTraceEnd) < 200;
|
|
366
375
|
// /** give every path an id so <mpath> can follow it */
|
|
367
376
|
path.setAttribute('id', 'lido-path-' + index); // ← NEW
|
|
368
377
|
// Create green path for tracing effect
|
|
@@ -484,7 +493,7 @@ export class LidoTrace {
|
|
|
484
493
|
}
|
|
485
494
|
// Modified handlePointerMove function
|
|
486
495
|
async handlePointerMove(state) {
|
|
487
|
-
var _a, _b, _c, _d, _e
|
|
496
|
+
var _a, _b, _c, _d, _e;
|
|
488
497
|
if (!state.isDragging)
|
|
489
498
|
return;
|
|
490
499
|
if (!state.circle || !state.paths || state.paths.length === 0)
|
|
@@ -584,19 +593,9 @@ export class LidoTrace {
|
|
|
584
593
|
// Move the draggable circle with the freehand trace
|
|
585
594
|
state.circle.setAttribute('cx', pointerPos.x.toString());
|
|
586
595
|
state.circle.setAttribute('cy', pointerPos.y.toString());
|
|
587
|
-
//
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
for (let i = 0; i < ((childNodes === null || childNodes === void 0 ? void 0 : childNodes.length) || 0); i++) {
|
|
591
|
-
const child = childNodes === null || childNodes === void 0 ? void 0 : childNodes.item(i);
|
|
592
|
-
if (child && child.tagName === 'circle') {
|
|
593
|
-
circleFound = true;
|
|
594
|
-
break; // No need to continue once found
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
// If not found, append the circle
|
|
598
|
-
if (!circleFound && state.circle) {
|
|
599
|
-
(_c = state.svg) === null || _c === void 0 ? void 0 : _c.appendChild(state.circle);
|
|
596
|
+
// Keep the original safety check without scanning every SVG child.
|
|
597
|
+
if (state.circle.parentNode !== state.svg) {
|
|
598
|
+
(_b = state.svg) === null || _b === void 0 ? void 0 : _b.appendChild(state.circle);
|
|
600
599
|
}
|
|
601
600
|
// Update the last pointer position
|
|
602
601
|
state.lastPointerPos = pointerPos;
|
|
@@ -640,27 +639,15 @@ export class LidoTrace {
|
|
|
640
639
|
state.circle.setAttribute('cx', guidedClosestPoint.x.toString());
|
|
641
640
|
state.circle.setAttribute('cy', guidedClosestPoint.y.toString());
|
|
642
641
|
}
|
|
643
|
-
//
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
for (let i = 0; i < ((childNodes === null || childNodes === void 0 ? void 0 : childNodes.length) || 0); i++) {
|
|
647
|
-
const child = childNodes === null || childNodes === void 0 ? void 0 : childNodes.item(i);
|
|
648
|
-
if (child && child.tagName === 'circle') {
|
|
649
|
-
circleFound = true;
|
|
650
|
-
break; // No need to continue once found
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
// If not found, append the circle
|
|
654
|
-
if (!circleFound && state.circle) {
|
|
655
|
-
(_e = state.svg) === null || _e === void 0 ? void 0 : _e.appendChild(state.circle);
|
|
642
|
+
// Keep the original safety check without scanning every SVG child.
|
|
643
|
+
if (state.circle.parentNode !== state.svg) {
|
|
644
|
+
(_c = state.svg) === null || _c === void 0 ? void 0 : _c.appendChild(state.circle);
|
|
656
645
|
}
|
|
657
|
-
(
|
|
646
|
+
(_d = currentPath.greenPath) === null || _d === void 0 ? void 0 : _d.setAttribute('stroke-dashoffset', (state.totalPathLength - state.lastLength).toString());
|
|
658
647
|
// Completion logic for closed paths: only allow completion if almost all points are traced
|
|
659
648
|
const COMPLETION_THRESHOLD = 0.95; // 95% of the path must be traced
|
|
660
649
|
let percentComplete = state.lastLength / state.totalPathLength;
|
|
661
|
-
|
|
662
|
-
let endPoint = currentPath.getPointAtLength(currentPath.getTotalLength());
|
|
663
|
-
let pathIsClosed = this.getDistanceSquared(startPoint, endPoint) < 200; // threshold for overlap
|
|
650
|
+
const pathIsClosed = (_e = currentPath._lidoTraceIsClosed) !== null && _e !== void 0 ? _e : false;
|
|
664
651
|
if (pathIsClosed && state.totalPathLength > 50) {
|
|
665
652
|
if (percentComplete >= COMPLETION_THRESHOLD) {
|
|
666
653
|
if (state.isCompletingPath)
|
|
@@ -854,7 +841,8 @@ export class LidoTrace {
|
|
|
854
841
|
}
|
|
855
842
|
// Find the closest point on the given path to the specified point using two-pass sampling (optimized)
|
|
856
843
|
getClosestPointOnPath(pathNode, point, lastLength) {
|
|
857
|
-
|
|
844
|
+
var _a;
|
|
845
|
+
const pathLength = (_a = pathNode._lidoTraceLength) !== null && _a !== void 0 ? _a : pathNode.getTotalLength();
|
|
858
846
|
let closestPoint = { x: 0, y: 0, length: 0 };
|
|
859
847
|
let minDistanceSquared = Infinity;
|
|
860
848
|
const coarseStep = 40;
|
|
@@ -1047,7 +1035,7 @@ export class LidoTrace {
|
|
|
1047
1035
|
};
|
|
1048
1036
|
}
|
|
1049
1037
|
render() {
|
|
1050
|
-
return (h(Host, { key: '
|
|
1038
|
+
return (h(Host, { key: '4955636a199ba56ca7f6d73144aca42ab4e3f411', class: "lido-trace", id: this.id, audio: this.audio, onCorrect: this.onCorrect, onInCorrect: this.onInCorrect, style: this.style, "aria-label": this.ariaLabel, "aria-hidden": this.ariaHidden, tabindex: this.tabIndex, "disable-speak": this.disableSpeak }, h("div", { key: 'b732946e97fefb0d4cb192e5c9b6863568ff64be', style: this.style, id: "lido-svgContainer" })));
|
|
1051
1039
|
}
|
|
1052
1040
|
static get is() { return "lido-trace"; }
|
|
1053
1041
|
static get originalStyleUrls() {
|
|
@@ -1060,7 +1048,7 @@ export class LidoTrace {
|
|
|
1060
1048
|
"$": ["lido-trace.css"]
|
|
1061
1049
|
};
|
|
1062
1050
|
}
|
|
1063
|
-
static get assetsDirs() { return ["
|
|
1051
|
+
static get assetsDirs() { return ["assets"]; }
|
|
1064
1052
|
static get properties() {
|
|
1065
1053
|
return {
|
|
1066
1054
|
"showSpeakIcon": {
|
|
@@ -1361,7 +1349,7 @@ export class LidoTrace {
|
|
|
1361
1349
|
"setter": false,
|
|
1362
1350
|
"reflect": false,
|
|
1363
1351
|
"attribute": "finger-hint-url",
|
|
1364
|
-
"defaultValue": "'
|
|
1352
|
+
"defaultValue": "getAssetPath('assets/Tracing-hand.svg')"
|
|
1365
1353
|
},
|
|
1366
1354
|
"onInCorrect": {
|
|
1367
1355
|
"type": "string",
|
|
@@ -1493,7 +1481,6 @@ export class LidoTrace {
|
|
|
1493
1481
|
"fileIndex": {},
|
|
1494
1482
|
"isDragging": {},
|
|
1495
1483
|
"activePointerId": {},
|
|
1496
|
-
"freeTraceUpdateCounter": {},
|
|
1497
1484
|
"idleTimer": {},
|
|
1498
1485
|
"fingerImg": {}
|
|
1499
1486
|
};
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
@
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
@font-face {
|
|
2
|
+
font-family: 'Baloo Bhai 2';
|
|
3
|
+
font-style: normal;
|
|
4
|
+
font-weight: 400 800;
|
|
5
|
+
font-display: swap;
|
|
6
|
+
src: url('../assets/offline-assets/fonts/Baloo-Bhai-2/Baloo-Bhai-2-Variable.woff2') format('woff2');
|
|
7
|
+
}
|
|
4
8
|
body {
|
|
5
9
|
overflow: hidden;
|
|
6
10
|
background-position: center;
|
|
@@ -189,7 +193,6 @@ body {
|
|
|
189
193
|
top: -25px;
|
|
190
194
|
right: -25px;
|
|
191
195
|
z-index: 10;
|
|
192
|
-
background-image : url("https://aeakbcdznktpsbrfsgys.supabase.co/storage/v1/object/public/template-assets/template/audioIcon.png");
|
|
193
196
|
background-color: white;
|
|
194
197
|
border : 4px solid #F34D08;
|
|
195
198
|
border-radius :16px;
|
|
@@ -39,13 +39,16 @@ function buildObjectiveFromNumber(num) {
|
|
|
39
39
|
const objective = [hStr, tStr, oStr].filter(s => s !== "").join(",");
|
|
40
40
|
return {
|
|
41
41
|
objective, // same as before
|
|
42
|
+
hundreds,
|
|
43
|
+
tens,
|
|
44
|
+
ones,
|
|
42
45
|
};
|
|
43
46
|
}
|
|
44
47
|
function getContainerXml(args) {
|
|
45
|
-
const { objective } = buildObjectiveFromNumber(args.number);
|
|
48
|
+
const { objective, hundreds, tens, ones } = buildObjectiveFromNumber(args.number);
|
|
46
49
|
return `
|
|
47
50
|
<main>
|
|
48
|
-
<lido-container id="lido-container" visible="true" template-id="
|
|
51
|
+
<lido-container id="lido-container" visible="true" template-id="blender" objective="${objective}" onCorrect="lido-avatar.avatarAnimate='Success'; this.sleep='2000';" onInCorrect="lido-avatar.avatarAnimate='Fail'; this.sleep='2000';" onEntry="" is-continue-on-correct="true" bg-color="transparent" bg-image="https://aeakbcdznktpsbrfsgys.supabase.co/storage/v1/object/public/template-assets/background-images/Blender.png" drop-action="infinite-drop" is-allow-only-correct="${args.isAllowOnlyCorrect}">
|
|
49
52
|
|
|
50
53
|
<!-- Chimple Avatar -->
|
|
51
54
|
<lido-cell layout="pos" id="pos1" disable-edit="true" value="pos2" height="landscape.448px,portrait.402px" width="landscape.350px,portrait.398px" x="landscape.1332px, portrait.-8%" y="landscape.547px, portrait.1%" aria-hidden="true" z="0" bg-color="transparent" visible="true" onEntry="">
|
|
@@ -65,7 +68,7 @@ function getContainerXml(args) {
|
|
|
65
68
|
<lido-text id="hundreds" height="70px" width="108px" visible="true" value="000" string="000" font-family="'Baloo Bhai 2'" font-color="#182A4F" border-radius="21px" bg-color="white" font-size="52px" onInCorrect="" onEntry="this.fontWeight='800';" border-image="">
|
|
66
69
|
</lido-text>
|
|
67
70
|
</lido-cell>
|
|
68
|
-
<lido-text id="hundredsDrop" value="100" dropAttr="landscape.stackcascade,portrait.verticalstack" is-allow-only-one-drop="false" type="drop" tab-index="1" layout="row" bg-color="white" visible="true" height="landscape.359px,portrait.752px"
|
|
71
|
+
<lido-text id="hundredsDrop" value="100" required-drops="${hundreds}" dropAttr="landscape.stackcascade,portrait.verticalstack" is-allow-only-one-drop="false" type="drop" tab-index="1" layout="row" bg-color="white" visible="true" height="landscape.359px,portrait.752px" width="landscape.698px,portrait.290px" onEntry="this.justify-content='flex-start';">
|
|
69
72
|
</lido-text>
|
|
70
73
|
</lido-cell>
|
|
71
74
|
|
|
@@ -77,7 +80,8 @@ function getContainerXml(args) {
|
|
|
77
80
|
<lido-text id="tens" height="70px" width="77px" visible="true" value="00" string="00" font-family="'Baloo Bhai 2'" font-color="#182A4F" border-radius="21px" bg-color="white" font-size="52px" onInCorrect="" onEntry="this.fontWeight='800';" border-image="">
|
|
78
81
|
</lido-text>
|
|
79
82
|
</lido-cell>
|
|
80
|
-
<lido-text id="tensDrop" value="10" dropAttr="landscape.stackcascade,portrait.verticalstack" type="drop" is-allow-only-one-drop="false" tab-index="2" layout="row" bg-color="white" visible="true"
|
|
83
|
+
<lido-text id="tensDrop" value="10" required-drops="${tens}" dropAttr="landscape.stackcascade,portrait.verticalstack" type="drop" is-allow-only-one-drop="false" tab-index="2" layout="row" bg-color="white" visible="true"
|
|
84
|
+
height="landscape.357px,portrait.752px" width="landscape.414px,portrait.290px" onEntry="this.justify-content='flex-start';" >
|
|
81
85
|
</lido-text>
|
|
82
86
|
</lido-cell>
|
|
83
87
|
|
|
@@ -89,7 +93,7 @@ function getContainerXml(args) {
|
|
|
89
93
|
<lido-text id="units" height="70px" width="55px" visible="true" value="0" string="0" font-family="'Baloo Bhai 2'" font-color="#182A4F" border-radius="21px" bg-color="white" font-size="52px" onInCorrect="" onEntry="this.fontWeight='800';" border-image="">
|
|
90
94
|
</lido-text>
|
|
91
95
|
</lido-cell>
|
|
92
|
-
<lido-text id="unitsDrop" value="1" dropAttr="landscape.stackcascade,portrait.verticalstack" type="drop" is-allow-only-one-drop="false" tab-index="3" layout="row" bg-color="white" visible="true" height="landscape.360px,portrait.752px" width="landscape.310px,portrait.290px" onEntry="this.justify-content='flex-start';">
|
|
96
|
+
<lido-text id="unitsDrop" value="1" required-drops="${ones}" dropAttr="landscape.stackcascade,portrait.verticalstack" type="drop" is-allow-only-one-drop="false" tab-index="3" layout="row" bg-color="white" visible="true" height="landscape.360px,portrait.752px" width="landscape.310px,portrait.290px" onEntry="this.justify-content='flex-start';">
|
|
93
97
|
</lido-text>
|
|
94
98
|
</lido-cell>
|
|
95
99
|
</lido-cell>
|
|
@@ -4,9 +4,18 @@ import { setDraggingDisabled } from "./utilsHandlers/dragDropHandler";
|
|
|
4
4
|
import { NextContainerKey, PrevContainerKey, ActivityChangeKey, GameCompletedKey, GameExitKey, ActivityEndKey, LessonEndKey, LidoContainer } from "./constants";
|
|
5
5
|
import { LANGUAGE_PROFILES, FAST_WORDS_BY_LANG } from "./constants";
|
|
6
6
|
export class AudioPlayer {
|
|
7
|
+
resolvePlaybackWait() {
|
|
8
|
+
if (!this.endPromiseResolve) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const resolve = this.endPromiseResolve;
|
|
12
|
+
this.endPromiseResolve = null;
|
|
13
|
+
resolve();
|
|
14
|
+
}
|
|
7
15
|
constructor() {
|
|
8
16
|
this.currentTargetElement = null;
|
|
9
17
|
this.pendingReplayElement = null;
|
|
18
|
+
this.playbackHasStarted = false;
|
|
10
19
|
this.highlightOverlay = null;
|
|
11
20
|
this.wordRects = [];
|
|
12
21
|
this.activeWordIndex = -1;
|
|
@@ -64,15 +73,12 @@ export class AudioPlayer {
|
|
|
64
73
|
window.speechSynthesis.cancel();
|
|
65
74
|
}
|
|
66
75
|
// Resolve any pending "ended" wait so callers can continue.
|
|
67
|
-
|
|
68
|
-
const resolve = this.endPromiseResolve;
|
|
69
|
-
this.endPromiseResolve = null;
|
|
70
|
-
resolve();
|
|
71
|
-
}
|
|
76
|
+
this.resolvePlaybackWait();
|
|
72
77
|
if (!preserveReplay) {
|
|
73
78
|
this.pendingReplayElement = null;
|
|
74
79
|
}
|
|
75
80
|
this.currentTargetElement = null;
|
|
81
|
+
this.playbackHasStarted = false;
|
|
76
82
|
this.audioElement.pause();
|
|
77
83
|
this.audioElement.currentTime = 0;
|
|
78
84
|
this.audioElement.src = '';
|
|
@@ -110,6 +116,7 @@ export class AudioPlayer {
|
|
|
110
116
|
}
|
|
111
117
|
async play(targetElement) {
|
|
112
118
|
this.registerVisibilityEvents();
|
|
119
|
+
this.playbackHasStarted = false;
|
|
113
120
|
if (!this.isWindowVisible()) {
|
|
114
121
|
this.pendingReplayElement = targetElement;
|
|
115
122
|
await this.stop(true);
|
|
@@ -163,6 +170,24 @@ export class AudioPlayer {
|
|
|
163
170
|
if (audioUrl) {
|
|
164
171
|
audioUrl = convertUrlToRelative(audioUrl);
|
|
165
172
|
this.audioElement.src = audioUrl;
|
|
173
|
+
this.audioElement.onplaying = () => {
|
|
174
|
+
this.playbackHasStarted = true;
|
|
175
|
+
};
|
|
176
|
+
this.audioElement.onpause = () => {
|
|
177
|
+
if (this.playbackHasStarted && !this.audioElement.ended) {
|
|
178
|
+
this.resolvePlaybackWait();
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
this.audioElement.onstalled = () => {
|
|
182
|
+
if (this.playbackHasStarted) {
|
|
183
|
+
this.resolvePlaybackWait();
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
this.audioElement.onerror = () => {
|
|
187
|
+
if (this.playbackHasStarted) {
|
|
188
|
+
this.resolvePlaybackWait();
|
|
189
|
+
}
|
|
190
|
+
};
|
|
166
191
|
try {
|
|
167
192
|
// setDraggingDisabled(true);
|
|
168
193
|
const language = container.getAttribute('Lang') || 'en';
|
|
@@ -192,10 +217,7 @@ export class AudioPlayer {
|
|
|
192
217
|
await new Promise(resolve => {
|
|
193
218
|
this.endPromiseResolve = resolve;
|
|
194
219
|
this.audioElement.onended = () => {
|
|
195
|
-
|
|
196
|
-
this.endPromiseResolve = null;
|
|
197
|
-
}
|
|
198
|
-
resolve();
|
|
220
|
+
this.resolvePlaybackWait();
|
|
199
221
|
};
|
|
200
222
|
});
|
|
201
223
|
}
|
|
@@ -337,10 +337,11 @@ export const executeActions = async (actionsString, thisElement, element) => {
|
|
|
337
337
|
if (dropTo === "hundredsDrop")
|
|
338
338
|
hundreds++;
|
|
339
339
|
});
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
const
|
|
343
|
-
const
|
|
340
|
+
// Blender displays the number of blocks placed in each column.
|
|
341
|
+
// Blender's drag/drop values are also the required block counts.
|
|
342
|
+
const unitsValue = units;
|
|
343
|
+
const tensValue = tens;
|
|
344
|
+
const hundredsValue = hundreds;
|
|
344
345
|
// ✅ Update Lido Text Boxes
|
|
345
346
|
const unitsBox = document.getElementById("units");
|
|
346
347
|
const tensBox = document.getElementById("tens");
|
|
@@ -601,18 +602,27 @@ export const calculateScore = () => {
|
|
|
601
602
|
gameScore.totalRightMovesCount += rightMoves;
|
|
602
603
|
gameScore.totalWrongMovesCount += wrongMoves;
|
|
603
604
|
let finalScore = Math.floor((rightMoves / (rightMoves + wrongMoves)) * 100);
|
|
605
|
+
console.log('[Activity Score]', { rightMoves, wrongMoves, activityScore: finalScore });
|
|
604
606
|
storeActivityScore(finalScore);
|
|
605
607
|
gameScore.rightMoves = 0;
|
|
606
608
|
gameScore.wrongMoves = 0;
|
|
607
609
|
};
|
|
608
610
|
export async function onActivityComplete(dragElement, dropElement) {
|
|
609
|
-
var _a, _b;
|
|
611
|
+
var _a, _b, _c;
|
|
610
612
|
const container = document.getElementById(LidoContainer);
|
|
611
613
|
if (!container)
|
|
612
614
|
return;
|
|
615
|
+
const isBlender = container.getAttribute('template-id') === 'blender';
|
|
613
616
|
await executeActions("this.alignMatch='true'", dropElement, dragElement);
|
|
614
617
|
if (dragElement && dropElement) {
|
|
615
|
-
|
|
618
|
+
let isCorrect = dropElement['value'].toLowerCase().includes(dragElement['value'].toLowerCase());
|
|
619
|
+
if (isBlender) {
|
|
620
|
+
const requiredDrops = Number((_a = dropElement.getAttribute('required-drops')) !== null && _a !== void 0 ? _a : 0);
|
|
621
|
+
const placedDrops = document.querySelectorAll(`[drop-to="${dropElement.id}"]`).length;
|
|
622
|
+
// Blender accepts every count from 1 through the required count.
|
|
623
|
+
// Zero or an overfilled drop zone uses the incorrect action.
|
|
624
|
+
isCorrect = placedDrops > 0 && placedDrops <= requiredDrops;
|
|
625
|
+
}
|
|
616
626
|
// storing each activity score based on isCorrect for (all drag-drop events)
|
|
617
627
|
// storingEachActivityScore(isCorrect);
|
|
618
628
|
if (isCorrect) {
|
|
@@ -621,10 +631,10 @@ export async function onActivityComplete(dragElement, dropElement) {
|
|
|
621
631
|
console.log("Right Moves : ", gameScore.rightMoves);
|
|
622
632
|
console.log("Wrong Moves : ", gameScore.wrongMoves);
|
|
623
633
|
}
|
|
624
|
-
const onCorrect = ((
|
|
634
|
+
const onCorrect = ((_b = container.getAttribute('dropAttr')) === null || _b === void 0 ? void 0 : _b.toLowerCase()) === DropMode.EnableAnimation.toLowerCase()
|
|
625
635
|
? ''
|
|
626
636
|
: dropElement.getAttribute('onCorrect');
|
|
627
|
-
if (onCorrect) {
|
|
637
|
+
if (onCorrect && !isBlender) {
|
|
628
638
|
await executeActions(onCorrect, dropElement, dragElement);
|
|
629
639
|
}
|
|
630
640
|
//for multiply beeds
|
|
@@ -639,7 +649,7 @@ export async function onActivityComplete(dragElement, dropElement) {
|
|
|
639
649
|
console.log("Wrong Moves : ", gameScore.wrongMoves);
|
|
640
650
|
}
|
|
641
651
|
const onInCorrect = dropElement.getAttribute('onInCorrect');
|
|
642
|
-
if (onInCorrect) {
|
|
652
|
+
if (onInCorrect && !isBlender) {
|
|
643
653
|
await executeActions(onInCorrect, dropElement, dragElement);
|
|
644
654
|
}
|
|
645
655
|
}
|
|
@@ -648,7 +658,7 @@ export async function onActivityComplete(dragElement, dropElement) {
|
|
|
648
658
|
const sortedValues = getSortedValuesArrayFromMap(dragScore);
|
|
649
659
|
container.setAttribute(SelectedValuesKey, JSON.stringify(sortedValues));
|
|
650
660
|
//localStorage
|
|
651
|
-
let drag = JSON.parse((
|
|
661
|
+
let drag = JSON.parse((_c = localStorage.getItem(DragMapKey)) !== null && _c !== void 0 ? _c : '{}');
|
|
652
662
|
const index = dropElement.getAttribute('tab-index');
|
|
653
663
|
if (!drag[index]) {
|
|
654
664
|
drag[index] = [];
|
|
@@ -60,7 +60,7 @@ export function dragDropAnimation(container, dragElement, dropElement) {
|
|
|
60
60
|
dropElement.classList.remove('zoom-fade-in');
|
|
61
61
|
dragElement.classList.add('zoom-fade-out');
|
|
62
62
|
dropElement.classList.add('zoom-fade-out');
|
|
63
|
-
|
|
63
|
+
const cleanup = () => {
|
|
64
64
|
div.remove();
|
|
65
65
|
container.style.pointerEvents = 'auto';
|
|
66
66
|
if (isObjectiveComplete) {
|
|
@@ -68,6 +68,13 @@ export function dragDropAnimation(container, dragElement, dropElement) {
|
|
|
68
68
|
triggerNextContainer();
|
|
69
69
|
container.removeAttribute(AnimationVanishedValuesKey);
|
|
70
70
|
}
|
|
71
|
-
}
|
|
71
|
+
};
|
|
72
|
+
const templateId = (container.getAttribute('template-id') || '').toLowerCase();
|
|
73
|
+
if (templateId === 'letterpairing' || templateId === 'numberpair') {
|
|
74
|
+
cleanup();
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
setTimeout(cleanup, 800); // match animation duration
|
|
78
|
+
}
|
|
72
79
|
}, 250);
|
|
73
80
|
}
|
|
@@ -65,6 +65,14 @@ export function addClickListenerForClickType(element) {
|
|
|
65
65
|
const container = document.getElementById(LidoContainer);
|
|
66
66
|
if (container.getAttribute('canplay') === 'false')
|
|
67
67
|
return;
|
|
68
|
+
const isBubbleTypeKeyboardKey = (container === null || container === void 0 ? void 0 : container.getAttribute('template-id')) === 'bubbleType' &&
|
|
69
|
+
element.closest('lido-keyboard') !== null;
|
|
70
|
+
// BubbleType manages key clicks and audio in lido-keyboard.tsx directly.
|
|
71
|
+
// Letting the generic click handler attach here creates a competing stop/play
|
|
72
|
+
// path that can interrupt the first bubble audio.
|
|
73
|
+
if (isBubbleTypeKeyboardKey) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
68
76
|
element.style.cursor = 'pointer';
|
|
69
77
|
if (!element) {
|
|
70
78
|
console.error('No element provided.');
|
|
@@ -5,6 +5,7 @@ import { DropLength, SelectedValuesKey, DropMode, DropToAttr, DropTimeAttr, Lido
|
|
|
5
5
|
import { dispatchElementDropEvent } from "../customEvents";
|
|
6
6
|
import { highlightElement, removeHighlight } from "./highlightHandler";
|
|
7
7
|
import { dragDropAnimation } from "./animationHandler";
|
|
8
|
+
const isBlenderTemplate = (container) => (container === null || container === void 0 ? void 0 : container.getAttribute('template-id')) === 'blender';
|
|
8
9
|
export function buildDropHasDragFromDOM() {
|
|
9
10
|
const dropHasDrag = {};
|
|
10
11
|
const dropElements = document.querySelectorAll("[type='drop']");
|
|
@@ -63,7 +64,6 @@ export function enableDraggingWithScaling(element) {
|
|
|
63
64
|
let mutationFlag = false;
|
|
64
65
|
// Fetch the container element
|
|
65
66
|
const container = document.getElementById(LidoContainer);
|
|
66
|
-
const templateId = container.getAttribute("template-id");
|
|
67
67
|
if (!container) {
|
|
68
68
|
console.error(`Container with ID "container" not found.`);
|
|
69
69
|
return;
|
|
@@ -230,7 +230,7 @@ export function enableDraggingWithScaling(element) {
|
|
|
230
230
|
allElements.forEach(otherElement => {
|
|
231
231
|
var _a;
|
|
232
232
|
if (storedTabIndexes.includes(JSON.parse(otherElement.getAttribute('tab-index')))) {
|
|
233
|
-
if (!(((_a = element.getAttribute('dropAttr')) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === DropMode.Diagonal) && container
|
|
233
|
+
if (!(((_a = element.getAttribute('dropAttr')) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === DropMode.Diagonal) && !isBlenderTemplate(container)) {
|
|
234
234
|
if (otherElement) {
|
|
235
235
|
setOpacityIfChanged(otherElement, "0.3");
|
|
236
236
|
}
|
|
@@ -318,7 +318,7 @@ export function enableDraggingWithScaling(element) {
|
|
|
318
318
|
else {
|
|
319
319
|
onElementDropComplete(element, mostOverlappedElement);
|
|
320
320
|
}
|
|
321
|
-
if (
|
|
321
|
+
if (isBlenderTemplate(container) && element && mostOverlappedElement) {
|
|
322
322
|
const allElements = document.querySelectorAll(`*`);
|
|
323
323
|
allElements.forEach(el => {
|
|
324
324
|
removeHighlight(el);
|
|
@@ -546,7 +546,7 @@ export async function handleResetDragElement(dragElement, dropElement, dropHasDr
|
|
|
546
546
|
highlightElement();
|
|
547
547
|
}
|
|
548
548
|
export async function onElementDropComplete(dragElement, dropElement) {
|
|
549
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
549
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
550
550
|
const container = document.getElementById(LidoContainer);
|
|
551
551
|
const selectedValueData = (_a = container.getAttribute(SelectedValuesKey)) !== null && _a !== void 0 ? _a : "[]";
|
|
552
552
|
const dragSelectedData = JSON.stringify(buildDragSelectedMapFromDOM());
|
|
@@ -769,28 +769,48 @@ export async function onElementDropComplete(dragElement, dropElement) {
|
|
|
769
769
|
// Add pulse and highlight effect for a successful match
|
|
770
770
|
const isCorrect = dropElement['value'].toLowerCase().includes(dragElement['value'].toLowerCase());
|
|
771
771
|
dispatchElementDropEvent(dragElement, dropElement, isCorrect);
|
|
772
|
-
if (container
|
|
772
|
+
if (!isBlenderTemplate(container)) {
|
|
773
773
|
storingEachActivityScore(isCorrect);
|
|
774
774
|
}
|
|
775
775
|
dragElement.style.opacity = '1';
|
|
776
776
|
const allDropElements = document.querySelectorAll('.drop-element');
|
|
777
777
|
allDropElements.forEach(el => updateDropBorder(el));
|
|
778
|
+
if (isBlenderTemplate(container)) {
|
|
779
|
+
const requiredDrops = Number((_j = dropElement.getAttribute('required-drops')) !== null && _j !== void 0 ? _j : 0);
|
|
780
|
+
const placedDrops = document.querySelectorAll(`[${DropToAttr}="${dropElement.id}"]`).length;
|
|
781
|
+
const action = placedDrops > 0 && placedDrops <= requiredDrops
|
|
782
|
+
? dropElement.getAttribute('onCorrect')
|
|
783
|
+
: dropElement.getAttribute('onInCorrect');
|
|
784
|
+
if (action) {
|
|
785
|
+
await executeActions(action, dropElement, dragElement);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
778
788
|
highlightElement();
|
|
779
789
|
await onActivityComplete(dragElement, dropElement);
|
|
780
790
|
}
|
|
781
791
|
export function updateDropBorder(element) {
|
|
792
|
+
var _a;
|
|
782
793
|
if (!element || !element.classList.contains('drop-element'))
|
|
783
794
|
return;
|
|
784
795
|
const container = document.getElementById(LidoContainer);
|
|
785
796
|
if (!container)
|
|
786
797
|
return;
|
|
787
798
|
const showBorder = container.getAttribute('show-drop-border');
|
|
788
|
-
if (showBorder !== 'true') {
|
|
799
|
+
if (showBorder !== 'true' && !isBlenderTemplate(container)) {
|
|
789
800
|
return;
|
|
790
801
|
}
|
|
791
802
|
const dropId = element.id;
|
|
792
803
|
const dragSelectedElements = document.querySelectorAll(`[${DropToAttr}="${dropId}"]`);
|
|
793
|
-
if (
|
|
804
|
+
if (isBlenderTemplate(container)) {
|
|
805
|
+
const requiredDrops = Number((_a = element.getAttribute('required-drops')) !== null && _a !== void 0 ? _a : 0);
|
|
806
|
+
const placedDrops = dragSelectedElements.length;
|
|
807
|
+
const showCorrectBorder = placedDrops > 0 && placedDrops <= requiredDrops;
|
|
808
|
+
element.classList.toggle('empty', !showCorrectBorder);
|
|
809
|
+
element.classList.remove('filled');
|
|
810
|
+
element.style.setProperty('border', showCorrectBorder ? '5px dashed green' : '5px dashed #f34d08', 'important');
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
if (dragSelectedElements.length > 0 && !isBlenderTemplate(container)) {
|
|
794
814
|
element.classList.add('filled');
|
|
795
815
|
element.classList.remove('empty');
|
|
796
816
|
element.classList.remove('highlight-element');
|
|
@@ -880,7 +900,7 @@ export async function onClickDropOrDragElement(element, type) {
|
|
|
880
900
|
// Move the drag element to the drop position
|
|
881
901
|
selectedDragElement.style.transform = `translate(${translateX}px, ${translateY}px)`;
|
|
882
902
|
// Remove highlights after moving the element
|
|
883
|
-
if (container
|
|
903
|
+
if (!isBlenderTemplate(container)) {
|
|
884
904
|
const allElements = document.querySelectorAll(`*`);
|
|
885
905
|
allElements.forEach(el => {
|
|
886
906
|
removeHighlight(el);
|
|
@@ -4,27 +4,24 @@ const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
|
4
4
|
/* ------------------ animation ------------------ */
|
|
5
5
|
const animationToRemoveEquationSolvedCellForNimbleTable = (activeCell, container) => {
|
|
6
6
|
return new Promise((resolve) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}`;
|
|
16
|
-
const styleSheet = document.styleSheets[0];
|
|
17
|
-
styleSheet.insertRule(keyframes, styleSheet.cssRules.length);
|
|
18
|
-
activeCell.style.animation = `widthDecrease 0s`;
|
|
19
|
-
activeCell.addEventListener("animationend", () => {
|
|
20
|
-
activeCell.remove();
|
|
7
|
+
let removed = false;
|
|
8
|
+
const removeActiveCell = () => {
|
|
9
|
+
if (removed)
|
|
10
|
+
return;
|
|
11
|
+
removed = true;
|
|
12
|
+
if (activeCell.isConnected) {
|
|
13
|
+
activeCell.remove();
|
|
14
|
+
}
|
|
21
15
|
// Trigger next container only after the last calculate cell is removed
|
|
22
16
|
const remainingCalculateTypes = container.querySelectorAll("[type='calculate']");
|
|
23
17
|
if (remainingCalculateTypes.length === 0) {
|
|
24
18
|
setTimeout(() => triggerNextContainer(), 2000);
|
|
25
19
|
}
|
|
26
20
|
resolve();
|
|
27
|
-
}
|
|
21
|
+
};
|
|
22
|
+
// Nimble uses a zero-duration removal; remove synchronously so progression
|
|
23
|
+
// does not depend on a browser animationend event.
|
|
24
|
+
removeActiveCell();
|
|
28
25
|
});
|
|
29
26
|
};
|
|
30
27
|
/* ------------------ PRACTICE MODE ------------------ */
|