Oviya
commited on
Commit
·
972a21e
1
Parent(s):
a998588
update pronvideo
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- package-lock.json +1730 -4
- src/app/app.module.ts +5 -0
- src/app/home/home.component.html +10 -0
- src/app/home/home.component.ts +20 -0
- src/app/pronunciationragg/pronunciationragg.component.css +785 -0
- src/app/pronunciationragg/pronunciationragg.component.html +129 -0
- src/app/pronunciationragg/pronunciationragg.component.ts +950 -0
- src/app/pronunciationvideo/pronunciationvideo.component.css +785 -0
- src/app/pronunciationvideo/pronunciationvideo.component.html +129 -0
- src/app/pronunciationvideo/pronunciationvideo.component.ts +911 -0
- src/assets/pronvideo/audio.png +3 -0
- src/assets/pronvideo/audio/apple.mp3 +3 -0
- src/assets/pronvideo/audio/ball.mp3 +3 -0
- src/assets/pronvideo/audio/cat.mp3 +3 -0
- src/assets/pronvideo/audio/dog.mp3 +3 -0
- src/assets/pronvideo/audio/egg.mp3 +3 -0
- src/assets/pronvideo/audio/fish.mp3 +3 -0
- src/assets/pronvideo/audio/grapes.mp3 +3 -0
- src/assets/pronvideo/audio/hat.mp3 +3 -0
- src/assets/pronvideo/audio/icecream.mp3 +3 -0
- src/assets/pronvideo/audio/jar.mp3 +3 -0
- src/assets/pronvideo/audio/kite.mp3 +3 -0
- src/assets/pronvideo/audio/lion.mp3 +3 -0
- src/assets/pronvideo/audio/moon.mp3 +3 -0
- src/assets/pronvideo/audio/nest.mp3 +3 -0
- src/assets/pronvideo/audio/orange.mp3 +3 -0
- src/assets/pronvideo/audio/pig.mp3 +3 -0
- src/assets/pronvideo/audio/queen.mp3 +3 -0
- src/assets/pronvideo/audio/rabbit.mp3 +3 -0
- src/assets/pronvideo/audio/sun.mp3 +3 -0
- src/assets/pronvideo/audio/tree.mp3 +3 -0
- src/assets/pronvideo/audio/umbrella.mp3 +3 -0
- src/assets/pronvideo/audio/van.mp3 +3 -0
- src/assets/pronvideo/audio/watch.mp3 +3 -0
- src/assets/pronvideo/audio/xylophone.mp3 +3 -0
- src/assets/pronvideo/audio/yarn.mp3 +3 -0
- src/assets/pronvideo/audio/zebra.mp3 +3 -0
- src/assets/pronvideo/feedback/consonant.mp4 +3 -0
- src/assets/pronvideo/feedback/ending.mp4 +3 -0
- src/assets/pronvideo/feedback/multipleword.mp4 +3 -0
- src/assets/pronvideo/feedback/silence.mp4 +3 -0
- src/assets/pronvideo/feedback/stress.mp4 +3 -0
- src/assets/pronvideo/feedback/success.mp4 +3 -0
- src/assets/pronvideo/feedback/syllable.mp4 +3 -0
- src/assets/pronvideo/feedback/vowels.mp4 +3 -0
- src/assets/pronvideo/feedback/wrongword.mp4 +3 -0
- src/assets/pronvideo/pause.png +3 -0
- src/assets/pronvideo/play.png +3 -0
- src/assets/pronvideo/teacher-nod.mp4 +3 -0
- src/assets/pronvideo/teacher.png +3 -0
package-lock.json
CHANGED
|
@@ -13,6 +13,7 @@
|
|
| 13 |
"@angular/compiler": "^17.1.0",
|
| 14 |
"@angular/core": "^17.1.0",
|
| 15 |
"@angular/forms": "^17.1.0",
|
|
|
|
| 16 |
"@angular/platform-browser": "^17.1.0",
|
| 17 |
"@angular/platform-browser-dynamic": "^17.1.0",
|
| 18 |
"@angular/router": "^17.1.0",
|
|
@@ -26,6 +27,7 @@
|
|
| 26 |
"rxjs": "~7.8.0",
|
| 27 |
"tailwindcss": "^3.4.17",
|
| 28 |
"tslib": "^2.3.0",
|
|
|
|
| 29 |
"zone.js": "~0.14.3"
|
| 30 |
},
|
| 31 |
"devDependencies": {
|
|
@@ -362,6 +364,24 @@
|
|
| 362 |
"@angular/core": "17.3.12"
|
| 363 |
}
|
| 364 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 365 |
"node_modules/@angular/cli": {
|
| 366 |
"version": "17.3.11",
|
| 367 |
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-17.3.11.tgz",
|
|
@@ -535,6 +555,71 @@
|
|
| 535 |
"rxjs": "^6.5.3 || ^7.4.0"
|
| 536 |
}
|
| 537 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 538 |
"node_modules/@angular/platform-browser": {
|
| 539 |
"version": "17.3.12",
|
| 540 |
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-17.3.12.tgz",
|
|
@@ -3196,6 +3281,808 @@
|
|
| 3196 |
"node": ">= 0.4"
|
| 3197 |
}
|
| 3198 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3199 |
"node_modules/@ngtools/webpack": {
|
| 3200 |
"version": "17.3.11",
|
| 3201 |
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.3.11.tgz",
|
|
@@ -6191,7 +7078,7 @@
|
|
| 6191 |
"version": "4.5.0",
|
| 6192 |
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
| 6193 |
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
| 6194 |
-
"
|
| 6195 |
"engines": {
|
| 6196 |
"node": ">=0.12"
|
| 6197 |
},
|
|
@@ -10274,7 +11161,7 @@
|
|
| 10274 |
"version": "7.2.1",
|
| 10275 |
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz",
|
| 10276 |
"integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==",
|
| 10277 |
-
"
|
| 10278 |
"dependencies": {
|
| 10279 |
"entities": "^4.5.0"
|
| 10280 |
},
|
|
@@ -11405,6 +12292,12 @@
|
|
| 11405 |
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
| 11406 |
"dev": true
|
| 11407 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11408 |
"node_modules/sass": {
|
| 11409 |
"version": "1.71.1",
|
| 11410 |
"resolved": "https://registry.npmjs.org/sass/-/sass-1.71.1.tgz",
|
|
@@ -13484,6 +14377,12 @@
|
|
| 13484 |
"node": ">=10.13.0"
|
| 13485 |
}
|
| 13486 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13487 |
"node_modules/wbuf": {
|
| 13488 |
"version": "1.7.3",
|
| 13489 |
"resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
|
|
@@ -14136,6 +15035,16 @@
|
|
| 14136 |
"tslib": "^2.3.0"
|
| 14137 |
}
|
| 14138 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14139 |
"@angular/cli": {
|
| 14140 |
"version": "17.3.11",
|
| 14141 |
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-17.3.11.tgz",
|
|
@@ -14249,6 +15158,61 @@
|
|
| 14249 |
"tslib": "^2.3.0"
|
| 14250 |
}
|
| 14251 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14252 |
"@angular/platform-browser": {
|
| 14253 |
"version": "17.3.12",
|
| 14254 |
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-17.3.12.tgz",
|
|
@@ -16010,6 +16974,758 @@
|
|
| 16010 |
"call-bind": "^1.0.7"
|
| 16011 |
}
|
| 16012 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16013 |
"@ngtools/webpack": {
|
| 16014 |
"version": "17.3.11",
|
| 16015 |
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.3.11.tgz",
|
|
@@ -18267,7 +19983,7 @@
|
|
| 18267 |
"version": "4.5.0",
|
| 18268 |
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
| 18269 |
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
| 18270 |
-
"
|
| 18271 |
},
|
| 18272 |
"env-paths": {
|
| 18273 |
"version": "2.2.1",
|
|
@@ -21309,7 +23025,7 @@
|
|
| 21309 |
"version": "7.2.1",
|
| 21310 |
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz",
|
| 21311 |
"integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==",
|
| 21312 |
-
"
|
| 21313 |
"requires": {
|
| 21314 |
"entities": "^4.5.0"
|
| 21315 |
}
|
|
@@ -22076,6 +23792,11 @@
|
|
| 22076 |
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
| 22077 |
"dev": true
|
| 22078 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22079 |
"sass": {
|
| 22080 |
"version": "1.71.1",
|
| 22081 |
"resolved": "https://registry.npmjs.org/sass/-/sass-1.71.1.tgz",
|
|
@@ -23461,6 +25182,11 @@
|
|
| 23461 |
"graceful-fs": "^4.1.2"
|
| 23462 |
}
|
| 23463 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23464 |
"wbuf": {
|
| 23465 |
"version": "1.7.3",
|
| 23466 |
"resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
|
|
|
|
| 13 |
"@angular/compiler": "^17.1.0",
|
| 14 |
"@angular/core": "^17.1.0",
|
| 15 |
"@angular/forms": "^17.1.0",
|
| 16 |
+
"@angular/material": "^17.3.10",
|
| 17 |
"@angular/platform-browser": "^17.1.0",
|
| 18 |
"@angular/platform-browser-dynamic": "^17.1.0",
|
| 19 |
"@angular/router": "^17.1.0",
|
|
|
|
| 27 |
"rxjs": "~7.8.0",
|
| 28 |
"tailwindcss": "^3.4.17",
|
| 29 |
"tslib": "^2.3.0",
|
| 30 |
+
"wavesurfer.js": "^7.11.1",
|
| 31 |
"zone.js": "~0.14.3"
|
| 32 |
},
|
| 33 |
"devDependencies": {
|
|
|
|
| 364 |
"@angular/core": "17.3.12"
|
| 365 |
}
|
| 366 |
},
|
| 367 |
+
"node_modules/@angular/cdk": {
|
| 368 |
+
"version": "17.3.10",
|
| 369 |
+
"resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-17.3.10.tgz",
|
| 370 |
+
"integrity": "sha512-b1qktT2c1TTTe5nTji/kFAVW92fULK0YhYAvJ+BjZTPKu2FniZNe8o4qqQ0pUuvtMu+ZQxp/QqFYoidIVCjScg==",
|
| 371 |
+
"license": "MIT",
|
| 372 |
+
"peer": true,
|
| 373 |
+
"dependencies": {
|
| 374 |
+
"tslib": "^2.3.0"
|
| 375 |
+
},
|
| 376 |
+
"optionalDependencies": {
|
| 377 |
+
"parse5": "^7.1.2"
|
| 378 |
+
},
|
| 379 |
+
"peerDependencies": {
|
| 380 |
+
"@angular/common": "^17.0.0 || ^18.0.0",
|
| 381 |
+
"@angular/core": "^17.0.0 || ^18.0.0",
|
| 382 |
+
"rxjs": "^6.5.3 || ^7.4.0"
|
| 383 |
+
}
|
| 384 |
+
},
|
| 385 |
"node_modules/@angular/cli": {
|
| 386 |
"version": "17.3.11",
|
| 387 |
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-17.3.11.tgz",
|
|
|
|
| 555 |
"rxjs": "^6.5.3 || ^7.4.0"
|
| 556 |
}
|
| 557 |
},
|
| 558 |
+
"node_modules/@angular/material": {
|
| 559 |
+
"version": "17.3.10",
|
| 560 |
+
"resolved": "https://registry.npmjs.org/@angular/material/-/material-17.3.10.tgz",
|
| 561 |
+
"integrity": "sha512-hHMQES0tQPH5JW33W+mpBPuM8ybsloDTqFPuRV8cboDjosAWfJhzAKF3ozICpNlUrs62La/2Wu/756GcQrxebg==",
|
| 562 |
+
"license": "MIT",
|
| 563 |
+
"dependencies": {
|
| 564 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 565 |
+
"@material/auto-init": "15.0.0-canary.7f224ddd4.0",
|
| 566 |
+
"@material/banner": "15.0.0-canary.7f224ddd4.0",
|
| 567 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 568 |
+
"@material/button": "15.0.0-canary.7f224ddd4.0",
|
| 569 |
+
"@material/card": "15.0.0-canary.7f224ddd4.0",
|
| 570 |
+
"@material/checkbox": "15.0.0-canary.7f224ddd4.0",
|
| 571 |
+
"@material/chips": "15.0.0-canary.7f224ddd4.0",
|
| 572 |
+
"@material/circular-progress": "15.0.0-canary.7f224ddd4.0",
|
| 573 |
+
"@material/data-table": "15.0.0-canary.7f224ddd4.0",
|
| 574 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 575 |
+
"@material/dialog": "15.0.0-canary.7f224ddd4.0",
|
| 576 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 577 |
+
"@material/drawer": "15.0.0-canary.7f224ddd4.0",
|
| 578 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 579 |
+
"@material/fab": "15.0.0-canary.7f224ddd4.0",
|
| 580 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 581 |
+
"@material/floating-label": "15.0.0-canary.7f224ddd4.0",
|
| 582 |
+
"@material/form-field": "15.0.0-canary.7f224ddd4.0",
|
| 583 |
+
"@material/icon-button": "15.0.0-canary.7f224ddd4.0",
|
| 584 |
+
"@material/image-list": "15.0.0-canary.7f224ddd4.0",
|
| 585 |
+
"@material/layout-grid": "15.0.0-canary.7f224ddd4.0",
|
| 586 |
+
"@material/line-ripple": "15.0.0-canary.7f224ddd4.0",
|
| 587 |
+
"@material/linear-progress": "15.0.0-canary.7f224ddd4.0",
|
| 588 |
+
"@material/list": "15.0.0-canary.7f224ddd4.0",
|
| 589 |
+
"@material/menu": "15.0.0-canary.7f224ddd4.0",
|
| 590 |
+
"@material/menu-surface": "15.0.0-canary.7f224ddd4.0",
|
| 591 |
+
"@material/notched-outline": "15.0.0-canary.7f224ddd4.0",
|
| 592 |
+
"@material/radio": "15.0.0-canary.7f224ddd4.0",
|
| 593 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 594 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 595 |
+
"@material/segmented-button": "15.0.0-canary.7f224ddd4.0",
|
| 596 |
+
"@material/select": "15.0.0-canary.7f224ddd4.0",
|
| 597 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 598 |
+
"@material/slider": "15.0.0-canary.7f224ddd4.0",
|
| 599 |
+
"@material/snackbar": "15.0.0-canary.7f224ddd4.0",
|
| 600 |
+
"@material/switch": "15.0.0-canary.7f224ddd4.0",
|
| 601 |
+
"@material/tab": "15.0.0-canary.7f224ddd4.0",
|
| 602 |
+
"@material/tab-bar": "15.0.0-canary.7f224ddd4.0",
|
| 603 |
+
"@material/tab-indicator": "15.0.0-canary.7f224ddd4.0",
|
| 604 |
+
"@material/tab-scroller": "15.0.0-canary.7f224ddd4.0",
|
| 605 |
+
"@material/textfield": "15.0.0-canary.7f224ddd4.0",
|
| 606 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 607 |
+
"@material/tooltip": "15.0.0-canary.7f224ddd4.0",
|
| 608 |
+
"@material/top-app-bar": "15.0.0-canary.7f224ddd4.0",
|
| 609 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 610 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 611 |
+
"tslib": "^2.3.0"
|
| 612 |
+
},
|
| 613 |
+
"peerDependencies": {
|
| 614 |
+
"@angular/animations": "^17.0.0 || ^18.0.0",
|
| 615 |
+
"@angular/cdk": "17.3.10",
|
| 616 |
+
"@angular/common": "^17.0.0 || ^18.0.0",
|
| 617 |
+
"@angular/core": "^17.0.0 || ^18.0.0",
|
| 618 |
+
"@angular/forms": "^17.0.0 || ^18.0.0",
|
| 619 |
+
"@angular/platform-browser": "^17.0.0 || ^18.0.0",
|
| 620 |
+
"rxjs": "^6.5.3 || ^7.4.0"
|
| 621 |
+
}
|
| 622 |
+
},
|
| 623 |
"node_modules/@angular/platform-browser": {
|
| 624 |
"version": "17.3.12",
|
| 625 |
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-17.3.12.tgz",
|
|
|
|
| 3281 |
"node": ">= 0.4"
|
| 3282 |
}
|
| 3283 |
},
|
| 3284 |
+
"node_modules/@material/animation": {
|
| 3285 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3286 |
+
"resolved": "https://registry.npmjs.org/@material/animation/-/animation-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3287 |
+
"integrity": "sha512-1GSJaPKef+7HRuV+HusVZHps64cmZuOItDbt40tjJVaikcaZvwmHlcTxRIqzcRoCdt5ZKHh3NoO7GB9Khg4Jnw==",
|
| 3288 |
+
"license": "MIT",
|
| 3289 |
+
"dependencies": {
|
| 3290 |
+
"tslib": "^2.1.0"
|
| 3291 |
+
}
|
| 3292 |
+
},
|
| 3293 |
+
"node_modules/@material/auto-init": {
|
| 3294 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3295 |
+
"resolved": "https://registry.npmjs.org/@material/auto-init/-/auto-init-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3296 |
+
"integrity": "sha512-t7ZGpRJ3ec0QDUO0nJu/SMgLW7qcuG2KqIsEYD1Ej8qhI2xpdR2ydSDQOkVEitXmKoGol1oq4nYSBjTlB65GqA==",
|
| 3297 |
+
"license": "MIT",
|
| 3298 |
+
"dependencies": {
|
| 3299 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3300 |
+
"tslib": "^2.1.0"
|
| 3301 |
+
}
|
| 3302 |
+
},
|
| 3303 |
+
"node_modules/@material/banner": {
|
| 3304 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3305 |
+
"resolved": "https://registry.npmjs.org/@material/banner/-/banner-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3306 |
+
"integrity": "sha512-g9wBUZzYBizyBcBQXTIafnRUUPi7efU9gPJfzeGgkynXiccP/vh5XMmH+PBxl5v+4MlP/d4cZ2NUYoAN7UTqSA==",
|
| 3307 |
+
"license": "MIT",
|
| 3308 |
+
"dependencies": {
|
| 3309 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3310 |
+
"@material/button": "15.0.0-canary.7f224ddd4.0",
|
| 3311 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3312 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 3313 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3314 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3315 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3316 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 3317 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3318 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 3319 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 3320 |
+
"tslib": "^2.1.0"
|
| 3321 |
+
}
|
| 3322 |
+
},
|
| 3323 |
+
"node_modules/@material/base": {
|
| 3324 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3325 |
+
"resolved": "https://registry.npmjs.org/@material/base/-/base-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3326 |
+
"integrity": "sha512-I9KQOKXpLfJkP8MqZyr8wZIzdPHrwPjFvGd9zSK91/vPyE4hzHRJc/0njsh9g8Lm9PRYLbifXX+719uTbHxx+A==",
|
| 3327 |
+
"license": "MIT",
|
| 3328 |
+
"dependencies": {
|
| 3329 |
+
"tslib": "^2.1.0"
|
| 3330 |
+
}
|
| 3331 |
+
},
|
| 3332 |
+
"node_modules/@material/button": {
|
| 3333 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3334 |
+
"resolved": "https://registry.npmjs.org/@material/button/-/button-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3335 |
+
"integrity": "sha512-BHB7iyHgRVH+JF16+iscR+Qaic+p7LU1FOLgP8KucRlpF9tTwIxQA6mJwGRi5gUtcG+vyCmzVS+hIQ6DqT/7BA==",
|
| 3336 |
+
"license": "MIT",
|
| 3337 |
+
"dependencies": {
|
| 3338 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 3339 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3340 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 3341 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3342 |
+
"@material/focus-ring": "15.0.0-canary.7f224ddd4.0",
|
| 3343 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3344 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3345 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 3346 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3347 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 3348 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 3349 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 3350 |
+
"tslib": "^2.1.0"
|
| 3351 |
+
}
|
| 3352 |
+
},
|
| 3353 |
+
"node_modules/@material/card": {
|
| 3354 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3355 |
+
"resolved": "https://registry.npmjs.org/@material/card/-/card-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3356 |
+
"integrity": "sha512-kt7y9/IWOtJTr3Z/AoWJT3ZLN7CLlzXhx2udCLP9ootZU2bfGK0lzNwmo80bv/pJfrY9ihQKCtuGTtNxUy+vIw==",
|
| 3357 |
+
"license": "MIT",
|
| 3358 |
+
"dependencies": {
|
| 3359 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3360 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 3361 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3362 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3363 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3364 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 3365 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3366 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 3367 |
+
"tslib": "^2.1.0"
|
| 3368 |
+
}
|
| 3369 |
+
},
|
| 3370 |
+
"node_modules/@material/checkbox": {
|
| 3371 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3372 |
+
"resolved": "https://registry.npmjs.org/@material/checkbox/-/checkbox-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3373 |
+
"integrity": "sha512-rURcrL5O1u6hzWR+dNgiQ/n89vk6tdmdP3mZgnxJx61q4I/k1yijKqNJSLrkXH7Rto3bM5NRKMOlgvMvVd7UMQ==",
|
| 3374 |
+
"license": "MIT",
|
| 3375 |
+
"dependencies": {
|
| 3376 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3377 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3378 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 3379 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3380 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3381 |
+
"@material/focus-ring": "15.0.0-canary.7f224ddd4.0",
|
| 3382 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3383 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3384 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3385 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 3386 |
+
"tslib": "^2.1.0"
|
| 3387 |
+
}
|
| 3388 |
+
},
|
| 3389 |
+
"node_modules/@material/chips": {
|
| 3390 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3391 |
+
"resolved": "https://registry.npmjs.org/@material/chips/-/chips-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3392 |
+
"integrity": "sha512-AYAivV3GSk/T/nRIpH27sOHFPaSMrE3L0WYbnb5Wa93FgY8a0fbsFYtSH2QmtwnzXveg+B1zGTt7/xIIcynKdQ==",
|
| 3393 |
+
"license": "MIT",
|
| 3394 |
+
"dependencies": {
|
| 3395 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3396 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3397 |
+
"@material/checkbox": "15.0.0-canary.7f224ddd4.0",
|
| 3398 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 3399 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3400 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 3401 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3402 |
+
"@material/focus-ring": "15.0.0-canary.7f224ddd4.0",
|
| 3403 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3404 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3405 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 3406 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3407 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 3408 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 3409 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 3410 |
+
"safevalues": "^0.3.4",
|
| 3411 |
+
"tslib": "^2.1.0"
|
| 3412 |
+
}
|
| 3413 |
+
},
|
| 3414 |
+
"node_modules/@material/circular-progress": {
|
| 3415 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3416 |
+
"resolved": "https://registry.npmjs.org/@material/circular-progress/-/circular-progress-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3417 |
+
"integrity": "sha512-DJrqCKb+LuGtjNvKl8XigvyK02y36GRkfhMUYTcJEi3PrOE00bwXtyj7ilhzEVshQiXg6AHGWXtf5UqwNrx3Ow==",
|
| 3418 |
+
"license": "MIT",
|
| 3419 |
+
"dependencies": {
|
| 3420 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3421 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3422 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3423 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3424 |
+
"@material/progress-indicator": "15.0.0-canary.7f224ddd4.0",
|
| 3425 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3426 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3427 |
+
"tslib": "^2.1.0"
|
| 3428 |
+
}
|
| 3429 |
+
},
|
| 3430 |
+
"node_modules/@material/data-table": {
|
| 3431 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3432 |
+
"resolved": "https://registry.npmjs.org/@material/data-table/-/data-table-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3433 |
+
"integrity": "sha512-/2WZsuBIq9z9RWYF5Jo6b7P6u0fwit+29/mN7rmAZ6akqUR54nXyNfoSNiyydMkzPlZZsep5KrSHododDhBZbA==",
|
| 3434 |
+
"license": "MIT",
|
| 3435 |
+
"dependencies": {
|
| 3436 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3437 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3438 |
+
"@material/checkbox": "15.0.0-canary.7f224ddd4.0",
|
| 3439 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 3440 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3441 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 3442 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3443 |
+
"@material/icon-button": "15.0.0-canary.7f224ddd4.0",
|
| 3444 |
+
"@material/linear-progress": "15.0.0-canary.7f224ddd4.0",
|
| 3445 |
+
"@material/list": "15.0.0-canary.7f224ddd4.0",
|
| 3446 |
+
"@material/menu": "15.0.0-canary.7f224ddd4.0",
|
| 3447 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3448 |
+
"@material/select": "15.0.0-canary.7f224ddd4.0",
|
| 3449 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 3450 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3451 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 3452 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 3453 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 3454 |
+
"tslib": "^2.1.0"
|
| 3455 |
+
}
|
| 3456 |
+
},
|
| 3457 |
+
"node_modules/@material/density": {
|
| 3458 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3459 |
+
"resolved": "https://registry.npmjs.org/@material/density/-/density-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3460 |
+
"integrity": "sha512-o9EXmGKVpiQ6mHhyV3oDDzc78Ow3E7v8dlaOhgaDSXgmqaE8v5sIlLNa/LKSyUga83/fpGk3QViSGXotpQx0jA==",
|
| 3461 |
+
"license": "MIT",
|
| 3462 |
+
"dependencies": {
|
| 3463 |
+
"tslib": "^2.1.0"
|
| 3464 |
+
}
|
| 3465 |
+
},
|
| 3466 |
+
"node_modules/@material/dialog": {
|
| 3467 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3468 |
+
"resolved": "https://registry.npmjs.org/@material/dialog/-/dialog-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3469 |
+
"integrity": "sha512-u0XpTlv1JqWC/bQ3DavJ1JguofTelLT2wloj59l3/1b60jv42JQ6Am7jU3I8/SIUB1MKaW7dYocXjDWtWJakLA==",
|
| 3470 |
+
"license": "MIT",
|
| 3471 |
+
"dependencies": {
|
| 3472 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3473 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3474 |
+
"@material/button": "15.0.0-canary.7f224ddd4.0",
|
| 3475 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3476 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 3477 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3478 |
+
"@material/icon-button": "15.0.0-canary.7f224ddd4.0",
|
| 3479 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3480 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3481 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 3482 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3483 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 3484 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 3485 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 3486 |
+
"tslib": "^2.1.0"
|
| 3487 |
+
}
|
| 3488 |
+
},
|
| 3489 |
+
"node_modules/@material/dom": {
|
| 3490 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3491 |
+
"resolved": "https://registry.npmjs.org/@material/dom/-/dom-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3492 |
+
"integrity": "sha512-mQ1HT186GPQSkRg5S18i70typ5ZytfjL09R0gJ2Qg5/G+MLCGi7TAjZZSH65tuD/QGOjel4rDdWOTmYbPYV6HA==",
|
| 3493 |
+
"license": "MIT",
|
| 3494 |
+
"dependencies": {
|
| 3495 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3496 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3497 |
+
"tslib": "^2.1.0"
|
| 3498 |
+
}
|
| 3499 |
+
},
|
| 3500 |
+
"node_modules/@material/drawer": {
|
| 3501 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3502 |
+
"resolved": "https://registry.npmjs.org/@material/drawer/-/drawer-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3503 |
+
"integrity": "sha512-qyO0W0KBftfH8dlLR0gVAgv7ZHNvU8ae11Ao6zJif/YxcvK4+gph1z8AO4H410YmC2kZiwpSKyxM1iQCCzbb4g==",
|
| 3504 |
+
"license": "MIT",
|
| 3505 |
+
"dependencies": {
|
| 3506 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3507 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3508 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3509 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 3510 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3511 |
+
"@material/list": "15.0.0-canary.7f224ddd4.0",
|
| 3512 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3513 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3514 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 3515 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3516 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 3517 |
+
"tslib": "^2.1.0"
|
| 3518 |
+
}
|
| 3519 |
+
},
|
| 3520 |
+
"node_modules/@material/elevation": {
|
| 3521 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3522 |
+
"resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3523 |
+
"integrity": "sha512-tV6s4/pUBECedaI36Yj18KmRCk1vfue/JP/5yYRlFNnLMRVISePbZaKkn/BHXVf+26I3W879+XqIGlDVdmOoMA==",
|
| 3524 |
+
"license": "MIT",
|
| 3525 |
+
"dependencies": {
|
| 3526 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3527 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3528 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3529 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3530 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3531 |
+
"tslib": "^2.1.0"
|
| 3532 |
+
}
|
| 3533 |
+
},
|
| 3534 |
+
"node_modules/@material/fab": {
|
| 3535 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3536 |
+
"resolved": "https://registry.npmjs.org/@material/fab/-/fab-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3537 |
+
"integrity": "sha512-4h76QrzfZTcPdd+awDPZ4Q0YdSqsXQnS540TPtyXUJ/5G99V6VwGpjMPIxAsW0y+pmI9UkLL/srrMaJec+7r4Q==",
|
| 3538 |
+
"license": "MIT",
|
| 3539 |
+
"dependencies": {
|
| 3540 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3541 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3542 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 3543 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3544 |
+
"@material/focus-ring": "15.0.0-canary.7f224ddd4.0",
|
| 3545 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3546 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3547 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 3548 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3549 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 3550 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 3551 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 3552 |
+
"tslib": "^2.1.0"
|
| 3553 |
+
}
|
| 3554 |
+
},
|
| 3555 |
+
"node_modules/@material/feature-targeting": {
|
| 3556 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3557 |
+
"resolved": "https://registry.npmjs.org/@material/feature-targeting/-/feature-targeting-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3558 |
+
"integrity": "sha512-SAjtxYh6YlKZriU83diDEQ7jNSP2MnxKsER0TvFeyG1vX/DWsUyYDOIJTOEa9K1N+fgJEBkNK8hY55QhQaspew==",
|
| 3559 |
+
"license": "MIT",
|
| 3560 |
+
"dependencies": {
|
| 3561 |
+
"tslib": "^2.1.0"
|
| 3562 |
+
}
|
| 3563 |
+
},
|
| 3564 |
+
"node_modules/@material/floating-label": {
|
| 3565 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3566 |
+
"resolved": "https://registry.npmjs.org/@material/floating-label/-/floating-label-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3567 |
+
"integrity": "sha512-0KMo5ijjYaEHPiZ2pCVIcbaTS2LycvH9zEhEMKwPPGssBCX7iz5ffYQFk7e5yrQand1r3jnQQgYfHAwtykArnQ==",
|
| 3568 |
+
"license": "MIT",
|
| 3569 |
+
"dependencies": {
|
| 3570 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3571 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3572 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3573 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3574 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3575 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3576 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 3577 |
+
"tslib": "^2.1.0"
|
| 3578 |
+
}
|
| 3579 |
+
},
|
| 3580 |
+
"node_modules/@material/focus-ring": {
|
| 3581 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3582 |
+
"resolved": "https://registry.npmjs.org/@material/focus-ring/-/focus-ring-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3583 |
+
"integrity": "sha512-Jmg1nltq4J6S6A10EGMZnvufrvU3YTi+8R8ZD9lkSbun0Fm2TVdICQt/Auyi6An9zP66oQN6c31eqO6KfIPsDg==",
|
| 3584 |
+
"license": "MIT",
|
| 3585 |
+
"dependencies": {
|
| 3586 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3587 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3588 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0"
|
| 3589 |
+
}
|
| 3590 |
+
},
|
| 3591 |
+
"node_modules/@material/form-field": {
|
| 3592 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3593 |
+
"resolved": "https://registry.npmjs.org/@material/form-field/-/form-field-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3594 |
+
"integrity": "sha512-fEPWgDQEPJ6WF7hNnIStxucHR9LE4DoDSMqCsGWS2Yu+NLZYLuCEecgR0UqQsl1EQdNRaFh8VH93KuxGd2hiPg==",
|
| 3595 |
+
"license": "MIT",
|
| 3596 |
+
"dependencies": {
|
| 3597 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3598 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3599 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3600 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3601 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3602 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 3603 |
+
"tslib": "^2.1.0"
|
| 3604 |
+
}
|
| 3605 |
+
},
|
| 3606 |
+
"node_modules/@material/icon-button": {
|
| 3607 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3608 |
+
"resolved": "https://registry.npmjs.org/@material/icon-button/-/icon-button-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3609 |
+
"integrity": "sha512-DcK7IL4ICY/DW+48YQZZs9g0U1kRaW0Wb0BxhvppDMYziHo/CTpFdle4gjyuTyRxPOdHQz5a97ru48Z9O4muTw==",
|
| 3610 |
+
"license": "MIT",
|
| 3611 |
+
"dependencies": {
|
| 3612 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3613 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 3614 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3615 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 3616 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3617 |
+
"@material/focus-ring": "15.0.0-canary.7f224ddd4.0",
|
| 3618 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3619 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3620 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3621 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 3622 |
+
"tslib": "^2.1.0"
|
| 3623 |
+
}
|
| 3624 |
+
},
|
| 3625 |
+
"node_modules/@material/image-list": {
|
| 3626 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3627 |
+
"resolved": "https://registry.npmjs.org/@material/image-list/-/image-list-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3628 |
+
"integrity": "sha512-voMjG2p80XbjL1B2lmF65zO5gEgJOVKClLdqh4wbYzYfwY/SR9c8eLvlYG7DLdFaFBl/7gGxD8TvvZ329HUFPw==",
|
| 3629 |
+
"license": "MIT",
|
| 3630 |
+
"dependencies": {
|
| 3631 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3632 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 3633 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3634 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 3635 |
+
"tslib": "^2.1.0"
|
| 3636 |
+
}
|
| 3637 |
+
},
|
| 3638 |
+
"node_modules/@material/layout-grid": {
|
| 3639 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3640 |
+
"resolved": "https://registry.npmjs.org/@material/layout-grid/-/layout-grid-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3641 |
+
"integrity": "sha512-veDABLxMn2RmvfnUO2RUmC1OFfWr4cU+MrxKPoDD2hl3l3eDYv5fxws6r5T1JoSyXoaN+oEZpheS0+M9Ure8Pg==",
|
| 3642 |
+
"license": "MIT",
|
| 3643 |
+
"dependencies": {
|
| 3644 |
+
"tslib": "^2.1.0"
|
| 3645 |
+
}
|
| 3646 |
+
},
|
| 3647 |
+
"node_modules/@material/line-ripple": {
|
| 3648 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3649 |
+
"resolved": "https://registry.npmjs.org/@material/line-ripple/-/line-ripple-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3650 |
+
"integrity": "sha512-f60hVJhIU6I3/17Tqqzch1emUKEcfVVgHVqADbU14JD+oEIz429ZX9ksZ3VChoU3+eejFl+jVdZMLE/LrAuwpg==",
|
| 3651 |
+
"license": "MIT",
|
| 3652 |
+
"dependencies": {
|
| 3653 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3654 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3655 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3656 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3657 |
+
"tslib": "^2.1.0"
|
| 3658 |
+
}
|
| 3659 |
+
},
|
| 3660 |
+
"node_modules/@material/linear-progress": {
|
| 3661 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3662 |
+
"resolved": "https://registry.npmjs.org/@material/linear-progress/-/linear-progress-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3663 |
+
"integrity": "sha512-pRDEwPQielDiC9Sc5XhCXrGxP8wWOnAO8sQlMebfBYHYqy5hhiIzibezS8CSaW4MFQFyXmCmpmqWlbqGYRmiyg==",
|
| 3664 |
+
"license": "MIT",
|
| 3665 |
+
"dependencies": {
|
| 3666 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3667 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3668 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3669 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3670 |
+
"@material/progress-indicator": "15.0.0-canary.7f224ddd4.0",
|
| 3671 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3672 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3673 |
+
"tslib": "^2.1.0"
|
| 3674 |
+
}
|
| 3675 |
+
},
|
| 3676 |
+
"node_modules/@material/list": {
|
| 3677 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3678 |
+
"resolved": "https://registry.npmjs.org/@material/list/-/list-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3679 |
+
"integrity": "sha512-Is0NV91sJlXF5pOebYAtWLF4wU2MJDbYqztML/zQNENkQxDOvEXu3nWNb3YScMIYJJXvARO0Liur5K4yPagS1Q==",
|
| 3680 |
+
"license": "MIT",
|
| 3681 |
+
"dependencies": {
|
| 3682 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3683 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 3684 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3685 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3686 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3687 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3688 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 3689 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3690 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 3691 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 3692 |
+
"tslib": "^2.1.0"
|
| 3693 |
+
}
|
| 3694 |
+
},
|
| 3695 |
+
"node_modules/@material/menu": {
|
| 3696 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3697 |
+
"resolved": "https://registry.npmjs.org/@material/menu/-/menu-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3698 |
+
"integrity": "sha512-D11QU1dXqLbh5X1zKlEhS3QWh0b5BPNXlafc5MXfkdJHhOiieb7LC9hMJhbrHtj24FadJ7evaFW/T2ugJbJNnQ==",
|
| 3699 |
+
"license": "MIT",
|
| 3700 |
+
"dependencies": {
|
| 3701 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3702 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3703 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 3704 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3705 |
+
"@material/list": "15.0.0-canary.7f224ddd4.0",
|
| 3706 |
+
"@material/menu-surface": "15.0.0-canary.7f224ddd4.0",
|
| 3707 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3708 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3709 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 3710 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3711 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 3712 |
+
"tslib": "^2.1.0"
|
| 3713 |
+
}
|
| 3714 |
+
},
|
| 3715 |
+
"node_modules/@material/menu-surface": {
|
| 3716 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3717 |
+
"resolved": "https://registry.npmjs.org/@material/menu-surface/-/menu-surface-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3718 |
+
"integrity": "sha512-7RZHvw0gbwppaAJ/Oh5SWmfAKJ62aw1IMB3+3MRwsb5PLoV666wInYa+zJfE4i7qBeOn904xqT2Nko5hY0ssrg==",
|
| 3719 |
+
"license": "MIT",
|
| 3720 |
+
"dependencies": {
|
| 3721 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3722 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3723 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 3724 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3725 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3726 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 3727 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3728 |
+
"tslib": "^2.1.0"
|
| 3729 |
+
}
|
| 3730 |
+
},
|
| 3731 |
+
"node_modules/@material/notched-outline": {
|
| 3732 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3733 |
+
"resolved": "https://registry.npmjs.org/@material/notched-outline/-/notched-outline-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3734 |
+
"integrity": "sha512-Yg2usuKB2DKlKIBISbie9BFsOVuffF71xjbxPbybvqemxqUBd+bD5/t6H1fLE+F8/NCu5JMigho4ewUU+0RCiw==",
|
| 3735 |
+
"license": "MIT",
|
| 3736 |
+
"dependencies": {
|
| 3737 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3738 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3739 |
+
"@material/floating-label": "15.0.0-canary.7f224ddd4.0",
|
| 3740 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3741 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 3742 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3743 |
+
"tslib": "^2.1.0"
|
| 3744 |
+
}
|
| 3745 |
+
},
|
| 3746 |
+
"node_modules/@material/progress-indicator": {
|
| 3747 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3748 |
+
"resolved": "https://registry.npmjs.org/@material/progress-indicator/-/progress-indicator-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3749 |
+
"integrity": "sha512-UPbDjE5CqT+SqTs0mNFG6uFEw7wBlgYmh+noSkQ6ty/EURm8lF125dmi4dv4kW0+octonMXqkGtAoZwLIHKf/w==",
|
| 3750 |
+
"license": "MIT",
|
| 3751 |
+
"dependencies": {
|
| 3752 |
+
"tslib": "^2.1.0"
|
| 3753 |
+
}
|
| 3754 |
+
},
|
| 3755 |
+
"node_modules/@material/radio": {
|
| 3756 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3757 |
+
"resolved": "https://registry.npmjs.org/@material/radio/-/radio-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3758 |
+
"integrity": "sha512-wR1X0Sr0KmQLu6+YOFKAI84G3L6psqd7Kys5kfb8WKBM36zxO5HQXC5nJm/Y0rdn22ixzsIz2GBo0MNU4V4k1A==",
|
| 3759 |
+
"license": "MIT",
|
| 3760 |
+
"dependencies": {
|
| 3761 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3762 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3763 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 3764 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3765 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3766 |
+
"@material/focus-ring": "15.0.0-canary.7f224ddd4.0",
|
| 3767 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3768 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3769 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 3770 |
+
"tslib": "^2.1.0"
|
| 3771 |
+
}
|
| 3772 |
+
},
|
| 3773 |
+
"node_modules/@material/ripple": {
|
| 3774 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3775 |
+
"resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3776 |
+
"integrity": "sha512-JqOsWM1f4aGdotP0rh1vZlPZTg6lZgh39FIYHFMfOwfhR+LAikUJ+37ciqZuewgzXB6iiRO6a8aUH6HR5SJYPg==",
|
| 3777 |
+
"license": "MIT",
|
| 3778 |
+
"dependencies": {
|
| 3779 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3780 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3781 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3782 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3783 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3784 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3785 |
+
"tslib": "^2.1.0"
|
| 3786 |
+
}
|
| 3787 |
+
},
|
| 3788 |
+
"node_modules/@material/rtl": {
|
| 3789 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3790 |
+
"resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3791 |
+
"integrity": "sha512-UVf14qAtmPiaaZjuJtmN36HETyoKWmsZM/qn1L5ciR2URb8O035dFWnz4ZWFMmAYBno/L7JiZaCkPurv2ZNrGA==",
|
| 3792 |
+
"license": "MIT",
|
| 3793 |
+
"dependencies": {
|
| 3794 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3795 |
+
"tslib": "^2.1.0"
|
| 3796 |
+
}
|
| 3797 |
+
},
|
| 3798 |
+
"node_modules/@material/segmented-button": {
|
| 3799 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3800 |
+
"resolved": "https://registry.npmjs.org/@material/segmented-button/-/segmented-button-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3801 |
+
"integrity": "sha512-LCnVRUSAhELTKI/9hSvyvIvQIpPpqF29BV+O9yM4WoNNmNWqTulvuiv7grHZl6Z+kJuxSg4BGbsPxxb9dXozPg==",
|
| 3802 |
+
"license": "MIT",
|
| 3803 |
+
"dependencies": {
|
| 3804 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3805 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 3806 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3807 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3808 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3809 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 3810 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 3811 |
+
"tslib": "^2.1.0"
|
| 3812 |
+
}
|
| 3813 |
+
},
|
| 3814 |
+
"node_modules/@material/select": {
|
| 3815 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3816 |
+
"resolved": "https://registry.npmjs.org/@material/select/-/select-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3817 |
+
"integrity": "sha512-WioZtQEXRpglum0cMSzSqocnhsGRr+ZIhvKb3FlaNrTaK8H3Y4QA7rVjv3emRtrLOOjaT6/RiIaUMTo9AGzWQQ==",
|
| 3818 |
+
"license": "MIT",
|
| 3819 |
+
"dependencies": {
|
| 3820 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3821 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3822 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 3823 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3824 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 3825 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3826 |
+
"@material/floating-label": "15.0.0-canary.7f224ddd4.0",
|
| 3827 |
+
"@material/line-ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3828 |
+
"@material/list": "15.0.0-canary.7f224ddd4.0",
|
| 3829 |
+
"@material/menu": "15.0.0-canary.7f224ddd4.0",
|
| 3830 |
+
"@material/menu-surface": "15.0.0-canary.7f224ddd4.0",
|
| 3831 |
+
"@material/notched-outline": "15.0.0-canary.7f224ddd4.0",
|
| 3832 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3833 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3834 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 3835 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3836 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 3837 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 3838 |
+
"tslib": "^2.1.0"
|
| 3839 |
+
}
|
| 3840 |
+
},
|
| 3841 |
+
"node_modules/@material/shape": {
|
| 3842 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3843 |
+
"resolved": "https://registry.npmjs.org/@material/shape/-/shape-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3844 |
+
"integrity": "sha512-8z8l1W3+cymObunJoRhwFPKZ+FyECfJ4MJykNiaZq7XJFZkV6xNmqAVrrbQj93FtLsECn9g4PjjIomguVn/OEw==",
|
| 3845 |
+
"license": "MIT",
|
| 3846 |
+
"dependencies": {
|
| 3847 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3848 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3849 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3850 |
+
"tslib": "^2.1.0"
|
| 3851 |
+
}
|
| 3852 |
+
},
|
| 3853 |
+
"node_modules/@material/slider": {
|
| 3854 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3855 |
+
"resolved": "https://registry.npmjs.org/@material/slider/-/slider-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3856 |
+
"integrity": "sha512-QU/WSaSWlLKQRqOhJrPgm29wqvvzRusMqwAcrCh1JTrCl+xwJ43q5WLDfjYhubeKtrEEgGu9tekkAiYfMG7EBw==",
|
| 3857 |
+
"license": "MIT",
|
| 3858 |
+
"dependencies": {
|
| 3859 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3860 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3861 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3862 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 3863 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3864 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3865 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3866 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3867 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 3868 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 3869 |
+
"tslib": "^2.1.0"
|
| 3870 |
+
}
|
| 3871 |
+
},
|
| 3872 |
+
"node_modules/@material/snackbar": {
|
| 3873 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3874 |
+
"resolved": "https://registry.npmjs.org/@material/snackbar/-/snackbar-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3875 |
+
"integrity": "sha512-sm7EbVKddaXpT/aXAYBdPoN0k8yeg9+dprgBUkrdqGzWJAeCkxb4fv2B3He88YiCtvkTz2KLY4CThPQBSEsMFQ==",
|
| 3876 |
+
"license": "MIT",
|
| 3877 |
+
"dependencies": {
|
| 3878 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3879 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3880 |
+
"@material/button": "15.0.0-canary.7f224ddd4.0",
|
| 3881 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3882 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 3883 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3884 |
+
"@material/icon-button": "15.0.0-canary.7f224ddd4.0",
|
| 3885 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3886 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3887 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 3888 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3889 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 3890 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 3891 |
+
"tslib": "^2.1.0"
|
| 3892 |
+
}
|
| 3893 |
+
},
|
| 3894 |
+
"node_modules/@material/switch": {
|
| 3895 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3896 |
+
"resolved": "https://registry.npmjs.org/@material/switch/-/switch-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3897 |
+
"integrity": "sha512-lEDJfRvkVyyeHWIBfoxYjJVl+WlEAE2kZ/+6OqB1FW0OV8ftTODZGhHRSzjVBA1/p4FPuhAtKtoK9jTpa4AZjA==",
|
| 3898 |
+
"license": "MIT",
|
| 3899 |
+
"dependencies": {
|
| 3900 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3901 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3902 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 3903 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3904 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 3905 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3906 |
+
"@material/focus-ring": "15.0.0-canary.7f224ddd4.0",
|
| 3907 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3908 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3909 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 3910 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3911 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 3912 |
+
"safevalues": "^0.3.4",
|
| 3913 |
+
"tslib": "^2.1.0"
|
| 3914 |
+
}
|
| 3915 |
+
},
|
| 3916 |
+
"node_modules/@material/tab": {
|
| 3917 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3918 |
+
"resolved": "https://registry.npmjs.org/@material/tab/-/tab-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3919 |
+
"integrity": "sha512-E1xGACImyCLurhnizyOTCgOiVezce4HlBFAI6YhJo/AyVwjN2Dtas4ZLQMvvWWqpyhITNkeYdOchwCC1mrz3AQ==",
|
| 3920 |
+
"license": "MIT",
|
| 3921 |
+
"dependencies": {
|
| 3922 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3923 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 3924 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3925 |
+
"@material/focus-ring": "15.0.0-canary.7f224ddd4.0",
|
| 3926 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3927 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3928 |
+
"@material/tab-indicator": "15.0.0-canary.7f224ddd4.0",
|
| 3929 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3930 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 3931 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 3932 |
+
"tslib": "^2.1.0"
|
| 3933 |
+
}
|
| 3934 |
+
},
|
| 3935 |
+
"node_modules/@material/tab-bar": {
|
| 3936 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3937 |
+
"resolved": "https://registry.npmjs.org/@material/tab-bar/-/tab-bar-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3938 |
+
"integrity": "sha512-p1Asb2NzrcECvAQU3b2SYrpyJGyJLQWR+nXTYzDKE8WOpLIRCXap2audNqD7fvN/A20UJ1J8U01ptrvCkwJ4eA==",
|
| 3939 |
+
"license": "MIT",
|
| 3940 |
+
"dependencies": {
|
| 3941 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3942 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3943 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 3944 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 3945 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3946 |
+
"@material/tab": "15.0.0-canary.7f224ddd4.0",
|
| 3947 |
+
"@material/tab-indicator": "15.0.0-canary.7f224ddd4.0",
|
| 3948 |
+
"@material/tab-scroller": "15.0.0-canary.7f224ddd4.0",
|
| 3949 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3950 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 3951 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 3952 |
+
"tslib": "^2.1.0"
|
| 3953 |
+
}
|
| 3954 |
+
},
|
| 3955 |
+
"node_modules/@material/tab-indicator": {
|
| 3956 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3957 |
+
"resolved": "https://registry.npmjs.org/@material/tab-indicator/-/tab-indicator-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3958 |
+
"integrity": "sha512-h9Td3MPqbs33spcPS7ecByRHraYgU4tNCZpZzZXw31RypjKvISDv/PS5wcA4RmWqNGih78T7xg4QIGsZg4Pk4w==",
|
| 3959 |
+
"license": "MIT",
|
| 3960 |
+
"dependencies": {
|
| 3961 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3962 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3963 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3964 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 3965 |
+
"tslib": "^2.1.0"
|
| 3966 |
+
}
|
| 3967 |
+
},
|
| 3968 |
+
"node_modules/@material/tab-scroller": {
|
| 3969 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3970 |
+
"resolved": "https://registry.npmjs.org/@material/tab-scroller/-/tab-scroller-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3971 |
+
"integrity": "sha512-LFeYNjQpdXecwECd8UaqHYbhscDCwhGln5Yh+3ctvcEgvmDPNjhKn/DL3sWprWvG8NAhP6sHMrsGhQFVdCWtTg==",
|
| 3972 |
+
"license": "MIT",
|
| 3973 |
+
"dependencies": {
|
| 3974 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3975 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3976 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3977 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3978 |
+
"@material/tab": "15.0.0-canary.7f224ddd4.0",
|
| 3979 |
+
"tslib": "^2.1.0"
|
| 3980 |
+
}
|
| 3981 |
+
},
|
| 3982 |
+
"node_modules/@material/textfield": {
|
| 3983 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 3984 |
+
"resolved": "https://registry.npmjs.org/@material/textfield/-/textfield-15.0.0-canary.7f224ddd4.0.tgz",
|
| 3985 |
+
"integrity": "sha512-AExmFvgE5nNF0UA4l2cSzPghtxSUQeeoyRjFLHLy+oAaE4eKZFrSy0zEpqPeWPQpEMDZk+6Y+6T3cOFYBeSvsw==",
|
| 3986 |
+
"license": "MIT",
|
| 3987 |
+
"dependencies": {
|
| 3988 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 3989 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 3990 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 3991 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 3992 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 3993 |
+
"@material/floating-label": "15.0.0-canary.7f224ddd4.0",
|
| 3994 |
+
"@material/line-ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3995 |
+
"@material/notched-outline": "15.0.0-canary.7f224ddd4.0",
|
| 3996 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 3997 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 3998 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 3999 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 4000 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 4001 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 4002 |
+
"tslib": "^2.1.0"
|
| 4003 |
+
}
|
| 4004 |
+
},
|
| 4005 |
+
"node_modules/@material/theme": {
|
| 4006 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 4007 |
+
"resolved": "https://registry.npmjs.org/@material/theme/-/theme-15.0.0-canary.7f224ddd4.0.tgz",
|
| 4008 |
+
"integrity": "sha512-hs45hJoE9yVnoVOcsN1jklyOa51U4lzWsEnQEuJTPOk2+0HqCQ0yv/q0InpSnm2i69fNSyZC60+8HADZGF8ugQ==",
|
| 4009 |
+
"license": "MIT",
|
| 4010 |
+
"dependencies": {
|
| 4011 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 4012 |
+
"tslib": "^2.1.0"
|
| 4013 |
+
}
|
| 4014 |
+
},
|
| 4015 |
+
"node_modules/@material/tokens": {
|
| 4016 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 4017 |
+
"resolved": "https://registry.npmjs.org/@material/tokens/-/tokens-15.0.0-canary.7f224ddd4.0.tgz",
|
| 4018 |
+
"integrity": "sha512-r9TDoicmcT7FhUXC4eYMFnt9TZsz0G8T3wXvkKncLppYvZ517gPyD/1+yhuGfGOxAzxTrM66S/oEc1fFE2q4hw==",
|
| 4019 |
+
"license": "MIT",
|
| 4020 |
+
"dependencies": {
|
| 4021 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0"
|
| 4022 |
+
}
|
| 4023 |
+
},
|
| 4024 |
+
"node_modules/@material/tooltip": {
|
| 4025 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 4026 |
+
"resolved": "https://registry.npmjs.org/@material/tooltip/-/tooltip-15.0.0-canary.7f224ddd4.0.tgz",
|
| 4027 |
+
"integrity": "sha512-8qNk3pmPLTnam3XYC1sZuplQXW9xLn4Z4MI3D+U17Q7pfNZfoOugGr+d2cLA9yWAEjVJYB0mj8Yu86+udo4N9w==",
|
| 4028 |
+
"license": "MIT",
|
| 4029 |
+
"dependencies": {
|
| 4030 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 4031 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 4032 |
+
"@material/button": "15.0.0-canary.7f224ddd4.0",
|
| 4033 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 4034 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 4035 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 4036 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 4037 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 4038 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 4039 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 4040 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 4041 |
+
"safevalues": "^0.3.4",
|
| 4042 |
+
"tslib": "^2.1.0"
|
| 4043 |
+
}
|
| 4044 |
+
},
|
| 4045 |
+
"node_modules/@material/top-app-bar": {
|
| 4046 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 4047 |
+
"resolved": "https://registry.npmjs.org/@material/top-app-bar/-/top-app-bar-15.0.0-canary.7f224ddd4.0.tgz",
|
| 4048 |
+
"integrity": "sha512-SARR5/ClYT4CLe9qAXakbr0i0cMY0V3V4pe3ElIJPfL2Z2c4wGR1mTR8m2LxU1MfGKK8aRoUdtfKaxWejp+eNA==",
|
| 4049 |
+
"license": "MIT",
|
| 4050 |
+
"dependencies": {
|
| 4051 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 4052 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 4053 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 4054 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 4055 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 4056 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 4057 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 4058 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 4059 |
+
"tslib": "^2.1.0"
|
| 4060 |
+
}
|
| 4061 |
+
},
|
| 4062 |
+
"node_modules/@material/touch-target": {
|
| 4063 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 4064 |
+
"resolved": "https://registry.npmjs.org/@material/touch-target/-/touch-target-15.0.0-canary.7f224ddd4.0.tgz",
|
| 4065 |
+
"integrity": "sha512-BJo/wFKHPYLGsRaIpd7vsQwKr02LtO2e89Psv0on/p0OephlNIgeB9dD9W+bQmaeZsZ6liKSKRl6wJWDiK71PA==",
|
| 4066 |
+
"license": "MIT",
|
| 4067 |
+
"dependencies": {
|
| 4068 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 4069 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 4070 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 4071 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 4072 |
+
"tslib": "^2.1.0"
|
| 4073 |
+
}
|
| 4074 |
+
},
|
| 4075 |
+
"node_modules/@material/typography": {
|
| 4076 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 4077 |
+
"resolved": "https://registry.npmjs.org/@material/typography/-/typography-15.0.0-canary.7f224ddd4.0.tgz",
|
| 4078 |
+
"integrity": "sha512-kBaZeCGD50iq1DeRRH5OM5Jl7Gdk+/NOfKArkY4ksBZvJiStJ7ACAhpvb8MEGm4s3jvDInQFLsDq3hL+SA79sQ==",
|
| 4079 |
+
"license": "MIT",
|
| 4080 |
+
"dependencies": {
|
| 4081 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 4082 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 4083 |
+
"tslib": "^2.1.0"
|
| 4084 |
+
}
|
| 4085 |
+
},
|
| 4086 |
"node_modules/@ngtools/webpack": {
|
| 4087 |
"version": "17.3.11",
|
| 4088 |
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.3.11.tgz",
|
|
|
|
| 7078 |
"version": "4.5.0",
|
| 7079 |
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
| 7080 |
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
| 7081 |
+
"devOptional": true,
|
| 7082 |
"engines": {
|
| 7083 |
"node": ">=0.12"
|
| 7084 |
},
|
|
|
|
| 11161 |
"version": "7.2.1",
|
| 11162 |
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz",
|
| 11163 |
"integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==",
|
| 11164 |
+
"devOptional": true,
|
| 11165 |
"dependencies": {
|
| 11166 |
"entities": "^4.5.0"
|
| 11167 |
},
|
|
|
|
| 12292 |
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
| 12293 |
"dev": true
|
| 12294 |
},
|
| 12295 |
+
"node_modules/safevalues": {
|
| 12296 |
+
"version": "0.3.4",
|
| 12297 |
+
"resolved": "https://registry.npmjs.org/safevalues/-/safevalues-0.3.4.tgz",
|
| 12298 |
+
"integrity": "sha512-LRneZZRXNgjzwG4bDQdOTSbze3fHm1EAKN/8bePxnlEZiBmkYEDggaHbuvHI9/hoqHbGfsEA7tWS9GhYHZBBsw==",
|
| 12299 |
+
"license": "Apache-2.0"
|
| 12300 |
+
},
|
| 12301 |
"node_modules/sass": {
|
| 12302 |
"version": "1.71.1",
|
| 12303 |
"resolved": "https://registry.npmjs.org/sass/-/sass-1.71.1.tgz",
|
|
|
|
| 14377 |
"node": ">=10.13.0"
|
| 14378 |
}
|
| 14379 |
},
|
| 14380 |
+
"node_modules/wavesurfer.js": {
|
| 14381 |
+
"version": "7.12.1",
|
| 14382 |
+
"resolved": "https://registry.npmjs.org/wavesurfer.js/-/wavesurfer.js-7.12.1.tgz",
|
| 14383 |
+
"integrity": "sha512-NswPjVHxk0Q1F/VMRemCPUzSojjuHHisQrBqQiRXg7MVbe3f5vQ6r0rTTXA/a/neC/4hnOEC4YpXca4LpH0SUg==",
|
| 14384 |
+
"license": "BSD-3-Clause"
|
| 14385 |
+
},
|
| 14386 |
"node_modules/wbuf": {
|
| 14387 |
"version": "1.7.3",
|
| 14388 |
"resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
|
|
|
|
| 15035 |
"tslib": "^2.3.0"
|
| 15036 |
}
|
| 15037 |
},
|
| 15038 |
+
"@angular/cdk": {
|
| 15039 |
+
"version": "17.3.10",
|
| 15040 |
+
"resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-17.3.10.tgz",
|
| 15041 |
+
"integrity": "sha512-b1qktT2c1TTTe5nTji/kFAVW92fULK0YhYAvJ+BjZTPKu2FniZNe8o4qqQ0pUuvtMu+ZQxp/QqFYoidIVCjScg==",
|
| 15042 |
+
"peer": true,
|
| 15043 |
+
"requires": {
|
| 15044 |
+
"parse5": "^7.1.2",
|
| 15045 |
+
"tslib": "^2.3.0"
|
| 15046 |
+
}
|
| 15047 |
+
},
|
| 15048 |
"@angular/cli": {
|
| 15049 |
"version": "17.3.11",
|
| 15050 |
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-17.3.11.tgz",
|
|
|
|
| 15158 |
"tslib": "^2.3.0"
|
| 15159 |
}
|
| 15160 |
},
|
| 15161 |
+
"@angular/material": {
|
| 15162 |
+
"version": "17.3.10",
|
| 15163 |
+
"resolved": "https://registry.npmjs.org/@angular/material/-/material-17.3.10.tgz",
|
| 15164 |
+
"integrity": "sha512-hHMQES0tQPH5JW33W+mpBPuM8ybsloDTqFPuRV8cboDjosAWfJhzAKF3ozICpNlUrs62La/2Wu/756GcQrxebg==",
|
| 15165 |
+
"requires": {
|
| 15166 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 15167 |
+
"@material/auto-init": "15.0.0-canary.7f224ddd4.0",
|
| 15168 |
+
"@material/banner": "15.0.0-canary.7f224ddd4.0",
|
| 15169 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 15170 |
+
"@material/button": "15.0.0-canary.7f224ddd4.0",
|
| 15171 |
+
"@material/card": "15.0.0-canary.7f224ddd4.0",
|
| 15172 |
+
"@material/checkbox": "15.0.0-canary.7f224ddd4.0",
|
| 15173 |
+
"@material/chips": "15.0.0-canary.7f224ddd4.0",
|
| 15174 |
+
"@material/circular-progress": "15.0.0-canary.7f224ddd4.0",
|
| 15175 |
+
"@material/data-table": "15.0.0-canary.7f224ddd4.0",
|
| 15176 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 15177 |
+
"@material/dialog": "15.0.0-canary.7f224ddd4.0",
|
| 15178 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 15179 |
+
"@material/drawer": "15.0.0-canary.7f224ddd4.0",
|
| 15180 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 15181 |
+
"@material/fab": "15.0.0-canary.7f224ddd4.0",
|
| 15182 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 15183 |
+
"@material/floating-label": "15.0.0-canary.7f224ddd4.0",
|
| 15184 |
+
"@material/form-field": "15.0.0-canary.7f224ddd4.0",
|
| 15185 |
+
"@material/icon-button": "15.0.0-canary.7f224ddd4.0",
|
| 15186 |
+
"@material/image-list": "15.0.0-canary.7f224ddd4.0",
|
| 15187 |
+
"@material/layout-grid": "15.0.0-canary.7f224ddd4.0",
|
| 15188 |
+
"@material/line-ripple": "15.0.0-canary.7f224ddd4.0",
|
| 15189 |
+
"@material/linear-progress": "15.0.0-canary.7f224ddd4.0",
|
| 15190 |
+
"@material/list": "15.0.0-canary.7f224ddd4.0",
|
| 15191 |
+
"@material/menu": "15.0.0-canary.7f224ddd4.0",
|
| 15192 |
+
"@material/menu-surface": "15.0.0-canary.7f224ddd4.0",
|
| 15193 |
+
"@material/notched-outline": "15.0.0-canary.7f224ddd4.0",
|
| 15194 |
+
"@material/radio": "15.0.0-canary.7f224ddd4.0",
|
| 15195 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 15196 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 15197 |
+
"@material/segmented-button": "15.0.0-canary.7f224ddd4.0",
|
| 15198 |
+
"@material/select": "15.0.0-canary.7f224ddd4.0",
|
| 15199 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 15200 |
+
"@material/slider": "15.0.0-canary.7f224ddd4.0",
|
| 15201 |
+
"@material/snackbar": "15.0.0-canary.7f224ddd4.0",
|
| 15202 |
+
"@material/switch": "15.0.0-canary.7f224ddd4.0",
|
| 15203 |
+
"@material/tab": "15.0.0-canary.7f224ddd4.0",
|
| 15204 |
+
"@material/tab-bar": "15.0.0-canary.7f224ddd4.0",
|
| 15205 |
+
"@material/tab-indicator": "15.0.0-canary.7f224ddd4.0",
|
| 15206 |
+
"@material/tab-scroller": "15.0.0-canary.7f224ddd4.0",
|
| 15207 |
+
"@material/textfield": "15.0.0-canary.7f224ddd4.0",
|
| 15208 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 15209 |
+
"@material/tooltip": "15.0.0-canary.7f224ddd4.0",
|
| 15210 |
+
"@material/top-app-bar": "15.0.0-canary.7f224ddd4.0",
|
| 15211 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 15212 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 15213 |
+
"tslib": "^2.3.0"
|
| 15214 |
+
}
|
| 15215 |
+
},
|
| 15216 |
"@angular/platform-browser": {
|
| 15217 |
"version": "17.3.12",
|
| 15218 |
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-17.3.12.tgz",
|
|
|
|
| 16974 |
"call-bind": "^1.0.7"
|
| 16975 |
}
|
| 16976 |
},
|
| 16977 |
+
"@material/animation": {
|
| 16978 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 16979 |
+
"resolved": "https://registry.npmjs.org/@material/animation/-/animation-15.0.0-canary.7f224ddd4.0.tgz",
|
| 16980 |
+
"integrity": "sha512-1GSJaPKef+7HRuV+HusVZHps64cmZuOItDbt40tjJVaikcaZvwmHlcTxRIqzcRoCdt5ZKHh3NoO7GB9Khg4Jnw==",
|
| 16981 |
+
"requires": {
|
| 16982 |
+
"tslib": "^2.1.0"
|
| 16983 |
+
}
|
| 16984 |
+
},
|
| 16985 |
+
"@material/auto-init": {
|
| 16986 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 16987 |
+
"resolved": "https://registry.npmjs.org/@material/auto-init/-/auto-init-15.0.0-canary.7f224ddd4.0.tgz",
|
| 16988 |
+
"integrity": "sha512-t7ZGpRJ3ec0QDUO0nJu/SMgLW7qcuG2KqIsEYD1Ej8qhI2xpdR2ydSDQOkVEitXmKoGol1oq4nYSBjTlB65GqA==",
|
| 16989 |
+
"requires": {
|
| 16990 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 16991 |
+
"tslib": "^2.1.0"
|
| 16992 |
+
}
|
| 16993 |
+
},
|
| 16994 |
+
"@material/banner": {
|
| 16995 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 16996 |
+
"resolved": "https://registry.npmjs.org/@material/banner/-/banner-15.0.0-canary.7f224ddd4.0.tgz",
|
| 16997 |
+
"integrity": "sha512-g9wBUZzYBizyBcBQXTIafnRUUPi7efU9gPJfzeGgkynXiccP/vh5XMmH+PBxl5v+4MlP/d4cZ2NUYoAN7UTqSA==",
|
| 16998 |
+
"requires": {
|
| 16999 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17000 |
+
"@material/button": "15.0.0-canary.7f224ddd4.0",
|
| 17001 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17002 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17003 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17004 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17005 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17006 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17007 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17008 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 17009 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17010 |
+
"tslib": "^2.1.0"
|
| 17011 |
+
}
|
| 17012 |
+
},
|
| 17013 |
+
"@material/base": {
|
| 17014 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17015 |
+
"resolved": "https://registry.npmjs.org/@material/base/-/base-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17016 |
+
"integrity": "sha512-I9KQOKXpLfJkP8MqZyr8wZIzdPHrwPjFvGd9zSK91/vPyE4hzHRJc/0njsh9g8Lm9PRYLbifXX+719uTbHxx+A==",
|
| 17017 |
+
"requires": {
|
| 17018 |
+
"tslib": "^2.1.0"
|
| 17019 |
+
}
|
| 17020 |
+
},
|
| 17021 |
+
"@material/button": {
|
| 17022 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17023 |
+
"resolved": "https://registry.npmjs.org/@material/button/-/button-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17024 |
+
"integrity": "sha512-BHB7iyHgRVH+JF16+iscR+Qaic+p7LU1FOLgP8KucRlpF9tTwIxQA6mJwGRi5gUtcG+vyCmzVS+hIQ6DqT/7BA==",
|
| 17025 |
+
"requires": {
|
| 17026 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 17027 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17028 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17029 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17030 |
+
"@material/focus-ring": "15.0.0-canary.7f224ddd4.0",
|
| 17031 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17032 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17033 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17034 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17035 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 17036 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 17037 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17038 |
+
"tslib": "^2.1.0"
|
| 17039 |
+
}
|
| 17040 |
+
},
|
| 17041 |
+
"@material/card": {
|
| 17042 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17043 |
+
"resolved": "https://registry.npmjs.org/@material/card/-/card-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17044 |
+
"integrity": "sha512-kt7y9/IWOtJTr3Z/AoWJT3ZLN7CLlzXhx2udCLP9ootZU2bfGK0lzNwmo80bv/pJfrY9ihQKCtuGTtNxUy+vIw==",
|
| 17045 |
+
"requires": {
|
| 17046 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17047 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17048 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17049 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17050 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17051 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17052 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17053 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 17054 |
+
"tslib": "^2.1.0"
|
| 17055 |
+
}
|
| 17056 |
+
},
|
| 17057 |
+
"@material/checkbox": {
|
| 17058 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17059 |
+
"resolved": "https://registry.npmjs.org/@material/checkbox/-/checkbox-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17060 |
+
"integrity": "sha512-rURcrL5O1u6hzWR+dNgiQ/n89vk6tdmdP3mZgnxJx61q4I/k1yijKqNJSLrkXH7Rto3bM5NRKMOlgvMvVd7UMQ==",
|
| 17061 |
+
"requires": {
|
| 17062 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17063 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17064 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 17065 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17066 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17067 |
+
"@material/focus-ring": "15.0.0-canary.7f224ddd4.0",
|
| 17068 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17069 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17070 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17071 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 17072 |
+
"tslib": "^2.1.0"
|
| 17073 |
+
}
|
| 17074 |
+
},
|
| 17075 |
+
"@material/chips": {
|
| 17076 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17077 |
+
"resolved": "https://registry.npmjs.org/@material/chips/-/chips-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17078 |
+
"integrity": "sha512-AYAivV3GSk/T/nRIpH27sOHFPaSMrE3L0WYbnb5Wa93FgY8a0fbsFYtSH2QmtwnzXveg+B1zGTt7/xIIcynKdQ==",
|
| 17079 |
+
"requires": {
|
| 17080 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17081 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17082 |
+
"@material/checkbox": "15.0.0-canary.7f224ddd4.0",
|
| 17083 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 17084 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17085 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17086 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17087 |
+
"@material/focus-ring": "15.0.0-canary.7f224ddd4.0",
|
| 17088 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17089 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17090 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17091 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17092 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 17093 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 17094 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17095 |
+
"safevalues": "^0.3.4",
|
| 17096 |
+
"tslib": "^2.1.0"
|
| 17097 |
+
}
|
| 17098 |
+
},
|
| 17099 |
+
"@material/circular-progress": {
|
| 17100 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17101 |
+
"resolved": "https://registry.npmjs.org/@material/circular-progress/-/circular-progress-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17102 |
+
"integrity": "sha512-DJrqCKb+LuGtjNvKl8XigvyK02y36GRkfhMUYTcJEi3PrOE00bwXtyj7ilhzEVshQiXg6AHGWXtf5UqwNrx3Ow==",
|
| 17103 |
+
"requires": {
|
| 17104 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17105 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17106 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17107 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17108 |
+
"@material/progress-indicator": "15.0.0-canary.7f224ddd4.0",
|
| 17109 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17110 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17111 |
+
"tslib": "^2.1.0"
|
| 17112 |
+
}
|
| 17113 |
+
},
|
| 17114 |
+
"@material/data-table": {
|
| 17115 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17116 |
+
"resolved": "https://registry.npmjs.org/@material/data-table/-/data-table-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17117 |
+
"integrity": "sha512-/2WZsuBIq9z9RWYF5Jo6b7P6u0fwit+29/mN7rmAZ6akqUR54nXyNfoSNiyydMkzPlZZsep5KrSHododDhBZbA==",
|
| 17118 |
+
"requires": {
|
| 17119 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17120 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17121 |
+
"@material/checkbox": "15.0.0-canary.7f224ddd4.0",
|
| 17122 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 17123 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17124 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17125 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17126 |
+
"@material/icon-button": "15.0.0-canary.7f224ddd4.0",
|
| 17127 |
+
"@material/linear-progress": "15.0.0-canary.7f224ddd4.0",
|
| 17128 |
+
"@material/list": "15.0.0-canary.7f224ddd4.0",
|
| 17129 |
+
"@material/menu": "15.0.0-canary.7f224ddd4.0",
|
| 17130 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17131 |
+
"@material/select": "15.0.0-canary.7f224ddd4.0",
|
| 17132 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17133 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17134 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 17135 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 17136 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17137 |
+
"tslib": "^2.1.0"
|
| 17138 |
+
}
|
| 17139 |
+
},
|
| 17140 |
+
"@material/density": {
|
| 17141 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17142 |
+
"resolved": "https://registry.npmjs.org/@material/density/-/density-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17143 |
+
"integrity": "sha512-o9EXmGKVpiQ6mHhyV3oDDzc78Ow3E7v8dlaOhgaDSXgmqaE8v5sIlLNa/LKSyUga83/fpGk3QViSGXotpQx0jA==",
|
| 17144 |
+
"requires": {
|
| 17145 |
+
"tslib": "^2.1.0"
|
| 17146 |
+
}
|
| 17147 |
+
},
|
| 17148 |
+
"@material/dialog": {
|
| 17149 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17150 |
+
"resolved": "https://registry.npmjs.org/@material/dialog/-/dialog-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17151 |
+
"integrity": "sha512-u0XpTlv1JqWC/bQ3DavJ1JguofTelLT2wloj59l3/1b60jv42JQ6Am7jU3I8/SIUB1MKaW7dYocXjDWtWJakLA==",
|
| 17152 |
+
"requires": {
|
| 17153 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17154 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17155 |
+
"@material/button": "15.0.0-canary.7f224ddd4.0",
|
| 17156 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17157 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17158 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17159 |
+
"@material/icon-button": "15.0.0-canary.7f224ddd4.0",
|
| 17160 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17161 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17162 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17163 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17164 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 17165 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 17166 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17167 |
+
"tslib": "^2.1.0"
|
| 17168 |
+
}
|
| 17169 |
+
},
|
| 17170 |
+
"@material/dom": {
|
| 17171 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17172 |
+
"resolved": "https://registry.npmjs.org/@material/dom/-/dom-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17173 |
+
"integrity": "sha512-mQ1HT186GPQSkRg5S18i70typ5ZytfjL09R0gJ2Qg5/G+MLCGi7TAjZZSH65tuD/QGOjel4rDdWOTmYbPYV6HA==",
|
| 17174 |
+
"requires": {
|
| 17175 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17176 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17177 |
+
"tslib": "^2.1.0"
|
| 17178 |
+
}
|
| 17179 |
+
},
|
| 17180 |
+
"@material/drawer": {
|
| 17181 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17182 |
+
"resolved": "https://registry.npmjs.org/@material/drawer/-/drawer-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17183 |
+
"integrity": "sha512-qyO0W0KBftfH8dlLR0gVAgv7ZHNvU8ae11Ao6zJif/YxcvK4+gph1z8AO4H410YmC2kZiwpSKyxM1iQCCzbb4g==",
|
| 17184 |
+
"requires": {
|
| 17185 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17186 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17187 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17188 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17189 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17190 |
+
"@material/list": "15.0.0-canary.7f224ddd4.0",
|
| 17191 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17192 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17193 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17194 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17195 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17196 |
+
"tslib": "^2.1.0"
|
| 17197 |
+
}
|
| 17198 |
+
},
|
| 17199 |
+
"@material/elevation": {
|
| 17200 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17201 |
+
"resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17202 |
+
"integrity": "sha512-tV6s4/pUBECedaI36Yj18KmRCk1vfue/JP/5yYRlFNnLMRVISePbZaKkn/BHXVf+26I3W879+XqIGlDVdmOoMA==",
|
| 17203 |
+
"requires": {
|
| 17204 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17205 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17206 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17207 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17208 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17209 |
+
"tslib": "^2.1.0"
|
| 17210 |
+
}
|
| 17211 |
+
},
|
| 17212 |
+
"@material/fab": {
|
| 17213 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17214 |
+
"resolved": "https://registry.npmjs.org/@material/fab/-/fab-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17215 |
+
"integrity": "sha512-4h76QrzfZTcPdd+awDPZ4Q0YdSqsXQnS540TPtyXUJ/5G99V6VwGpjMPIxAsW0y+pmI9UkLL/srrMaJec+7r4Q==",
|
| 17216 |
+
"requires": {
|
| 17217 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17218 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17219 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17220 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17221 |
+
"@material/focus-ring": "15.0.0-canary.7f224ddd4.0",
|
| 17222 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17223 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17224 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17225 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17226 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 17227 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 17228 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17229 |
+
"tslib": "^2.1.0"
|
| 17230 |
+
}
|
| 17231 |
+
},
|
| 17232 |
+
"@material/feature-targeting": {
|
| 17233 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17234 |
+
"resolved": "https://registry.npmjs.org/@material/feature-targeting/-/feature-targeting-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17235 |
+
"integrity": "sha512-SAjtxYh6YlKZriU83diDEQ7jNSP2MnxKsER0TvFeyG1vX/DWsUyYDOIJTOEa9K1N+fgJEBkNK8hY55QhQaspew==",
|
| 17236 |
+
"requires": {
|
| 17237 |
+
"tslib": "^2.1.0"
|
| 17238 |
+
}
|
| 17239 |
+
},
|
| 17240 |
+
"@material/floating-label": {
|
| 17241 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17242 |
+
"resolved": "https://registry.npmjs.org/@material/floating-label/-/floating-label-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17243 |
+
"integrity": "sha512-0KMo5ijjYaEHPiZ2pCVIcbaTS2LycvH9zEhEMKwPPGssBCX7iz5ffYQFk7e5yrQand1r3jnQQgYfHAwtykArnQ==",
|
| 17244 |
+
"requires": {
|
| 17245 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17246 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17247 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17248 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17249 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17250 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17251 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17252 |
+
"tslib": "^2.1.0"
|
| 17253 |
+
}
|
| 17254 |
+
},
|
| 17255 |
+
"@material/focus-ring": {
|
| 17256 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17257 |
+
"resolved": "https://registry.npmjs.org/@material/focus-ring/-/focus-ring-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17258 |
+
"integrity": "sha512-Jmg1nltq4J6S6A10EGMZnvufrvU3YTi+8R8ZD9lkSbun0Fm2TVdICQt/Auyi6An9zP66oQN6c31eqO6KfIPsDg==",
|
| 17259 |
+
"requires": {
|
| 17260 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17261 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17262 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0"
|
| 17263 |
+
}
|
| 17264 |
+
},
|
| 17265 |
+
"@material/form-field": {
|
| 17266 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17267 |
+
"resolved": "https://registry.npmjs.org/@material/form-field/-/form-field-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17268 |
+
"integrity": "sha512-fEPWgDQEPJ6WF7hNnIStxucHR9LE4DoDSMqCsGWS2Yu+NLZYLuCEecgR0UqQsl1EQdNRaFh8VH93KuxGd2hiPg==",
|
| 17269 |
+
"requires": {
|
| 17270 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17271 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17272 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17273 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17274 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17275 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17276 |
+
"tslib": "^2.1.0"
|
| 17277 |
+
}
|
| 17278 |
+
},
|
| 17279 |
+
"@material/icon-button": {
|
| 17280 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17281 |
+
"resolved": "https://registry.npmjs.org/@material/icon-button/-/icon-button-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17282 |
+
"integrity": "sha512-DcK7IL4ICY/DW+48YQZZs9g0U1kRaW0Wb0BxhvppDMYziHo/CTpFdle4gjyuTyRxPOdHQz5a97ru48Z9O4muTw==",
|
| 17283 |
+
"requires": {
|
| 17284 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17285 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 17286 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17287 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17288 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17289 |
+
"@material/focus-ring": "15.0.0-canary.7f224ddd4.0",
|
| 17290 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17291 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17292 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17293 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 17294 |
+
"tslib": "^2.1.0"
|
| 17295 |
+
}
|
| 17296 |
+
},
|
| 17297 |
+
"@material/image-list": {
|
| 17298 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17299 |
+
"resolved": "https://registry.npmjs.org/@material/image-list/-/image-list-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17300 |
+
"integrity": "sha512-voMjG2p80XbjL1B2lmF65zO5gEgJOVKClLdqh4wbYzYfwY/SR9c8eLvlYG7DLdFaFBl/7gGxD8TvvZ329HUFPw==",
|
| 17301 |
+
"requires": {
|
| 17302 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17303 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17304 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17305 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17306 |
+
"tslib": "^2.1.0"
|
| 17307 |
+
}
|
| 17308 |
+
},
|
| 17309 |
+
"@material/layout-grid": {
|
| 17310 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17311 |
+
"resolved": "https://registry.npmjs.org/@material/layout-grid/-/layout-grid-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17312 |
+
"integrity": "sha512-veDABLxMn2RmvfnUO2RUmC1OFfWr4cU+MrxKPoDD2hl3l3eDYv5fxws6r5T1JoSyXoaN+oEZpheS0+M9Ure8Pg==",
|
| 17313 |
+
"requires": {
|
| 17314 |
+
"tslib": "^2.1.0"
|
| 17315 |
+
}
|
| 17316 |
+
},
|
| 17317 |
+
"@material/line-ripple": {
|
| 17318 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17319 |
+
"resolved": "https://registry.npmjs.org/@material/line-ripple/-/line-ripple-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17320 |
+
"integrity": "sha512-f60hVJhIU6I3/17Tqqzch1emUKEcfVVgHVqADbU14JD+oEIz429ZX9ksZ3VChoU3+eejFl+jVdZMLE/LrAuwpg==",
|
| 17321 |
+
"requires": {
|
| 17322 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17323 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17324 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17325 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17326 |
+
"tslib": "^2.1.0"
|
| 17327 |
+
}
|
| 17328 |
+
},
|
| 17329 |
+
"@material/linear-progress": {
|
| 17330 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17331 |
+
"resolved": "https://registry.npmjs.org/@material/linear-progress/-/linear-progress-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17332 |
+
"integrity": "sha512-pRDEwPQielDiC9Sc5XhCXrGxP8wWOnAO8sQlMebfBYHYqy5hhiIzibezS8CSaW4MFQFyXmCmpmqWlbqGYRmiyg==",
|
| 17333 |
+
"requires": {
|
| 17334 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17335 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17336 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17337 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17338 |
+
"@material/progress-indicator": "15.0.0-canary.7f224ddd4.0",
|
| 17339 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17340 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17341 |
+
"tslib": "^2.1.0"
|
| 17342 |
+
}
|
| 17343 |
+
},
|
| 17344 |
+
"@material/list": {
|
| 17345 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17346 |
+
"resolved": "https://registry.npmjs.org/@material/list/-/list-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17347 |
+
"integrity": "sha512-Is0NV91sJlXF5pOebYAtWLF4wU2MJDbYqztML/zQNENkQxDOvEXu3nWNb3YScMIYJJXvARO0Liur5K4yPagS1Q==",
|
| 17348 |
+
"requires": {
|
| 17349 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17350 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 17351 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17352 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17353 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17354 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17355 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17356 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17357 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 17358 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17359 |
+
"tslib": "^2.1.0"
|
| 17360 |
+
}
|
| 17361 |
+
},
|
| 17362 |
+
"@material/menu": {
|
| 17363 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17364 |
+
"resolved": "https://registry.npmjs.org/@material/menu/-/menu-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17365 |
+
"integrity": "sha512-D11QU1dXqLbh5X1zKlEhS3QWh0b5BPNXlafc5MXfkdJHhOiieb7LC9hMJhbrHtj24FadJ7evaFW/T2ugJbJNnQ==",
|
| 17366 |
+
"requires": {
|
| 17367 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17368 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17369 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17370 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17371 |
+
"@material/list": "15.0.0-canary.7f224ddd4.0",
|
| 17372 |
+
"@material/menu-surface": "15.0.0-canary.7f224ddd4.0",
|
| 17373 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17374 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17375 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17376 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17377 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 17378 |
+
"tslib": "^2.1.0"
|
| 17379 |
+
}
|
| 17380 |
+
},
|
| 17381 |
+
"@material/menu-surface": {
|
| 17382 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17383 |
+
"resolved": "https://registry.npmjs.org/@material/menu-surface/-/menu-surface-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17384 |
+
"integrity": "sha512-7RZHvw0gbwppaAJ/Oh5SWmfAKJ62aw1IMB3+3MRwsb5PLoV666wInYa+zJfE4i7qBeOn904xqT2Nko5hY0ssrg==",
|
| 17385 |
+
"requires": {
|
| 17386 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17387 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17388 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17389 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17390 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17391 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17392 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17393 |
+
"tslib": "^2.1.0"
|
| 17394 |
+
}
|
| 17395 |
+
},
|
| 17396 |
+
"@material/notched-outline": {
|
| 17397 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17398 |
+
"resolved": "https://registry.npmjs.org/@material/notched-outline/-/notched-outline-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17399 |
+
"integrity": "sha512-Yg2usuKB2DKlKIBISbie9BFsOVuffF71xjbxPbybvqemxqUBd+bD5/t6H1fLE+F8/NCu5JMigho4ewUU+0RCiw==",
|
| 17400 |
+
"requires": {
|
| 17401 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17402 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17403 |
+
"@material/floating-label": "15.0.0-canary.7f224ddd4.0",
|
| 17404 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17405 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17406 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17407 |
+
"tslib": "^2.1.0"
|
| 17408 |
+
}
|
| 17409 |
+
},
|
| 17410 |
+
"@material/progress-indicator": {
|
| 17411 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17412 |
+
"resolved": "https://registry.npmjs.org/@material/progress-indicator/-/progress-indicator-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17413 |
+
"integrity": "sha512-UPbDjE5CqT+SqTs0mNFG6uFEw7wBlgYmh+noSkQ6ty/EURm8lF125dmi4dv4kW0+octonMXqkGtAoZwLIHKf/w==",
|
| 17414 |
+
"requires": {
|
| 17415 |
+
"tslib": "^2.1.0"
|
| 17416 |
+
}
|
| 17417 |
+
},
|
| 17418 |
+
"@material/radio": {
|
| 17419 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17420 |
+
"resolved": "https://registry.npmjs.org/@material/radio/-/radio-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17421 |
+
"integrity": "sha512-wR1X0Sr0KmQLu6+YOFKAI84G3L6psqd7Kys5kfb8WKBM36zxO5HQXC5nJm/Y0rdn22ixzsIz2GBo0MNU4V4k1A==",
|
| 17422 |
+
"requires": {
|
| 17423 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17424 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17425 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 17426 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17427 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17428 |
+
"@material/focus-ring": "15.0.0-canary.7f224ddd4.0",
|
| 17429 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17430 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17431 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 17432 |
+
"tslib": "^2.1.0"
|
| 17433 |
+
}
|
| 17434 |
+
},
|
| 17435 |
+
"@material/ripple": {
|
| 17436 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17437 |
+
"resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17438 |
+
"integrity": "sha512-JqOsWM1f4aGdotP0rh1vZlPZTg6lZgh39FIYHFMfOwfhR+LAikUJ+37ciqZuewgzXB6iiRO6a8aUH6HR5SJYPg==",
|
| 17439 |
+
"requires": {
|
| 17440 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17441 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17442 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17443 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17444 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17445 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17446 |
+
"tslib": "^2.1.0"
|
| 17447 |
+
}
|
| 17448 |
+
},
|
| 17449 |
+
"@material/rtl": {
|
| 17450 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17451 |
+
"resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17452 |
+
"integrity": "sha512-UVf14qAtmPiaaZjuJtmN36HETyoKWmsZM/qn1L5ciR2URb8O035dFWnz4ZWFMmAYBno/L7JiZaCkPurv2ZNrGA==",
|
| 17453 |
+
"requires": {
|
| 17454 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17455 |
+
"tslib": "^2.1.0"
|
| 17456 |
+
}
|
| 17457 |
+
},
|
| 17458 |
+
"@material/segmented-button": {
|
| 17459 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17460 |
+
"resolved": "https://registry.npmjs.org/@material/segmented-button/-/segmented-button-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17461 |
+
"integrity": "sha512-LCnVRUSAhELTKI/9hSvyvIvQIpPpqF29BV+O9yM4WoNNmNWqTulvuiv7grHZl6Z+kJuxSg4BGbsPxxb9dXozPg==",
|
| 17462 |
+
"requires": {
|
| 17463 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17464 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17465 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17466 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17467 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17468 |
+
"@material/touch-target": "15.0.0-canary.7f224ddd4.0",
|
| 17469 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17470 |
+
"tslib": "^2.1.0"
|
| 17471 |
+
}
|
| 17472 |
+
},
|
| 17473 |
+
"@material/select": {
|
| 17474 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17475 |
+
"resolved": "https://registry.npmjs.org/@material/select/-/select-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17476 |
+
"integrity": "sha512-WioZtQEXRpglum0cMSzSqocnhsGRr+ZIhvKb3FlaNrTaK8H3Y4QA7rVjv3emRtrLOOjaT6/RiIaUMTo9AGzWQQ==",
|
| 17477 |
+
"requires": {
|
| 17478 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17479 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17480 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 17481 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17482 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17483 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17484 |
+
"@material/floating-label": "15.0.0-canary.7f224ddd4.0",
|
| 17485 |
+
"@material/line-ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17486 |
+
"@material/list": "15.0.0-canary.7f224ddd4.0",
|
| 17487 |
+
"@material/menu": "15.0.0-canary.7f224ddd4.0",
|
| 17488 |
+
"@material/menu-surface": "15.0.0-canary.7f224ddd4.0",
|
| 17489 |
+
"@material/notched-outline": "15.0.0-canary.7f224ddd4.0",
|
| 17490 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17491 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17492 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17493 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17494 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 17495 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17496 |
+
"tslib": "^2.1.0"
|
| 17497 |
+
}
|
| 17498 |
+
},
|
| 17499 |
+
"@material/shape": {
|
| 17500 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17501 |
+
"resolved": "https://registry.npmjs.org/@material/shape/-/shape-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17502 |
+
"integrity": "sha512-8z8l1W3+cymObunJoRhwFPKZ+FyECfJ4MJykNiaZq7XJFZkV6xNmqAVrrbQj93FtLsECn9g4PjjIomguVn/OEw==",
|
| 17503 |
+
"requires": {
|
| 17504 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17505 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17506 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17507 |
+
"tslib": "^2.1.0"
|
| 17508 |
+
}
|
| 17509 |
+
},
|
| 17510 |
+
"@material/slider": {
|
| 17511 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17512 |
+
"resolved": "https://registry.npmjs.org/@material/slider/-/slider-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17513 |
+
"integrity": "sha512-QU/WSaSWlLKQRqOhJrPgm29wqvvzRusMqwAcrCh1JTrCl+xwJ43q5WLDfjYhubeKtrEEgGu9tekkAiYfMG7EBw==",
|
| 17514 |
+
"requires": {
|
| 17515 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17516 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17517 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17518 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17519 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17520 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17521 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17522 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17523 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 17524 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17525 |
+
"tslib": "^2.1.0"
|
| 17526 |
+
}
|
| 17527 |
+
},
|
| 17528 |
+
"@material/snackbar": {
|
| 17529 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17530 |
+
"resolved": "https://registry.npmjs.org/@material/snackbar/-/snackbar-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17531 |
+
"integrity": "sha512-sm7EbVKddaXpT/aXAYBdPoN0k8yeg9+dprgBUkrdqGzWJAeCkxb4fv2B3He88YiCtvkTz2KLY4CThPQBSEsMFQ==",
|
| 17532 |
+
"requires": {
|
| 17533 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17534 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17535 |
+
"@material/button": "15.0.0-canary.7f224ddd4.0",
|
| 17536 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17537 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17538 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17539 |
+
"@material/icon-button": "15.0.0-canary.7f224ddd4.0",
|
| 17540 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17541 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17542 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17543 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17544 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 17545 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17546 |
+
"tslib": "^2.1.0"
|
| 17547 |
+
}
|
| 17548 |
+
},
|
| 17549 |
+
"@material/switch": {
|
| 17550 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17551 |
+
"resolved": "https://registry.npmjs.org/@material/switch/-/switch-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17552 |
+
"integrity": "sha512-lEDJfRvkVyyeHWIBfoxYjJVl+WlEAE2kZ/+6OqB1FW0OV8ftTODZGhHRSzjVBA1/p4FPuhAtKtoK9jTpa4AZjA==",
|
| 17553 |
+
"requires": {
|
| 17554 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17555 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17556 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 17557 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17558 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17559 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17560 |
+
"@material/focus-ring": "15.0.0-canary.7f224ddd4.0",
|
| 17561 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17562 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17563 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17564 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17565 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 17566 |
+
"safevalues": "^0.3.4",
|
| 17567 |
+
"tslib": "^2.1.0"
|
| 17568 |
+
}
|
| 17569 |
+
},
|
| 17570 |
+
"@material/tab": {
|
| 17571 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17572 |
+
"resolved": "https://registry.npmjs.org/@material/tab/-/tab-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17573 |
+
"integrity": "sha512-E1xGACImyCLurhnizyOTCgOiVezce4HlBFAI6YhJo/AyVwjN2Dtas4ZLQMvvWWqpyhITNkeYdOchwCC1mrz3AQ==",
|
| 17574 |
+
"requires": {
|
| 17575 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17576 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17577 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17578 |
+
"@material/focus-ring": "15.0.0-canary.7f224ddd4.0",
|
| 17579 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17580 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17581 |
+
"@material/tab-indicator": "15.0.0-canary.7f224ddd4.0",
|
| 17582 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17583 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 17584 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17585 |
+
"tslib": "^2.1.0"
|
| 17586 |
+
}
|
| 17587 |
+
},
|
| 17588 |
+
"@material/tab-bar": {
|
| 17589 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17590 |
+
"resolved": "https://registry.npmjs.org/@material/tab-bar/-/tab-bar-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17591 |
+
"integrity": "sha512-p1Asb2NzrcECvAQU3b2SYrpyJGyJLQWR+nXTYzDKE8WOpLIRCXap2audNqD7fvN/A20UJ1J8U01ptrvCkwJ4eA==",
|
| 17592 |
+
"requires": {
|
| 17593 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17594 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17595 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 17596 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17597 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17598 |
+
"@material/tab": "15.0.0-canary.7f224ddd4.0",
|
| 17599 |
+
"@material/tab-indicator": "15.0.0-canary.7f224ddd4.0",
|
| 17600 |
+
"@material/tab-scroller": "15.0.0-canary.7f224ddd4.0",
|
| 17601 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17602 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 17603 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17604 |
+
"tslib": "^2.1.0"
|
| 17605 |
+
}
|
| 17606 |
+
},
|
| 17607 |
+
"@material/tab-indicator": {
|
| 17608 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17609 |
+
"resolved": "https://registry.npmjs.org/@material/tab-indicator/-/tab-indicator-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17610 |
+
"integrity": "sha512-h9Td3MPqbs33spcPS7ecByRHraYgU4tNCZpZzZXw31RypjKvISDv/PS5wcA4RmWqNGih78T7xg4QIGsZg4Pk4w==",
|
| 17611 |
+
"requires": {
|
| 17612 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17613 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17614 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17615 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17616 |
+
"tslib": "^2.1.0"
|
| 17617 |
+
}
|
| 17618 |
+
},
|
| 17619 |
+
"@material/tab-scroller": {
|
| 17620 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17621 |
+
"resolved": "https://registry.npmjs.org/@material/tab-scroller/-/tab-scroller-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17622 |
+
"integrity": "sha512-LFeYNjQpdXecwECd8UaqHYbhscDCwhGln5Yh+3ctvcEgvmDPNjhKn/DL3sWprWvG8NAhP6sHMrsGhQFVdCWtTg==",
|
| 17623 |
+
"requires": {
|
| 17624 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17625 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17626 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17627 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17628 |
+
"@material/tab": "15.0.0-canary.7f224ddd4.0",
|
| 17629 |
+
"tslib": "^2.1.0"
|
| 17630 |
+
}
|
| 17631 |
+
},
|
| 17632 |
+
"@material/textfield": {
|
| 17633 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17634 |
+
"resolved": "https://registry.npmjs.org/@material/textfield/-/textfield-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17635 |
+
"integrity": "sha512-AExmFvgE5nNF0UA4l2cSzPghtxSUQeeoyRjFLHLy+oAaE4eKZFrSy0zEpqPeWPQpEMDZk+6Y+6T3cOFYBeSvsw==",
|
| 17636 |
+
"requires": {
|
| 17637 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17638 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17639 |
+
"@material/density": "15.0.0-canary.7f224ddd4.0",
|
| 17640 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17641 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17642 |
+
"@material/floating-label": "15.0.0-canary.7f224ddd4.0",
|
| 17643 |
+
"@material/line-ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17644 |
+
"@material/notched-outline": "15.0.0-canary.7f224ddd4.0",
|
| 17645 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17646 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17647 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17648 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17649 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 17650 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17651 |
+
"tslib": "^2.1.0"
|
| 17652 |
+
}
|
| 17653 |
+
},
|
| 17654 |
+
"@material/theme": {
|
| 17655 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17656 |
+
"resolved": "https://registry.npmjs.org/@material/theme/-/theme-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17657 |
+
"integrity": "sha512-hs45hJoE9yVnoVOcsN1jklyOa51U4lzWsEnQEuJTPOk2+0HqCQ0yv/q0InpSnm2i69fNSyZC60+8HADZGF8ugQ==",
|
| 17658 |
+
"requires": {
|
| 17659 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17660 |
+
"tslib": "^2.1.0"
|
| 17661 |
+
}
|
| 17662 |
+
},
|
| 17663 |
+
"@material/tokens": {
|
| 17664 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17665 |
+
"resolved": "https://registry.npmjs.org/@material/tokens/-/tokens-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17666 |
+
"integrity": "sha512-r9TDoicmcT7FhUXC4eYMFnt9TZsz0G8T3wXvkKncLppYvZ517gPyD/1+yhuGfGOxAzxTrM66S/oEc1fFE2q4hw==",
|
| 17667 |
+
"requires": {
|
| 17668 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0"
|
| 17669 |
+
}
|
| 17670 |
+
},
|
| 17671 |
+
"@material/tooltip": {
|
| 17672 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17673 |
+
"resolved": "https://registry.npmjs.org/@material/tooltip/-/tooltip-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17674 |
+
"integrity": "sha512-8qNk3pmPLTnam3XYC1sZuplQXW9xLn4Z4MI3D+U17Q7pfNZfoOugGr+d2cLA9yWAEjVJYB0mj8Yu86+udo4N9w==",
|
| 17675 |
+
"requires": {
|
| 17676 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17677 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17678 |
+
"@material/button": "15.0.0-canary.7f224ddd4.0",
|
| 17679 |
+
"@material/dom": "15.0.0-canary.7f224ddd4.0",
|
| 17680 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17681 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17682 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17683 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17684 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17685 |
+
"@material/tokens": "15.0.0-canary.7f224ddd4.0",
|
| 17686 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17687 |
+
"safevalues": "^0.3.4",
|
| 17688 |
+
"tslib": "^2.1.0"
|
| 17689 |
+
}
|
| 17690 |
+
},
|
| 17691 |
+
"@material/top-app-bar": {
|
| 17692 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17693 |
+
"resolved": "https://registry.npmjs.org/@material/top-app-bar/-/top-app-bar-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17694 |
+
"integrity": "sha512-SARR5/ClYT4CLe9qAXakbr0i0cMY0V3V4pe3ElIJPfL2Z2c4wGR1mTR8m2LxU1MfGKK8aRoUdtfKaxWejp+eNA==",
|
| 17695 |
+
"requires": {
|
| 17696 |
+
"@material/animation": "15.0.0-canary.7f224ddd4.0",
|
| 17697 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17698 |
+
"@material/elevation": "15.0.0-canary.7f224ddd4.0",
|
| 17699 |
+
"@material/ripple": "15.0.0-canary.7f224ddd4.0",
|
| 17700 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17701 |
+
"@material/shape": "15.0.0-canary.7f224ddd4.0",
|
| 17702 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17703 |
+
"@material/typography": "15.0.0-canary.7f224ddd4.0",
|
| 17704 |
+
"tslib": "^2.1.0"
|
| 17705 |
+
}
|
| 17706 |
+
},
|
| 17707 |
+
"@material/touch-target": {
|
| 17708 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17709 |
+
"resolved": "https://registry.npmjs.org/@material/touch-target/-/touch-target-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17710 |
+
"integrity": "sha512-BJo/wFKHPYLGsRaIpd7vsQwKr02LtO2e89Psv0on/p0OephlNIgeB9dD9W+bQmaeZsZ6liKSKRl6wJWDiK71PA==",
|
| 17711 |
+
"requires": {
|
| 17712 |
+
"@material/base": "15.0.0-canary.7f224ddd4.0",
|
| 17713 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17714 |
+
"@material/rtl": "15.0.0-canary.7f224ddd4.0",
|
| 17715 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17716 |
+
"tslib": "^2.1.0"
|
| 17717 |
+
}
|
| 17718 |
+
},
|
| 17719 |
+
"@material/typography": {
|
| 17720 |
+
"version": "15.0.0-canary.7f224ddd4.0",
|
| 17721 |
+
"resolved": "https://registry.npmjs.org/@material/typography/-/typography-15.0.0-canary.7f224ddd4.0.tgz",
|
| 17722 |
+
"integrity": "sha512-kBaZeCGD50iq1DeRRH5OM5Jl7Gdk+/NOfKArkY4ksBZvJiStJ7ACAhpvb8MEGm4s3jvDInQFLsDq3hL+SA79sQ==",
|
| 17723 |
+
"requires": {
|
| 17724 |
+
"@material/feature-targeting": "15.0.0-canary.7f224ddd4.0",
|
| 17725 |
+
"@material/theme": "15.0.0-canary.7f224ddd4.0",
|
| 17726 |
+
"tslib": "^2.1.0"
|
| 17727 |
+
}
|
| 17728 |
+
},
|
| 17729 |
"@ngtools/webpack": {
|
| 17730 |
"version": "17.3.11",
|
| 17731 |
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.3.11.tgz",
|
|
|
|
| 19983 |
"version": "4.5.0",
|
| 19984 |
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
| 19985 |
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
| 19986 |
+
"devOptional": true
|
| 19987 |
},
|
| 19988 |
"env-paths": {
|
| 19989 |
"version": "2.2.1",
|
|
|
|
| 23025 |
"version": "7.2.1",
|
| 23026 |
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz",
|
| 23027 |
"integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==",
|
| 23028 |
+
"devOptional": true,
|
| 23029 |
"requires": {
|
| 23030 |
"entities": "^4.5.0"
|
| 23031 |
}
|
|
|
|
| 23792 |
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
| 23793 |
"dev": true
|
| 23794 |
},
|
| 23795 |
+
"safevalues": {
|
| 23796 |
+
"version": "0.3.4",
|
| 23797 |
+
"resolved": "https://registry.npmjs.org/safevalues/-/safevalues-0.3.4.tgz",
|
| 23798 |
+
"integrity": "sha512-LRneZZRXNgjzwG4bDQdOTSbze3fHm1EAKN/8bePxnlEZiBmkYEDggaHbuvHI9/hoqHbGfsEA7tWS9GhYHZBBsw=="
|
| 23799 |
+
},
|
| 23800 |
"sass": {
|
| 23801 |
"version": "1.71.1",
|
| 23802 |
"resolved": "https://registry.npmjs.org/sass/-/sass-1.71.1.tgz",
|
|
|
|
| 25182 |
"graceful-fs": "^4.1.2"
|
| 25183 |
}
|
| 25184 |
},
|
| 25185 |
+
"wavesurfer.js": {
|
| 25186 |
+
"version": "7.12.1",
|
| 25187 |
+
"resolved": "https://registry.npmjs.org/wavesurfer.js/-/wavesurfer.js-7.12.1.tgz",
|
| 25188 |
+
"integrity": "sha512-NswPjVHxk0Q1F/VMRemCPUzSojjuHHisQrBqQiRXg7MVbe3f5vQ6r0rTTXA/a/neC/4hnOEC4YpXca4LpH0SUg=="
|
| 25189 |
+
},
|
| 25190 |
"wbuf": {
|
| 25191 |
"version": "1.7.3",
|
| 25192 |
"resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
|
src/app/app.module.ts
CHANGED
|
@@ -25,6 +25,9 @@ import { RootRedirectComponent } from './root-redirect/root-redirect.component';
|
|
| 25 |
import { HeaderComponent } from './shared/header/header.component';
|
| 26 |
import { SignInComponent } from './sign-in/sign-in.component';
|
| 27 |
import { PronunciationComponent } from './pronunciation/pronunciation.component';
|
|
|
|
|
|
|
|
|
|
| 28 |
import { FooterComponent } from './footer/footer.component';
|
| 29 |
// If you have AppButtonComponent, import it here as well
|
| 30 |
// import { AppButtonComponent } from './app-button/app-button.component';
|
|
@@ -37,6 +40,8 @@ import { FooterComponent } from './footer/footer.component';
|
|
| 37 |
AuthComponent,
|
| 38 |
RootRedirectComponent,
|
| 39 |
PronunciationComponent,
|
|
|
|
|
|
|
| 40 |
FooterComponent,
|
| 41 |
//GenerateQuestionsComponent,
|
| 42 |
//VocabularyBuilderComponent,
|
|
|
|
| 25 |
import { HeaderComponent } from './shared/header/header.component';
|
| 26 |
import { SignInComponent } from './sign-in/sign-in.component';
|
| 27 |
import { PronunciationComponent } from './pronunciation/pronunciation.component';
|
| 28 |
+
import { PronunciationVideoComponent } from './pronunciationvideo/pronunciationvideo.component';
|
| 29 |
+
import { PronunciationRaggComponent } from './pronunciationragg/pronunciationragg.component';
|
| 30 |
+
|
| 31 |
import { FooterComponent } from './footer/footer.component';
|
| 32 |
// If you have AppButtonComponent, import it here as well
|
| 33 |
// import { AppButtonComponent } from './app-button/app-button.component';
|
|
|
|
| 40 |
AuthComponent,
|
| 41 |
RootRedirectComponent,
|
| 42 |
PronunciationComponent,
|
| 43 |
+
PronunciationVideoComponent,
|
| 44 |
+
PronunciationRaggComponent,
|
| 45 |
FooterComponent,
|
| 46 |
//GenerateQuestionsComponent,
|
| 47 |
//VocabularyBuilderComponent,
|
src/app/home/home.component.html
CHANGED
|
@@ -25,6 +25,16 @@
|
|
| 25 |
Pronunciation Trainer
|
| 26 |
</a>
|
| 27 |
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
<li><a class="nav-link--disabled" routerLink="/personality-improvement" routerLinkActive="active-link">Personality Improvement</a></li>
|
| 29 |
<li><a class="nav-link--disabled" routerLink="/body-language-improvement" routerLinkActive="active-link">Body Language Improvement</a></li>
|
| 30 |
</ul>
|
|
|
|
| 25 |
Pronunciation Trainer
|
| 26 |
</a>
|
| 27 |
</li>
|
| 28 |
+
<li>
|
| 29 |
+
<a href="#" (click)="openPronunciationVideo(); $event.preventDefault()" role="button" aria-pressed="false">
|
| 30 |
+
Pronunciation Trainer Video
|
| 31 |
+
</a>
|
| 32 |
+
</li>
|
| 33 |
+
<li>
|
| 34 |
+
<a href="#" (click)="openPronunciationRagg(); $event.preventDefault()" role="button" aria-pressed="false">
|
| 35 |
+
Pronunciation Trainer Ragg
|
| 36 |
+
</a>
|
| 37 |
+
</li>
|
| 38 |
<li><a class="nav-link--disabled" routerLink="/personality-improvement" routerLinkActive="active-link">Personality Improvement</a></li>
|
| 39 |
<li><a class="nav-link--disabled" routerLink="/body-language-improvement" routerLinkActive="active-link">Body Language Improvement</a></li>
|
| 40 |
</ul>
|
src/app/home/home.component.ts
CHANGED
|
@@ -5,6 +5,8 @@ import { Subscription } from 'rxjs';
|
|
| 5 |
import { BrandService } from '../shared/brand.service';
|
| 6 |
import { MatDialog } from '@angular/material/dialog';
|
| 7 |
import { PronunciationComponent } from '../pronunciation/pronunciation.component';
|
|
|
|
|
|
|
| 8 |
|
| 9 |
@Component({
|
| 10 |
selector: 'app-home',
|
|
@@ -170,4 +172,22 @@ export class HomeComponent implements AfterViewInit, OnInit, OnDestroy {
|
|
| 170 |
disableClose: true
|
| 171 |
});
|
| 172 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 173 |
}
|
|
|
|
| 5 |
import { BrandService } from '../shared/brand.service';
|
| 6 |
import { MatDialog } from '@angular/material/dialog';
|
| 7 |
import { PronunciationComponent } from '../pronunciation/pronunciation.component';
|
| 8 |
+
import { PronunciationVideoComponent } from '../pronunciationvideo/pronunciationvideo.component';
|
| 9 |
+
import { PronunciationRaggComponent } from '../pronunciationragg/pronunciationragg.component';
|
| 10 |
|
| 11 |
@Component({
|
| 12 |
selector: 'app-home',
|
|
|
|
| 172 |
disableClose: true
|
| 173 |
});
|
| 174 |
}
|
| 175 |
+
|
| 176 |
+
openPronunciationVideo(): void {
|
| 177 |
+
const dialogRef = this.dialog.open(PronunciationVideoComponent, {
|
| 178 |
+
width: '90vw',
|
| 179 |
+
maxWidth: '95vw',
|
| 180 |
+
height: '85vh',
|
| 181 |
+
disableClose: true
|
| 182 |
+
});
|
| 183 |
+
}
|
| 184 |
+
|
| 185 |
+
openPronunciationRagg(): void {
|
| 186 |
+
const dialogRef = this.dialog.open(PronunciationRaggComponent, {
|
| 187 |
+
width: '90vw',
|
| 188 |
+
maxWidth: '95vw',
|
| 189 |
+
height: '85vh',
|
| 190 |
+
disableClose: true
|
| 191 |
+
});
|
| 192 |
+
}
|
| 193 |
}
|
src/app/pronunciationragg/pronunciationragg.component.css
ADDED
|
@@ -0,0 +1,785 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
:host {
|
| 2 |
+
display: block;
|
| 3 |
+
/*font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;*/
|
| 4 |
+
font-family: Raleway, Roboto, "Helvetica Neue", sans-serif;
|
| 5 |
+
}
|
| 6 |
+
|
| 7 |
+
/* Page background */
|
| 8 |
+
.pp-page {
|
| 9 |
+
height: 85vh;
|
| 10 |
+
/* background: #e9f7f6;*/
|
| 11 |
+
padding: 28px 24px 18px;
|
| 12 |
+
box-sizing: border-box;
|
| 13 |
+
border: 7px solid #3aaea8;
|
| 14 |
+
border-radius: 1vw;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
/* Header */
|
| 18 |
+
.pp-header {
|
| 19 |
+
text-align: center;
|
| 20 |
+
margin-bottom: 18px;
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
.pp-header h1 {
|
| 24 |
+
margin: 0;
|
| 25 |
+
font-size: 42px;
|
| 26 |
+
font-weight: 800;
|
| 27 |
+
color: #3aaea8;
|
| 28 |
+
letter-spacing: 0.3px;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
.pp-sub {
|
| 32 |
+
margin-top: 6px;
|
| 33 |
+
color: #6b7f7e;
|
| 34 |
+
font-size: 15px;
|
| 35 |
+
position: relative;
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
.pp-tooltip {
|
| 39 |
+
margin-left: 8px;
|
| 40 |
+
display: inline-block;
|
| 41 |
+
background: #ffffff;
|
| 42 |
+
border: 1px solid #d8eeee;
|
| 43 |
+
color: #2f6f6b;
|
| 44 |
+
padding: 6px 10px;
|
| 45 |
+
border-radius: 14px;
|
| 46 |
+
font-size: 12px;
|
| 47 |
+
box-shadow: 0 6px 14px rgba(0,0,0,0.06);
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
/* Main 3 columns */
|
| 51 |
+
.pp-main {
|
| 52 |
+
display: flex;
|
| 53 |
+
gap: 1vw;
|
| 54 |
+
align-items: start;
|
| 55 |
+
justify-content: space-around;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
/* LEFT */
|
| 59 |
+
.pp-left {
|
| 60 |
+
display: flex;
|
| 61 |
+
justify-content: center;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
.word-card {
|
| 65 |
+
width: 22vw;
|
| 66 |
+
height: 34vw;
|
| 67 |
+
background: #e9f7f6;
|
| 68 |
+
border-radius: 18px;
|
| 69 |
+
padding: 22px 18px 26px;
|
| 70 |
+
text-align: center;
|
| 71 |
+
box-shadow: 0 12px 26px rgba(0, 0, 0, 0.08);
|
| 72 |
+
border: 3px dashed #3aaea8;
|
| 73 |
+
gap: 0.5vw;
|
| 74 |
+
display: flex;
|
| 75 |
+
flex-direction: column;
|
| 76 |
+
align-items: center;
|
| 77 |
+
justify-content: space-between;
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
.word-img-wrap {
|
| 81 |
+
width: 20vw;
|
| 82 |
+
height: 20vw;
|
| 83 |
+
display: flex;
|
| 84 |
+
align-items: center;
|
| 85 |
+
justify-content: center;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
.word-img-wrap img {
|
| 89 |
+
max-width: 100%;
|
| 90 |
+
max-height: 100%;
|
| 91 |
+
object-fit: contain;
|
| 92 |
+
border-radius:1vw;
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
.word-text {
|
| 96 |
+
font-size: 3vw;
|
| 97 |
+
font-weight: 800;
|
| 98 |
+
color: #1f2b2a;
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
.phonetic-pill {
|
| 102 |
+
color: #3aaea8;
|
| 103 |
+
font-size: 1.5vw;
|
| 104 |
+
font-weight: 600;
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
.audio-img {
|
| 108 |
+
width: 4.8vw;
|
| 109 |
+
cursor: pointer;
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
}
|
| 113 |
+
/* CENTER */
|
| 114 |
+
.pp-center {
|
| 115 |
+
display: flex;
|
| 116 |
+
flex-direction: column;
|
| 117 |
+
align-items: center;
|
| 118 |
+
gap: 14px;
|
| 119 |
+
position: relative;
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
.teacher-frame {
|
| 123 |
+
/* width: 240px;
|
| 124 |
+
height: 210px;
|
| 125 |
+
border-radius: 18px;
|
| 126 |
+
padding: 12px;
|
| 127 |
+
background: #e7f4f3;
|
| 128 |
+
border: 2px dashed #b9dedb;
|
| 129 |
+
display: flex;
|
| 130 |
+
align-items: center;
|
| 131 |
+
justify-content: center;*/
|
| 132 |
+
width: 22vw;
|
| 133 |
+
height: 33vw;
|
| 134 |
+
background: #e9f7f6;
|
| 135 |
+
border-radius: 18px;
|
| 136 |
+
padding: 22px 18px 26px;
|
| 137 |
+
text-align: center;
|
| 138 |
+
box-shadow: 0 12px 26px rgba(0, 0, 0, 0.08);
|
| 139 |
+
border: 3px dashed #3aaea8;
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
.teacher-frame img {
|
| 143 |
+
width: 100%;
|
| 144 |
+
height: 100%;
|
| 145 |
+
object-fit: cover;
|
| 146 |
+
border-radius: 12px;
|
| 147 |
+
background: #ffffff;
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
/* Listen button */
|
| 151 |
+
.listen-btn {
|
| 152 |
+
border: none;
|
| 153 |
+
background: #49b6ae;
|
| 154 |
+
color: #ffffff;
|
| 155 |
+
padding: 12px 18px;
|
| 156 |
+
border-radius: 12px;
|
| 157 |
+
font-weight: 700;
|
| 158 |
+
font-size: 16px;
|
| 159 |
+
display: inline-flex;
|
| 160 |
+
align-items: center;
|
| 161 |
+
gap: 10px;
|
| 162 |
+
cursor: pointer;
|
| 163 |
+
box-shadow: 0 8px 18px rgba(0,0,0,0.08);
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
.listen-btn:active {
|
| 167 |
+
transform: scale(0.99);
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
.listen-ico {
|
| 171 |
+
font-size: 18px;
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
/* Record circle */
|
| 175 |
+
.rec-circle {
|
| 176 |
+
width: 92px;
|
| 177 |
+
height: 92px;
|
| 178 |
+
border-radius: 50%;
|
| 179 |
+
border: none;
|
| 180 |
+
background: #f07b48;
|
| 181 |
+
color: #ffffff;
|
| 182 |
+
cursor: pointer;
|
| 183 |
+
/* box-shadow: 0 12px 22px rgba(0,0,0,0.12);*/
|
| 184 |
+
display: flex;
|
| 185 |
+
align-items: center;
|
| 186 |
+
justify-content: center;
|
| 187 |
+
/* transition: transform 0.08s ease, filter 0.2s ease;*/
|
| 188 |
+
box-shadow: 0px 10px 30px rgba(0, 0, 0, 0.4);
|
| 189 |
+
transition: all 0.3s ease;
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
.rec-circle:active {
|
| 193 |
+
transform: scale(0.98);
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
.rec-circle.recording {
|
| 197 |
+
filter: brightness(0.95);
|
| 198 |
+
animation: recPulse 1s infinite;
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
@keyframes recPulse {
|
| 202 |
+
0% {
|
| 203 |
+
box-shadow: 0 0 0 0 rgba(240,123,72,0.35);
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
70% {
|
| 207 |
+
box-shadow: 0 0 0 18px rgba(240,123,72,0);
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
100% {
|
| 211 |
+
box-shadow: 0 0 0 0 rgba(240,123,72,0);
|
| 212 |
+
}
|
| 213 |
+
}
|
| 214 |
+
|
| 215 |
+
.rec-inner {
|
| 216 |
+
text-align: center;
|
| 217 |
+
line-height: 1.1;
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
+
.mic {
|
| 221 |
+
font-size: 22px;
|
| 222 |
+
margin-bottom: 4px;
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
.rec-text {
|
| 226 |
+
font-size: 12px;
|
| 227 |
+
font-weight: 800;
|
| 228 |
+
letter-spacing: 0.6px;
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
/* RIGHT */
|
| 232 |
+
.pp-right {
|
| 233 |
+
|
| 234 |
+
display: flex;
|
| 235 |
+
justify-content: flex-start;
|
| 236 |
+
align-items: center;
|
| 237 |
+
flex-direction: column;
|
| 238 |
+
gap: 18vw;
|
| 239 |
+
}
|
| 240 |
+
|
| 241 |
+
/* little connector dots */
|
| 242 |
+
.connector {
|
| 243 |
+
|
| 244 |
+
display: flex;
|
| 245 |
+
flex-direction: column;
|
| 246 |
+
gap: 2vw;
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
.connector span {
|
| 250 |
+
width: 34px;
|
| 251 |
+
height: 10px;
|
| 252 |
+
border-radius: 999px;
|
| 253 |
+
background: #98d8d4;
|
| 254 |
+
opacity: 0.6;
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
/* feedback card */
|
| 258 |
+
.feedback-card {
|
| 259 |
+
width: 15vw;
|
| 260 |
+
background: #9edfd9;
|
| 261 |
+
border-radius: 16px;
|
| 262 |
+
padding: 22px 22px 24px;
|
| 263 |
+
box-shadow: 0 12px 22px rgba(0,0,0,0.08);
|
| 264 |
+
height: 15vw;
|
| 265 |
+
}
|
| 266 |
+
|
| 267 |
+
.feedback-title {
|
| 268 |
+
font-size: 18px;
|
| 269 |
+
font-weight: 800;
|
| 270 |
+
color: #205f5a;
|
| 271 |
+
letter-spacing: 0.6px;
|
| 272 |
+
margin-bottom: 8px;
|
| 273 |
+
}
|
| 274 |
+
|
| 275 |
+
.feedback-body {
|
| 276 |
+
background: transparent;
|
| 277 |
+
}
|
| 278 |
+
|
| 279 |
+
.feedback-muted {
|
| 280 |
+
color: #2c6d68;
|
| 281 |
+
opacity: 0.8;
|
| 282 |
+
font-style: italic;
|
| 283 |
+
font-size: 14px;
|
| 284 |
+
margin-top: 8px;
|
| 285 |
+
}
|
| 286 |
+
|
| 287 |
+
/* Result UI inside feedback */
|
| 288 |
+
.feedback-result {
|
| 289 |
+
margin-top: 8px;
|
| 290 |
+
}
|
| 291 |
+
|
| 292 |
+
.score-row {
|
| 293 |
+
display: flex;
|
| 294 |
+
align-items: baseline;
|
| 295 |
+
gap: 10px;
|
| 296 |
+
}
|
| 297 |
+
|
| 298 |
+
.score-label {
|
| 299 |
+
font-size: 12px;
|
| 300 |
+
color: #1d514d;
|
| 301 |
+
font-weight: 700;
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
.score-value {
|
| 305 |
+
font-size: 28px;
|
| 306 |
+
font-weight: 900;
|
| 307 |
+
color: #103c39;
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
+
/* Speakometer */
|
| 311 |
+
.meter {
|
| 312 |
+
margin-top: 10px;
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
.meter-track {
|
| 316 |
+
height: 10px;
|
| 317 |
+
background: rgba(255,255,255,0.45);
|
| 318 |
+
border-radius: 999px;
|
| 319 |
+
overflow: hidden;
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
.meter-fill {
|
| 323 |
+
height: 100%;
|
| 324 |
+
width: 0%;
|
| 325 |
+
background: #2b8f88;
|
| 326 |
+
transition: width 0.5s ease;
|
| 327 |
+
}
|
| 328 |
+
|
| 329 |
+
/* Stars */
|
| 330 |
+
.stars {
|
| 331 |
+
margin-top: 10px;
|
| 332 |
+
font-size: 22px;
|
| 333 |
+
display: flex;
|
| 334 |
+
gap: 4px;
|
| 335 |
+
}
|
| 336 |
+
|
| 337 |
+
.stars span {
|
| 338 |
+
color: rgba(255,255,255,0.55);
|
| 339 |
+
}
|
| 340 |
+
|
| 341 |
+
.stars span.active {
|
| 342 |
+
color: #ffcc4d;
|
| 343 |
+
animation: starPop 0.3s ease;
|
| 344 |
+
}
|
| 345 |
+
|
| 346 |
+
@keyframes starPop {
|
| 347 |
+
0% {
|
| 348 |
+
transform: scale(0.85);
|
| 349 |
+
}
|
| 350 |
+
|
| 351 |
+
60% {
|
| 352 |
+
transform: scale(1.12);
|
| 353 |
+
}
|
| 354 |
+
|
| 355 |
+
100% {
|
| 356 |
+
transform: scale(1);
|
| 357 |
+
}
|
| 358 |
+
}
|
| 359 |
+
|
| 360 |
+
/* 3 lines feedback */
|
| 361 |
+
.feedback-lines {
|
| 362 |
+
margin: 10px 0 0 18px;
|
| 363 |
+
color: #114744;
|
| 364 |
+
font-size: 13.5px;
|
| 365 |
+
font-weight: 600;
|
| 366 |
+
}
|
| 367 |
+
|
| 368 |
+
/* Bottom area */
|
| 369 |
+
.pp-bottom {
|
| 370 |
+
max-width: 1200px;
|
| 371 |
+
margin: 22px auto 0;
|
| 372 |
+
display: flex;
|
| 373 |
+
flex-direction: column;
|
| 374 |
+
align-items: center;
|
| 375 |
+
gap: 14px;
|
| 376 |
+
}
|
| 377 |
+
|
| 378 |
+
/* Prev/Next line */
|
| 379 |
+
/* Prev/Next line */
|
| 380 |
+
.nav-row {
|
| 381 |
+
display: flex;
|
| 382 |
+
align-items: center;
|
| 383 |
+
gap: 3vw;
|
| 384 |
+
}
|
| 385 |
+
|
| 386 |
+
/* Increased arrow size and perfectly center it inside the circular button */
|
| 387 |
+
.nav-btn {
|
| 388 |
+
width: 7vw;
|
| 389 |
+
height: 7vw;
|
| 390 |
+
border-radius: 50%;
|
| 391 |
+
border: none;
|
| 392 |
+
background: #dcefee;
|
| 393 |
+
color: #1b5551;
|
| 394 |
+
font-size: 7vw; /* larger arrow */
|
| 395 |
+
display: flex; /* center text horizontally & vertically */
|
| 396 |
+
align-items: center;
|
| 397 |
+
justify-content: center;
|
| 398 |
+
text-align: center;
|
| 399 |
+
line-height: 1; /* avoid font baseline shifts */
|
| 400 |
+
padding: 0; /* ensure perfect centering */
|
| 401 |
+
cursor: pointer;
|
| 402 |
+
font-weight: 700;
|
| 403 |
+
box-shadow: 0 8px 18px rgba(0,0,0,0.06);
|
| 404 |
+
transition: transform 0.08s ease;
|
| 405 |
+
}
|
| 406 |
+
|
| 407 |
+
.nav-btn:active {
|
| 408 |
+
transform: scale(0.98);
|
| 409 |
+
}
|
| 410 |
+
|
| 411 |
+
.nav-btn:disabled {
|
| 412 |
+
opacity: 0.5;
|
| 413 |
+
cursor: not-allowed;
|
| 414 |
+
}
|
| 415 |
+
.nav-center {
|
| 416 |
+
display: inline-flex;
|
| 417 |
+
align-items: baseline;
|
| 418 |
+
gap: 8px;
|
| 419 |
+
}
|
| 420 |
+
|
| 421 |
+
.nav-letter {
|
| 422 |
+
font-size: 5vw;
|
| 423 |
+
font-weight: 900;
|
| 424 |
+
color: #3aaea8;
|
| 425 |
+
}
|
| 426 |
+
|
| 427 |
+
.nav-count {
|
| 428 |
+
font-size: 14px;
|
| 429 |
+
color: #667b79;
|
| 430 |
+
font-weight: 600;
|
| 431 |
+
}
|
| 432 |
+
|
| 433 |
+
/* Responsive override so buttons don't overflow on smaller screens */
|
| 434 |
+
@media (max-width: 980px) {
|
| 435 |
+
.nav-btn {
|
| 436 |
+
width: 56px;
|
| 437 |
+
height: 56px;
|
| 438 |
+
font-size: 28px;
|
| 439 |
+
}
|
| 440 |
+
}
|
| 441 |
+
|
| 442 |
+
/* Alphabet pills */
|
| 443 |
+
.alpha-row {
|
| 444 |
+
display: flex;
|
| 445 |
+
flex-wrap: wrap;
|
| 446 |
+
justify-content: center;
|
| 447 |
+
gap: 8px;
|
| 448 |
+
max-width: 900px;
|
| 449 |
+
}
|
| 450 |
+
|
| 451 |
+
.alpha-pill {
|
| 452 |
+
width: 34px;
|
| 453 |
+
height: 34px;
|
| 454 |
+
border-radius: 50%;
|
| 455 |
+
border: none;
|
| 456 |
+
background: #dfeeee;
|
| 457 |
+
color: #3a5a58;
|
| 458 |
+
font-weight: 700;
|
| 459 |
+
cursor: pointer;
|
| 460 |
+
font-size: 13px;
|
| 461 |
+
}
|
| 462 |
+
|
| 463 |
+
.alpha-pill.active {
|
| 464 |
+
background: #49b6ae;
|
| 465 |
+
color: #ffffff;
|
| 466 |
+
box-shadow: 0 6px 14px rgba(0,0,0,0.08);
|
| 467 |
+
}
|
| 468 |
+
|
| 469 |
+
/* Responsive */
|
| 470 |
+
@media (max-width: 1100px) {
|
| 471 |
+
.pp-main {
|
| 472 |
+
grid-template-columns: 260px 320px 1fr;
|
| 473 |
+
}
|
| 474 |
+
}
|
| 475 |
+
|
| 476 |
+
@media (max-width: 980px) {
|
| 477 |
+
.pp-main {
|
| 478 |
+
grid-template-columns: 1fr;
|
| 479 |
+
}
|
| 480 |
+
|
| 481 |
+
.pp-left, .pp-center, .pp-right {
|
| 482 |
+
justify-content: center;
|
| 483 |
+
}
|
| 484 |
+
|
| 485 |
+
.connector {
|
| 486 |
+
display: none;
|
| 487 |
+
}
|
| 488 |
+
|
| 489 |
+
.feedback-card {
|
| 490 |
+
width: 100%;
|
| 491 |
+
max-width: 520px;
|
| 492 |
+
}
|
| 493 |
+
}
|
| 494 |
+
.gauge-wrapper {
|
| 495 |
+
position: relative;
|
| 496 |
+
width: 20vw;
|
| 497 |
+
height: 10vw;
|
| 498 |
+
}
|
| 499 |
+
|
| 500 |
+
.gauge {
|
| 501 |
+
position: absolute;
|
| 502 |
+
left: 50%;
|
| 503 |
+
top: 0;
|
| 504 |
+
transform: translateX(-50%);
|
| 505 |
+
width: 100%;
|
| 506 |
+
height: 100%;
|
| 507 |
+
border-radius: 260px 260px 0 0;
|
| 508 |
+
overflow: hidden;
|
| 509 |
+
background: #f3f3f3;
|
| 510 |
+
box-shadow: 0 4px 10px rgba(0,0,0,0.25) inset;
|
| 511 |
+
}
|
| 512 |
+
|
| 513 |
+
.gauge-arc {
|
| 514 |
+
position: absolute;
|
| 515 |
+
inset: 0;
|
| 516 |
+
border-radius: 50%;
|
| 517 |
+
background: conic-gradient( from 270deg, #e53935 0deg 45deg, #fb8c00 45deg 90deg, #fbc02d 90deg 135deg, #43a047 135deg 180deg, transparent 180deg 360deg );
|
| 518 |
+
height: 20vw;
|
| 519 |
+
}
|
| 520 |
+
|
| 521 |
+
.needle {
|
| 522 |
+
position: absolute;
|
| 523 |
+
bottom: 0vw;
|
| 524 |
+
left: 50%;
|
| 525 |
+
width: 0.7vw;
|
| 526 |
+
height: 8vw;
|
| 527 |
+
background: #333;
|
| 528 |
+
transform: translateX(-50%) rotate(var(--angle, -90deg));
|
| 529 |
+
transform-origin: 50% 100%;
|
| 530 |
+
transition: transform 700ms cubic-bezier(.2,.9,.2,1);
|
| 531 |
+
border-radius: 10px;
|
| 532 |
+
box-shadow: 0 2px 6px rgba(0,0,0,0.5);
|
| 533 |
+
}
|
| 534 |
+
|
| 535 |
+
.mic-badge {
|
| 536 |
+
position: absolute;
|
| 537 |
+
bottom: -0.3vw;
|
| 538 |
+
left: 50%;
|
| 539 |
+
transform: translate(-50%, 35%);
|
| 540 |
+
width: 3vw;
|
| 541 |
+
height: 3vw;
|
| 542 |
+
border-radius: 50%;
|
| 543 |
+
background: #000;
|
| 544 |
+
box-shadow: 0 8px 18px rgba(0,0,0,0.4);
|
| 545 |
+
display: flex;
|
| 546 |
+
align-items: center;
|
| 547 |
+
justify-content: center;
|
| 548 |
+
}
|
| 549 |
+
|
| 550 |
+
.score-span {
|
| 551 |
+
color: white;
|
| 552 |
+
font-size: 1vw;
|
| 553 |
+
font-weight: bold;
|
| 554 |
+
}
|
| 555 |
+
.notepad{
|
| 556 |
+
display:flex;
|
| 557 |
+
align-items:center;
|
| 558 |
+
}
|
| 559 |
+
|
| 560 |
+
.user-guide-close-icon {
|
| 561 |
+
position: fixed;
|
| 562 |
+
top: 3vw;
|
| 563 |
+
right: 4vw;
|
| 564 |
+
background: #009688;
|
| 565 |
+
border: none;
|
| 566 |
+
width: 44px;
|
| 567 |
+
height: 44px;
|
| 568 |
+
border-radius: 50%;
|
| 569 |
+
display: flex;
|
| 570 |
+
align-items: center;
|
| 571 |
+
justify-content: center;
|
| 572 |
+
font-size: 2vw;
|
| 573 |
+
color: black;
|
| 574 |
+
cursor: pointer;
|
| 575 |
+
z-index: 2010;
|
| 576 |
+
box-shadow: 0 2px 8px rgba(93, 145, 195, 0.18);
|
| 577 |
+
transition: background 0.2s, color 0.2s;
|
| 578 |
+
}
|
| 579 |
+
/* Teacher media container — ensures image and video occupy exactly the same box */
|
| 580 |
+
.teacher-media {
|
| 581 |
+
width: 20vw; /* same as you used inline before */
|
| 582 |
+
max-width: 260px; /* optional limit for very wide screens */
|
| 583 |
+
min-width: 140px; /* optional floor */
|
| 584 |
+
aspect-ratio: 3 / 4; /* change to 16 / 9 if your videos are widescreen */
|
| 585 |
+
position: relative;
|
| 586 |
+
overflow: hidden;
|
| 587 |
+
display: block;
|
| 588 |
+
}
|
| 589 |
+
|
| 590 |
+
/* Shared styles for image and video so sizes match exactly */
|
| 591 |
+
.teacher-media__img,
|
| 592 |
+
.teacher-media__video {
|
| 593 |
+
width: 100%;
|
| 594 |
+
height: 100%;
|
| 595 |
+
display: block;
|
| 596 |
+
border-radius: 1vw;
|
| 597 |
+
border: 2px solid #ccc; /* keep previously visible border */
|
| 598 |
+
object-fit: cover; /* makes video/image fill box similarly */
|
| 599 |
+
}
|
| 600 |
+
|
| 601 |
+
/* A neutral background for video while it loads */
|
| 602 |
+
.teacher-media__video {
|
| 603 |
+
background-color: #000;
|
| 604 |
+
}
|
| 605 |
+
/* Make play/pause image match record button size and add shadow */
|
| 606 |
+
.listen-img {
|
| 607 |
+
width: 92px; /* match .rec-circle size */
|
| 608 |
+
height: 92px;
|
| 609 |
+
border-radius: 50%;
|
| 610 |
+
display: inline-block;
|
| 611 |
+
object-fit: contain; /* keep icon aspect */
|
| 612 |
+
cursor: pointer;
|
| 613 |
+
user-select: none;
|
| 614 |
+
margin-right: 1vw;
|
| 615 |
+
box-shadow: 0px 10px 30px rgba(0, 0, 0, 0.4);
|
| 616 |
+
transition: all 0.3s ease;
|
| 617 |
+
/*box-shadow: 0 12px 22px rgba(0,0,0,0.12);
|
| 618 |
+
transition: transform 0.08s ease, filter 0.15s ease, box-shadow 0.15s ease;
|
| 619 |
+
|
| 620 |
+
box-sizing: border-box;*/
|
| 621 |
+
border: none;
|
| 622 |
+
}
|
| 623 |
+
|
| 624 |
+
/* pressed / active */
|
| 625 |
+
.listen-img:active {
|
| 626 |
+
transform: scale(0.98);
|
| 627 |
+
}
|
| 628 |
+
|
| 629 |
+
/* playing state — subtle visual change */
|
| 630 |
+
.listen-img.playing,
|
| 631 |
+
.listen-img[aria-pressed="true"] {
|
| 632 |
+
filter: brightness(0.95);
|
| 633 |
+
box-shadow: 0 18px 30px rgba(0,0,0,0.16);
|
| 634 |
+
}
|
| 635 |
+
|
| 636 |
+
/* keyboard focus for accessibility */
|
| 637 |
+
.listen-img:focus {
|
| 638 |
+
outline: 3px solid rgba(58,174,168,0.18);
|
| 639 |
+
outline-offset: 3px;
|
| 640 |
+
}
|
| 641 |
+
|
| 642 |
+
/* Small-screen fallback (keep sizes proportional) */
|
| 643 |
+
@media (max-width: 980px) {
|
| 644 |
+
.listen-img {
|
| 645 |
+
width: 72px;
|
| 646 |
+
height: 72px;
|
| 647 |
+
padding: 14px;
|
| 648 |
+
}
|
| 649 |
+
}
|
| 650 |
+
/* add oscillation keyframes and state */
|
| 651 |
+
@keyframes needleOscillate {
|
| 652 |
+
0% {
|
| 653 |
+
transform: translateX(-50%) rotate(-70deg);
|
| 654 |
+
}
|
| 655 |
+
|
| 656 |
+
25% {
|
| 657 |
+
transform: translateX(-50%) rotate(-20deg);
|
| 658 |
+
}
|
| 659 |
+
|
| 660 |
+
50% {
|
| 661 |
+
transform: translateX(-50%) rotate(60deg);
|
| 662 |
+
}
|
| 663 |
+
|
| 664 |
+
75% {
|
| 665 |
+
transform: translateX(-50%) rotate(-10deg);
|
| 666 |
+
}
|
| 667 |
+
|
| 668 |
+
100% {
|
| 669 |
+
transform: translateX(-50%) rotate(-70deg);
|
| 670 |
+
}
|
| 671 |
+
}
|
| 672 |
+
|
| 673 |
+
/* existing needle default uses CSS variable for final angle */
|
| 674 |
+
.needle {
|
| 675 |
+
position: absolute;
|
| 676 |
+
bottom: 0vw;
|
| 677 |
+
left: 50%;
|
| 678 |
+
width: 0.7vw;
|
| 679 |
+
height: 8vw;
|
| 680 |
+
background: #333;
|
| 681 |
+
transform: translateX(-50%) rotate(var(--angle, -90deg));
|
| 682 |
+
transform-origin: 50% 100%;
|
| 683 |
+
transition: transform 700ms cubic-bezier(.2,.9,.2,1);
|
| 684 |
+
border-radius: 10px;
|
| 685 |
+
box-shadow: 0 2px 6px rgba(0,0,0,0.5);
|
| 686 |
+
}
|
| 687 |
+
|
| 688 |
+
/* while recording / waiting for score, run oscillation animation */
|
| 689 |
+
.needle.oscillate {
|
| 690 |
+
/* override transform with animation while oscillating */
|
| 691 |
+
animation: needleOscillate 1.2s ease-in-out infinite;
|
| 692 |
+
/* disable the smooth transition while animation runs to prevent conflicts */
|
| 693 |
+
transition: none;
|
| 694 |
+
}
|
| 695 |
+
|
| 696 |
+
/* when oscillation ends (isRecording/isScoring false), the animation class is removed
|
| 697 |
+
and the element will smoothly transition to the value provided by --angle */
|
| 698 |
+
.container {
|
| 699 |
+
display: flex;
|
| 700 |
+
justify-content: center;
|
| 701 |
+
align-items: center;
|
| 702 |
+
gap: 40px; /* Increase the space between elements */
|
| 703 |
+
}
|
| 704 |
+
|
| 705 |
+
.arrow {
|
| 706 |
+
font-size: 4rem; /* Increased font size for bigger buttons */
|
| 707 |
+
background-color: #e0f7fa;
|
| 708 |
+
border: none;
|
| 709 |
+
width: 92px; /* Set width */
|
| 710 |
+
height: 92px; /* Set height */
|
| 711 |
+
border-radius: 50%; /* Make the button circular */
|
| 712 |
+
display: flex;
|
| 713 |
+
justify-content: center;
|
| 714 |
+
align-items: center;
|
| 715 |
+
cursor: pointer;
|
| 716 |
+
box-shadow: 4px 4px 15px rgba(0, 0, 0, 0.2); /* Box shadow for the button */
|
| 717 |
+
color: #00796b; /* Set color of the arrows */
|
| 718 |
+
transition: background-color 0.3s, color 0.3s; /* Smooth transition for background and text color */
|
| 719 |
+
}
|
| 720 |
+
|
| 721 |
+
/* Disabled state styles */
|
| 722 |
+
.arrow:disabled {
|
| 723 |
+
background-color: #cfd8dc; /* Light gray background when disabled */
|
| 724 |
+
color: #90a4ae; /* Gray color for the arrow */
|
| 725 |
+
cursor: not-allowed; /* Change cursor to indicate the button is disabled */
|
| 726 |
+
box-shadow: none; /* Remove box shadow for disabled button */
|
| 727 |
+
}
|
| 728 |
+
|
| 729 |
+
.center-text {
|
| 730 |
+
font-size: 5rem; /* Increased font size for the 'Y' text */
|
| 731 |
+
font-weight: bold;
|
| 732 |
+
color: #00796b;
|
| 733 |
+
width: 4vw;
|
| 734 |
+
text-align: center;
|
| 735 |
+
}
|
| 736 |
+
|
| 737 |
+
|
| 738 |
+
/* Styling the container */
|
| 739 |
+
.image-container {
|
| 740 |
+
display: flex;
|
| 741 |
+
justify-content: center;
|
| 742 |
+
align-items: center;
|
| 743 |
+
height: 100vh;
|
| 744 |
+
}
|
| 745 |
+
|
| 746 |
+
/* Styling the round image with shadow */
|
| 747 |
+
.round-image {
|
| 748 |
+
width: 4.8vw; /* Adjust the size as needed */
|
| 749 |
+
height: 4.8vw;
|
| 750 |
+
border-radius: 50%; /* Makes the image round */
|
| 751 |
+
box-shadow: 0px 10px 30px rgba(0, 0, 0, 0.4);
|
| 752 |
+
transition: all 0.3s ease; /* Smooth transition for animation */
|
| 753 |
+
cursor: pointer;
|
| 754 |
+
}
|
| 755 |
+
|
| 756 |
+
/* Scaling effect on click */
|
| 757 |
+
.round-image:active {
|
| 758 |
+
transform: scale(1.1); /* Scale up by 10% when clicked */
|
| 759 |
+
}
|
| 760 |
+
|
| 761 |
+
/* Subtle zoom in/out */
|
| 762 |
+
.apple-anim {
|
| 763 |
+
transform-origin: 50% 50%;
|
| 764 |
+
animation: appleZoom 2.8s ease-in-out infinite alternate;
|
| 765 |
+
will-change: transform;
|
| 766 |
+
}
|
| 767 |
+
|
| 768 |
+
@keyframes appleZoom {
|
| 769 |
+
from {
|
| 770 |
+
transform: scale(0.8);
|
| 771 |
+
}
|
| 772 |
+
|
| 773 |
+
to {
|
| 774 |
+
transform: scale(1.06);
|
| 775 |
+
}
|
| 776 |
+
/* slight zoom */
|
| 777 |
+
}
|
| 778 |
+
|
| 779 |
+
/* Respect reduced motion preference */
|
| 780 |
+
@media (prefers-reduced-motion: reduce) {
|
| 781 |
+
.apple-anim {
|
| 782 |
+
animation: none;
|
| 783 |
+
transform: none;
|
| 784 |
+
}
|
| 785 |
+
}
|
src/app/pronunciationragg/pronunciationragg.component.html
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<div class="pp-page">
|
| 2 |
+
|
| 3 |
+
<!-- Header -->
|
| 4 |
+
<div class="pp-header">
|
| 5 |
+
<h1>Pronunciation Practice</h1>
|
| 6 |
+
</div>
|
| 7 |
+
|
| 8 |
+
<!-- Main area -->
|
| 9 |
+
<div class="pp-main">
|
| 10 |
+
|
| 11 |
+
<!-- LEFT: Word card -->
|
| 12 |
+
<div class="pp-left">
|
| 13 |
+
<div class="word-card">
|
| 14 |
+
<div class="word-img-wrap">
|
| 15 |
+
<img class="apple-anim" [src]="current.imgSrc" [alt]="current.word" />
|
| 16 |
+
</div>
|
| 17 |
+
|
| 18 |
+
<div class="word-text">{{ current.word }}</div>
|
| 19 |
+
|
| 20 |
+
<div class="phonetic-pill">
|
| 21 |
+
{{ current.phonetics }}
|
| 22 |
+
</div>
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
<div class="image-container">
|
| 26 |
+
<img src="assets/pronvideo/audio.png" alt="Round Image" class="round-image" (click)="playWordAudio()">
|
| 27 |
+
</div>
|
| 28 |
+
|
| 29 |
+
</div>
|
| 30 |
+
</div>
|
| 31 |
+
|
| 32 |
+
<!-- CENTER: Teacher area -->
|
| 33 |
+
<div class="pp-center">
|
| 34 |
+
<div class="word-card" style="width:30vw!important">
|
| 35 |
+
<div style="width:28vw;height:25vw">
|
| 36 |
+
<!-- show teacher image when no video is active -->
|
| 37 |
+
<img *ngIf="!showVideo"
|
| 38 |
+
style="height:100%; border-radius:1vw;"
|
| 39 |
+
src="assets/pronvideo/teacher.png"
|
| 40 |
+
alt="Teacher" />
|
| 41 |
+
|
| 42 |
+
<!-- single video element used for both teacher and feedback videos -->
|
| 43 |
+
<video *ngIf="showVideo"
|
| 44 |
+
#videoEl
|
| 45 |
+
[src]="videoSrc"
|
| 46 |
+
style="border-radius:1vw; object-fit:cover;"
|
| 47 |
+
controls
|
| 48 |
+
autoplay
|
| 49 |
+
(ended)="onVideoEnded()"
|
| 50 |
+
height="469"
|
| 51 |
+
width="521">
|
| 52 |
+
Your browser does not support the video tag.
|
| 53 |
+
</video>
|
| 54 |
+
</div>
|
| 55 |
+
|
| 56 |
+
<!-- Toggle listen button: image acts as the button and switches between play/pause -->
|
| 57 |
+
<!-- Replace the button with a single image that acts as a toggle control -->
|
| 58 |
+
|
| 59 |
+
<div style="display:flex;margin-top:1.8vw;gap:2vw;">
|
| 60 |
+
<img class="listen-img"
|
| 61 |
+
[src]="isPlayingVideo ? pauseIconDataUrl : playIconDataUrl"
|
| 62 |
+
[attr.alt]="isPlayingVideo ? 'Pause pronunciation' : 'Play pronunciation'"
|
| 63 |
+
[attr.aria-label]="isPlayingVideo ? 'Pause pronunciation' : 'Play pronunciation'"
|
| 64 |
+
[attr.aria-pressed]="isPlayingVideo"
|
| 65 |
+
role="button"
|
| 66 |
+
tabindex="0"
|
| 67 |
+
(click)="toggleVideoPlay()"
|
| 68 |
+
(keydown.enter)="toggleVideoPlay()"
|
| 69 |
+
(keydown.space)="toggleVideoPlay(); $event.preventDefault()" />
|
| 70 |
+
|
| 71 |
+
<!-- Record circle -->
|
| 72 |
+
<button class="rec-circle"
|
| 73 |
+
[class.recording]="isRecording"
|
| 74 |
+
(mousedown)="startRecording()"
|
| 75 |
+
(mouseup)="stopRecording()"
|
| 76 |
+
(mouseleave)="stopRecording()"
|
| 77 |
+
(touchstart)="startRecording($event)"
|
| 78 |
+
(touchend)="stopRecording($event)"
|
| 79 |
+
(touchcancel)="stopRecording($event)">
|
| 80 |
+
<div class="rec-inner">
|
| 81 |
+
<div class="mic">🎤</div>
|
| 82 |
+
<div class="rec-text">REC</div>
|
| 83 |
+
</div>
|
| 84 |
+
</button>
|
| 85 |
+
</div>
|
| 86 |
+
</div>
|
| 87 |
+
</div>
|
| 88 |
+
|
| 89 |
+
<!-- RIGHT: Feedback panel -->
|
| 90 |
+
<div class="pp-right">
|
| 91 |
+
|
| 92 |
+
<!-- needle binding changed to use isOscillating -->
|
| 93 |
+
<div class="gauge-wrapper">
|
| 94 |
+
<div class="gauge">
|
| 95 |
+
<div class="gauge-arc"></div>
|
| 96 |
+
<div class="needle" [class.oscillate]="isOscillating" [style.--angle]="needleAngle + 'deg'"></div>
|
| 97 |
+
</div>
|
| 98 |
+
|
| 99 |
+
<div class="mic-badge">
|
| 100 |
+
<span class="score-span">{{score}}%</span>
|
| 101 |
+
</div>
|
| 102 |
+
</div>
|
| 103 |
+
|
| 104 |
+
<!--<div class="nav-row">
|
| 105 |
+
<button class="nav-btn" (click)="prev()" [disabled]="index === 0" aria-label="Previous">
|
| 106 |
+
<span class="nav-icon">‹</span>
|
| 107 |
+
</button>
|
| 108 |
+
|
| 109 |
+
<div class="nav-center">
|
| 110 |
+
<div class="nav-letter">{{ current.letter }}</div>
|
| 111 |
+
</div>
|
| 112 |
+
|
| 113 |
+
<button class="nav-btn" (click)="next()" [disabled]="index === items.length - 1" aria-label="Next">
|
| 114 |
+
<span class="nav-icon">›</span>
|
| 115 |
+
</button>
|
| 116 |
+
</div>-->
|
| 117 |
+
|
| 118 |
+
<div class="container">
|
| 119 |
+
<button class="arrow left" (click)="prev()" [disabled]="index === 0">‹</button>
|
| 120 |
+
<span class="center-text">{{ current.letter }}</span>
|
| 121 |
+
<button class="arrow right" (click)="next()" [disabled]="index === items.length - 1">›</button>
|
| 122 |
+
</div>
|
| 123 |
+
|
| 124 |
+
</div>
|
| 125 |
+
|
| 126 |
+
</div>
|
| 127 |
+
|
| 128 |
+
</div>
|
| 129 |
+
<button aria-label="Close" class="user-guide-close-icon" (click)="closePopup()">×</button>
|
src/app/pronunciationragg/pronunciationragg.component.ts
ADDED
|
@@ -0,0 +1,950 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Component, ElementRef, Inject, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
| 2 |
+
import { HttpClient } from '@angular/common/http';
|
| 3 |
+
import { finalize } from 'rxjs/operators';
|
| 4 |
+
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
| 5 |
+
import { ChangeDetectorRef } from '@angular/core';
|
| 6 |
+
|
| 7 |
+
interface PracticeItem {
|
| 8 |
+
letter: string;
|
| 9 |
+
word: string;
|
| 10 |
+
phonetics: string;
|
| 11 |
+
imgSrc: string;
|
| 12 |
+
audioSrc: string;
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
@Component({
|
| 16 |
+
selector: 'app-pronunciationragg',
|
| 17 |
+
templateUrl: './pronunciationragg.component.html',
|
| 18 |
+
styleUrls: ['./pronunciationragg.component.css']
|
| 19 |
+
})
|
| 20 |
+
export class PronunciationRaggComponent implements OnInit, OnDestroy {
|
| 21 |
+
@ViewChild('videoEl') videoElRef?: ElementRef<HTMLVideoElement>;
|
| 22 |
+
|
| 23 |
+
// toggle & src for teacher video
|
| 24 |
+
showVideo = false;
|
| 25 |
+
videoSrc = '';
|
| 26 |
+
|
| 27 |
+
// track play/pause state for the toggle button
|
| 28 |
+
isPlayingVideo = false;
|
| 29 |
+
|
| 30 |
+
// use asset image paths (replace with your actual asset filenames)
|
| 31 |
+
playIconDataUrl = '';
|
| 32 |
+
pauseIconDataUrl = '';
|
| 33 |
+
|
| 34 |
+
// ---------------------------
|
| 35 |
+
// CONFIG
|
| 36 |
+
// ---------------------------
|
| 37 |
+
// Change this to your server domain
|
| 38 |
+
|
| 39 |
+
private API_BASE = location.hostname.endsWith('hf.space')
|
| 40 |
+
? 'https://pykara-py-learn-backend.hf.space'
|
| 41 |
+
: 'http://localhost:5000';
|
| 42 |
+
|
| 43 |
+
private readonly SCORE_ENDPOINT = `${this.API_BASE}/pronragg/score`;
|
| 44 |
+
|
| 45 |
+
// Prefer a mime type supported by the browser
|
| 46 |
+
private readonly preferredMimeTypes = [
|
| 47 |
+
'audio/webm;codecs=opus',
|
| 48 |
+
'audio/webm',
|
| 49 |
+
'audio/ogg;codecs=opus',
|
| 50 |
+
'audio/ogg'
|
| 51 |
+
];
|
| 52 |
+
|
| 53 |
+
// ---------------------------
|
| 54 |
+
// DATA
|
| 55 |
+
// ---------------------------
|
| 56 |
+
items: PracticeItem[] = [
|
| 57 |
+
{
|
| 58 |
+
letter: 'A',
|
| 59 |
+
word: 'Apple',
|
| 60 |
+
phonetics: '/ˈæpəl/',
|
| 61 |
+
imgSrc: 'assets/images/pron/letter-a.png',
|
| 62 |
+
audioSrc: 'assets/pronvideo/audio/apple.mp3'
|
| 63 |
+
|
| 64 |
+
},
|
| 65 |
+
{
|
| 66 |
+
letter: 'B',
|
| 67 |
+
word: 'Ball',
|
| 68 |
+
phonetics: '/bɔːl/',
|
| 69 |
+
imgSrc: 'assets/images/pron/letter-b.png',
|
| 70 |
+
audioSrc: 'assets/pronvideo/audio/ball.mp3'
|
| 71 |
+
|
| 72 |
+
},
|
| 73 |
+
{
|
| 74 |
+
letter: 'C',
|
| 75 |
+
word: 'Cat',
|
| 76 |
+
phonetics: '/kæt/',
|
| 77 |
+
imgSrc: 'assets/images/pron/letter-c.png',
|
| 78 |
+
audioSrc: 'assets/pronvideo/audio/cat.mp3'
|
| 79 |
+
|
| 80 |
+
},
|
| 81 |
+
{
|
| 82 |
+
letter: 'D',
|
| 83 |
+
word: 'Dog',
|
| 84 |
+
phonetics: '/dɒɡ/',
|
| 85 |
+
imgSrc: 'assets/images/pron/letter-d.png',
|
| 86 |
+
audioSrc: 'assets/pronvideo/audio/dog.mp3'
|
| 87 |
+
|
| 88 |
+
},
|
| 89 |
+
{
|
| 90 |
+
letter: 'E',
|
| 91 |
+
word: 'Egg',
|
| 92 |
+
phonetics: '/eɡ/',
|
| 93 |
+
imgSrc: 'assets/images/pron/letter-e.png',
|
| 94 |
+
audioSrc: 'assets/pronvideo/audio/egg.mp3'
|
| 95 |
+
|
| 96 |
+
},
|
| 97 |
+
{
|
| 98 |
+
letter: 'F',
|
| 99 |
+
word: 'Fish',
|
| 100 |
+
phonetics: '/fɪʃ/',
|
| 101 |
+
imgSrc: 'assets/images/pron/letter-f.png',
|
| 102 |
+
audioSrc: 'assets/pronvideo/audio/fish.mp3'
|
| 103 |
+
|
| 104 |
+
},
|
| 105 |
+
{
|
| 106 |
+
letter: 'G',
|
| 107 |
+
word: 'Grapes',
|
| 108 |
+
phonetics: '/ɡreɪps/',
|
| 109 |
+
imgSrc: 'assets/images/pron/letter-g.png',
|
| 110 |
+
audioSrc: 'assets/pronvideo/audio/grapes.mp3'
|
| 111 |
+
|
| 112 |
+
},
|
| 113 |
+
{
|
| 114 |
+
letter: 'H',
|
| 115 |
+
word: 'Hat',
|
| 116 |
+
phonetics: '/hæt/',
|
| 117 |
+
imgSrc: 'assets/images/pron/letter-h.png',
|
| 118 |
+
audioSrc: 'assets/pronvideo/audio/hat.mp3'
|
| 119 |
+
|
| 120 |
+
},
|
| 121 |
+
{
|
| 122 |
+
letter: 'I',
|
| 123 |
+
word: 'Ice cream',
|
| 124 |
+
phonetics: '/ˈaɪs ˌkriːm/',
|
| 125 |
+
imgSrc: 'assets/images/pron/letter-i.png',
|
| 126 |
+
audioSrc: 'assets/pronvideo/audio/icecream.mp3'
|
| 127 |
+
|
| 128 |
+
},
|
| 129 |
+
{
|
| 130 |
+
letter: 'J',
|
| 131 |
+
word: 'Jar',
|
| 132 |
+
phonetics: '/dʒɑːr/',
|
| 133 |
+
imgSrc: 'assets/images/pron/letter-j.png',
|
| 134 |
+
audioSrc: 'assets/pronvideo/audio/jar.mp3'
|
| 135 |
+
|
| 136 |
+
},
|
| 137 |
+
{
|
| 138 |
+
letter: 'K',
|
| 139 |
+
word: 'Kite',
|
| 140 |
+
phonetics: '/kaɪt/',
|
| 141 |
+
imgSrc: 'assets/images/pron/letter-k.png',
|
| 142 |
+
audioSrc: 'assets/pronvideo/audio/kite.mp3'
|
| 143 |
+
|
| 144 |
+
},
|
| 145 |
+
{
|
| 146 |
+
letter: 'L',
|
| 147 |
+
word: 'Lion',
|
| 148 |
+
phonetics: '/ˈlaɪən/',
|
| 149 |
+
imgSrc: 'assets/images/pron/letter-l.png',
|
| 150 |
+
audioSrc: 'assets/pronvideo/audio/lion.mp3'
|
| 151 |
+
|
| 152 |
+
},
|
| 153 |
+
{
|
| 154 |
+
letter: 'M',
|
| 155 |
+
word: 'Moon',
|
| 156 |
+
phonetics: '/muːn/',
|
| 157 |
+
imgSrc: 'assets/images/pron/letter-m.png',
|
| 158 |
+
audioSrc: 'assets/pronvideo/audio/moon.mp3'
|
| 159 |
+
|
| 160 |
+
},
|
| 161 |
+
{
|
| 162 |
+
letter: 'N',
|
| 163 |
+
word: 'Nest',
|
| 164 |
+
phonetics: '/nest/',
|
| 165 |
+
imgSrc: 'assets/images/pron/letter-n.png',
|
| 166 |
+
audioSrc: 'assets/pronvideo/audio/nest.mp3'
|
| 167 |
+
|
| 168 |
+
},
|
| 169 |
+
{
|
| 170 |
+
letter: 'O',
|
| 171 |
+
word: 'Orange',
|
| 172 |
+
phonetics: '/ˈɒrɪndʒ/',
|
| 173 |
+
imgSrc: 'assets/images/pron/letter-o.png',
|
| 174 |
+
audioSrc: 'assets/pronvideo/audio/orange.mp3'
|
| 175 |
+
|
| 176 |
+
},
|
| 177 |
+
{
|
| 178 |
+
letter: 'P',
|
| 179 |
+
word: 'Pig',
|
| 180 |
+
phonetics: '/pɪɡ/',
|
| 181 |
+
imgSrc: 'assets/images/pron/letter-p.png',
|
| 182 |
+
audioSrc: 'assets/pronvideo/audio/pig.mp3'
|
| 183 |
+
|
| 184 |
+
},
|
| 185 |
+
{
|
| 186 |
+
letter: 'Q',
|
| 187 |
+
word: 'Queen',
|
| 188 |
+
phonetics: '/kwiːn/',
|
| 189 |
+
imgSrc: 'assets/images/pron/letter-q.png',
|
| 190 |
+
audioSrc: 'assets/pronvideo/audio/queen.mp3'
|
| 191 |
+
|
| 192 |
+
},
|
| 193 |
+
{
|
| 194 |
+
letter: 'R',
|
| 195 |
+
word: 'Rabbit',
|
| 196 |
+
phonetics: '/ˈræbɪt/',
|
| 197 |
+
imgSrc: 'assets/images/pron/letter-r.png',
|
| 198 |
+
audioSrc: 'assets/pronvideo/audio/rabbit.mp3'
|
| 199 |
+
|
| 200 |
+
},
|
| 201 |
+
{
|
| 202 |
+
letter: 'S',
|
| 203 |
+
word: 'Sun',
|
| 204 |
+
phonetics: '/sʌn/',
|
| 205 |
+
imgSrc: 'assets/images/pron/letter-s.png',
|
| 206 |
+
audioSrc: 'assets/pronvideo/audio/sun.mp3'
|
| 207 |
+
|
| 208 |
+
},
|
| 209 |
+
{
|
| 210 |
+
letter: 'T',
|
| 211 |
+
word: 'Tree',
|
| 212 |
+
phonetics: '/triː/',
|
| 213 |
+
imgSrc: 'assets/images/pron/letter-t.png',
|
| 214 |
+
audioSrc: 'assets/pronvideo/audio/tree.mp3'
|
| 215 |
+
|
| 216 |
+
},
|
| 217 |
+
{
|
| 218 |
+
letter: 'U',
|
| 219 |
+
word: 'Umbrella',
|
| 220 |
+
phonetics: '/ʌmˈbrelə/',
|
| 221 |
+
imgSrc: 'assets/images/pron/letter-u.png',
|
| 222 |
+
audioSrc: 'assets/pronvideo/audio/umbrella.mp3'
|
| 223 |
+
|
| 224 |
+
},
|
| 225 |
+
{
|
| 226 |
+
letter: 'V',
|
| 227 |
+
word: 'Van',
|
| 228 |
+
phonetics: '/væn/',
|
| 229 |
+
imgSrc: 'assets/images/pron/letter-v.png',
|
| 230 |
+
audioSrc: 'assets/pronvideo/audio/van.mp3'
|
| 231 |
+
|
| 232 |
+
},
|
| 233 |
+
{
|
| 234 |
+
letter: 'W',
|
| 235 |
+
word: 'Watch',
|
| 236 |
+
phonetics: '/wɒtʃ/',
|
| 237 |
+
imgSrc: 'assets/images/pron/letter-w.png',
|
| 238 |
+
audioSrc: 'assets/pronvideo/audio/watch.mp3'
|
| 239 |
+
|
| 240 |
+
},
|
| 241 |
+
{
|
| 242 |
+
letter: 'X',
|
| 243 |
+
word: 'Xylophone',
|
| 244 |
+
phonetics: '/ˈzaɪləfəʊn/',
|
| 245 |
+
imgSrc: 'assets/images/pron/letter-x.png',
|
| 246 |
+
audioSrc: 'assets/pronvideo/audio/xylophone.mp3'
|
| 247 |
+
|
| 248 |
+
},
|
| 249 |
+
{
|
| 250 |
+
letter: 'Y',
|
| 251 |
+
word: 'Yarn',
|
| 252 |
+
phonetics: '/jɑːn/',
|
| 253 |
+
imgSrc: 'assets/images/pron/letter-y.png',
|
| 254 |
+
audioSrc: 'assets/pronvideo/audio/yarn.mp3'
|
| 255 |
+
|
| 256 |
+
},
|
| 257 |
+
{
|
| 258 |
+
letter: 'Z',
|
| 259 |
+
word: 'Zebra',
|
| 260 |
+
phonetics: '/ˈzebrə/',
|
| 261 |
+
imgSrc: 'assets/images/pron/letter-z.png',
|
| 262 |
+
audioSrc: 'assets/pronvideo/audio/zebra.mp3'
|
| 263 |
+
|
| 264 |
+
}
|
| 265 |
+
];
|
| 266 |
+
|
| 267 |
+
|
| 268 |
+
index = 0;
|
| 269 |
+
|
| 270 |
+
get current(): PracticeItem {
|
| 271 |
+
return this.items[this.index];
|
| 272 |
+
}
|
| 273 |
+
|
| 274 |
+
// ---------------------------
|
| 275 |
+
// AUDIO (word)
|
| 276 |
+
// ---------------------------
|
| 277 |
+
private wordAudio = new Audio();
|
| 278 |
+
|
| 279 |
+
// ---------------------------
|
| 280 |
+
// RECORDING STATE
|
| 281 |
+
// ---------------------------
|
| 282 |
+
isRecording = false;
|
| 283 |
+
isScoring = false;
|
| 284 |
+
|
| 285 |
+
// NEW: flag to trigger needle oscillation after release and while waiting for score
|
| 286 |
+
isOscillating = false;
|
| 287 |
+
|
| 288 |
+
private mediaStream?: MediaStream;
|
| 289 |
+
private mediaRecorder?: MediaRecorder;
|
| 290 |
+
private chunks: BlobPart[] = [];
|
| 291 |
+
private currentMimeType = 'audio/webm';
|
| 292 |
+
|
| 293 |
+
recordedAudioUrl: string | null = null;
|
| 294 |
+
lastRecordedBlob: Blob | null = null;
|
| 295 |
+
|
| 296 |
+
// pending gesture play support (to satisfy autoplay policies)
|
| 297 |
+
private pendingVideoUrl: string | null = null;
|
| 298 |
+
private pendingGestureListener?: (e: Event) => void;
|
| 299 |
+
|
| 300 |
+
// Last created video blob URL (revoked when replaced) — DECLARED HERE
|
| 301 |
+
private lastVideoBlobUrl: string | null = null;
|
| 302 |
+
|
| 303 |
+
// ---------------------------
|
| 304 |
+
// RESULT UI
|
| 305 |
+
// ---------------------------
|
| 306 |
+
showResult = false;
|
| 307 |
+
score = 0;
|
| 308 |
+
stars = 0;
|
| 309 |
+
feedbackLines: string[] = [];
|
| 310 |
+
feedbackHint: string = '';
|
| 311 |
+
videoUrl: string = '';
|
| 312 |
+
|
| 313 |
+
// ---------------------------
|
| 314 |
+
// LIFECYCLE
|
| 315 |
+
// ---------------------------
|
| 316 |
+
constructor(private http: HttpClient, public dialogRef: MatDialogRef<PronunciationRaggComponent>,
|
| 317 |
+
@Inject(MAT_DIALOG_DATA) public data: any, private cdr: ChangeDetectorRef) { }
|
| 318 |
+
|
| 319 |
+
ngOnInit(): void {
|
| 320 |
+
this.resetResult();
|
| 321 |
+
this.setupBestMimeType();
|
| 322 |
+
|
| 323 |
+
// Use images from assets instead of inline SVG data URIs.
|
| 324 |
+
// Ensure the files exist at these paths or update the paths to match your project.
|
| 325 |
+
this.playIconDataUrl = 'assets/pronvideo/play.png';
|
| 326 |
+
this.pauseIconDataUrl = 'assets/pronvideo/pause.png';
|
| 327 |
+
}
|
| 328 |
+
|
| 329 |
+
ngOnDestroy(): void {
|
| 330 |
+
this.cleanupRecordingUrl();
|
| 331 |
+
this.stopTracks();
|
| 332 |
+
this.safeStopRecorder();
|
| 333 |
+
this.wordAudio.pause();
|
| 334 |
+
this.wordAudio.src = '';
|
| 335 |
+
// ensure video cleaned up
|
| 336 |
+
this.resetVideo();
|
| 337 |
+
// revoke any created blob URL
|
| 338 |
+
if (this.lastVideoBlobUrl) {
|
| 339 |
+
try { URL.revokeObjectURL(this.lastVideoBlobUrl); } catch { }
|
| 340 |
+
this.lastVideoBlobUrl = null;
|
| 341 |
+
}
|
| 342 |
+
// remove any pending gesture listener to avoid leaks
|
| 343 |
+
if (this.pendingGestureListener) {
|
| 344 |
+
try { document.body.removeEventListener('click', this.pendingGestureListener, true); } catch { }
|
| 345 |
+
this.pendingGestureListener = undefined;
|
| 346 |
+
this.pendingVideoUrl = null;
|
| 347 |
+
}
|
| 348 |
+
}
|
| 349 |
+
|
| 350 |
+
// ---------------------------
|
| 351 |
+
// RECORD & HOLD - EVENTS
|
| 352 |
+
// ---------------------------
|
| 353 |
+
async startRecording(evt?: Event): Promise<void> {
|
| 354 |
+
evt?.preventDefault();
|
| 355 |
+
|
| 356 |
+
if (this.isRecording || this.isScoring) return;
|
| 357 |
+
|
| 358 |
+
this.resetResult();
|
| 359 |
+
this.cleanupRecordingUrl();
|
| 360 |
+
this.lastRecordedBlob = null;
|
| 361 |
+
|
| 362 |
+
try {
|
| 363 |
+
this.mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
| 364 |
+
|
| 365 |
+
const options: MediaRecorderOptions = {};
|
| 366 |
+
if (this.currentMimeType) {
|
| 367 |
+
options.mimeType = this.currentMimeType;
|
| 368 |
+
}
|
| 369 |
+
|
| 370 |
+
this.mediaRecorder = new MediaRecorder(this.mediaStream, options);
|
| 371 |
+
|
| 372 |
+
this.chunks = [];
|
| 373 |
+
|
| 374 |
+
this.mediaRecorder.ondataavailable = (e: BlobEvent) => {
|
| 375 |
+
if (e.data && e.data.size > 0) this.chunks.push(e.data);
|
| 376 |
+
};
|
| 377 |
+
|
| 378 |
+
this.mediaRecorder.onstop = () => {
|
| 379 |
+
this.onRecordingStopped();
|
| 380 |
+
};
|
| 381 |
+
|
| 382 |
+
this.mediaRecorder.start();
|
| 383 |
+
this.isRecording = true;
|
| 384 |
+
|
| 385 |
+
} catch {
|
| 386 |
+
this.isRecording = false;
|
| 387 |
+
this.stopTracks();
|
| 388 |
+
}
|
| 389 |
+
}
|
| 390 |
+
|
| 391 |
+
stopRecording(evt?: Event): void {
|
| 392 |
+
evt?.preventDefault();
|
| 393 |
+
|
| 394 |
+
if (!this.isRecording) return;
|
| 395 |
+
|
| 396 |
+
// End recording state
|
| 397 |
+
this.isRecording = false;
|
| 398 |
+
|
| 399 |
+
// Start oscillation immediately when user releases the record button:
|
| 400 |
+
// visual feedback that we are waiting for the backend scoring result.
|
| 401 |
+
this.isOscillating = true;
|
| 402 |
+
|
| 403 |
+
// Stop recorder safely
|
| 404 |
+
this.safeStopRecorder();
|
| 405 |
+
|
| 406 |
+
// Stop mic tracks
|
| 407 |
+
this.stopTracks();
|
| 408 |
+
}
|
| 409 |
+
|
| 410 |
+
private safeStopRecorder(): void {
|
| 411 |
+
try {
|
| 412 |
+
if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {
|
| 413 |
+
this.mediaRecorder.stop();
|
| 414 |
+
}
|
| 415 |
+
} catch {
|
| 416 |
+
// ignore
|
| 417 |
+
}
|
| 418 |
+
}
|
| 419 |
+
|
| 420 |
+
private onRecordingStopped(): void {
|
| 421 |
+
try {
|
| 422 |
+
const blob = new Blob(this.chunks, { type: this.currentMimeType || 'audio/webm' });
|
| 423 |
+
this.lastRecordedBlob = blob;
|
| 424 |
+
this.recordedAudioUrl = URL.createObjectURL(blob);
|
| 425 |
+
|
| 426 |
+
// Send to backend for scoring
|
| 427 |
+
this.sendForScoring(blob, this.current.word);
|
| 428 |
+
} catch {
|
| 429 |
+
// If blob creation fails, stop oscillation and keep score hidden
|
| 430 |
+
this.isOscillating = false;
|
| 431 |
+
this.showResult = false;
|
| 432 |
+
} finally {
|
| 433 |
+
this.chunks = [];
|
| 434 |
+
}
|
| 435 |
+
}
|
| 436 |
+
|
| 437 |
+
// Optional: play student recording from UI button
|
| 438 |
+
playUserRecording(): void {
|
| 439 |
+
if (!this.recordedAudioUrl) return;
|
| 440 |
+
try {
|
| 441 |
+
const a = new Audio(this.recordedAudioUrl);
|
| 442 |
+
a.play().catch(() => { });
|
| 443 |
+
} catch {
|
| 444 |
+
// ignore
|
| 445 |
+
}
|
| 446 |
+
}
|
| 447 |
+
|
| 448 |
+
// ---------------------------
|
| 449 |
+
// BACKEND SCORING
|
| 450 |
+
// ---------------------------
|
| 451 |
+
private sendForScoring(blob: Blob, expectedWord: string): void {
|
| 452 |
+
if (!blob || !expectedWord) {
|
| 453 |
+
// nothing to do -> stop oscillation
|
| 454 |
+
this.isOscillating = false;
|
| 455 |
+
return;
|
| 456 |
+
}
|
| 457 |
+
|
| 458 |
+
const fd = new FormData();
|
| 459 |
+
|
| 460 |
+
// Give a reasonable filename extension
|
| 461 |
+
const ext = this.currentMimeType.includes('ogg') ? 'ogg' : 'webm';
|
| 462 |
+
fd.append('audio', blob, `student.${ext}`);
|
| 463 |
+
fd.append('word', expectedWord);
|
| 464 |
+
|
| 465 |
+
// Request inline base64 MP4 segment from the backend
|
| 466 |
+
fd.append('return_segment_base64', '1');
|
| 467 |
+
|
| 468 |
+
// show scoring state
|
| 469 |
+
this.isScoring = true;
|
| 470 |
+
|
| 471 |
+
this.http.post<any>(this.SCORE_ENDPOINT, fd)
|
| 472 |
+
.pipe(finalize(() => {
|
| 473 |
+
|
| 474 |
+
// stop scoring state and oscillation once HTTP completes (success or error)
|
| 475 |
+
this.isScoring = false;
|
| 476 |
+
this.isOscillating = false;
|
| 477 |
+
this.cdr.detectChanges();
|
| 478 |
+
}))
|
| 479 |
+
.subscribe({
|
| 480 |
+
next: (res) => {
|
| 481 |
+
const s = this.normalizeScore(res?.score);
|
| 482 |
+
this.score = s;
|
| 483 |
+
this.feedbackHint = res.hint || '';
|
| 484 |
+
// prefer inline blob when returned
|
| 485 |
+
if (res?.videoBlobBase64) {
|
| 486 |
+
// revoke previous blob URL if present
|
| 487 |
+
if (this.lastVideoBlobUrl) {
|
| 488 |
+
try { URL.revokeObjectURL(this.lastVideoBlobUrl); } catch { }
|
| 489 |
+
this.lastVideoBlobUrl = null;
|
| 490 |
+
}
|
| 491 |
+
try {
|
| 492 |
+
const binary = atob(res.videoBlobBase64);
|
| 493 |
+
const len = binary.length;
|
| 494 |
+
const bytes = new Uint8Array(len);
|
| 495 |
+
for (let i = 0; i < len; i++) {
|
| 496 |
+
bytes[i] = binary.charCodeAt(i);
|
| 497 |
+
}
|
| 498 |
+
const blob = new Blob([bytes], { type: 'video/mp4' });
|
| 499 |
+
const url = URL.createObjectURL(blob);
|
| 500 |
+
this.lastVideoBlobUrl = url;
|
| 501 |
+
this.videoUrl = url;
|
| 502 |
+
} catch {
|
| 503 |
+
// fallback: use server-provided videoUrl if base64 decoding fails
|
| 504 |
+
this.videoUrl = res.videoUrl || '';
|
| 505 |
+
}
|
| 506 |
+
} else {
|
| 507 |
+
this.videoUrl = res.videoUrl || '';
|
| 508 |
+
}
|
| 509 |
+
|
| 510 |
+
this.stars = this.mapStars(s);
|
| 511 |
+
|
| 512 |
+
this.feedbackLines = this.buildFeedbackFromScore(s);
|
| 513 |
+
|
| 514 |
+
this.showResult = true;
|
| 515 |
+
|
| 516 |
+
// Try to play feedback video; if autoplay blocked we register a gesture fallback.
|
| 517 |
+
if (this.videoUrl) {
|
| 518 |
+
this.tryPlayFeedbackVideo(s, this.videoUrl);
|
| 519 |
+
}
|
| 520 |
+
},
|
| 521 |
+
error: () => {
|
| 522 |
+
this.score = 0;
|
| 523 |
+
this.stars = 1;
|
| 524 |
+
this.feedbackLines = this.buildFeedbackFromScore(0);
|
| 525 |
+
this.showResult = true;
|
| 526 |
+
this.cdr.detectChanges();
|
| 527 |
+
}
|
| 528 |
+
});
|
| 529 |
+
}
|
| 530 |
+
|
| 531 |
+
private normalizeScore(val: any): number {
|
| 532 |
+
const n = Number(val);
|
| 533 |
+
if (Number.isNaN(n)) return 0;
|
| 534 |
+
if (n < 0) return 0;
|
| 535 |
+
if (n > 100) return 100;
|
| 536 |
+
return Math.round(n);
|
| 537 |
+
}
|
| 538 |
+
|
| 539 |
+
// ---------------------------
|
| 540 |
+
// RESULT HELPERS (frontend-only)
|
| 541 |
+
// ---------------------------
|
| 542 |
+
private resetResult(): void {
|
| 543 |
+
this.showResult = false;
|
| 544 |
+
this.score = 0;
|
| 545 |
+
this.stars = 0;
|
| 546 |
+
this.feedbackLines = [];
|
| 547 |
+
this.isPlayingVideo = false;
|
| 548 |
+
this.isOscillating = false;
|
| 549 |
+
}
|
| 550 |
+
|
| 551 |
+
/**
|
| 552 |
+
* Reset only the speakometer/score UI without touching recording state or video playback flags.
|
| 553 |
+
*/
|
| 554 |
+
private resetSpeakometer(): void {
|
| 555 |
+
this.score = 0;
|
| 556 |
+
this.stars = 0;
|
| 557 |
+
this.feedbackLines = [];
|
| 558 |
+
this.feedbackHint = '';
|
| 559 |
+
this.showResult = false;
|
| 560 |
+
this.isOscillating = false;
|
| 561 |
+
}
|
| 562 |
+
|
| 563 |
+
private mapStars(s: number): number {
|
| 564 |
+
if (s >= 90) return 5;
|
| 565 |
+
if (s >= 80) return 4;
|
| 566 |
+
if (s >= 70) return 3;
|
| 567 |
+
if (s >= 60) return 2;
|
| 568 |
+
return 1;
|
| 569 |
+
}
|
| 570 |
+
|
| 571 |
+
private buildFeedbackFromScore(s: number): string[] {
|
| 572 |
+
if (s >= 90) {
|
| 573 |
+
return [
|
| 574 |
+
'Excellent pronunciation.',
|
| 575 |
+
'Very clear vowel and ending sound.',
|
| 576 |
+
'Keep the same speed.'
|
| 577 |
+
];
|
| 578 |
+
}
|
| 579 |
+
if (s >= 80) {
|
| 580 |
+
return [
|
| 581 |
+
'Very good attempt.',
|
| 582 |
+
'Slightly improve the main vowel.',
|
| 583 |
+
'Ending sound is almost perfect.'
|
| 584 |
+
];
|
| 585 |
+
}
|
| 586 |
+
if (s >= 70) {
|
| 587 |
+
return [
|
| 588 |
+
'Good try.',
|
| 589 |
+
'Listen once more and repeat slowly.',
|
| 590 |
+
'Focus on the first sound.'
|
| 591 |
+
];
|
| 592 |
+
}
|
| 593 |
+
if (s >= 50) {
|
| 594 |
+
return [
|
| 595 |
+
'Nice effort.',
|
| 596 |
+
'Try a slower pronunciation.',
|
| 597 |
+
'Record again after listening.'
|
| 598 |
+
];
|
| 599 |
+
}
|
| 600 |
+
return [
|
| 601 |
+
'Try again.',
|
| 602 |
+
'Listen to the model carefully.',
|
| 603 |
+
'Speak clearly and record once more.'
|
| 604 |
+
];
|
| 605 |
+
}
|
| 606 |
+
|
| 607 |
+
// ---------------------------
|
| 608 |
+
// MIME TYPE SELECTION
|
| 609 |
+
// ---------------------------
|
| 610 |
+
private setupBestMimeType(): void {
|
| 611 |
+
if (!(window as any).MediaRecorder) {
|
| 612 |
+
this.currentMimeType = 'audio/webm';
|
| 613 |
+
return;
|
| 614 |
+
}
|
| 615 |
+
|
| 616 |
+
for (const t of this.preferredMimeTypes) {
|
| 617 |
+
try {
|
| 618 |
+
if ((window as any).MediaRecorder.isTypeSupported(t)) {
|
| 619 |
+
this.currentMimeType = t;
|
| 620 |
+
return;
|
| 621 |
+
}
|
| 622 |
+
} catch {
|
| 623 |
+
// ignore
|
| 624 |
+
}
|
| 625 |
+
}
|
| 626 |
+
|
| 627 |
+
this.currentMimeType = 'audio/webm';
|
| 628 |
+
}
|
| 629 |
+
|
| 630 |
+
// ---------------------------
|
| 631 |
+
// CLEANUP
|
| 632 |
+
// ---------------------------
|
| 633 |
+
private stopTracks(): void {
|
| 634 |
+
try {
|
| 635 |
+
this.mediaStream?.getTracks().forEach(t => t.stop());
|
| 636 |
+
} catch {
|
| 637 |
+
// ignore
|
| 638 |
+
} finally {
|
| 639 |
+
this.mediaStream = undefined;
|
| 640 |
+
}
|
| 641 |
+
}
|
| 642 |
+
|
| 643 |
+
private cleanupRecordingUrl(): void {
|
| 644 |
+
if (this.recordedAudioUrl) {
|
| 645 |
+
try {
|
| 646 |
+
URL.revokeObjectURL(this.recordedAudioUrl);
|
| 647 |
+
} catch {
|
| 648 |
+
// ignore
|
| 649 |
+
}
|
| 650 |
+
this.recordedAudioUrl = null;
|
| 651 |
+
}
|
| 652 |
+
}
|
| 653 |
+
|
| 654 |
+
// ---------------------------
|
| 655 |
+
// NAVIGATION
|
| 656 |
+
// ---------------------------
|
| 657 |
+
prev(): void {
|
| 658 |
+
if (this.index === 0) return;
|
| 659 |
+
this.index--;
|
| 660 |
+
this.resetExerciseState();
|
| 661 |
+
}
|
| 662 |
+
|
| 663 |
+
next(): void {
|
| 664 |
+
if (this.index >= this.items.length - 1) return;
|
| 665 |
+
this.index++;
|
| 666 |
+
this.resetExerciseState();
|
| 667 |
+
}
|
| 668 |
+
|
| 669 |
+
goTo(i: number): void {
|
| 670 |
+
if (i < 0 || i >= this.items.length) return;
|
| 671 |
+
this.index = i;
|
| 672 |
+
this.resetExerciseState();
|
| 673 |
+
}
|
| 674 |
+
|
| 675 |
+
private resetExerciseState(): void {
|
| 676 |
+
// reset UI result data
|
| 677 |
+
this.resetResult();
|
| 678 |
+
this.cleanupRecordingUrl();
|
| 679 |
+
this.lastRecordedBlob = null;
|
| 680 |
+
|
| 681 |
+
// stop any recording/scoring
|
| 682 |
+
this.isRecording = false;
|
| 683 |
+
this.isScoring = false;
|
| 684 |
+
|
| 685 |
+
// stop media tracks and recorder
|
| 686 |
+
this.stopTracks();
|
| 687 |
+
this.safeStopRecorder();
|
| 688 |
+
|
| 689 |
+
// STOP and CLEAR any playing video so next exercise starts clean
|
| 690 |
+
this.resetVideo();
|
| 691 |
+
}
|
| 692 |
+
|
| 693 |
+
// new helper: stop & clear video element + reset related flags
|
| 694 |
+
private resetVideo(): void {
|
| 695 |
+
try {
|
| 696 |
+
const v = this.videoElRef?.nativeElement;
|
| 697 |
+
if (v) {
|
| 698 |
+
try { v.pause(); } catch { /* ignore */ }
|
| 699 |
+
try { v.currentTime = 0; } catch { /* ignore */ }
|
| 700 |
+
try { v.removeAttribute('src'); } catch { /* ignore */ }
|
| 701 |
+
try { v.load(); } catch { /* ignore */ }
|
| 702 |
+
}
|
| 703 |
+
} catch {
|
| 704 |
+
// ignore any DOM errors
|
| 705 |
+
} finally {
|
| 706 |
+
// revoke any blob url we created
|
| 707 |
+
if (this.lastVideoBlobUrl) {
|
| 708 |
+
try { URL.revokeObjectURL(this.lastVideoBlobUrl); } catch { }
|
| 709 |
+
this.lastVideoBlobUrl = null;
|
| 710 |
+
}
|
| 711 |
+
this.showVideo = false;
|
| 712 |
+
this.videoSrc = '';
|
| 713 |
+
this.isPlayingVideo = false;
|
| 714 |
+
}
|
| 715 |
+
}
|
| 716 |
+
|
| 717 |
+
// ---------------------------
|
| 718 |
+
// WORD AUDIO
|
| 719 |
+
// ---------------------------
|
| 720 |
+
playWordAudio(): void {
|
| 721 |
+
// reset speakometer when starting model audio playback
|
| 722 |
+
this.resetSpeakometer();
|
| 723 |
+
|
| 724 |
+
const src = this.current.audioSrc || this.getAudioSrcFromWord(this.current.word);
|
| 725 |
+
if (!src) return;
|
| 726 |
+
|
| 727 |
+
try {
|
| 728 |
+
this.wordAudio.pause();
|
| 729 |
+
this.wordAudio.currentTime = 0;
|
| 730 |
+
this.wordAudio.src = src;
|
| 731 |
+
this.wordAudio.play().catch(() => { });
|
| 732 |
+
} catch {
|
| 733 |
+
// ignore
|
| 734 |
+
}
|
| 735 |
+
}
|
| 736 |
+
|
| 737 |
+
private getAudioSrcFromWord(word: string): string {
|
| 738 |
+
if (!word) return '';
|
| 739 |
+
const fileName = word.trim().toLowerCase().replace(/\s+/g, '-');
|
| 740 |
+
return `assets/pronvideo/audio/${fileName}.mp3`;
|
| 741 |
+
}
|
| 742 |
+
|
| 743 |
+
get needleAngle(): number {
|
| 744 |
+
const val = Math.max(0, Math.min(100, Number(this.score ?? 0)));
|
| 745 |
+
return -90 + (val * 1.8);
|
| 746 |
+
}
|
| 747 |
+
|
| 748 |
+
closePopup(): void {
|
| 749 |
+
this.dialogRef.close();
|
| 750 |
+
}
|
| 751 |
+
|
| 752 |
+
// ---------------------------
|
| 753 |
+
// TEACHER VIDEO
|
| 754 |
+
// ---------------------------
|
| 755 |
+
playWordVideo(): void {
|
| 756 |
+
// Reset speakometer when user requests the teacher video
|
| 757 |
+
this.resetSpeakometer();
|
| 758 |
+
|
| 759 |
+
// Build video path based on current.word (assets/videos/<word>.mp4)
|
| 760 |
+
const src = this.getVideoSrcFromWord(this.current.word);
|
| 761 |
+
if (!src) return;
|
| 762 |
+
|
| 763 |
+
this.showVideo = true;
|
| 764 |
+
this.videoSrc = src;
|
| 765 |
+
|
| 766 |
+
// Wait for template to render, then set and play video safely
|
| 767 |
+
setTimeout(() => {
|
| 768 |
+
try {
|
| 769 |
+
const v = this.videoElRef?.nativeElement;
|
| 770 |
+
if (v) {
|
| 771 |
+
// sync UI state to element events and reset speakometer when native play occurs
|
| 772 |
+
v.addEventListener('play', () => {
|
| 773 |
+
this.isPlayingVideo = true;
|
| 774 |
+
// keep resetting speakometer on native play to ensure gauge clears
|
| 775 |
+
this.resetSpeakometer();
|
| 776 |
+
});
|
| 777 |
+
v.addEventListener('pause', () => this.isPlayingVideo = false);
|
| 778 |
+
|
| 779 |
+
v.pause();
|
| 780 |
+
v.src = this.videoSrc;
|
| 781 |
+
v.load();
|
| 782 |
+
v.play().then(() => {
|
| 783 |
+
this.isPlayingVideo = true;
|
| 784 |
+
}).catch(() => {
|
| 785 |
+
// ignore autoplay errors; UI still shows the control
|
| 786 |
+
this.isPlayingVideo = !v.paused;
|
| 787 |
+
});
|
| 788 |
+
}
|
| 789 |
+
} catch {
|
| 790 |
+
// ignore
|
| 791 |
+
}
|
| 792 |
+
}, 0);
|
| 793 |
+
}
|
| 794 |
+
|
| 795 |
+
/**
|
| 796 |
+
* Toggles play/pause for the currently-displayed video.
|
| 797 |
+
*/
|
| 798 |
+
toggleVideoPlay(): void {
|
| 799 |
+
try {
|
| 800 |
+
if (!this.showVideo) {
|
| 801 |
+
this.playWordVideo();
|
| 802 |
+
return;
|
| 803 |
+
}
|
| 804 |
+
|
| 805 |
+
const v = this.videoElRef?.nativeElement;
|
| 806 |
+
if (!v) {
|
| 807 |
+
this.videoSrc = this.getVideoSrcFromWord(this.current.word);
|
| 808 |
+
this.showVideo = true;
|
| 809 |
+
return;
|
| 810 |
+
}
|
| 811 |
+
|
| 812 |
+
if (v.paused) {
|
| 813 |
+
// user is starting playback -> reset speakometer
|
| 814 |
+
this.resetSpeakometer();
|
| 815 |
+
|
| 816 |
+
v.play().then(() => {
|
| 817 |
+
this.isPlayingVideo = true;
|
| 818 |
+
}).catch(() => {
|
| 819 |
+
this.isPlayingVideo = !v.paused;
|
| 820 |
+
});
|
| 821 |
+
} else {
|
| 822 |
+
v.pause();
|
| 823 |
+
this.isPlayingVideo = false;
|
| 824 |
+
}
|
| 825 |
+
} catch {
|
| 826 |
+
// ignore
|
| 827 |
+
}
|
| 828 |
+
}
|
| 829 |
+
|
| 830 |
+
/**
|
| 831 |
+
* Attempts to play a feedback video returned by the backend in the same video element.
|
| 832 |
+
* If autoplay is blocked we register a one-time body click handler so the first user gesture starts playback.
|
| 833 |
+
*/
|
| 834 |
+
private tryPlayFeedbackVideo(score: number, videoUrl: string): void {
|
| 835 |
+
if (!videoUrl) return;
|
| 836 |
+
|
| 837 |
+
// ensure UI shows the video element
|
| 838 |
+
this.showVideo = true;
|
| 839 |
+
this.videoSrc = videoUrl;
|
| 840 |
+
|
| 841 |
+
setTimeout(() => {
|
| 842 |
+
try {
|
| 843 |
+
const v = this.videoElRef?.nativeElement;
|
| 844 |
+
if (!v) {
|
| 845 |
+
// element not yet available -> register gesture fallback
|
| 846 |
+
this.registerGestureForPendingVideo(videoUrl);
|
| 847 |
+
return;
|
| 848 |
+
}
|
| 849 |
+
|
| 850 |
+
try { v.pause(); } catch { /* ignore */ }
|
| 851 |
+
|
| 852 |
+
v.src = this.videoSrc;
|
| 853 |
+
v.load();
|
| 854 |
+
v.play().then(() => {
|
| 855 |
+
this.isPlayingVideo = true;
|
| 856 |
+
}).catch(() => {
|
| 857 |
+
// autoplay likely blocked -> register gesture fallback
|
| 858 |
+
this.isPlayingVideo = !v.paused;
|
| 859 |
+
this.registerGestureForPendingVideo(videoUrl);
|
| 860 |
+
});
|
| 861 |
+
} catch {
|
| 862 |
+
// ignore
|
| 863 |
+
}
|
| 864 |
+
}, 0);
|
| 865 |
+
}
|
| 866 |
+
|
| 867 |
+
/**
|
| 868 |
+
* Register a one-time body click handler to play a pending feedback video when user interacts.
|
| 869 |
+
* This satisfies browser autoplay policies (requires a user gesture).
|
| 870 |
+
*/
|
| 871 |
+
private registerGestureForPendingVideo(videoUrl: string): void {
|
| 872 |
+
// if already registered, update pending URL and exit
|
| 873 |
+
this.pendingVideoUrl = videoUrl;
|
| 874 |
+
|
| 875 |
+
if (this.pendingGestureListener) return;
|
| 876 |
+
|
| 877 |
+
this.pendingGestureListener = (e: Event) => {
|
| 878 |
+
try {
|
| 879 |
+
// show video and set src so element renders if it wasn't already
|
| 880 |
+
this.showVideo = true;
|
| 881 |
+
this.videoSrc = this.pendingVideoUrl || videoUrl;
|
| 882 |
+
|
| 883 |
+
// attempt play on the element after change detection
|
| 884 |
+
setTimeout(() => {
|
| 885 |
+
try {
|
| 886 |
+
const v = this.videoElRef?.nativeElement;
|
| 887 |
+
if (v) {
|
| 888 |
+
v.src = this.videoSrc;
|
| 889 |
+
v.load();
|
| 890 |
+
v.play().then(() => {
|
| 891 |
+
this.isPlayingVideo = true;
|
| 892 |
+
}).catch(() => {
|
| 893 |
+
this.isPlayingVideo = !v.paused;
|
| 894 |
+
});
|
| 895 |
+
}
|
| 896 |
+
} catch {
|
| 897 |
+
// ignore
|
| 898 |
+
}
|
| 899 |
+
}, 0);
|
| 900 |
+
} finally {
|
| 901 |
+
// cleanup listener and pending state
|
| 902 |
+
try { if (this.pendingGestureListener) document.body.removeEventListener('click', this.pendingGestureListener, true); } catch { }
|
| 903 |
+
this.pendingGestureListener = undefined;
|
| 904 |
+
this.pendingVideoUrl = null;
|
| 905 |
+
// ensure gauge is not oscillating after user gesture
|
| 906 |
+
this.isOscillating = false;
|
| 907 |
+
}
|
| 908 |
+
};
|
| 909 |
+
|
| 910 |
+
// use capture so early gestures are caught even if other handlers stop propagation
|
| 911 |
+
try { document.body.addEventListener('click', this.pendingGestureListener, true); } catch { /* ignore */ }
|
| 912 |
+
}
|
| 913 |
+
|
| 914 |
+
onVideoEnded(): void {
|
| 915 |
+
// Ensure the native element is stopped and cleared so the thumbnail can re-appear.
|
| 916 |
+
try {
|
| 917 |
+
const v = this.videoElRef?.nativeElement;
|
| 918 |
+
if (v) {
|
| 919 |
+
try { v.pause(); } catch { }
|
| 920 |
+
try { v.currentTime = 0; } catch { }
|
| 921 |
+
try { v.src = ''; } catch { }
|
| 922 |
+
try { v.load(); } catch { }
|
| 923 |
+
}
|
| 924 |
+
} catch {
|
| 925 |
+
// ignore DOM errors
|
| 926 |
+
} finally {
|
| 927 |
+
// show the thumbnail again and reset video state
|
| 928 |
+
this.showVideo = false;
|
| 929 |
+
this.isPlayingVideo = false;
|
| 930 |
+
this.videoSrc = '';
|
| 931 |
+
|
| 932 |
+
// stop any lingering oscillation and pending gesture state
|
| 933 |
+
this.isOscillating = false;
|
| 934 |
+
if (this.pendingGestureListener) {
|
| 935 |
+
try { document.body.removeEventListener('click', this.pendingGestureListener, true); } catch { }
|
| 936 |
+
this.pendingGestureListener = undefined;
|
| 937 |
+
this.pendingVideoUrl = null;
|
| 938 |
+
}
|
| 939 |
+
|
| 940 |
+
// ensure template updates immediately
|
| 941 |
+
try { this.cdr.detectChanges(); } catch { }
|
| 942 |
+
}
|
| 943 |
+
}
|
| 944 |
+
|
| 945 |
+
private getVideoSrcFromWord(word: string): string {
|
| 946 |
+
if (!word) return '';
|
| 947 |
+
const fileName = word.trim().toLowerCase().replace(/\s+/g, '-');
|
| 948 |
+
return `assets/pronvideo/videos/${fileName}.mp4`;
|
| 949 |
+
}
|
| 950 |
+
}
|
src/app/pronunciationvideo/pronunciationvideo.component.css
ADDED
|
@@ -0,0 +1,785 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
:host {
|
| 2 |
+
display: block;
|
| 3 |
+
/*font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;*/
|
| 4 |
+
font-family: Raleway, Roboto, "Helvetica Neue", sans-serif;
|
| 5 |
+
}
|
| 6 |
+
|
| 7 |
+
/* Page background */
|
| 8 |
+
.pp-page {
|
| 9 |
+
height: 85vh;
|
| 10 |
+
/* background: #e9f7f6;*/
|
| 11 |
+
padding: 28px 24px 18px;
|
| 12 |
+
box-sizing: border-box;
|
| 13 |
+
border: 7px solid #3aaea8;
|
| 14 |
+
border-radius: 1vw;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
/* Header */
|
| 18 |
+
.pp-header {
|
| 19 |
+
text-align: center;
|
| 20 |
+
margin-bottom: 18px;
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
.pp-header h1 {
|
| 24 |
+
margin: 0;
|
| 25 |
+
font-size: 42px;
|
| 26 |
+
font-weight: 800;
|
| 27 |
+
color: #3aaea8;
|
| 28 |
+
letter-spacing: 0.3px;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
.pp-sub {
|
| 32 |
+
margin-top: 6px;
|
| 33 |
+
color: #6b7f7e;
|
| 34 |
+
font-size: 15px;
|
| 35 |
+
position: relative;
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
.pp-tooltip {
|
| 39 |
+
margin-left: 8px;
|
| 40 |
+
display: inline-block;
|
| 41 |
+
background: #ffffff;
|
| 42 |
+
border: 1px solid #d8eeee;
|
| 43 |
+
color: #2f6f6b;
|
| 44 |
+
padding: 6px 10px;
|
| 45 |
+
border-radius: 14px;
|
| 46 |
+
font-size: 12px;
|
| 47 |
+
box-shadow: 0 6px 14px rgba(0,0,0,0.06);
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
/* Main 3 columns */
|
| 51 |
+
.pp-main {
|
| 52 |
+
display: flex;
|
| 53 |
+
gap: 1vw;
|
| 54 |
+
align-items: start;
|
| 55 |
+
justify-content: space-around;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
/* LEFT */
|
| 59 |
+
.pp-left {
|
| 60 |
+
display: flex;
|
| 61 |
+
justify-content: center;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
.word-card {
|
| 65 |
+
width: 22vw;
|
| 66 |
+
height: 34vw;
|
| 67 |
+
background: #e9f7f6;
|
| 68 |
+
border-radius: 18px;
|
| 69 |
+
padding: 22px 18px 26px;
|
| 70 |
+
text-align: center;
|
| 71 |
+
box-shadow: 0 12px 26px rgba(0, 0, 0, 0.08);
|
| 72 |
+
border: 3px dashed #3aaea8;
|
| 73 |
+
gap: 0.5vw;
|
| 74 |
+
display: flex;
|
| 75 |
+
flex-direction: column;
|
| 76 |
+
align-items: center;
|
| 77 |
+
justify-content: space-between;
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
.word-img-wrap {
|
| 81 |
+
width: 20vw;
|
| 82 |
+
height: 20vw;
|
| 83 |
+
display: flex;
|
| 84 |
+
align-items: center;
|
| 85 |
+
justify-content: center;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
.word-img-wrap img {
|
| 89 |
+
max-width: 100%;
|
| 90 |
+
max-height: 100%;
|
| 91 |
+
object-fit: contain;
|
| 92 |
+
border-radius:1vw;
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
.word-text {
|
| 96 |
+
font-size: 3vw;
|
| 97 |
+
font-weight: 800;
|
| 98 |
+
color: #1f2b2a;
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
.phonetic-pill {
|
| 102 |
+
color: #3aaea8;
|
| 103 |
+
font-size: 1.5vw;
|
| 104 |
+
font-weight: 600;
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
.audio-img {
|
| 108 |
+
width: 4.8vw;
|
| 109 |
+
cursor: pointer;
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
}
|
| 113 |
+
/* CENTER */
|
| 114 |
+
.pp-center {
|
| 115 |
+
display: flex;
|
| 116 |
+
flex-direction: column;
|
| 117 |
+
align-items: center;
|
| 118 |
+
gap: 14px;
|
| 119 |
+
position: relative;
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
.teacher-frame {
|
| 123 |
+
/* width: 240px;
|
| 124 |
+
height: 210px;
|
| 125 |
+
border-radius: 18px;
|
| 126 |
+
padding: 12px;
|
| 127 |
+
background: #e7f4f3;
|
| 128 |
+
border: 2px dashed #b9dedb;
|
| 129 |
+
display: flex;
|
| 130 |
+
align-items: center;
|
| 131 |
+
justify-content: center;*/
|
| 132 |
+
width: 22vw;
|
| 133 |
+
height: 33vw;
|
| 134 |
+
background: #e9f7f6;
|
| 135 |
+
border-radius: 18px;
|
| 136 |
+
padding: 22px 18px 26px;
|
| 137 |
+
text-align: center;
|
| 138 |
+
box-shadow: 0 12px 26px rgba(0, 0, 0, 0.08);
|
| 139 |
+
border: 3px dashed #3aaea8;
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
.teacher-frame img {
|
| 143 |
+
width: 100%;
|
| 144 |
+
height: 100%;
|
| 145 |
+
object-fit: cover;
|
| 146 |
+
border-radius: 12px;
|
| 147 |
+
background: #ffffff;
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
/* Listen button */
|
| 151 |
+
.listen-btn {
|
| 152 |
+
border: none;
|
| 153 |
+
background: #49b6ae;
|
| 154 |
+
color: #ffffff;
|
| 155 |
+
padding: 12px 18px;
|
| 156 |
+
border-radius: 12px;
|
| 157 |
+
font-weight: 700;
|
| 158 |
+
font-size: 16px;
|
| 159 |
+
display: inline-flex;
|
| 160 |
+
align-items: center;
|
| 161 |
+
gap: 10px;
|
| 162 |
+
cursor: pointer;
|
| 163 |
+
box-shadow: 0 8px 18px rgba(0,0,0,0.08);
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
.listen-btn:active {
|
| 167 |
+
transform: scale(0.99);
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
.listen-ico {
|
| 171 |
+
font-size: 18px;
|
| 172 |
+
}
|
| 173 |
+
|
| 174 |
+
/* Record circle */
|
| 175 |
+
.rec-circle {
|
| 176 |
+
width: 92px;
|
| 177 |
+
height: 92px;
|
| 178 |
+
border-radius: 50%;
|
| 179 |
+
border: none;
|
| 180 |
+
background: #f07b48;
|
| 181 |
+
color: #ffffff;
|
| 182 |
+
cursor: pointer;
|
| 183 |
+
/* box-shadow: 0 12px 22px rgba(0,0,0,0.12);*/
|
| 184 |
+
display: flex;
|
| 185 |
+
align-items: center;
|
| 186 |
+
justify-content: center;
|
| 187 |
+
/* transition: transform 0.08s ease, filter 0.2s ease;*/
|
| 188 |
+
box-shadow: 0px 10px 30px rgba(0, 0, 0, 0.4);
|
| 189 |
+
transition: all 0.3s ease;
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
.rec-circle:active {
|
| 193 |
+
transform: scale(0.98);
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
.rec-circle.recording {
|
| 197 |
+
filter: brightness(0.95);
|
| 198 |
+
animation: recPulse 1s infinite;
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
@keyframes recPulse {
|
| 202 |
+
0% {
|
| 203 |
+
box-shadow: 0 0 0 0 rgba(240,123,72,0.35);
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
70% {
|
| 207 |
+
box-shadow: 0 0 0 18px rgba(240,123,72,0);
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
100% {
|
| 211 |
+
box-shadow: 0 0 0 0 rgba(240,123,72,0);
|
| 212 |
+
}
|
| 213 |
+
}
|
| 214 |
+
|
| 215 |
+
.rec-inner {
|
| 216 |
+
text-align: center;
|
| 217 |
+
line-height: 1.1;
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
+
.mic {
|
| 221 |
+
font-size: 22px;
|
| 222 |
+
margin-bottom: 4px;
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
.rec-text {
|
| 226 |
+
font-size: 12px;
|
| 227 |
+
font-weight: 800;
|
| 228 |
+
letter-spacing: 0.6px;
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
/* RIGHT */
|
| 232 |
+
.pp-right {
|
| 233 |
+
|
| 234 |
+
display: flex;
|
| 235 |
+
justify-content: flex-start;
|
| 236 |
+
align-items: center;
|
| 237 |
+
flex-direction: column;
|
| 238 |
+
gap: 18vw;
|
| 239 |
+
}
|
| 240 |
+
|
| 241 |
+
/* little connector dots */
|
| 242 |
+
.connector {
|
| 243 |
+
|
| 244 |
+
display: flex;
|
| 245 |
+
flex-direction: column;
|
| 246 |
+
gap: 2vw;
|
| 247 |
+
}
|
| 248 |
+
|
| 249 |
+
.connector span {
|
| 250 |
+
width: 34px;
|
| 251 |
+
height: 10px;
|
| 252 |
+
border-radius: 999px;
|
| 253 |
+
background: #98d8d4;
|
| 254 |
+
opacity: 0.6;
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
/* feedback card */
|
| 258 |
+
.feedback-card {
|
| 259 |
+
width: 15vw;
|
| 260 |
+
background: #9edfd9;
|
| 261 |
+
border-radius: 16px;
|
| 262 |
+
padding: 22px 22px 24px;
|
| 263 |
+
box-shadow: 0 12px 22px rgba(0,0,0,0.08);
|
| 264 |
+
height: 15vw;
|
| 265 |
+
}
|
| 266 |
+
|
| 267 |
+
.feedback-title {
|
| 268 |
+
font-size: 18px;
|
| 269 |
+
font-weight: 800;
|
| 270 |
+
color: #205f5a;
|
| 271 |
+
letter-spacing: 0.6px;
|
| 272 |
+
margin-bottom: 8px;
|
| 273 |
+
}
|
| 274 |
+
|
| 275 |
+
.feedback-body {
|
| 276 |
+
background: transparent;
|
| 277 |
+
}
|
| 278 |
+
|
| 279 |
+
.feedback-muted {
|
| 280 |
+
color: #2c6d68;
|
| 281 |
+
opacity: 0.8;
|
| 282 |
+
font-style: italic;
|
| 283 |
+
font-size: 14px;
|
| 284 |
+
margin-top: 8px;
|
| 285 |
+
}
|
| 286 |
+
|
| 287 |
+
/* Result UI inside feedback */
|
| 288 |
+
.feedback-result {
|
| 289 |
+
margin-top: 8px;
|
| 290 |
+
}
|
| 291 |
+
|
| 292 |
+
.score-row {
|
| 293 |
+
display: flex;
|
| 294 |
+
align-items: baseline;
|
| 295 |
+
gap: 10px;
|
| 296 |
+
}
|
| 297 |
+
|
| 298 |
+
.score-label {
|
| 299 |
+
font-size: 12px;
|
| 300 |
+
color: #1d514d;
|
| 301 |
+
font-weight: 700;
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
.score-value {
|
| 305 |
+
font-size: 28px;
|
| 306 |
+
font-weight: 900;
|
| 307 |
+
color: #103c39;
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
+
/* Speakometer */
|
| 311 |
+
.meter {
|
| 312 |
+
margin-top: 10px;
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
.meter-track {
|
| 316 |
+
height: 10px;
|
| 317 |
+
background: rgba(255,255,255,0.45);
|
| 318 |
+
border-radius: 999px;
|
| 319 |
+
overflow: hidden;
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
.meter-fill {
|
| 323 |
+
height: 100%;
|
| 324 |
+
width: 0%;
|
| 325 |
+
background: #2b8f88;
|
| 326 |
+
transition: width 0.5s ease;
|
| 327 |
+
}
|
| 328 |
+
|
| 329 |
+
/* Stars */
|
| 330 |
+
.stars {
|
| 331 |
+
margin-top: 10px;
|
| 332 |
+
font-size: 22px;
|
| 333 |
+
display: flex;
|
| 334 |
+
gap: 4px;
|
| 335 |
+
}
|
| 336 |
+
|
| 337 |
+
.stars span {
|
| 338 |
+
color: rgba(255,255,255,0.55);
|
| 339 |
+
}
|
| 340 |
+
|
| 341 |
+
.stars span.active {
|
| 342 |
+
color: #ffcc4d;
|
| 343 |
+
animation: starPop 0.3s ease;
|
| 344 |
+
}
|
| 345 |
+
|
| 346 |
+
@keyframes starPop {
|
| 347 |
+
0% {
|
| 348 |
+
transform: scale(0.85);
|
| 349 |
+
}
|
| 350 |
+
|
| 351 |
+
60% {
|
| 352 |
+
transform: scale(1.12);
|
| 353 |
+
}
|
| 354 |
+
|
| 355 |
+
100% {
|
| 356 |
+
transform: scale(1);
|
| 357 |
+
}
|
| 358 |
+
}
|
| 359 |
+
|
| 360 |
+
/* 3 lines feedback */
|
| 361 |
+
.feedback-lines {
|
| 362 |
+
margin: 10px 0 0 18px;
|
| 363 |
+
color: #114744;
|
| 364 |
+
font-size: 13.5px;
|
| 365 |
+
font-weight: 600;
|
| 366 |
+
}
|
| 367 |
+
|
| 368 |
+
/* Bottom area */
|
| 369 |
+
.pp-bottom {
|
| 370 |
+
max-width: 1200px;
|
| 371 |
+
margin: 22px auto 0;
|
| 372 |
+
display: flex;
|
| 373 |
+
flex-direction: column;
|
| 374 |
+
align-items: center;
|
| 375 |
+
gap: 14px;
|
| 376 |
+
}
|
| 377 |
+
|
| 378 |
+
/* Prev/Next line */
|
| 379 |
+
/* Prev/Next line */
|
| 380 |
+
.nav-row {
|
| 381 |
+
display: flex;
|
| 382 |
+
align-items: center;
|
| 383 |
+
gap: 3vw;
|
| 384 |
+
}
|
| 385 |
+
|
| 386 |
+
/* Increased arrow size and perfectly center it inside the circular button */
|
| 387 |
+
.nav-btn {
|
| 388 |
+
width: 7vw;
|
| 389 |
+
height: 7vw;
|
| 390 |
+
border-radius: 50%;
|
| 391 |
+
border: none;
|
| 392 |
+
background: #dcefee;
|
| 393 |
+
color: #1b5551;
|
| 394 |
+
font-size: 7vw; /* larger arrow */
|
| 395 |
+
display: flex; /* center text horizontally & vertically */
|
| 396 |
+
align-items: center;
|
| 397 |
+
justify-content: center;
|
| 398 |
+
text-align: center;
|
| 399 |
+
line-height: 1; /* avoid font baseline shifts */
|
| 400 |
+
padding: 0; /* ensure perfect centering */
|
| 401 |
+
cursor: pointer;
|
| 402 |
+
font-weight: 700;
|
| 403 |
+
box-shadow: 0 8px 18px rgba(0,0,0,0.06);
|
| 404 |
+
transition: transform 0.08s ease;
|
| 405 |
+
}
|
| 406 |
+
|
| 407 |
+
.nav-btn:active {
|
| 408 |
+
transform: scale(0.98);
|
| 409 |
+
}
|
| 410 |
+
|
| 411 |
+
.nav-btn:disabled {
|
| 412 |
+
opacity: 0.5;
|
| 413 |
+
cursor: not-allowed;
|
| 414 |
+
}
|
| 415 |
+
.nav-center {
|
| 416 |
+
display: inline-flex;
|
| 417 |
+
align-items: baseline;
|
| 418 |
+
gap: 8px;
|
| 419 |
+
}
|
| 420 |
+
|
| 421 |
+
.nav-letter {
|
| 422 |
+
font-size: 5vw;
|
| 423 |
+
font-weight: 900;
|
| 424 |
+
color: #3aaea8;
|
| 425 |
+
}
|
| 426 |
+
|
| 427 |
+
.nav-count {
|
| 428 |
+
font-size: 14px;
|
| 429 |
+
color: #667b79;
|
| 430 |
+
font-weight: 600;
|
| 431 |
+
}
|
| 432 |
+
|
| 433 |
+
/* Responsive override so buttons don't overflow on smaller screens */
|
| 434 |
+
@media (max-width: 980px) {
|
| 435 |
+
.nav-btn {
|
| 436 |
+
width: 56px;
|
| 437 |
+
height: 56px;
|
| 438 |
+
font-size: 28px;
|
| 439 |
+
}
|
| 440 |
+
}
|
| 441 |
+
|
| 442 |
+
/* Alphabet pills */
|
| 443 |
+
.alpha-row {
|
| 444 |
+
display: flex;
|
| 445 |
+
flex-wrap: wrap;
|
| 446 |
+
justify-content: center;
|
| 447 |
+
gap: 8px;
|
| 448 |
+
max-width: 900px;
|
| 449 |
+
}
|
| 450 |
+
|
| 451 |
+
.alpha-pill {
|
| 452 |
+
width: 34px;
|
| 453 |
+
height: 34px;
|
| 454 |
+
border-radius: 50%;
|
| 455 |
+
border: none;
|
| 456 |
+
background: #dfeeee;
|
| 457 |
+
color: #3a5a58;
|
| 458 |
+
font-weight: 700;
|
| 459 |
+
cursor: pointer;
|
| 460 |
+
font-size: 13px;
|
| 461 |
+
}
|
| 462 |
+
|
| 463 |
+
.alpha-pill.active {
|
| 464 |
+
background: #49b6ae;
|
| 465 |
+
color: #ffffff;
|
| 466 |
+
box-shadow: 0 6px 14px rgba(0,0,0,0.08);
|
| 467 |
+
}
|
| 468 |
+
|
| 469 |
+
/* Responsive */
|
| 470 |
+
@media (max-width: 1100px) {
|
| 471 |
+
.pp-main {
|
| 472 |
+
grid-template-columns: 260px 320px 1fr;
|
| 473 |
+
}
|
| 474 |
+
}
|
| 475 |
+
|
| 476 |
+
@media (max-width: 980px) {
|
| 477 |
+
.pp-main {
|
| 478 |
+
grid-template-columns: 1fr;
|
| 479 |
+
}
|
| 480 |
+
|
| 481 |
+
.pp-left, .pp-center, .pp-right {
|
| 482 |
+
justify-content: center;
|
| 483 |
+
}
|
| 484 |
+
|
| 485 |
+
.connector {
|
| 486 |
+
display: none;
|
| 487 |
+
}
|
| 488 |
+
|
| 489 |
+
.feedback-card {
|
| 490 |
+
width: 100%;
|
| 491 |
+
max-width: 520px;
|
| 492 |
+
}
|
| 493 |
+
}
|
| 494 |
+
.gauge-wrapper {
|
| 495 |
+
position: relative;
|
| 496 |
+
width: 20vw;
|
| 497 |
+
height: 10vw;
|
| 498 |
+
}
|
| 499 |
+
|
| 500 |
+
.gauge {
|
| 501 |
+
position: absolute;
|
| 502 |
+
left: 50%;
|
| 503 |
+
top: 0;
|
| 504 |
+
transform: translateX(-50%);
|
| 505 |
+
width: 100%;
|
| 506 |
+
height: 100%;
|
| 507 |
+
border-radius: 260px 260px 0 0;
|
| 508 |
+
overflow: hidden;
|
| 509 |
+
background: #f3f3f3;
|
| 510 |
+
box-shadow: 0 4px 10px rgba(0,0,0,0.25) inset;
|
| 511 |
+
}
|
| 512 |
+
|
| 513 |
+
.gauge-arc {
|
| 514 |
+
position: absolute;
|
| 515 |
+
inset: 0;
|
| 516 |
+
border-radius: 50%;
|
| 517 |
+
background: conic-gradient( from 270deg, #e53935 0deg 45deg, #fb8c00 45deg 90deg, #fbc02d 90deg 135deg, #43a047 135deg 180deg, transparent 180deg 360deg );
|
| 518 |
+
height: 20vw;
|
| 519 |
+
}
|
| 520 |
+
|
| 521 |
+
.needle {
|
| 522 |
+
position: absolute;
|
| 523 |
+
bottom: 0vw;
|
| 524 |
+
left: 50%;
|
| 525 |
+
width: 0.7vw;
|
| 526 |
+
height: 8vw;
|
| 527 |
+
background: #333;
|
| 528 |
+
transform: translateX(-50%) rotate(var(--angle, -90deg));
|
| 529 |
+
transform-origin: 50% 100%;
|
| 530 |
+
transition: transform 700ms cubic-bezier(.2,.9,.2,1);
|
| 531 |
+
border-radius: 10px;
|
| 532 |
+
box-shadow: 0 2px 6px rgba(0,0,0,0.5);
|
| 533 |
+
}
|
| 534 |
+
|
| 535 |
+
.mic-badge {
|
| 536 |
+
position: absolute;
|
| 537 |
+
bottom: -0.3vw;
|
| 538 |
+
left: 50%;
|
| 539 |
+
transform: translate(-50%, 35%);
|
| 540 |
+
width: 3vw;
|
| 541 |
+
height: 3vw;
|
| 542 |
+
border-radius: 50%;
|
| 543 |
+
background: #000;
|
| 544 |
+
box-shadow: 0 8px 18px rgba(0,0,0,0.4);
|
| 545 |
+
display: flex;
|
| 546 |
+
align-items: center;
|
| 547 |
+
justify-content: center;
|
| 548 |
+
}
|
| 549 |
+
|
| 550 |
+
.score-span {
|
| 551 |
+
color: white;
|
| 552 |
+
font-size: 1vw;
|
| 553 |
+
font-weight: bold;
|
| 554 |
+
}
|
| 555 |
+
.notepad{
|
| 556 |
+
display:flex;
|
| 557 |
+
align-items:center;
|
| 558 |
+
}
|
| 559 |
+
|
| 560 |
+
.user-guide-close-icon {
|
| 561 |
+
position: fixed;
|
| 562 |
+
top: 3vw;
|
| 563 |
+
right: 4vw;
|
| 564 |
+
background: #009688;
|
| 565 |
+
border: none;
|
| 566 |
+
width: 44px;
|
| 567 |
+
height: 44px;
|
| 568 |
+
border-radius: 50%;
|
| 569 |
+
display: flex;
|
| 570 |
+
align-items: center;
|
| 571 |
+
justify-content: center;
|
| 572 |
+
font-size: 2vw;
|
| 573 |
+
color: black;
|
| 574 |
+
cursor: pointer;
|
| 575 |
+
z-index: 2010;
|
| 576 |
+
box-shadow: 0 2px 8px rgba(93, 145, 195, 0.18);
|
| 577 |
+
transition: background 0.2s, color 0.2s;
|
| 578 |
+
}
|
| 579 |
+
/* Teacher media container — ensures image and video occupy exactly the same box */
|
| 580 |
+
.teacher-media {
|
| 581 |
+
width: 20vw; /* same as you used inline before */
|
| 582 |
+
max-width: 260px; /* optional limit for very wide screens */
|
| 583 |
+
min-width: 140px; /* optional floor */
|
| 584 |
+
aspect-ratio: 3 / 4; /* change to 16 / 9 if your videos are widescreen */
|
| 585 |
+
position: relative;
|
| 586 |
+
overflow: hidden;
|
| 587 |
+
display: block;
|
| 588 |
+
}
|
| 589 |
+
|
| 590 |
+
/* Shared styles for image and video so sizes match exactly */
|
| 591 |
+
.teacher-media__img,
|
| 592 |
+
.teacher-media__video {
|
| 593 |
+
width: 100%;
|
| 594 |
+
height: 100%;
|
| 595 |
+
display: block;
|
| 596 |
+
border-radius: 1vw;
|
| 597 |
+
border: 2px solid #ccc; /* keep previously visible border */
|
| 598 |
+
object-fit: cover; /* makes video/image fill box similarly */
|
| 599 |
+
}
|
| 600 |
+
|
| 601 |
+
/* A neutral background for video while it loads */
|
| 602 |
+
.teacher-media__video {
|
| 603 |
+
background-color: #000;
|
| 604 |
+
}
|
| 605 |
+
/* Make play/pause image match record button size and add shadow */
|
| 606 |
+
.listen-img {
|
| 607 |
+
width: 92px; /* match .rec-circle size */
|
| 608 |
+
height: 92px;
|
| 609 |
+
border-radius: 50%;
|
| 610 |
+
display: inline-block;
|
| 611 |
+
object-fit: contain; /* keep icon aspect */
|
| 612 |
+
cursor: pointer;
|
| 613 |
+
user-select: none;
|
| 614 |
+
margin-right: 1vw;
|
| 615 |
+
box-shadow: 0px 10px 30px rgba(0, 0, 0, 0.4);
|
| 616 |
+
transition: all 0.3s ease;
|
| 617 |
+
/*box-shadow: 0 12px 22px rgba(0,0,0,0.12);
|
| 618 |
+
transition: transform 0.08s ease, filter 0.15s ease, box-shadow 0.15s ease;
|
| 619 |
+
|
| 620 |
+
box-sizing: border-box;*/
|
| 621 |
+
border: none;
|
| 622 |
+
}
|
| 623 |
+
|
| 624 |
+
/* pressed / active */
|
| 625 |
+
.listen-img:active {
|
| 626 |
+
transform: scale(0.98);
|
| 627 |
+
}
|
| 628 |
+
|
| 629 |
+
/* playing state — subtle visual change */
|
| 630 |
+
.listen-img.playing,
|
| 631 |
+
.listen-img[aria-pressed="true"] {
|
| 632 |
+
filter: brightness(0.95);
|
| 633 |
+
box-shadow: 0 18px 30px rgba(0,0,0,0.16);
|
| 634 |
+
}
|
| 635 |
+
|
| 636 |
+
/* keyboard focus for accessibility */
|
| 637 |
+
.listen-img:focus {
|
| 638 |
+
outline: 3px solid rgba(58,174,168,0.18);
|
| 639 |
+
outline-offset: 3px;
|
| 640 |
+
}
|
| 641 |
+
|
| 642 |
+
/* Small-screen fallback (keep sizes proportional) */
|
| 643 |
+
@media (max-width: 980px) {
|
| 644 |
+
.listen-img {
|
| 645 |
+
width: 72px;
|
| 646 |
+
height: 72px;
|
| 647 |
+
padding: 14px;
|
| 648 |
+
}
|
| 649 |
+
}
|
| 650 |
+
/* add oscillation keyframes and state */
|
| 651 |
+
@keyframes needleOscillate {
|
| 652 |
+
0% {
|
| 653 |
+
transform: translateX(-50%) rotate(-70deg);
|
| 654 |
+
}
|
| 655 |
+
|
| 656 |
+
25% {
|
| 657 |
+
transform: translateX(-50%) rotate(-20deg);
|
| 658 |
+
}
|
| 659 |
+
|
| 660 |
+
50% {
|
| 661 |
+
transform: translateX(-50%) rotate(60deg);
|
| 662 |
+
}
|
| 663 |
+
|
| 664 |
+
75% {
|
| 665 |
+
transform: translateX(-50%) rotate(-10deg);
|
| 666 |
+
}
|
| 667 |
+
|
| 668 |
+
100% {
|
| 669 |
+
transform: translateX(-50%) rotate(-70deg);
|
| 670 |
+
}
|
| 671 |
+
}
|
| 672 |
+
|
| 673 |
+
/* existing needle default uses CSS variable for final angle */
|
| 674 |
+
.needle {
|
| 675 |
+
position: absolute;
|
| 676 |
+
bottom: 0vw;
|
| 677 |
+
left: 50%;
|
| 678 |
+
width: 0.7vw;
|
| 679 |
+
height: 8vw;
|
| 680 |
+
background: #333;
|
| 681 |
+
transform: translateX(-50%) rotate(var(--angle, -90deg));
|
| 682 |
+
transform-origin: 50% 100%;
|
| 683 |
+
transition: transform 700ms cubic-bezier(.2,.9,.2,1);
|
| 684 |
+
border-radius: 10px;
|
| 685 |
+
box-shadow: 0 2px 6px rgba(0,0,0,0.5);
|
| 686 |
+
}
|
| 687 |
+
|
| 688 |
+
/* while recording / waiting for score, run oscillation animation */
|
| 689 |
+
.needle.oscillate {
|
| 690 |
+
/* override transform with animation while oscillating */
|
| 691 |
+
animation: needleOscillate 1.2s ease-in-out infinite;
|
| 692 |
+
/* disable the smooth transition while animation runs to prevent conflicts */
|
| 693 |
+
transition: none;
|
| 694 |
+
}
|
| 695 |
+
|
| 696 |
+
/* when oscillation ends (isRecording/isScoring false), the animation class is removed
|
| 697 |
+
and the element will smoothly transition to the value provided by --angle */
|
| 698 |
+
.container {
|
| 699 |
+
display: flex;
|
| 700 |
+
justify-content: center;
|
| 701 |
+
align-items: center;
|
| 702 |
+
gap: 40px; /* Increase the space between elements */
|
| 703 |
+
}
|
| 704 |
+
|
| 705 |
+
.arrow {
|
| 706 |
+
font-size: 4rem; /* Increased font size for bigger buttons */
|
| 707 |
+
background-color: #e0f7fa;
|
| 708 |
+
border: none;
|
| 709 |
+
width: 92px; /* Set width */
|
| 710 |
+
height: 92px; /* Set height */
|
| 711 |
+
border-radius: 50%; /* Make the button circular */
|
| 712 |
+
display: flex;
|
| 713 |
+
justify-content: center;
|
| 714 |
+
align-items: center;
|
| 715 |
+
cursor: pointer;
|
| 716 |
+
box-shadow: 4px 4px 15px rgba(0, 0, 0, 0.2); /* Box shadow for the button */
|
| 717 |
+
color: #00796b; /* Set color of the arrows */
|
| 718 |
+
transition: background-color 0.3s, color 0.3s; /* Smooth transition for background and text color */
|
| 719 |
+
}
|
| 720 |
+
|
| 721 |
+
/* Disabled state styles */
|
| 722 |
+
.arrow:disabled {
|
| 723 |
+
background-color: #cfd8dc; /* Light gray background when disabled */
|
| 724 |
+
color: #90a4ae; /* Gray color for the arrow */
|
| 725 |
+
cursor: not-allowed; /* Change cursor to indicate the button is disabled */
|
| 726 |
+
box-shadow: none; /* Remove box shadow for disabled button */
|
| 727 |
+
}
|
| 728 |
+
|
| 729 |
+
.center-text {
|
| 730 |
+
font-size: 5rem; /* Increased font size for the 'Y' text */
|
| 731 |
+
font-weight: bold;
|
| 732 |
+
color: #00796b;
|
| 733 |
+
width: 4vw;
|
| 734 |
+
text-align: center;
|
| 735 |
+
}
|
| 736 |
+
|
| 737 |
+
|
| 738 |
+
/* Styling the container */
|
| 739 |
+
.image-container {
|
| 740 |
+
display: flex;
|
| 741 |
+
justify-content: center;
|
| 742 |
+
align-items: center;
|
| 743 |
+
height: 100vh;
|
| 744 |
+
}
|
| 745 |
+
|
| 746 |
+
/* Styling the round image with shadow */
|
| 747 |
+
.round-image {
|
| 748 |
+
width: 4.8vw; /* Adjust the size as needed */
|
| 749 |
+
height: 4.8vw;
|
| 750 |
+
border-radius: 50%; /* Makes the image round */
|
| 751 |
+
box-shadow: 0px 10px 30px rgba(0, 0, 0, 0.4);
|
| 752 |
+
transition: all 0.3s ease; /* Smooth transition for animation */
|
| 753 |
+
cursor: pointer;
|
| 754 |
+
}
|
| 755 |
+
|
| 756 |
+
/* Scaling effect on click */
|
| 757 |
+
.round-image:active {
|
| 758 |
+
transform: scale(1.1); /* Scale up by 10% when clicked */
|
| 759 |
+
}
|
| 760 |
+
|
| 761 |
+
/* Subtle zoom in/out */
|
| 762 |
+
.apple-anim {
|
| 763 |
+
transform-origin: 50% 50%;
|
| 764 |
+
animation: appleZoom 2.8s ease-in-out infinite alternate;
|
| 765 |
+
will-change: transform;
|
| 766 |
+
}
|
| 767 |
+
|
| 768 |
+
@keyframes appleZoom {
|
| 769 |
+
from {
|
| 770 |
+
transform: scale(0.8);
|
| 771 |
+
}
|
| 772 |
+
|
| 773 |
+
to {
|
| 774 |
+
transform: scale(1.06);
|
| 775 |
+
}
|
| 776 |
+
/* slight zoom */
|
| 777 |
+
}
|
| 778 |
+
|
| 779 |
+
/* Respect reduced motion preference */
|
| 780 |
+
@media (prefers-reduced-motion: reduce) {
|
| 781 |
+
.apple-anim {
|
| 782 |
+
animation: none;
|
| 783 |
+
transform: none;
|
| 784 |
+
}
|
| 785 |
+
}
|
src/app/pronunciationvideo/pronunciationvideo.component.html
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<div class="pp-page">
|
| 2 |
+
|
| 3 |
+
<!-- Header -->
|
| 4 |
+
<div class="pp-header">
|
| 5 |
+
<h1>Pronunciation Practice</h1>
|
| 6 |
+
</div>
|
| 7 |
+
|
| 8 |
+
<!-- Main area -->
|
| 9 |
+
<div class="pp-main">
|
| 10 |
+
|
| 11 |
+
<!-- LEFT: Word card -->
|
| 12 |
+
<div class="pp-left">
|
| 13 |
+
<div class="word-card">
|
| 14 |
+
<div class="word-img-wrap">
|
| 15 |
+
<img class="apple-anim" [src]="current.imgSrc" [alt]="current.word" />
|
| 16 |
+
</div>
|
| 17 |
+
|
| 18 |
+
<div class="word-text">{{ current.word }}</div>
|
| 19 |
+
|
| 20 |
+
<div class="phonetic-pill">
|
| 21 |
+
{{ current.phonetics }}
|
| 22 |
+
</div>
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
<div class="image-container">
|
| 26 |
+
<img src="assets/pronvideo/audio.png" alt="Round Image" class="round-image" (click)="playWordAudio()">
|
| 27 |
+
</div>
|
| 28 |
+
|
| 29 |
+
</div>
|
| 30 |
+
</div>
|
| 31 |
+
|
| 32 |
+
<!-- CENTER: Teacher area -->
|
| 33 |
+
<div class="pp-center">
|
| 34 |
+
<div class="word-card" style="width:30vw!important">
|
| 35 |
+
<div style="width:28vw;height:25vw">
|
| 36 |
+
<!-- show teacher image when no video is active -->
|
| 37 |
+
<img *ngIf="!showVideo"
|
| 38 |
+
style="height:100%; border-radius:1vw;"
|
| 39 |
+
src="assets/pronvideo/teacher.png"
|
| 40 |
+
alt="Teacher" />
|
| 41 |
+
|
| 42 |
+
<!-- single video element used for both teacher and feedback videos -->
|
| 43 |
+
<video *ngIf="showVideo"
|
| 44 |
+
#videoEl
|
| 45 |
+
[src]="videoSrc"
|
| 46 |
+
style="border-radius:1vw; object-fit:cover;"
|
| 47 |
+
controls
|
| 48 |
+
autoplay
|
| 49 |
+
(ended)="onVideoEnded()"
|
| 50 |
+
height="469"
|
| 51 |
+
width="521">
|
| 52 |
+
Your browser does not support the video tag.
|
| 53 |
+
</video>
|
| 54 |
+
</div>
|
| 55 |
+
|
| 56 |
+
<!-- Toggle listen button: image acts as the button and switches between play/pause -->
|
| 57 |
+
<!-- Replace the button with a single image that acts as a toggle control -->
|
| 58 |
+
|
| 59 |
+
<div style="display:flex;margin-top:1.8vw;gap:2vw;">
|
| 60 |
+
<img class="listen-img"
|
| 61 |
+
[src]="isPlayingVideo ? pauseIconDataUrl : playIconDataUrl"
|
| 62 |
+
[attr.alt]="isPlayingVideo ? 'Pause pronunciation' : 'Play pronunciation'"
|
| 63 |
+
[attr.aria-label]="isPlayingVideo ? 'Pause pronunciation' : 'Play pronunciation'"
|
| 64 |
+
[attr.aria-pressed]="isPlayingVideo"
|
| 65 |
+
role="button"
|
| 66 |
+
tabindex="0"
|
| 67 |
+
(click)="toggleVideoPlay()"
|
| 68 |
+
(keydown.enter)="toggleVideoPlay()"
|
| 69 |
+
(keydown.space)="toggleVideoPlay(); $event.preventDefault()" />
|
| 70 |
+
|
| 71 |
+
<!-- Record circle -->
|
| 72 |
+
<button class="rec-circle"
|
| 73 |
+
[class.recording]="isRecording"
|
| 74 |
+
(mousedown)="startRecording()"
|
| 75 |
+
(mouseup)="stopRecording()"
|
| 76 |
+
(mouseleave)="stopRecording()"
|
| 77 |
+
(touchstart)="startRecording($event)"
|
| 78 |
+
(touchend)="stopRecording($event)"
|
| 79 |
+
(touchcancel)="stopRecording($event)">
|
| 80 |
+
<div class="rec-inner">
|
| 81 |
+
<div class="mic">🎤</div>
|
| 82 |
+
<div class="rec-text">REC</div>
|
| 83 |
+
</div>
|
| 84 |
+
</button>
|
| 85 |
+
</div>
|
| 86 |
+
</div>
|
| 87 |
+
</div>
|
| 88 |
+
|
| 89 |
+
<!-- RIGHT: Feedback panel -->
|
| 90 |
+
<div class="pp-right">
|
| 91 |
+
|
| 92 |
+
<!-- needle binding changed to use isOscillating -->
|
| 93 |
+
<div class="gauge-wrapper">
|
| 94 |
+
<div class="gauge">
|
| 95 |
+
<div class="gauge-arc"></div>
|
| 96 |
+
<div class="needle" [class.oscillate]="isOscillating" [style.--angle]="needleAngle + 'deg'"></div>
|
| 97 |
+
</div>
|
| 98 |
+
|
| 99 |
+
<div class="mic-badge">
|
| 100 |
+
<span class="score-span">{{score}}%</span>
|
| 101 |
+
</div>
|
| 102 |
+
</div>
|
| 103 |
+
|
| 104 |
+
<!--<div class="nav-row">
|
| 105 |
+
<button class="nav-btn" (click)="prev()" [disabled]="index === 0" aria-label="Previous">
|
| 106 |
+
<span class="nav-icon">‹</span>
|
| 107 |
+
</button>
|
| 108 |
+
|
| 109 |
+
<div class="nav-center">
|
| 110 |
+
<div class="nav-letter">{{ current.letter }}</div>
|
| 111 |
+
</div>
|
| 112 |
+
|
| 113 |
+
<button class="nav-btn" (click)="next()" [disabled]="index === items.length - 1" aria-label="Next">
|
| 114 |
+
<span class="nav-icon">›</span>
|
| 115 |
+
</button>
|
| 116 |
+
</div>-->
|
| 117 |
+
|
| 118 |
+
<div class="container">
|
| 119 |
+
<button class="arrow left" (click)="prev()" [disabled]="index === 0">‹</button>
|
| 120 |
+
<span class="center-text">{{ current.letter }}</span>
|
| 121 |
+
<button class="arrow right" (click)="next()" [disabled]="index === items.length - 1">›</button>
|
| 122 |
+
</div>
|
| 123 |
+
|
| 124 |
+
</div>
|
| 125 |
+
|
| 126 |
+
</div>
|
| 127 |
+
|
| 128 |
+
</div>
|
| 129 |
+
<button aria-label="Close" class="user-guide-close-icon" (click)="closePopup()">×</button>
|
src/app/pronunciationvideo/pronunciationvideo.component.ts
ADDED
|
@@ -0,0 +1,911 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Component, ElementRef, Inject, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
| 2 |
+
import { HttpClient } from '@angular/common/http';
|
| 3 |
+
import { finalize } from 'rxjs/operators';
|
| 4 |
+
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
| 5 |
+
import { ChangeDetectorRef } from '@angular/core';
|
| 6 |
+
|
| 7 |
+
interface PracticeItem {
|
| 8 |
+
letter: string;
|
| 9 |
+
word: string;
|
| 10 |
+
phonetics: string;
|
| 11 |
+
imgSrc: string;
|
| 12 |
+
audioSrc: string;
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
@Component({
|
| 16 |
+
selector: 'app-pronunciationvideo',
|
| 17 |
+
templateUrl: './pronunciationvideo.component.html',
|
| 18 |
+
styleUrls: ['./pronunciationvideo.component.css']
|
| 19 |
+
})
|
| 20 |
+
export class PronunciationVideoComponent implements OnInit, OnDestroy {
|
| 21 |
+
@ViewChild('videoEl') videoElRef?: ElementRef<HTMLVideoElement>;
|
| 22 |
+
|
| 23 |
+
// toggle & src for teacher video
|
| 24 |
+
showVideo = false;
|
| 25 |
+
videoSrc = '';
|
| 26 |
+
|
| 27 |
+
// track play/pause state for the toggle button
|
| 28 |
+
isPlayingVideo = false;
|
| 29 |
+
|
| 30 |
+
// use asset image paths (replace with your actual asset filenames)
|
| 31 |
+
playIconDataUrl = '';
|
| 32 |
+
pauseIconDataUrl = '';
|
| 33 |
+
|
| 34 |
+
// ---------------------------
|
| 35 |
+
// CONFIG
|
| 36 |
+
// ---------------------------
|
| 37 |
+
// Change this to your server domain
|
| 38 |
+
|
| 39 |
+
private API_BASE = location.hostname.endsWith('hf.space')
|
| 40 |
+
? 'https://pykara-py-learn-backend.hf.space'
|
| 41 |
+
: 'http://localhost:5000';
|
| 42 |
+
|
| 43 |
+
private readonly SCORE_ENDPOINT = `${this.API_BASE}/pronvideo/score`;
|
| 44 |
+
|
| 45 |
+
// Prefer a mime type supported by the browser
|
| 46 |
+
private readonly preferredMimeTypes = [
|
| 47 |
+
'audio/webm;codecs=opus',
|
| 48 |
+
'audio/webm',
|
| 49 |
+
'audio/ogg;codecs=opus',
|
| 50 |
+
'audio/ogg'
|
| 51 |
+
];
|
| 52 |
+
|
| 53 |
+
// ---------------------------
|
| 54 |
+
// DATA
|
| 55 |
+
// ---------------------------
|
| 56 |
+
items: PracticeItem[] = [
|
| 57 |
+
{
|
| 58 |
+
letter: 'A',
|
| 59 |
+
word: 'Apple',
|
| 60 |
+
phonetics: '/ˈæpəl/',
|
| 61 |
+
imgSrc: 'assets/images/pron/letter-a.png',
|
| 62 |
+
audioSrc: 'assets/pronvideo/audio/apple.mp3'
|
| 63 |
+
|
| 64 |
+
},
|
| 65 |
+
{
|
| 66 |
+
letter: 'B',
|
| 67 |
+
word: 'Ball',
|
| 68 |
+
phonetics: '/bɔːl/',
|
| 69 |
+
imgSrc: 'assets/images/pron/letter-b.png',
|
| 70 |
+
audioSrc: 'assets/pronvideo/audio/ball.mp3'
|
| 71 |
+
|
| 72 |
+
},
|
| 73 |
+
{
|
| 74 |
+
letter: 'C',
|
| 75 |
+
word: 'Cat',
|
| 76 |
+
phonetics: '/kæt/',
|
| 77 |
+
imgSrc: 'assets/images/pron/letter-c.png',
|
| 78 |
+
audioSrc: 'assets/pronvideo/audio/cat.mp3'
|
| 79 |
+
|
| 80 |
+
},
|
| 81 |
+
{
|
| 82 |
+
letter: 'D',
|
| 83 |
+
word: 'Dog',
|
| 84 |
+
phonetics: '/dɒɡ/',
|
| 85 |
+
imgSrc: 'assets/images/pron/letter-d.png',
|
| 86 |
+
audioSrc: 'assets/pronvideo/audio/dog.mp3'
|
| 87 |
+
|
| 88 |
+
},
|
| 89 |
+
{
|
| 90 |
+
letter: 'E',
|
| 91 |
+
word: 'Egg',
|
| 92 |
+
phonetics: '/eɡ/',
|
| 93 |
+
imgSrc: 'assets/images/pron/letter-e.png',
|
| 94 |
+
audioSrc: 'assets/pronvideo/audio/egg.mp3'
|
| 95 |
+
|
| 96 |
+
},
|
| 97 |
+
{
|
| 98 |
+
letter: 'F',
|
| 99 |
+
word: 'Fish',
|
| 100 |
+
phonetics: '/fɪʃ/',
|
| 101 |
+
imgSrc: 'assets/images/pron/letter-f.png',
|
| 102 |
+
audioSrc: 'assets/pronvideo/audio/fish.mp3'
|
| 103 |
+
|
| 104 |
+
},
|
| 105 |
+
{
|
| 106 |
+
letter: 'G',
|
| 107 |
+
word: 'Grapes',
|
| 108 |
+
phonetics: '/ɡreɪps/',
|
| 109 |
+
imgSrc: 'assets/images/pron/letter-g.png',
|
| 110 |
+
audioSrc: 'assets/pronvideo/audio/grapes.mp3'
|
| 111 |
+
|
| 112 |
+
},
|
| 113 |
+
{
|
| 114 |
+
letter: 'H',
|
| 115 |
+
word: 'Hat',
|
| 116 |
+
phonetics: '/hæt/',
|
| 117 |
+
imgSrc: 'assets/images/pron/letter-h.png',
|
| 118 |
+
audioSrc: 'assets/pronvideo/audio/hat.mp3'
|
| 119 |
+
|
| 120 |
+
},
|
| 121 |
+
{
|
| 122 |
+
letter: 'I',
|
| 123 |
+
word: 'Ice cream',
|
| 124 |
+
phonetics: '/ˈaɪs ˌkriːm/',
|
| 125 |
+
imgSrc: 'assets/images/pron/letter-i.png',
|
| 126 |
+
audioSrc: 'assets/pronvideo/audio/icecream.mp3'
|
| 127 |
+
|
| 128 |
+
},
|
| 129 |
+
{
|
| 130 |
+
letter: 'J',
|
| 131 |
+
word: 'Jar',
|
| 132 |
+
phonetics: '/dʒɑːr/',
|
| 133 |
+
imgSrc: 'assets/images/pron/letter-j.png',
|
| 134 |
+
audioSrc: 'assets/pronvideo/audio/jar.mp3'
|
| 135 |
+
|
| 136 |
+
},
|
| 137 |
+
{
|
| 138 |
+
letter: 'K',
|
| 139 |
+
word: 'Kite',
|
| 140 |
+
phonetics: '/kaɪt/',
|
| 141 |
+
imgSrc: 'assets/images/pron/letter-k.png',
|
| 142 |
+
audioSrc: 'assets/pronvideo/audio/kite.mp3'
|
| 143 |
+
|
| 144 |
+
},
|
| 145 |
+
{
|
| 146 |
+
letter: 'L',
|
| 147 |
+
word: 'Lion',
|
| 148 |
+
phonetics: '/ˈlaɪən/',
|
| 149 |
+
imgSrc: 'assets/images/pron/letter-l.png',
|
| 150 |
+
audioSrc: 'assets/pronvideo/audio/lion.mp3'
|
| 151 |
+
|
| 152 |
+
},
|
| 153 |
+
{
|
| 154 |
+
letter: 'M',
|
| 155 |
+
word: 'Moon',
|
| 156 |
+
phonetics: '/muːn/',
|
| 157 |
+
imgSrc: 'assets/images/pron/letter-m.png',
|
| 158 |
+
audioSrc: 'assets/pronvideo/audio/moon.mp3'
|
| 159 |
+
|
| 160 |
+
},
|
| 161 |
+
{
|
| 162 |
+
letter: 'N',
|
| 163 |
+
word: 'Nest',
|
| 164 |
+
phonetics: '/nest/',
|
| 165 |
+
imgSrc: 'assets/images/pron/letter-n.png',
|
| 166 |
+
audioSrc: 'assets/pronvideo/audio/nest.mp3'
|
| 167 |
+
|
| 168 |
+
},
|
| 169 |
+
{
|
| 170 |
+
letter: 'O',
|
| 171 |
+
word: 'Orange',
|
| 172 |
+
phonetics: '/ˈɒrɪndʒ/',
|
| 173 |
+
imgSrc: 'assets/images/pron/letter-o.png',
|
| 174 |
+
audioSrc: 'assets/pronvideo/audio/orange.mp3'
|
| 175 |
+
|
| 176 |
+
},
|
| 177 |
+
{
|
| 178 |
+
letter: 'P',
|
| 179 |
+
word: 'Pig',
|
| 180 |
+
phonetics: '/pɪɡ/',
|
| 181 |
+
imgSrc: 'assets/images/pron/letter-p.png',
|
| 182 |
+
audioSrc: 'assets/pronvideo/audio/pig.mp3'
|
| 183 |
+
|
| 184 |
+
},
|
| 185 |
+
{
|
| 186 |
+
letter: 'Q',
|
| 187 |
+
word: 'Queen',
|
| 188 |
+
phonetics: '/kwiːn/',
|
| 189 |
+
imgSrc: 'assets/images/pron/letter-q.png',
|
| 190 |
+
audioSrc: 'assets/pronvideo/audio/queen.mp3'
|
| 191 |
+
|
| 192 |
+
},
|
| 193 |
+
{
|
| 194 |
+
letter: 'R',
|
| 195 |
+
word: 'Rabbit',
|
| 196 |
+
phonetics: '/ˈræbɪt/',
|
| 197 |
+
imgSrc: 'assets/images/pron/letter-r.png',
|
| 198 |
+
audioSrc: 'assets/pronvideo/audio/rabbit.mp3'
|
| 199 |
+
|
| 200 |
+
},
|
| 201 |
+
{
|
| 202 |
+
letter: 'S',
|
| 203 |
+
word: 'Sun',
|
| 204 |
+
phonetics: '/sʌn/',
|
| 205 |
+
imgSrc: 'assets/images/pron/letter-s.png',
|
| 206 |
+
audioSrc: 'assets/pronvideo/audio/sun.mp3'
|
| 207 |
+
|
| 208 |
+
},
|
| 209 |
+
{
|
| 210 |
+
letter: 'T',
|
| 211 |
+
word: 'Tree',
|
| 212 |
+
phonetics: '/triː/',
|
| 213 |
+
imgSrc: 'assets/images/pron/letter-t.png',
|
| 214 |
+
audioSrc: 'assets/pronvideo/audio/tree.mp3'
|
| 215 |
+
|
| 216 |
+
},
|
| 217 |
+
{
|
| 218 |
+
letter: 'U',
|
| 219 |
+
word: 'Umbrella',
|
| 220 |
+
phonetics: '/ʌmˈbrelə/',
|
| 221 |
+
imgSrc: 'assets/images/pron/letter-u.png',
|
| 222 |
+
audioSrc: 'assets/pronvideo/audio/umbrella.mp3'
|
| 223 |
+
|
| 224 |
+
},
|
| 225 |
+
{
|
| 226 |
+
letter: 'V',
|
| 227 |
+
word: 'Van',
|
| 228 |
+
phonetics: '/væn/',
|
| 229 |
+
imgSrc: 'assets/images/pron/letter-v.png',
|
| 230 |
+
audioSrc: 'assets/pronvideo/audio/van.mp3'
|
| 231 |
+
|
| 232 |
+
},
|
| 233 |
+
{
|
| 234 |
+
letter: 'W',
|
| 235 |
+
word: 'Watch',
|
| 236 |
+
phonetics: '/wɒtʃ/',
|
| 237 |
+
imgSrc: 'assets/images/pron/letter-w.png',
|
| 238 |
+
audioSrc: 'assets/pronvideo/audio/watch.mp3'
|
| 239 |
+
|
| 240 |
+
},
|
| 241 |
+
{
|
| 242 |
+
letter: 'X',
|
| 243 |
+
word: 'Xylophone',
|
| 244 |
+
phonetics: '/ˈzaɪləfəʊn/',
|
| 245 |
+
imgSrc: 'assets/images/pron/letter-x.png',
|
| 246 |
+
audioSrc: 'assets/pronvideo/audio/xylophone.mp3'
|
| 247 |
+
|
| 248 |
+
},
|
| 249 |
+
{
|
| 250 |
+
letter: 'Y',
|
| 251 |
+
word: 'Yarn',
|
| 252 |
+
phonetics: '/jɑːn/',
|
| 253 |
+
imgSrc: 'assets/images/pron/letter-y.png',
|
| 254 |
+
audioSrc: 'assets/pronvideo/audio/yarn.mp3'
|
| 255 |
+
|
| 256 |
+
},
|
| 257 |
+
{
|
| 258 |
+
letter: 'Z',
|
| 259 |
+
word: 'Zebra',
|
| 260 |
+
phonetics: '/ˈzebrə/',
|
| 261 |
+
imgSrc: 'assets/images/pron/letter-z.png',
|
| 262 |
+
audioSrc: 'assets/pronvideo/audio/zebra.mp3'
|
| 263 |
+
|
| 264 |
+
}
|
| 265 |
+
];
|
| 266 |
+
|
| 267 |
+
|
| 268 |
+
index = 0;
|
| 269 |
+
|
| 270 |
+
get current(): PracticeItem {
|
| 271 |
+
return this.items[this.index];
|
| 272 |
+
}
|
| 273 |
+
|
| 274 |
+
// ---------------------------
|
| 275 |
+
// AUDIO (word)
|
| 276 |
+
// ---------------------------
|
| 277 |
+
private wordAudio = new Audio();
|
| 278 |
+
|
| 279 |
+
// ---------------------------
|
| 280 |
+
// RECORDING STATE
|
| 281 |
+
// ---------------------------
|
| 282 |
+
isRecording = false;
|
| 283 |
+
isScoring = false;
|
| 284 |
+
|
| 285 |
+
// NEW: flag to trigger needle oscillation after release and while waiting for score
|
| 286 |
+
isOscillating = false;
|
| 287 |
+
|
| 288 |
+
private mediaStream?: MediaStream;
|
| 289 |
+
private mediaRecorder?: MediaRecorder;
|
| 290 |
+
private chunks: BlobPart[] = [];
|
| 291 |
+
private currentMimeType = 'audio/webm';
|
| 292 |
+
|
| 293 |
+
recordedAudioUrl: string | null = null;
|
| 294 |
+
lastRecordedBlob: Blob | null = null;
|
| 295 |
+
|
| 296 |
+
// pending gesture play support (to satisfy autoplay policies)
|
| 297 |
+
private pendingVideoUrl: string | null = null;
|
| 298 |
+
private pendingGestureListener?: (e: Event) => void;
|
| 299 |
+
|
| 300 |
+
// ---------------------------
|
| 301 |
+
// RESULT UI
|
| 302 |
+
// ---------------------------
|
| 303 |
+
showResult = false;
|
| 304 |
+
score = 0;
|
| 305 |
+
stars = 0;
|
| 306 |
+
feedbackLines: string[] = [];
|
| 307 |
+
feedbackHint: string = '';
|
| 308 |
+
videoUrl: string = '';
|
| 309 |
+
|
| 310 |
+
// ---------------------------
|
| 311 |
+
// LIFECYCLE
|
| 312 |
+
// ---------------------------
|
| 313 |
+
constructor(private http: HttpClient, public dialogRef: MatDialogRef<PronunciationVideoComponent>,
|
| 314 |
+
@Inject(MAT_DIALOG_DATA) public data: any, private cdr: ChangeDetectorRef) { }
|
| 315 |
+
|
| 316 |
+
ngOnInit(): void {
|
| 317 |
+
this.resetResult();
|
| 318 |
+
this.setupBestMimeType();
|
| 319 |
+
|
| 320 |
+
// Use images from assets instead of inline SVG data URIs.
|
| 321 |
+
// Ensure the files exist at these paths or update the paths to match your project.
|
| 322 |
+
this.playIconDataUrl = 'assets/pronvideo/play.png';
|
| 323 |
+
this.pauseIconDataUrl = 'assets/pronvideo/pause.png';
|
| 324 |
+
}
|
| 325 |
+
|
| 326 |
+
ngOnDestroy(): void {
|
| 327 |
+
this.cleanupRecordingUrl();
|
| 328 |
+
this.stopTracks();
|
| 329 |
+
this.safeStopRecorder();
|
| 330 |
+
this.wordAudio.pause();
|
| 331 |
+
this.wordAudio.src = '';
|
| 332 |
+
// ensure video cleaned up
|
| 333 |
+
this.resetVideo();
|
| 334 |
+
// remove any pending gesture listener to avoid leaks
|
| 335 |
+
if (this.pendingGestureListener) {
|
| 336 |
+
try { document.body.removeEventListener('click', this.pendingGestureListener, true); } catch { }
|
| 337 |
+
this.pendingGestureListener = undefined;
|
| 338 |
+
this.pendingVideoUrl = null;
|
| 339 |
+
}
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
// ---------------------------
|
| 343 |
+
// RECORD & HOLD - EVENTS
|
| 344 |
+
// ---------------------------
|
| 345 |
+
async startRecording(evt?: Event): Promise<void> {
|
| 346 |
+
evt?.preventDefault();
|
| 347 |
+
|
| 348 |
+
if (this.isRecording || this.isScoring) return;
|
| 349 |
+
|
| 350 |
+
this.resetResult();
|
| 351 |
+
this.cleanupRecordingUrl();
|
| 352 |
+
this.lastRecordedBlob = null;
|
| 353 |
+
|
| 354 |
+
try {
|
| 355 |
+
this.mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
| 356 |
+
|
| 357 |
+
const options: MediaRecorderOptions = {};
|
| 358 |
+
if (this.currentMimeType) {
|
| 359 |
+
options.mimeType = this.currentMimeType;
|
| 360 |
+
}
|
| 361 |
+
|
| 362 |
+
this.mediaRecorder = new MediaRecorder(this.mediaStream, options);
|
| 363 |
+
|
| 364 |
+
this.chunks = [];
|
| 365 |
+
|
| 366 |
+
this.mediaRecorder.ondataavailable = (e: BlobEvent) => {
|
| 367 |
+
if (e.data && e.data.size > 0) this.chunks.push(e.data);
|
| 368 |
+
};
|
| 369 |
+
|
| 370 |
+
this.mediaRecorder.onstop = () => {
|
| 371 |
+
this.onRecordingStopped();
|
| 372 |
+
};
|
| 373 |
+
|
| 374 |
+
this.mediaRecorder.start();
|
| 375 |
+
this.isRecording = true;
|
| 376 |
+
|
| 377 |
+
} catch {
|
| 378 |
+
this.isRecording = false;
|
| 379 |
+
this.stopTracks();
|
| 380 |
+
}
|
| 381 |
+
}
|
| 382 |
+
|
| 383 |
+
stopRecording(evt?: Event): void {
|
| 384 |
+
evt?.preventDefault();
|
| 385 |
+
|
| 386 |
+
if (!this.isRecording) return;
|
| 387 |
+
|
| 388 |
+
// End recording state
|
| 389 |
+
this.isRecording = false;
|
| 390 |
+
|
| 391 |
+
// Start oscillation immediately when user releases the record button:
|
| 392 |
+
// visual feedback that we are waiting for the backend scoring result.
|
| 393 |
+
this.isOscillating = true;
|
| 394 |
+
|
| 395 |
+
// Stop recorder safely
|
| 396 |
+
this.safeStopRecorder();
|
| 397 |
+
|
| 398 |
+
// Stop mic tracks
|
| 399 |
+
this.stopTracks();
|
| 400 |
+
}
|
| 401 |
+
|
| 402 |
+
private safeStopRecorder(): void {
|
| 403 |
+
try {
|
| 404 |
+
if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {
|
| 405 |
+
this.mediaRecorder.stop();
|
| 406 |
+
}
|
| 407 |
+
} catch {
|
| 408 |
+
// ignore
|
| 409 |
+
}
|
| 410 |
+
}
|
| 411 |
+
|
| 412 |
+
private onRecordingStopped(): void {
|
| 413 |
+
try {
|
| 414 |
+
const blob = new Blob(this.chunks, { type: this.currentMimeType || 'audio/webm' });
|
| 415 |
+
this.lastRecordedBlob = blob;
|
| 416 |
+
this.recordedAudioUrl = URL.createObjectURL(blob);
|
| 417 |
+
|
| 418 |
+
// Send to backend for scoring
|
| 419 |
+
this.sendForScoring(blob, this.current.word);
|
| 420 |
+
} catch {
|
| 421 |
+
// If blob creation fails, stop oscillation and keep score hidden
|
| 422 |
+
this.isOscillating = false;
|
| 423 |
+
this.showResult = false;
|
| 424 |
+
} finally {
|
| 425 |
+
this.chunks = [];
|
| 426 |
+
}
|
| 427 |
+
}
|
| 428 |
+
|
| 429 |
+
// Optional: play student recording from UI button
|
| 430 |
+
playUserRecording(): void {
|
| 431 |
+
if (!this.recordedAudioUrl) return;
|
| 432 |
+
try {
|
| 433 |
+
const a = new Audio(this.recordedAudioUrl);
|
| 434 |
+
a.play().catch(() => { });
|
| 435 |
+
} catch {
|
| 436 |
+
// ignore
|
| 437 |
+
}
|
| 438 |
+
}
|
| 439 |
+
|
| 440 |
+
// ---------------------------
|
| 441 |
+
// BACKEND SCORING
|
| 442 |
+
// ---------------------------
|
| 443 |
+
private sendForScoring(blob: Blob, expectedWord: string): void {
|
| 444 |
+
if (!blob || !expectedWord) {
|
| 445 |
+
// nothing to do -> stop oscillation
|
| 446 |
+
this.isOscillating = false;
|
| 447 |
+
return;
|
| 448 |
+
}
|
| 449 |
+
|
| 450 |
+
const fd = new FormData();
|
| 451 |
+
|
| 452 |
+
// Give a reasonable filename extension
|
| 453 |
+
const ext = this.currentMimeType.includes('ogg') ? 'ogg' : 'webm';
|
| 454 |
+
fd.append('audio', blob, `student.${ext}`);
|
| 455 |
+
fd.append('word', expectedWord);
|
| 456 |
+
|
| 457 |
+
// show scoring state
|
| 458 |
+
this.isScoring = true;
|
| 459 |
+
|
| 460 |
+
this.http.post<{ score: number, hint: string, videoUrl: string }>(this.SCORE_ENDPOINT, fd)
|
| 461 |
+
.pipe(finalize(() => {
|
| 462 |
+
|
| 463 |
+
// stop scoring state and oscillation once HTTP completes (success or error)
|
| 464 |
+
this.isScoring = false;
|
| 465 |
+
this.isOscillating = false;
|
| 466 |
+
this.cdr.detectChanges();
|
| 467 |
+
}))
|
| 468 |
+
.subscribe({
|
| 469 |
+
next: (res) => {
|
| 470 |
+
const s = this.normalizeScore(res?.score);
|
| 471 |
+
this.score = s;
|
| 472 |
+
this.feedbackHint = res.hint || '';
|
| 473 |
+
this.videoUrl = res.videoUrl || '';
|
| 474 |
+
this.stars = this.mapStars(s);
|
| 475 |
+
|
| 476 |
+
this.feedbackLines = this.buildFeedbackFromScore(s);
|
| 477 |
+
|
| 478 |
+
this.showResult = true;
|
| 479 |
+
//this.cdr.detectChanges();
|
| 480 |
+
|
| 481 |
+
// Try to play feedback video; if autoplay blocked we register a gesture fallback.
|
| 482 |
+
if (this.videoUrl) {
|
| 483 |
+
this.tryPlayFeedbackVideo(s, this.videoUrl);
|
| 484 |
+
}
|
| 485 |
+
},
|
| 486 |
+
error: () => {
|
| 487 |
+
this.score = 0;
|
| 488 |
+
this.stars = 1;
|
| 489 |
+
this.feedbackLines = this.buildFeedbackFromScore(0);
|
| 490 |
+
this.showResult = true;
|
| 491 |
+
this.cdr.detectChanges();
|
| 492 |
+
}
|
| 493 |
+
});
|
| 494 |
+
}
|
| 495 |
+
|
| 496 |
+
private normalizeScore(val: any): number {
|
| 497 |
+
const n = Number(val);
|
| 498 |
+
if (Number.isNaN(n)) return 0;
|
| 499 |
+
if (n < 0) return 0;
|
| 500 |
+
if (n > 100) return 100;
|
| 501 |
+
return Math.round(n);
|
| 502 |
+
}
|
| 503 |
+
|
| 504 |
+
// ---------------------------
|
| 505 |
+
// RESULT HELPERS (frontend-only)
|
| 506 |
+
// ---------------------------
|
| 507 |
+
private resetResult(): void {
|
| 508 |
+
this.showResult = false;
|
| 509 |
+
this.score = 0;
|
| 510 |
+
this.stars = 0;
|
| 511 |
+
this.feedbackLines = [];
|
| 512 |
+
this.isPlayingVideo = false;
|
| 513 |
+
this.isOscillating = false;
|
| 514 |
+
}
|
| 515 |
+
|
| 516 |
+
/**
|
| 517 |
+
* Reset only the speakometer/score UI without touching recording state or video playback flags.
|
| 518 |
+
*/
|
| 519 |
+
private resetSpeakometer(): void {
|
| 520 |
+
this.score = 0;
|
| 521 |
+
this.stars = 0;
|
| 522 |
+
this.feedbackLines = [];
|
| 523 |
+
this.feedbackHint = '';
|
| 524 |
+
this.showResult = false;
|
| 525 |
+
this.isOscillating = false;
|
| 526 |
+
}
|
| 527 |
+
|
| 528 |
+
private mapStars(s: number): number {
|
| 529 |
+
if (s >= 90) return 5;
|
| 530 |
+
if (s >= 80) return 4;
|
| 531 |
+
if (s >= 70) return 3;
|
| 532 |
+
if (s >= 60) return 2;
|
| 533 |
+
return 1;
|
| 534 |
+
}
|
| 535 |
+
|
| 536 |
+
private buildFeedbackFromScore(s: number): string[] {
|
| 537 |
+
if (s >= 90) {
|
| 538 |
+
return [
|
| 539 |
+
'Excellent pronunciation.',
|
| 540 |
+
'Very clear vowel and ending sound.',
|
| 541 |
+
'Keep the same speed.'
|
| 542 |
+
];
|
| 543 |
+
}
|
| 544 |
+
if (s >= 80) {
|
| 545 |
+
return [
|
| 546 |
+
'Very good attempt.',
|
| 547 |
+
'Slightly improve the main vowel.',
|
| 548 |
+
'Ending sound is almost perfect.'
|
| 549 |
+
];
|
| 550 |
+
}
|
| 551 |
+
if (s >= 70) {
|
| 552 |
+
return [
|
| 553 |
+
'Good try.',
|
| 554 |
+
'Listen once more and repeat slowly.',
|
| 555 |
+
'Focus on the first sound.'
|
| 556 |
+
];
|
| 557 |
+
}
|
| 558 |
+
if (s >= 50) {
|
| 559 |
+
return [
|
| 560 |
+
'Nice effort.',
|
| 561 |
+
'Try a slower pronunciation.',
|
| 562 |
+
'Record again after listening.'
|
| 563 |
+
];
|
| 564 |
+
}
|
| 565 |
+
return [
|
| 566 |
+
'Try again.',
|
| 567 |
+
'Listen to the model carefully.',
|
| 568 |
+
'Speak clearly and record once more.'
|
| 569 |
+
];
|
| 570 |
+
}
|
| 571 |
+
|
| 572 |
+
// ---------------------------
|
| 573 |
+
// MIME TYPE SELECTION
|
| 574 |
+
// ---------------------------
|
| 575 |
+
private setupBestMimeType(): void {
|
| 576 |
+
if (!(window as any).MediaRecorder) {
|
| 577 |
+
this.currentMimeType = 'audio/webm';
|
| 578 |
+
return;
|
| 579 |
+
}
|
| 580 |
+
|
| 581 |
+
for (const t of this.preferredMimeTypes) {
|
| 582 |
+
try {
|
| 583 |
+
if ((window as any).MediaRecorder.isTypeSupported(t)) {
|
| 584 |
+
this.currentMimeType = t;
|
| 585 |
+
return;
|
| 586 |
+
}
|
| 587 |
+
} catch {
|
| 588 |
+
// ignore
|
| 589 |
+
}
|
| 590 |
+
}
|
| 591 |
+
|
| 592 |
+
this.currentMimeType = 'audio/webm';
|
| 593 |
+
}
|
| 594 |
+
|
| 595 |
+
// ---------------------------
|
| 596 |
+
// CLEANUP
|
| 597 |
+
// ---------------------------
|
| 598 |
+
private stopTracks(): void {
|
| 599 |
+
try {
|
| 600 |
+
this.mediaStream?.getTracks().forEach(t => t.stop());
|
| 601 |
+
} catch {
|
| 602 |
+
// ignore
|
| 603 |
+
} finally {
|
| 604 |
+
this.mediaStream = undefined;
|
| 605 |
+
}
|
| 606 |
+
}
|
| 607 |
+
|
| 608 |
+
private cleanupRecordingUrl(): void {
|
| 609 |
+
if (this.recordedAudioUrl) {
|
| 610 |
+
try {
|
| 611 |
+
URL.revokeObjectURL(this.recordedAudioUrl);
|
| 612 |
+
} catch {
|
| 613 |
+
// ignore
|
| 614 |
+
}
|
| 615 |
+
this.recordedAudioUrl = null;
|
| 616 |
+
}
|
| 617 |
+
}
|
| 618 |
+
|
| 619 |
+
// ---------------------------
|
| 620 |
+
// NAVIGATION
|
| 621 |
+
// ---------------------------
|
| 622 |
+
prev(): void {
|
| 623 |
+
if (this.index === 0) return;
|
| 624 |
+
this.index--;
|
| 625 |
+
this.resetExerciseState();
|
| 626 |
+
}
|
| 627 |
+
|
| 628 |
+
next(): void {
|
| 629 |
+
if (this.index >= this.items.length - 1) return;
|
| 630 |
+
this.index++;
|
| 631 |
+
this.resetExerciseState();
|
| 632 |
+
}
|
| 633 |
+
|
| 634 |
+
goTo(i: number): void {
|
| 635 |
+
if (i < 0 || i >= this.items.length) return;
|
| 636 |
+
this.index = i;
|
| 637 |
+
this.resetExerciseState();
|
| 638 |
+
}
|
| 639 |
+
|
| 640 |
+
private resetExerciseState(): void {
|
| 641 |
+
// reset UI result data
|
| 642 |
+
this.resetResult();
|
| 643 |
+
this.cleanupRecordingUrl();
|
| 644 |
+
this.lastRecordedBlob = null;
|
| 645 |
+
|
| 646 |
+
// stop any recording/scoring
|
| 647 |
+
this.isRecording = false;
|
| 648 |
+
this.isScoring = false;
|
| 649 |
+
|
| 650 |
+
// stop media tracks and recorder
|
| 651 |
+
this.stopTracks();
|
| 652 |
+
this.safeStopRecorder();
|
| 653 |
+
|
| 654 |
+
// STOP and CLEAR any playing video so next exercise starts clean
|
| 655 |
+
this.resetVideo();
|
| 656 |
+
}
|
| 657 |
+
|
| 658 |
+
// new helper: stop & clear video element + reset related flags
|
| 659 |
+
private resetVideo(): void {
|
| 660 |
+
try {
|
| 661 |
+
const v = this.videoElRef?.nativeElement;
|
| 662 |
+
if (v) {
|
| 663 |
+
try { v.pause(); } catch { /* ignore */ }
|
| 664 |
+
try { v.currentTime = 0; } catch { /* ignore */ }
|
| 665 |
+
// remove src so browser releases resource
|
| 666 |
+
try { v.removeAttribute('src'); } catch { /* ignore */ }
|
| 667 |
+
try { v.load(); } catch { /* ignore */ }
|
| 668 |
+
}
|
| 669 |
+
} catch {
|
| 670 |
+
// ignore any DOM errors
|
| 671 |
+
} finally {
|
| 672 |
+
this.showVideo = false;
|
| 673 |
+
this.videoSrc = '';
|
| 674 |
+
this.isPlayingVideo = false;
|
| 675 |
+
}
|
| 676 |
+
}
|
| 677 |
+
|
| 678 |
+
// ---------------------------
|
| 679 |
+
// WORD AUDIO
|
| 680 |
+
// ---------------------------
|
| 681 |
+
playWordAudio(): void {
|
| 682 |
+
// reset speakometer when starting model audio playback
|
| 683 |
+
this.resetSpeakometer();
|
| 684 |
+
|
| 685 |
+
const src = this.current.audioSrc || this.getAudioSrcFromWord(this.current.word);
|
| 686 |
+
if (!src) return;
|
| 687 |
+
|
| 688 |
+
try {
|
| 689 |
+
this.wordAudio.pause();
|
| 690 |
+
this.wordAudio.currentTime = 0;
|
| 691 |
+
this.wordAudio.src = src;
|
| 692 |
+
this.wordAudio.play().catch(() => { });
|
| 693 |
+
} catch {
|
| 694 |
+
// ignore
|
| 695 |
+
}
|
| 696 |
+
}
|
| 697 |
+
|
| 698 |
+
private getAudioSrcFromWord(word: string): string {
|
| 699 |
+
if (!word) return '';
|
| 700 |
+
const fileName = word.trim().toLowerCase().replace(/\s+/g, '-');
|
| 701 |
+
return `assets/pronvideo/audio/${fileName}.mp3`;
|
| 702 |
+
}
|
| 703 |
+
|
| 704 |
+
get needleAngle(): number {
|
| 705 |
+
const val = Math.max(0, Math.min(100, Number(this.score ?? 0)));
|
| 706 |
+
return -90 + (val * 1.8);
|
| 707 |
+
}
|
| 708 |
+
|
| 709 |
+
closePopup(): void {
|
| 710 |
+
this.dialogRef.close();
|
| 711 |
+
}
|
| 712 |
+
|
| 713 |
+
// ---------------------------
|
| 714 |
+
// TEACHER VIDEO
|
| 715 |
+
// ---------------------------
|
| 716 |
+
playWordVideo(): void {
|
| 717 |
+
// Reset speakometer when user requests the teacher video
|
| 718 |
+
this.resetSpeakometer();
|
| 719 |
+
|
| 720 |
+
// Build video path based on current.word (assets/videos/<word>.mp4)
|
| 721 |
+
const src = this.getVideoSrcFromWord(this.current.word);
|
| 722 |
+
if (!src) return;
|
| 723 |
+
|
| 724 |
+
this.showVideo = true;
|
| 725 |
+
this.videoSrc = src;
|
| 726 |
+
|
| 727 |
+
// Wait for template to render, then set and play video safely
|
| 728 |
+
setTimeout(() => {
|
| 729 |
+
try {
|
| 730 |
+
const v = this.videoElRef?.nativeElement;
|
| 731 |
+
if (v) {
|
| 732 |
+
// sync UI state to element events and reset speakometer when native play occurs
|
| 733 |
+
v.addEventListener('play', () => {
|
| 734 |
+
this.isPlayingVideo = true;
|
| 735 |
+
// keep resetting speakometer on native play to ensure gauge clears
|
| 736 |
+
this.resetSpeakometer();
|
| 737 |
+
});
|
| 738 |
+
v.addEventListener('pause', () => this.isPlayingVideo = false);
|
| 739 |
+
|
| 740 |
+
v.pause();
|
| 741 |
+
v.src = this.videoSrc;
|
| 742 |
+
v.load();
|
| 743 |
+
v.play().then(() => {
|
| 744 |
+
this.isPlayingVideo = true;
|
| 745 |
+
}).catch(() => {
|
| 746 |
+
// ignore autoplay errors; UI still shows the control
|
| 747 |
+
this.isPlayingVideo = !v.paused;
|
| 748 |
+
});
|
| 749 |
+
}
|
| 750 |
+
} catch {
|
| 751 |
+
// ignore
|
| 752 |
+
}
|
| 753 |
+
}, 0);
|
| 754 |
+
}
|
| 755 |
+
|
| 756 |
+
/**
|
| 757 |
+
* Toggles play/pause for the currently-displayed video.
|
| 758 |
+
*/
|
| 759 |
+
toggleVideoPlay(): void {
|
| 760 |
+
try {
|
| 761 |
+
if (!this.showVideo) {
|
| 762 |
+
this.playWordVideo();
|
| 763 |
+
return;
|
| 764 |
+
}
|
| 765 |
+
|
| 766 |
+
const v = this.videoElRef?.nativeElement;
|
| 767 |
+
if (!v) {
|
| 768 |
+
this.videoSrc = this.getVideoSrcFromWord(this.current.word);
|
| 769 |
+
this.showVideo = true;
|
| 770 |
+
return;
|
| 771 |
+
}
|
| 772 |
+
|
| 773 |
+
if (v.paused) {
|
| 774 |
+
// user is starting playback -> reset speakometer
|
| 775 |
+
this.resetSpeakometer();
|
| 776 |
+
|
| 777 |
+
v.play().then(() => {
|
| 778 |
+
this.isPlayingVideo = true;
|
| 779 |
+
}).catch(() => {
|
| 780 |
+
this.isPlayingVideo = !v.paused;
|
| 781 |
+
});
|
| 782 |
+
} else {
|
| 783 |
+
v.pause();
|
| 784 |
+
this.isPlayingVideo = false;
|
| 785 |
+
}
|
| 786 |
+
} catch {
|
| 787 |
+
// ignore
|
| 788 |
+
}
|
| 789 |
+
}
|
| 790 |
+
|
| 791 |
+
/**
|
| 792 |
+
* Attempts to play a feedback video returned by the backend in the same video element.
|
| 793 |
+
* If autoplay is blocked we register a one-time body click handler so the first user gesture starts playback.
|
| 794 |
+
*/
|
| 795 |
+
private tryPlayFeedbackVideo(score: number, videoUrl: string): void {
|
| 796 |
+
if (!videoUrl) return;
|
| 797 |
+
|
| 798 |
+
// ensure UI shows the video element
|
| 799 |
+
this.showVideo = true;
|
| 800 |
+
this.videoSrc = videoUrl;
|
| 801 |
+
|
| 802 |
+
setTimeout(() => {
|
| 803 |
+
try {
|
| 804 |
+
const v = this.videoElRef?.nativeElement;
|
| 805 |
+
if (!v) {
|
| 806 |
+
// element not yet available -> register gesture fallback
|
| 807 |
+
this.registerGestureForPendingVideo(videoUrl);
|
| 808 |
+
return;
|
| 809 |
+
}
|
| 810 |
+
|
| 811 |
+
try { v.pause(); } catch { /* ignore */ }
|
| 812 |
+
|
| 813 |
+
v.src = this.videoSrc;
|
| 814 |
+
v.load();
|
| 815 |
+
v.play().then(() => {
|
| 816 |
+
this.isPlayingVideo = true;
|
| 817 |
+
}).catch(() => {
|
| 818 |
+
// autoplay likely blocked -> register gesture fallback
|
| 819 |
+
this.isPlayingVideo = !v.paused;
|
| 820 |
+
this.registerGestureForPendingVideo(videoUrl);
|
| 821 |
+
});
|
| 822 |
+
} catch {
|
| 823 |
+
// ignore
|
| 824 |
+
}
|
| 825 |
+
}, 0);
|
| 826 |
+
}
|
| 827 |
+
|
| 828 |
+
/**
|
| 829 |
+
* Register a one-time body click handler to play a pending feedback video when user interacts.
|
| 830 |
+
* This satisfies browser autoplay policies (requires a user gesture).
|
| 831 |
+
*/
|
| 832 |
+
private registerGestureForPendingVideo(videoUrl: string): void {
|
| 833 |
+
// if already registered, update pending URL and exit
|
| 834 |
+
this.pendingVideoUrl = videoUrl;
|
| 835 |
+
|
| 836 |
+
if (this.pendingGestureListener) return;
|
| 837 |
+
|
| 838 |
+
this.pendingGestureListener = (e: Event) => {
|
| 839 |
+
try {
|
| 840 |
+
// show video and set src so element renders if it wasn't already
|
| 841 |
+
this.showVideo = true;
|
| 842 |
+
this.videoSrc = this.pendingVideoUrl || videoUrl;
|
| 843 |
+
|
| 844 |
+
// attempt play on the element after change detection
|
| 845 |
+
setTimeout(() => {
|
| 846 |
+
try {
|
| 847 |
+
const v = this.videoElRef?.nativeElement;
|
| 848 |
+
if (v) {
|
| 849 |
+
v.src = this.videoSrc;
|
| 850 |
+
v.load();
|
| 851 |
+
v.play().then(() => {
|
| 852 |
+
this.isPlayingVideo = true;
|
| 853 |
+
}).catch(() => {
|
| 854 |
+
this.isPlayingVideo = !v.paused;
|
| 855 |
+
});
|
| 856 |
+
}
|
| 857 |
+
} catch {
|
| 858 |
+
// ignore
|
| 859 |
+
}
|
| 860 |
+
}, 0);
|
| 861 |
+
} finally {
|
| 862 |
+
// cleanup listener and pending state
|
| 863 |
+
try { if (this.pendingGestureListener) document.body.removeEventListener('click', this.pendingGestureListener, true); } catch { }
|
| 864 |
+
this.pendingGestureListener = undefined;
|
| 865 |
+
this.pendingVideoUrl = null;
|
| 866 |
+
// ensure gauge is not oscillating after user gesture
|
| 867 |
+
this.isOscillating = false;
|
| 868 |
+
}
|
| 869 |
+
};
|
| 870 |
+
|
| 871 |
+
// use capture so early gestures are caught even if other handlers stop propagation
|
| 872 |
+
try { document.body.addEventListener('click', this.pendingGestureListener, true); } catch { /* ignore */ }
|
| 873 |
+
}
|
| 874 |
+
|
| 875 |
+
onVideoEnded(): void {
|
| 876 |
+
// Ensure the native element is stopped and cleared so the thumbnail can re-appear.
|
| 877 |
+
try {
|
| 878 |
+
const v = this.videoElRef?.nativeElement;
|
| 879 |
+
if (v) {
|
| 880 |
+
try { v.pause(); } catch { }
|
| 881 |
+
try { v.currentTime = 0; } catch { }
|
| 882 |
+
try { v.src = ''; } catch { }
|
| 883 |
+
try { v.load(); } catch { }
|
| 884 |
+
}
|
| 885 |
+
} catch {
|
| 886 |
+
// ignore DOM errors
|
| 887 |
+
} finally {
|
| 888 |
+
// show the thumbnail again and reset video state
|
| 889 |
+
this.showVideo = false;
|
| 890 |
+
this.isPlayingVideo = false;
|
| 891 |
+
this.videoSrc = '';
|
| 892 |
+
|
| 893 |
+
// stop any lingering oscillation and pending gesture state
|
| 894 |
+
this.isOscillating = false;
|
| 895 |
+
if (this.pendingGestureListener) {
|
| 896 |
+
try { document.body.removeEventListener('click', this.pendingGestureListener, true); } catch { }
|
| 897 |
+
this.pendingGestureListener = undefined;
|
| 898 |
+
this.pendingVideoUrl = null;
|
| 899 |
+
}
|
| 900 |
+
|
| 901 |
+
// ensure template updates immediately
|
| 902 |
+
try { this.cdr.detectChanges(); } catch { }
|
| 903 |
+
}
|
| 904 |
+
}
|
| 905 |
+
|
| 906 |
+
private getVideoSrcFromWord(word: string): string {
|
| 907 |
+
if (!word) return '';
|
| 908 |
+
const fileName = word.trim().toLowerCase().replace(/\s+/g, '-');
|
| 909 |
+
return `assets/pronvideo/videos/${fileName}.mp4`;
|
| 910 |
+
}
|
| 911 |
+
}
|
src/assets/pronvideo/audio.png
ADDED
|
Git LFS Details
|
src/assets/pronvideo/audio/apple.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:cd3749451facc8a9736f5ec3c16ab71c1c0a44e23c88bc2faaaba86676cfd930
|
| 3 |
+
size 13560
|
src/assets/pronvideo/audio/ball.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:eae7be3c52cf56a513aa701d71b1fbc93db1db23d5f15cb7a34b6b3f3cfa320f
|
| 3 |
+
size 12792
|
src/assets/pronvideo/audio/cat.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d5f8746b9ea52ac6f34f449603c8d24dac05bdf1463e7b2217ed3dfb36e877a9
|
| 3 |
+
size 12912
|
src/assets/pronvideo/audio/dog.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:8198fcb9e7ef7ff2eb4a2a57f5bad61bb5de4896750e4004917c8a51c82ce0cb
|
| 3 |
+
size 11592
|
src/assets/pronvideo/audio/egg.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b72a200ec8e163f9615b89599b4e6cc034c93d49e9d05580ea96c5fa5a94ec45
|
| 3 |
+
size 9312
|
src/assets/pronvideo/audio/fish.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2f1c7898a6fe74acf4a509755dbcd5a14961622ab212bd9e13ce2dd423d1077a
|
| 3 |
+
size 8976
|
src/assets/pronvideo/audio/grapes.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:cda848a9e69ea6f80a617d1f6f718820f86667e468087bdd89a388629e147057
|
| 3 |
+
size 12264
|
src/assets/pronvideo/audio/hat.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:09df5945baf67d5d6f3b9337dc65b768a458b70e7046e2441218e1037fe7fdb1
|
| 3 |
+
size 9672
|
src/assets/pronvideo/audio/icecream.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:60a2a41f57a2fdadce831e6b18582cfcdfe4a87b80256effb5d832a429d784d2
|
| 3 |
+
size 13200
|
src/assets/pronvideo/audio/jar.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c96580ccebde2b23c3b23399aa1d1956c7f290a8235ec3dd4881f250c6f4c0c1
|
| 3 |
+
size 11616
|
src/assets/pronvideo/audio/kite.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:27a9dee3aaa483d21ac7cf45ab11208f1c2541481d38900a2eeb0912a7d1eafe
|
| 3 |
+
size 10896
|
src/assets/pronvideo/audio/lion.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9c4c156b7f55749be6d0a81045fadc7fed907d7ad4ffe338ba2c60140f861ff1
|
| 3 |
+
size 10680
|
src/assets/pronvideo/audio/moon.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2595f31a5d53a3f48535975f196807d4e5b01d50a895b462e7de2b0fc84ab2aa
|
| 3 |
+
size 9960
|
src/assets/pronvideo/audio/nest.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:530beb8d1ebd6b89cce0187d8a3cb401b0c237eb5f656e430caf1fe96b67c9a1
|
| 3 |
+
size 12024
|
src/assets/pronvideo/audio/orange.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c96726c87265cadcdf3f392190fd8b66964451da60add484d39dcb5db4226879
|
| 3 |
+
size 9792
|
src/assets/pronvideo/audio/pig.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:48c66e98d9b044cfde83397ae699c6a90c3c396e747dc2d71f1290820082bf43
|
| 3 |
+
size 8544
|
src/assets/pronvideo/audio/queen.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1b7fc5588e5bada0d30e696253c0c47829d5a374ec8dc17de8c7b3df5200c5aa
|
| 3 |
+
size 9216
|
src/assets/pronvideo/audio/rabbit.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b22661ed72eaff38af8cccc055a2ac91200e213cad78371ee50db8023a0078f0
|
| 3 |
+
size 10848
|
src/assets/pronvideo/audio/sun.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:170d1bf45ca7c8f1dc268b4a1a5f19a986faae55780a834ecb5470509ac5ceff
|
| 3 |
+
size 11184
|
src/assets/pronvideo/audio/tree.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ab5cf4ad1e05e45125bab5f1ed611402e2c16c1175827e1d4fffd80cb7c45c11
|
| 3 |
+
size 9288
|
src/assets/pronvideo/audio/umbrella.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:fa1bf35b7f8f9ef437639cc80c9a2b231fae5096327f7069c176bde84efc216d
|
| 3 |
+
size 11640
|
src/assets/pronvideo/audio/van.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:249632f20e354aa4c41ecd60ef9e8cc8ee55601f72eb66b4a3a07bc7a2bb92af
|
| 3 |
+
size 9624
|
src/assets/pronvideo/audio/watch.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:629b00cae653b2aedb022391b6c9b4e0e869145f3c348fda674f206ffb635101
|
| 3 |
+
size 11568
|
src/assets/pronvideo/audio/xylophone.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:0b8f2764c762e59440f4bfcc40dfcdc516e86a437fbf7fc5623aa130f6dbec25
|
| 3 |
+
size 15744
|
src/assets/pronvideo/audio/yarn.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b8e6f8aa4e3b7e44aa3faafe13f113fb2704fc7fbcd0378e74006f9b0ebc1684
|
| 3 |
+
size 9504
|
src/assets/pronvideo/audio/zebra.mp3
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2873545095c089d763fd6d9185ffc868629041e7c0965d0fbbb1223d7c1a1730
|
| 3 |
+
size 12984
|
src/assets/pronvideo/feedback/consonant.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:eae0c82c7556e573bd3d4c0e9b4b885430641885fe4a445e0425f6d90a04589a
|
| 3 |
+
size 5481531
|
src/assets/pronvideo/feedback/ending.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e1bbfff2a733efd22b952ae4e32f686b06ada31b247208b81c8cb187e818695f
|
| 3 |
+
size 4184262
|
src/assets/pronvideo/feedback/multipleword.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7da6fc60d82f728164d12cb57acae93af3d7092be447f3b884ba262cf5533a1d
|
| 3 |
+
size 2252316
|
src/assets/pronvideo/feedback/silence.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b31c9c9bf22c6ebcf0ab84e23398ae019f613d5cfc494ea3d01c4541e16a56b0
|
| 3 |
+
size 5405291
|
src/assets/pronvideo/feedback/stress.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:67cbdef5635080cf0d38afbd1e4c5a0c79051363dd6fc138c7f3a1632ce47d7b
|
| 3 |
+
size 5214043
|
src/assets/pronvideo/feedback/success.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7065eb4444fff7033ffae8183901123ce45bca47114d8307652523006ca4b7b9
|
| 3 |
+
size 7149268
|
src/assets/pronvideo/feedback/syllable.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:01c7ecb44cc4eee9fb9cb32ec7f363e367c17479c0ae91883d902f428e3db9c9
|
| 3 |
+
size 3955318
|
src/assets/pronvideo/feedback/vowels.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:cd9a3f4ddfdadb90b0aaadbfa0a00c5aa80342f4b133543836d2b21592eb3443
|
| 3 |
+
size 5837969
|
src/assets/pronvideo/feedback/wrongword.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b0a32e7b4ed1f4355aa0eca1bd48c5ed4030e3deb7f2e5a412cb6a3fc3d06df1
|
| 3 |
+
size 5194285
|
src/assets/pronvideo/pause.png
ADDED
|
Git LFS Details
|
src/assets/pronvideo/play.png
ADDED
|
Git LFS Details
|
src/assets/pronvideo/teacher-nod.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:8f85a86632a64280579167285cfe71bd32d556797ec8e58e2fc14cf8285e1fb3
|
| 3 |
+
size 117067
|
src/assets/pronvideo/teacher.png
ADDED
|
Git LFS Details
|