diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 000000000..980f43068 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,2 @@ +#!/usr/bin/env sh +lint-staged diff --git a/CHANGELOG.md b/CHANGELOG.md index 40611b2ad..777d41645 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,27 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [3.84.0] - 2025-01-15 + +### Added +- Support for changing the font style of subtitles and closed captions +- Support for changing the edge color of characters of subtitles and closed captions + +## [3.83.0] - 2025-01-14 + +## Fixed +- Exception when disabling smooth playback position updating by setting `SeekbarConfig.smoothPlaybackPositionUpdateIntervalMs` to `-1` + +## [3.82.0] - 2025-01-13 + +### Added +- Chore: Pre-commit hook for linting TypeScript file changes + +## [3.81.0] - 2025-01-10 + +### Fixed +- Positioning of CEA-608 caption cues when multiple cues are displayed on the same line + ## [3.80.0] - 2025-01-08 ### Fixed @@ -1047,6 +1068,11 @@ Version 2.0 of the UI framework is built for player 7.1. If absolutely necessary ## 1.0.0 (2017-02-03) - First release +[3.85.0]: https://github.com/bitmovin/bitmovin-player-ui/compare/v3.84.0...v3.85.0 +[3.84.0]: https://github.com/bitmovin/bitmovin-player-ui/compare/v3.83.0...v3.84.0 +[3.83.0]: https://github.com/bitmovin/bitmovin-player-ui/compare/v3.82.0...v3.83.0 +[3.82.0]: https://github.com/bitmovin/bitmovin-player-ui/compare/v3.81.0...v3.82.0 +[3.81.0]: https://github.com/bitmovin/bitmovin-player-ui/compare/v3.80.0...v3.81.0 [3.80.0]: https://github.com/bitmovin/bitmovin-player-ui/compare/v3.79.0...v3.80.0 [3.79.0]: https://github.com/bitmovin/bitmovin-player-ui/compare/v3.78.0...v3.79.0 [3.78.0]: https://github.com/bitmovin/bitmovin-player-ui/compare/v3.77.0...v3.78.0 diff --git a/assets/images/logo.svg b/assets/images/logo.svg index 8e5c9cbf3..38b6eabc5 100644 --- a/assets/images/logo.svg +++ b/assets/images/logo.svg @@ -1,3 +1,15 @@ - - + + + + + + + + + diff --git a/package-lock.json b/package-lock.json index 4847b02f2..2b7f2ad19 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "bitmovin-player-ui", - "version": "3.80.0", + "version": "3.85.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "bitmovin-player-ui", - "version": "3.80.0", + "version": "3.85.0", "license": "MIT", "devDependencies": { "@eslint/js": "^9.17.0", @@ -32,8 +32,10 @@ "gulp-sourcemaps": "^3.0.0", "gulp-typescript": "^5.0.1", "gulp-uglify": "^3.0.2", + "husky": "^9.1.7", "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", + "lint-staged": "^15.3.0", "merge2": "^1.4.1", "postcss-svg": "^3.0.0", "sass": "^1.59.3", @@ -6861,6 +6863,120 @@ "node": ">=0.10.0" } }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-truncate/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/cli-width": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", @@ -7062,6 +7178,13 @@ "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", "dev": true }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, "node_modules/combine-source-map": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.7.2.tgz", @@ -8440,6 +8563,19 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/error-ex": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", @@ -10096,6 +10232,19 @@ "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", "dev": true }, + "node_modules/get-east-asian-width": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", @@ -11491,6 +11640,22 @@ "node": ">=10.17.0" } }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/iconv-lite": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", @@ -14419,6 +14584,425 @@ "uc.micro": "^2.0.0" } }, + "node_modules/lint-staged": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.3.0.tgz", + "integrity": "sha512-vHFahytLoF2enJklgtOtCtIjZrKD/LoxlaUusd5nh7dWv/dkKQJY74ndFSzxCdv7g0ueGg1ORgTSt4Y9LPZn9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "~5.4.1", + "commander": "~12.1.0", + "debug": "~4.4.0", + "execa": "~8.0.1", + "lilconfig": "~3.1.3", + "listr2": "~8.2.5", + "micromatch": "~4.0.8", + "pidtree": "~0.6.0", + "string-argv": "~0.3.2", + "yaml": "~2.6.1" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/lint-staged/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/lint-staged/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lint-staged/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/lint-staged/node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/lint-staged/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lint-staged/node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/lint-staged/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lint-staged/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/lint-staged/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/lint-staged/node_modules/yaml": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/listr2": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", + "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/listr2/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true, + "license": "MIT" + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -14702,6 +15286,222 @@ "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", "dev": true }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/lru-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", @@ -15034,6 +15834,19 @@ "node": ">=6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -15971,6 +16784,19 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -17708,6 +18534,13 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, "node_modules/rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -19244,6 +20077,16 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -27078,6 +27921,72 @@ "restore-cursor": "^1.0.1" } }, + "cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "requires": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true + }, + "slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + } + }, + "string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "requires": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, "cli-width": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", @@ -27246,6 +28155,12 @@ "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", "dev": true }, + "colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, "combine-source-map": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.7.2.tgz", @@ -28353,6 +29268,12 @@ "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", "dev": true }, + "environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true + }, "error-ex": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", @@ -29623,6 +30544,12 @@ "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", "dev": true }, + "get-east-asian-width": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", + "dev": true + }, "get-intrinsic": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", @@ -30734,6 +31661,12 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true }, + "husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true + }, "iconv-lite": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", @@ -32909,6 +33842,256 @@ "uc.micro": "^2.0.0" } }, + "lint-staged": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.3.0.tgz", + "integrity": "sha512-vHFahytLoF2enJklgtOtCtIjZrKD/LoxlaUusd5nh7dWv/dkKQJY74ndFSzxCdv7g0ueGg1ORgTSt4Y9LPZn9A==", + "dev": true, + "requires": { + "chalk": "~5.4.1", + "commander": "~12.1.0", + "debug": "~4.4.0", + "execa": "~8.0.1", + "lilconfig": "~3.1.3", + "listr2": "~8.2.5", + "micromatch": "~4.0.8", + "pidtree": "~0.6.0", + "string-argv": "~0.3.2", + "yaml": "~2.6.1" + }, + "dependencies": { + "braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "requires": { + "fill-range": "^7.1.1" + } + }, + "chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "dev": true + }, + "commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true + }, + "debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "requires": { + "ms": "^2.1.3" + } + }, + "execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + } + }, + "fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true + }, + "human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true + }, + "lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true + }, + "micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "requires": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + } + }, + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "requires": { + "path-key": "^4.0.0" + } + }, + "onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "requires": { + "mimic-fn": "^4.0.0" + } + }, + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true + }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, + "strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "yaml": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", + "dev": true + } + } + }, + "listr2": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", + "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", + "dev": true, + "requires": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true + }, + "eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true + }, + "string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "requires": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "requires": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + } + } + } + }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -33132,6 +34315,132 @@ "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", "dev": true }, + "log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "requires": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "dev": true, + "requires": { + "environment": "^1.0.0" + } + }, + "ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "requires": { + "restore-cursor": "^5.0.0" + } + }, + "emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "requires": { + "get-east-asian-width": "^1.0.0" + } + }, + "onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "requires": { + "mimic-function": "^5.0.0" + } + }, + "restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "requires": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + } + }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, + "slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "requires": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + } + }, + "string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "requires": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "requires": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + } + } + } + }, "lru-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", @@ -33411,6 +34720,12 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, + "mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true + }, "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -34151,6 +35466,12 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, + "pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true + }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -35427,6 +36748,12 @@ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true }, + "rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true + }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -36646,6 +37973,12 @@ "safe-buffer": "~5.1.0" } }, + "string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true + }, "string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", diff --git a/package.json b/package.json index 2f92ca594..3ac8bf039 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,12 @@ { "name": "bitmovin-player-ui", - "version": "3.80.0", + "version": "3.85.0", "description": "Bitmovin Player UI Framework", "main": "./dist/js/framework/main.js", "types": "./dist/js/framework/main.d.ts", "scripts": { - "test": "npx jest" + "test": "npx jest", + "prepare": "husky" }, "repository": { "type": "git", @@ -22,6 +23,11 @@ "last 2 versions", "Firefox ESR" ], + "lint-staged": { + "*.ts": [ + "eslint --fix" + ] + }, "devDependencies": { "@eslint/js": "^9.17.0", "@inrupt/jest-jsdom-polyfills": "^1.6.0", @@ -46,8 +52,10 @@ "gulp-sourcemaps": "^3.0.0", "gulp-typescript": "^5.0.1", "gulp-uglify": "^3.0.2", + "husky": "^9.1.7", "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", + "lint-staged": "^15.3.0", "merge2": "^1.4.1", "postcss-svg": "^3.0.0", "sass": "^1.59.3", diff --git a/src/html/index.html b/src/html/index.html index 3600eb91c..856b076f6 100644 --- a/src/html/index.html +++ b/src/html/index.html @@ -118,15 +118,15 @@

diff --git a/src/scss/_ads.scss b/src/scss/_ads.scss index 650878701..1c1fa81d3 100644 --- a/src/scss/_ads.scss +++ b/src/scss/_ads.scss @@ -2,8 +2,8 @@ // sass-lint:disable nesting-depth .#{$prefix}-ui-ads { - @import 'components/ads/adskipbutton'; - @import 'components/ads/adstatusoverlay'; + @import 'components/ads/ad-skip-button'; + @import 'components/ads/ad-status-overlay'; .#{$prefix}-ui-seekbar { .#{$prefix}-seekbar, diff --git a/src/scss/_mixins.scss b/src/scss/_mixins.scss index 7bf444b62..7c7ac5dd2 100644 --- a/src/scss/_mixins.scss +++ b/src/scss/_mixins.scss @@ -140,3 +140,18 @@ } } } + +/// Replace `$search` with `$replace` in `$string`. From https://css-tricks.com/snippets/sass/str-replace-function/ +/// @param {String} $string - Initial string +/// @param {String} $search - Substring to replace +/// @param {String} $replace ('') - New value +/// @return {String} - Updated string +@function str-replace($string, $search, $replace: '') { + $index: str-index($string, $search); + + @if $index { + @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace); + } + + @return $string; +} diff --git a/src/scss/_smallscreen.scss b/src/scss/_small-screen.scss similarity index 100% rename from src/scss/_smallscreen.scss rename to src/scss/_small-screen.scss diff --git a/src/scss/bitmovinplayer-ui.scss b/src/scss/bitmovinplayer-ui.scss index 8d65a7b7d..81b910f05 100644 --- a/src/scss/bitmovinplayer-ui.scss +++ b/src/scss/bitmovinplayer-ui.scss @@ -1,56 +1,56 @@ @import 'variables'; @import 'mixins'; -@import 'components/buttons/subtitletogglebutton'; +@import 'components/buttons/subtitle-toggle-button'; @import 'components/component'; @import 'components/container'; @import 'components/uicontainer'; -@import 'components/controlbar'; +@import 'components/control-bar'; @import 'components/buttons/button'; -@import 'components/buttons/playbacktogglebutton'; -@import 'components/buttons/quickseekbutton'; -@import 'components/buttons/fullscreentogglebutton'; -@import 'components/buttons/vrtogglebutton'; -@import 'components/buttons/volumetogglebutton'; -@import 'components/buttons/ecomodetogglebutton'; -@import 'components/seekbar/seekbar'; +@import 'components/buttons/playback-toggle-button'; +@import 'components/buttons/quick-seek-button'; +@import 'components/buttons/fullscreen-toggle-button'; +@import 'components/buttons/vr-toggle-button'; +@import 'components/buttons/volume-toggle-button'; +@import 'components/buttons/eco-mode-toggle-button'; +@import 'components/seekbar/seek-bar'; @import 'components/watermark'; -@import 'components/buttons/hugeplaybacktogglebutton'; +@import 'components/buttons/huge-playback-toggle-button'; @import 'components/labels/label'; -@import 'components/settings/settingspanel'; -@import 'components/settings/settingspanelpage'; -@import 'components/settings/settingspanelitem'; -@import 'components/settings/settingspanelpageopenbutton'; -@import 'components/settings/settingspanelpagebackbutton'; -@import 'components/settings/settingstogglebutton'; -@import 'components/settings/selectbox'; -@import 'components/lists/listbox'; -@import 'components/labels/seekbarlabel'; -@import 'components/seekbar/volumeslider'; -@import 'components/overlays/subtitleoverlay'; -@import 'components/overlays/subtitleoverlay-cea608'; -@import 'components/buttons/volumecontrolbutton'; -@import 'components/buttons/casttogglebutton'; -@import 'components/overlays/caststatusoverlay'; -@import 'components/overlays/errormessageoverlay'; -@import 'components/titlebar'; -@import 'components/overlays/recommendationoverlay'; -@import 'components/overlays/clickoverlay'; -@import 'components/buttons/hugereplaybutton'; -@import 'components/buttons/replaybutton'; -@import 'components/labels/playbacktimelabel'; -@import 'components/overlays/bufferingoverlay'; -@import 'components/overlays/playbacktoggleoverlay'; -@import 'components/buttons/closebutton'; -@import 'components/buttons/airplaytogglebutton'; -@import 'components/buttons/pictureinpicturetogglebutton'; +@import 'components/settings/settings-panel'; +@import 'components/settings/settings-panel-page'; +@import 'components/settings/settings-panel-item'; +@import 'components/settings/settings-panel-page-open-button'; +@import 'components/settings/settings-panel-page-back-button'; +@import 'components/settings/settings-toggle-button'; +@import 'components/settings/select-box'; +@import 'components/lists/list-box'; +@import 'components/labels/seek-bar-label'; +@import 'components/seekbar/volume-slider'; +@import 'components/overlays/subtitle-overlay'; +@import 'components/overlays/subtitle-overlay-cea608'; +@import 'components/buttons/volume-control-button'; +@import 'components/buttons/cast-toggle-button'; +@import 'components/overlays/cast-status-overlay'; +@import 'components/overlays/error-message-overlay'; +@import 'components/title-bar'; +@import 'components/overlays/recommendation-overlay'; +@import 'components/overlays/click-overlay'; +@import 'components/buttons/huge-replay-button'; +@import 'components/buttons/replay-button'; +@import 'components/labels/playback-time-label'; +@import 'components/overlays/buffering-overlay'; +@import 'components/overlays/playback-toggle-overlay'; +@import 'components/buttons/close-button'; +@import 'components/buttons/airplay-toggle-button'; +@import 'components/buttons/picture-in-picture-toggle-button'; @import 'components/spacer'; -@import 'components/settings/subtitlesettings/subtitlesettings'; -@import 'components/buttons/subtitlesettingspaneltogglebutton'; -@import 'components/overlays/touchcontroloverlay'; -@import 'components/buttons/smallcenteredplaybacktogglebutton'; +@import 'components/settings/subtitlesettings/subtitle-settings'; +@import 'components/buttons/subtitle-settings-panel-toggle-button'; +@import 'components/overlays/touch-control-overlay'; +@import 'components/buttons/small-centered-playback-toggle-button'; @import 'ads'; @import 'cast-receiver'; -@import 'smallscreen'; +@import 'small-screen'; @import 'tv'; // sass-lint:disable nesting-depth diff --git a/src/scss/components/_controlbar.scss b/src/scss/components/_control-bar.scss similarity index 100% rename from src/scss/components/_controlbar.scss rename to src/scss/components/_control-bar.scss diff --git a/src/scss/components/_titlebar.scss b/src/scss/components/_title-bar.scss similarity index 100% rename from src/scss/components/_titlebar.scss rename to src/scss/components/_title-bar.scss diff --git a/src/scss/components/ads/_adskipbutton.scss b/src/scss/components/ads/_ad-skip-button.scss similarity index 100% rename from src/scss/components/ads/_adskipbutton.scss rename to src/scss/components/ads/_ad-skip-button.scss diff --git a/src/scss/components/ads/_adstatusoverlay.scss b/src/scss/components/ads/_ad-status-overlay.scss similarity index 100% rename from src/scss/components/ads/_adstatusoverlay.scss rename to src/scss/components/ads/_ad-status-overlay.scss diff --git a/src/scss/components/buttons/_airplaytogglebutton.scss b/src/scss/components/buttons/_airplay-toggle-button.scss similarity index 100% rename from src/scss/components/buttons/_airplaytogglebutton.scss rename to src/scss/components/buttons/_airplay-toggle-button.scss diff --git a/src/scss/components/buttons/_casttogglebutton.scss b/src/scss/components/buttons/_cast-toggle-button.scss similarity index 100% rename from src/scss/components/buttons/_casttogglebutton.scss rename to src/scss/components/buttons/_cast-toggle-button.scss diff --git a/src/scss/components/buttons/_closebutton.scss b/src/scss/components/buttons/_close-button.scss similarity index 100% rename from src/scss/components/buttons/_closebutton.scss rename to src/scss/components/buttons/_close-button.scss diff --git a/src/scss/components/buttons/_ecomodetogglebutton.scss b/src/scss/components/buttons/_eco-mode-toggle-button.scss similarity index 100% rename from src/scss/components/buttons/_ecomodetogglebutton.scss rename to src/scss/components/buttons/_eco-mode-toggle-button.scss diff --git a/src/scss/components/buttons/_fullscreentogglebutton.scss b/src/scss/components/buttons/_fullscreen-toggle-button.scss similarity index 100% rename from src/scss/components/buttons/_fullscreentogglebutton.scss rename to src/scss/components/buttons/_fullscreen-toggle-button.scss diff --git a/src/scss/components/buttons/_hugeplaybacktogglebutton.scss b/src/scss/components/buttons/_huge-playback-toggle-button.scss similarity index 100% rename from src/scss/components/buttons/_hugeplaybacktogglebutton.scss rename to src/scss/components/buttons/_huge-playback-toggle-button.scss diff --git a/src/scss/components/buttons/_hugereplaybutton.scss b/src/scss/components/buttons/_huge-replay-button.scss similarity index 100% rename from src/scss/components/buttons/_hugereplaybutton.scss rename to src/scss/components/buttons/_huge-replay-button.scss diff --git a/src/scss/components/buttons/_pictureinpicturetogglebutton.scss b/src/scss/components/buttons/_picture-in-picture-toggle-button.scss similarity index 100% rename from src/scss/components/buttons/_pictureinpicturetogglebutton.scss rename to src/scss/components/buttons/_picture-in-picture-toggle-button.scss diff --git a/src/scss/components/buttons/_playbacktogglebutton.scss b/src/scss/components/buttons/_playback-toggle-button.scss similarity index 100% rename from src/scss/components/buttons/_playbacktogglebutton.scss rename to src/scss/components/buttons/_playback-toggle-button.scss diff --git a/src/scss/components/buttons/_quickseekbutton.scss b/src/scss/components/buttons/_quick-seek-button.scss similarity index 100% rename from src/scss/components/buttons/_quickseekbutton.scss rename to src/scss/components/buttons/_quick-seek-button.scss diff --git a/src/scss/components/buttons/_replaybutton.scss b/src/scss/components/buttons/_replay-button.scss similarity index 100% rename from src/scss/components/buttons/_replaybutton.scss rename to src/scss/components/buttons/_replay-button.scss diff --git a/src/scss/components/buttons/_smallcenteredplaybacktogglebutton.scss b/src/scss/components/buttons/_small-centered-playback-toggle-button.scss similarity index 100% rename from src/scss/components/buttons/_smallcenteredplaybacktogglebutton.scss rename to src/scss/components/buttons/_small-centered-playback-toggle-button.scss diff --git a/src/scss/components/buttons/_subtitlesettingspaneltogglebutton.scss b/src/scss/components/buttons/_subtitle-settings-panel-toggle-button.scss similarity index 100% rename from src/scss/components/buttons/_subtitlesettingspaneltogglebutton.scss rename to src/scss/components/buttons/_subtitle-settings-panel-toggle-button.scss diff --git a/src/scss/components/buttons/_subtitletogglebutton.scss b/src/scss/components/buttons/_subtitle-toggle-button.scss similarity index 100% rename from src/scss/components/buttons/_subtitletogglebutton.scss rename to src/scss/components/buttons/_subtitle-toggle-button.scss diff --git a/src/scss/components/buttons/_volumecontrolbutton.scss b/src/scss/components/buttons/_volume-control-button.scss similarity index 100% rename from src/scss/components/buttons/_volumecontrolbutton.scss rename to src/scss/components/buttons/_volume-control-button.scss diff --git a/src/scss/components/buttons/_volumetogglebutton.scss b/src/scss/components/buttons/_volume-toggle-button.scss similarity index 100% rename from src/scss/components/buttons/_volumetogglebutton.scss rename to src/scss/components/buttons/_volume-toggle-button.scss diff --git a/src/scss/components/buttons/_vrtogglebutton.scss b/src/scss/components/buttons/_vr-toggle-button.scss similarity index 100% rename from src/scss/components/buttons/_vrtogglebutton.scss rename to src/scss/components/buttons/_vr-toggle-button.scss diff --git a/src/scss/components/labels/_playbacktimelabel.scss b/src/scss/components/labels/_playback-time-label.scss similarity index 100% rename from src/scss/components/labels/_playbacktimelabel.scss rename to src/scss/components/labels/_playback-time-label.scss diff --git a/src/scss/components/labels/_seekbarlabel.scss b/src/scss/components/labels/_seek-bar-label.scss similarity index 100% rename from src/scss/components/labels/_seekbarlabel.scss rename to src/scss/components/labels/_seek-bar-label.scss diff --git a/src/scss/components/lists/_listbox.scss b/src/scss/components/lists/_list-box.scss similarity index 100% rename from src/scss/components/lists/_listbox.scss rename to src/scss/components/lists/_list-box.scss diff --git a/src/scss/components/overlays/_bufferingoverlay.scss b/src/scss/components/overlays/_buffering-overlay.scss similarity index 100% rename from src/scss/components/overlays/_bufferingoverlay.scss rename to src/scss/components/overlays/_buffering-overlay.scss diff --git a/src/scss/components/overlays/_caststatusoverlay.scss b/src/scss/components/overlays/_cast-status-overlay.scss similarity index 100% rename from src/scss/components/overlays/_caststatusoverlay.scss rename to src/scss/components/overlays/_cast-status-overlay.scss diff --git a/src/scss/components/overlays/_clickoverlay.scss b/src/scss/components/overlays/_click-overlay.scss similarity index 100% rename from src/scss/components/overlays/_clickoverlay.scss rename to src/scss/components/overlays/_click-overlay.scss diff --git a/src/scss/components/overlays/_errormessageoverlay.scss b/src/scss/components/overlays/_error-message-overlay.scss similarity index 100% rename from src/scss/components/overlays/_errormessageoverlay.scss rename to src/scss/components/overlays/_error-message-overlay.scss diff --git a/src/scss/components/overlays/_playbacktoggleoverlay.scss b/src/scss/components/overlays/_playback-toggle-overlay.scss similarity index 100% rename from src/scss/components/overlays/_playbacktoggleoverlay.scss rename to src/scss/components/overlays/_playback-toggle-overlay.scss diff --git a/src/scss/components/overlays/_recommendationoverlay.scss b/src/scss/components/overlays/_recommendation-overlay.scss similarity index 100% rename from src/scss/components/overlays/_recommendationoverlay.scss rename to src/scss/components/overlays/_recommendation-overlay.scss diff --git a/src/scss/components/overlays/_subtitleoverlay-cea608.scss b/src/scss/components/overlays/_subtitle-overlay-cea608.scss similarity index 97% rename from src/scss/components/overlays/_subtitleoverlay-cea608.scss rename to src/scss/components/overlays/_subtitle-overlay-cea608.scss index 5911bd7ba..12266697a 100644 --- a/src/scss/components/overlays/_subtitleoverlay-cea608.scss +++ b/src/scss/components/overlays/_subtitle-overlay-cea608.scss @@ -26,6 +26,7 @@ .#{$prefix}-ui-subtitle-label { display: inline-block; font-family: 'Courier New', Courier, 'Nimbus Mono L', 'Cutive Mono', monospace; + position: absolute; text-transform: uppercase; vertical-align: bottom; diff --git a/src/scss/components/overlays/_subtitleoverlay.scss b/src/scss/components/overlays/_subtitle-overlay.scss similarity index 100% rename from src/scss/components/overlays/_subtitleoverlay.scss rename to src/scss/components/overlays/_subtitle-overlay.scss diff --git a/src/scss/components/overlays/_touchcontroloverlay.scss b/src/scss/components/overlays/_touch-control-overlay.scss similarity index 100% rename from src/scss/components/overlays/_touchcontroloverlay.scss rename to src/scss/components/overlays/_touch-control-overlay.scss diff --git a/src/scss/components/seekbar/_seekbar.scss b/src/scss/components/seekbar/_seek-bar.scss similarity index 100% rename from src/scss/components/seekbar/_seekbar.scss rename to src/scss/components/seekbar/_seek-bar.scss diff --git a/src/scss/components/seekbar/_volumeslider.scss b/src/scss/components/seekbar/_volume-slider.scss similarity index 94% rename from src/scss/components/seekbar/_volumeslider.scss rename to src/scss/components/seekbar/_volume-slider.scss index fccbc603f..1aa63111f 100644 --- a/src/scss/components/seekbar/_volumeslider.scss +++ b/src/scss/components/seekbar/_volume-slider.scss @@ -1,6 +1,6 @@ @import '../../variables'; @import '../../mixins'; -@import 'seekbar'; +@import 'seek-bar'; .#{$prefix}-ui-volumeslider { @extend %ui-seekbar; diff --git a/src/scss/components/settings/_selectbox.scss b/src/scss/components/settings/_select-box.scss similarity index 100% rename from src/scss/components/settings/_selectbox.scss rename to src/scss/components/settings/_select-box.scss diff --git a/src/scss/components/settings/_settingspanelitem.scss b/src/scss/components/settings/_settings-panel-item.scss similarity index 100% rename from src/scss/components/settings/_settingspanelitem.scss rename to src/scss/components/settings/_settings-panel-item.scss diff --git a/src/scss/components/settings/_settingspanelpagebackbutton.scss b/src/scss/components/settings/_settings-panel-page-back-button.scss similarity index 100% rename from src/scss/components/settings/_settingspanelpagebackbutton.scss rename to src/scss/components/settings/_settings-panel-page-back-button.scss diff --git a/src/scss/components/settings/_settingspanelpageopenbutton.scss b/src/scss/components/settings/_settings-panel-page-open-button.scss similarity index 100% rename from src/scss/components/settings/_settingspanelpageopenbutton.scss rename to src/scss/components/settings/_settings-panel-page-open-button.scss diff --git a/src/scss/components/settings/_settingspanelpage.scss b/src/scss/components/settings/_settings-panel-page.scss similarity index 100% rename from src/scss/components/settings/_settingspanelpage.scss rename to src/scss/components/settings/_settings-panel-page.scss diff --git a/src/scss/components/settings/_settingspanel.scss b/src/scss/components/settings/_settings-panel.scss similarity index 100% rename from src/scss/components/settings/_settingspanel.scss rename to src/scss/components/settings/_settings-panel.scss diff --git a/src/scss/components/settings/_settingstogglebutton.scss b/src/scss/components/settings/_settings-toggle-button.scss similarity index 100% rename from src/scss/components/settings/_settingstogglebutton.scss rename to src/scss/components/settings/_settings-toggle-button.scss diff --git a/src/scss/components/settings/subtitlesettings/_subtitleoverlay-settings.scss b/src/scss/components/settings/subtitlesettings/_subtitle-overlay-settings.scss similarity index 76% rename from src/scss/components/settings/subtitlesettings/_subtitleoverlay-settings.scss rename to src/scss/components/settings/subtitlesettings/_subtitle-overlay-settings.scss index 28eb839a1..287350bd5 100644 --- a/src/scss/components/settings/subtitlesettings/_subtitleoverlay-settings.scss +++ b/src/scss/components/settings/subtitlesettings/_subtitle-overlay-settings.scss @@ -23,10 +23,10 @@ $character-edges: ( 'none': 'none', - 'raised': '0px 0px 4px rgba(0, 0, 0, 0.9), 0px 1px 4px rgba(0, 0, 0, 0.9), 0px 2px 4px rgba(0, 0, 0, 0.9)', - 'depressed': 'rgba(0, 0, 0, 0.8) 0px -2px 1px', - 'uniform': '-2px 0px 1px rgba(0, 0, 0, 0.8), 2px 0px 1px rgba(0, 0, 0, 0.8), 0px -2px 1px rgba(0, 0, 0, 0.8), 0px 2px 1px rgba(0, 0, 0, 0.8), -1px 1px 1px rgba(0, 0, 0, 0.8), 1px 1px 1px rgba(0, 0, 0, 0.8), 1px -1px 1px rgba(0, 0, 0, 0.8), 1px 1px 1px rgba(0, 0, 0, 0.8)', - 'dropshadowed': ' 0px 2px 1px rgba(0, 0, 0, 0.8)', + 'raised': '0px 0px 4px $COLOR$, 0px 1px 4px $COLOR$, 0px 2px 4px $COLOR$', + 'depressed': '$COLOR$ 0px -2px 1px', + 'uniform': '-2px 0px 1px $COLOR$, 2px 0px 1px $COLOR$, 0px -2px 1px $COLOR$, 0px 2px 1px $COLOR$, -1px 1px 1px $COLOR$, 1px 1px 1px $COLOR$, 1px -1px 1px $COLOR$, 1px 1px 1px $COLOR$', + 'dropshadowed': ' 0px 2px 1px $COLOR$', ); $font-sizes: ( @@ -83,11 +83,13 @@ } } - // Font character edge - @each $name, $value in $character-edges { - &.#{$prefix}-characteredge-#{$name} { - .#{$prefix}-ui-subtitle-label { - text-shadow: unquote($value); + // Font character edge and character edge color + @each $color-name, $color-value in $colors { + @each $name, $value in $character-edges { + &.#{$prefix}-characteredge-#{$name}-#{$color-name} { + .#{$prefix}-ui-subtitle-label { + text-shadow: unquote(str-replace($value, '$COLOR$', $color-value)); + } } } } @@ -135,4 +137,17 @@ font-variant: small-caps; } } + + // Font Style + &.#{$prefix}-fontstyle-italic { + .#{$prefix}-ui-subtitle-label { + font-style: italic; + } + } + + &.#{$prefix}-fontstyle-bold { + .#{$prefix}-ui-subtitle-label { + font-weight: bold; + } + } } diff --git a/src/scss/components/settings/subtitlesettings/_subtitlesettingsresetbutton.scss b/src/scss/components/settings/subtitlesettings/_subtitle-settings-reset-button.scss similarity index 100% rename from src/scss/components/settings/subtitlesettings/_subtitlesettingsresetbutton.scss rename to src/scss/components/settings/subtitlesettings/_subtitle-settings-reset-button.scss diff --git a/src/scss/components/settings/subtitlesettings/_subtitle-settings.scss b/src/scss/components/settings/subtitlesettings/_subtitle-settings.scss new file mode 100644 index 000000000..06b01cbd2 --- /dev/null +++ b/src/scss/components/settings/subtitlesettings/_subtitle-settings.scss @@ -0,0 +1,2 @@ +@import 'subtitle-settings-reset-button'; +@import 'subtitle-overlay-settings'; diff --git a/src/scss/components/settings/subtitlesettings/_subtitlesettings.scss b/src/scss/components/settings/subtitlesettings/_subtitlesettings.scss deleted file mode 100644 index 1a4267a39..000000000 --- a/src/scss/components/settings/subtitlesettings/_subtitlesettings.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import 'subtitlesettingsresetbutton'; -@import 'subtitleoverlay-settings'; diff --git a/src/ts/UIConfig.ts b/src/ts/UIConfig.ts index 117e8c654..252f538b7 100644 --- a/src/ts/UIConfig.ts +++ b/src/ts/UIConfig.ts @@ -131,4 +131,11 @@ export interface UIConfig { * Specifies if the `EcoModeToggleButton` should be displayed within the `SettingsPanel` */ ecoMode?: boolean; + /** + * Specifies if the Watermark element should be included in the UI. + * Per default, the Watermark shows the Bitmovin Logo. + * + * Default: false + */ + includeWatermark?: boolean; } diff --git a/src/ts/UIFactory.ts b/src/ts/UIFactory.ts index fdcd51544..9a28d29da 100644 --- a/src/ts/UIFactory.ts +++ b/src/ts/UIFactory.ts @@ -173,7 +173,7 @@ export namespace UIFactory { * @param config The UIConfig object */ export function buildCastReceiverUI(player: PlayerAPI, config: UIConfig = {}): UIManager { - return new UIManager(player, castReceiverUILayout(), config); + return new UIManager(player, castReceiverUILayout(config), config); } /** @@ -309,6 +309,10 @@ function uiLayout(config: UIConfig) { ], }); + const conditionalComponents = [ + config.includeWatermark ? new Watermark() : null, + ].filter((e) => e); + return new UIContainer({ components: [ subtitleOverlay, @@ -318,8 +322,8 @@ function uiLayout(config: UIConfig) { controlBar, new TitleBar(), new RecommendationOverlay(), - new Watermark(), settingsPanel, + ...conditionalComponents, new ErrorMessageOverlay(), ], hideDelay: 2000, @@ -543,7 +547,7 @@ function smallScreenAdsUILayout() { }); } -function castReceiverUILayout() { +function castReceiverUILayout(config: UIConfig) { let controlBar = new ControlBar({ components: [ new Container({ @@ -563,14 +567,18 @@ function castReceiverUILayout() { ], }); + const conditionalComponents = [ + config.includeWatermark ? new Watermark() : null, + ].filter((e) => e); + return new CastUIContainer({ components: [ new SubtitleOverlay(), new BufferingOverlay(), new PlaybackToggleOverlay(), - new Watermark(), controlBar, new TitleBar({ keepHiddenWithoutMetadata: true }), + ...conditionalComponents, new ErrorMessageOverlay(), ], cssClasses: ['ui-cast-receiver'], diff --git a/src/ts/components/lists/ListSelector.ts b/src/ts/components/lists/ListSelector.ts index 8fd1fcff2..d096d3718 100644 --- a/src/ts/components/lists/ListSelector.ts +++ b/src/ts/components/lists/ListSelector.ts @@ -111,7 +111,7 @@ export abstract class ListSelector extends Co * @param sortedInsert whether the item should be added respecting the order of keys * @param ariaLabel custom aria label for the listItem */ - addItem(key: string, label: LocalizableText, sortedInsert = false, ariaLabel = '') { + addItem(key: string|null, label: LocalizableText, sortedInsert = false, ariaLabel = '') { const listItem = { key: key, label: i18n.performLocalization(label), ...(ariaLabel && { ariaLabel })}; // Apply filter function diff --git a/src/ts/components/overlays/SubtitleOverlay.ts b/src/ts/components/overlays/SubtitleOverlay.ts index 42eadb119..0abf61423 100644 --- a/src/ts/components/overlays/SubtitleOverlay.ts +++ b/src/ts/components/overlays/SubtitleOverlay.ts @@ -325,7 +325,7 @@ export class SubtitleOverlay extends Container { } label.getDomElement().css({ - 'margin-left': `${event.position.column * SubtitleOverlay.CEA608_COLUMN_OFFSET}%`, + 'left': `${event.position.column * SubtitleOverlay.CEA608_COLUMN_OFFSET}%`, 'font-size': `${fontSize}px`, 'letter-spacing': `${fontLetterSpacing}px`, }); diff --git a/src/ts/components/seekbar/SeekBar.ts b/src/ts/components/seekbar/SeekBar.ts index ace899f26..8b4e450e7 100644 --- a/src/ts/components/seekbar/SeekBar.ts +++ b/src/ts/components/seekbar/SeekBar.ts @@ -246,7 +246,7 @@ export class SeekBar extends Component { uimanager.onControlsShow.subscribe(() => { this.isUiShown = true; - if (!player.isLive() && !this.smoothPlaybackPositionUpdater.isActive()) { + if (this.smoothPlaybackPositionUpdater && !player.isLive() && !this.smoothPlaybackPositionUpdater.isActive()) { playbackPositionHandler(null, true); this.smoothPlaybackPositionUpdater.start(); } @@ -254,7 +254,7 @@ export class SeekBar extends Component { uimanager.onControlsHide.subscribe(() => { this.isUiShown = false; - if (this.smoothPlaybackPositionUpdater.isActive()) { + if (this.smoothPlaybackPositionUpdater && this.smoothPlaybackPositionUpdater.isActive()) { this.smoothPlaybackPositionUpdater.clear(); } }); diff --git a/src/ts/components/settings/subtitlesettings/CharacterEdgeColorSelectBox.ts b/src/ts/components/settings/subtitlesettings/CharacterEdgeColorSelectBox.ts new file mode 100644 index 000000000..f7c73f342 --- /dev/null +++ b/src/ts/components/settings/subtitlesettings/CharacterEdgeColorSelectBox.ts @@ -0,0 +1,57 @@ +import { PlayerAPI } from 'bitmovin-player'; +import { SubtitleSettingSelectBox, SubtitleSettingSelectBoxConfig } from './SubtitleSettingSelectBox'; +import { UIInstanceManager } from '../../../UIManager'; +import { i18n } from '../../../localization/i18n'; + +/** + * A select box providing a selection of different character edge colors. + * + * @category Components + */ +export class CharacterEdgeColorSelectBox extends SubtitleSettingSelectBox { + + constructor(config: SubtitleSettingSelectBoxConfig) { + super(config); + + this.config = this.mergeConfig(config, { + cssClasses: ['ui-subtitle-settings-character-edge-color-select-box'], + }, this.config); + } + + configure(player: PlayerAPI, uimanager: UIInstanceManager): void { + super.configure(player, uimanager); + + this.addItem(null, i18n.getLocalizer('default')); + this.addItem('white', i18n.getLocalizer('colors.white')); + this.addItem('black', i18n.getLocalizer('colors.black')); + this.addItem('red', i18n.getLocalizer('colors.red')); + this.addItem('green', i18n.getLocalizer('colors.green')); + this.addItem('blue', i18n.getLocalizer('colors.blue')); + this.addItem('cyan', i18n.getLocalizer('colors.cyan')); + this.addItem('yellow', i18n.getLocalizer('colors.yellow')); + this.addItem('magenta', i18n.getLocalizer('colors.magenta')); + + this.onItemSelected.subscribe((sender, key: string) => { + this.settingsManager.characterEdgeColor.value = key; + + // Edge type and color go together, so we need to... + if (!this.settingsManager.characterEdgeColor.isSet()) { + // ... clear the edge type when the color is not set + this.settingsManager.characterEdge.clear(); + } else if (!this.settingsManager.characterEdge.isSet()) { + // ... set a edge type when the color is set + this.settingsManager.characterEdge.value = 'uniform'; + } + }); + + // Update selected item when value is set from somewhere else + this.settingsManager.characterEdgeColor.onChanged.subscribe((sender, property) => { + this.selectItem(property.value); + }); + + // Load initial value + if (this.settingsManager.characterEdgeColor.isSet()) { + this.selectItem(this.settingsManager.characterEdgeColor.value); + } + } +} diff --git a/src/ts/components/settings/subtitlesettings/CharacterEdgeSelectBox.ts b/src/ts/components/settings/subtitlesettings/CharacterEdgeSelectBox.ts index 346bb11c5..932f74aca 100644 --- a/src/ts/components/settings/subtitlesettings/CharacterEdgeSelectBox.ts +++ b/src/ts/components/settings/subtitlesettings/CharacterEdgeSelectBox.ts @@ -27,20 +27,34 @@ export class CharacterEdgeSelectBox extends SubtitleSettingSelectBox { this.addItem('uniform', i18n.getLocalizer('settings.subtitles.characterEdge.uniform')); this.addItem('dropshadowed', i18n.getLocalizer('settings.subtitles.characterEdge.dropshadowed')); - this.settingsManager.characterEdge.onChanged.subscribe((sender, property) => { - if (property.isSet()) { - this.toggleOverlayClass('characteredge-' + property.value); + const setColorAndEdgeType = () => { + if (this.settingsManager.characterEdge.isSet() && this.settingsManager.characterEdgeColor.isSet()) { + this.toggleOverlayClass('characteredge-' + this.settingsManager.characterEdge.value + '-' + this.settingsManager.characterEdgeColor.value); } else { this.toggleOverlayClass(null); } - - // Select the item in case the property was set from outside - this.selectItem(property.value); - }); + } this.onItemSelected.subscribe((sender, key: string) => { this.settingsManager.characterEdge.value = key; }); + + this.settingsManager.characterEdge.onChanged.subscribe((sender, property) => { + // Edge type and color go together, so we need to... + if (!this.settingsManager.characterEdge.isSet()) { + // ... clear the color when the edge type is not set + this.settingsManager.characterEdgeColor.clear(); + } else if (!this.settingsManager.characterEdgeColor.isSet()) { + // ... set a color when the edge type is set + this.settingsManager.characterEdgeColor.value = 'black'; + } + this.selectItem(property.value); + setColorAndEdgeType(); + }); + + this.settingsManager.characterEdgeColor.onChanged.subscribe(() => { + setColorAndEdgeType(); + }); // Load initial value if (this.settingsManager.characterEdge.isSet()) { diff --git a/src/ts/components/settings/subtitlesettings/FontStyleSelectBox.ts b/src/ts/components/settings/subtitlesettings/FontStyleSelectBox.ts new file mode 100644 index 000000000..e9bea8f9d --- /dev/null +++ b/src/ts/components/settings/subtitlesettings/FontStyleSelectBox.ts @@ -0,0 +1,50 @@ +import { PlayerAPI } from 'bitmovin-player'; +import { SubtitleSettingSelectBox, SubtitleSettingSelectBoxConfig } from './SubtitleSettingSelectBox'; +import { UIInstanceManager } from '../../../UIManager'; +import { i18n } from '../../../localization/i18n'; + +/** + * A select box providing a selection of different font styles. + * + * @category Components + */ +export class FontStyleSelectBox extends SubtitleSettingSelectBox { + + constructor(config: SubtitleSettingSelectBoxConfig) { + super(config); + + this.config = this.mergeConfig(config, { + cssClasses: ['ui-subtitle-settings-font-style-select-box'], + }, this.config); + } + + configure(player: PlayerAPI, uimanager: UIInstanceManager): void { + super.configure(player, uimanager); + + this.addItem(null, i18n.getLocalizer('default')); + this.addItem('italic', i18n.getLocalizer('settings.subtitles.font.style.italic')); + this.addItem('bold', i18n.getLocalizer('settings.subtitles.font.style.bold')); + + this.settingsManager?.fontStyle.onChanged.subscribe((sender, property) => { + if (property.isSet()) { + this.toggleOverlayClass('fontstyle-' + property.value); + } else { + this.toggleOverlayClass(null); + } + + // Select the item in case the property was set from outside + this.selectItem(property.value); + }); + + this.onItemSelected.subscribe((sender, key: string) => { + if (this.settingsManager) { + this.settingsManager.fontStyle.value = key; + } + }); + + // Load initial value + if (this.settingsManager?.fontStyle.isSet()) { + this.selectItem(this.settingsManager.fontStyle.value); + } + } +} diff --git a/src/ts/components/settings/subtitlesettings/SubtitleSettingSelectBox.ts b/src/ts/components/settings/subtitlesettings/SubtitleSettingSelectBox.ts index 00532c8ac..c954c9ea1 100644 --- a/src/ts/components/settings/subtitlesettings/SubtitleSettingSelectBox.ts +++ b/src/ts/components/settings/subtitlesettings/SubtitleSettingSelectBox.ts @@ -33,7 +33,7 @@ export class SubtitleSettingSelectBox extends SelectBox { * Removes a previously set class and adds the passed in class. * @param cssClass The new class to replace the previous class with or null to just remove the previous class */ - protected toggleOverlayClass(cssClass: string): void { + protected toggleOverlayClass(cssClass: string|null): void { // Remove previous class if existing if (this.currentCssClass) { this.overlay.getDomElement().removeClass(this.currentCssClass); diff --git a/src/ts/components/settings/subtitlesettings/SubtitleSettingsPanelPage.ts b/src/ts/components/settings/subtitlesettings/SubtitleSettingsPanelPage.ts index 43820166b..f308f9d65 100644 --- a/src/ts/components/settings/subtitlesettings/SubtitleSettingsPanelPage.ts +++ b/src/ts/components/settings/subtitlesettings/SubtitleSettingsPanelPage.ts @@ -19,6 +19,8 @@ import { PlayerAPI } from 'bitmovin-player'; import { i18n, LocalizableText } from '../../../localization/i18n'; import { DynamicSettingsPanelItem } from '../DynamicSettingsPanelItem'; import { ListSelector, ListSelectorConfig } from '../../lists/ListSelector'; +import { FontStyleSelectBox } from './FontStyleSelectBox'; +import { CharacterEdgeColorSelectBox } from './CharacterEdgeColorSelectBox'; /** * @category Configs @@ -51,6 +53,13 @@ export class SubtitleSettingsPanelPage extends SettingsPanelPage { }), config.useDynamicSettingsPanelItem, ), + this.buildSettingsPanelItem( + i18n.getLocalizer('settings.subtitles.font.style'), + new FontStyleSelectBox({ + overlay: this.overlay, + }), + config.useDynamicSettingsPanelItem, + ), this.buildSettingsPanelItem( i18n.getLocalizer('settings.subtitles.font.family'), new FontFamilySelectBox({ @@ -79,6 +88,13 @@ export class SubtitleSettingsPanelPage extends SettingsPanelPage { }), config.useDynamicSettingsPanelItem, ), + this.buildSettingsPanelItem( + i18n.getLocalizer('settings.subtitles.characterEdge.color'), + new CharacterEdgeColorSelectBox({ + overlay: this.overlay, + }), + config.useDynamicSettingsPanelItem, + ), this.buildSettingsPanelItem( i18n.getLocalizer('settings.subtitles.background.color'), new BackgroundColorSelectBox({ diff --git a/src/ts/localization/languages/de.json b/src/ts/localization/languages/de.json index f8fe68b80..a77b8496d 100644 --- a/src/ts/localization/languages/de.json +++ b/src/ts/localization/languages/de.json @@ -19,10 +19,14 @@ "off": "aus", "settings.subtitles": "Untertitel", "settings.subtitles.font.size": "Größe", + "settings.subtitles.font.style": "Schriftstil", + "settings.subtitles.font.style.bold": "Fett", + "settings.subtitles.font.style.italic": "Kursiv", "settings.subtitles.font.family": "Schriftart", "settings.subtitles.font.color": "Farbe", "settings.subtitles.font.opacity": "Deckkraft", "settings.subtitles.characterEdge": "Ränder", + "settings.subtitles.characterEdge.color": "Buchstabenrandfarbe", "settings.subtitles.background.color": "Hintergrundfarbe", "settings.subtitles.background.opacity": "Hintergrunddeckkraft", "settings.subtitles.window.color": "Hintergrundfarbe", diff --git a/src/ts/localization/languages/en.json b/src/ts/localization/languages/en.json index ffc1167dc..08ccc5770 100644 --- a/src/ts/localization/languages/en.json +++ b/src/ts/localization/languages/en.json @@ -21,11 +21,15 @@ "colors.magenta": "magenta", "percent": "{value}%", "settings.subtitles.font.size": "Font size", + "settings.subtitles.font.style": "Font style", + "settings.subtitles.font.style.bold": "bold", + "settings.subtitles.font.style.italic": "italic", "settings.subtitles.characterEdge": "Character edge", "settings.subtitles.characterEdge.raised": "raised", "settings.subtitles.characterEdge.depressed": "depressed", "settings.subtitles.characterEdge.uniform": "uniform", "settings.subtitles.characterEdge.dropshadowed": "drop shadowed", + "settings.subtitles.characterEdge.color": "Character edge color", "settings.subtitles.font.family": "Font family", "settings.subtitles.font.family.monospacedserif": "monospaced serif", "settings.subtitles.font.family.proportionalserif": "proportional serif", diff --git a/src/ts/localization/languages/es.json b/src/ts/localization/languages/es.json index 22224d616..8b47b2e85 100644 --- a/src/ts/localization/languages/es.json +++ b/src/ts/localization/languages/es.json @@ -21,11 +21,15 @@ "colors.magenta": "magenta", "percent": "{value}%", "settings.subtitles.font.size": "tamaño de Fuente", + "settings.subtitles.font.style": "Estilo de Fuente", + "settings.subtitles.font.style.bold": "negrita", + "settings.subtitles.font.style.italic": "cursiva", "settings.subtitles.characterEdge": "borde del Caracter", "settings.subtitles.characterEdge.raised": "alzado", "settings.subtitles.characterEdge.depressed": "discreto", "settings.subtitles.characterEdge.uniform": "uniforme", "settings.subtitles.characterEdge.dropshadowed": "sombreado", + "settings.subtitles.characterEdge.color": "color de contorno de texto", "settings.subtitles.font.family": "tipo de Fuente", "settings.subtitles.font.family.monospacedserif": "monospaced serif", "settings.subtitles.font.family.proportionalserif": "proportional serif", diff --git a/src/ts/utils/SubtitleSettingsManager.ts b/src/ts/utils/SubtitleSettingsManager.ts index 0a422a88c..10c75b35e 100644 --- a/src/ts/utils/SubtitleSettingsManager.ts +++ b/src/ts/utils/SubtitleSettingsManager.ts @@ -8,7 +8,9 @@ interface SubtitleSettings { fontOpacity?: string; fontFamily?: string; fontSize?: string; + fontStyle?: string; characterEdge?: string; + characterEdgeColor?: string; backgroundColor?: string; backgroundOpacity?: string; windowColor?: string; @@ -31,7 +33,9 @@ export class SubtitleSettingsManager { fontOpacity: new SubtitleSettingsProperty(this), fontFamily: new SubtitleSettingsProperty(this), fontSize: new SubtitleSettingsProperty(this), + fontStyle: new SubtitleSettingsProperty(this), characterEdge: new SubtitleSettingsProperty(this), + characterEdgeColor: new SubtitleSettingsProperty(this), backgroundColor: new SubtitleSettingsProperty(this), backgroundOpacity: new SubtitleSettingsProperty(this), windowColor: new SubtitleSettingsProperty(this), @@ -65,10 +69,18 @@ export class SubtitleSettingsManager { return this._properties.fontSize; } + public get fontStyle(): SubtitleSettingsProperty { + return this._properties.fontStyle; + } + public get characterEdge(): SubtitleSettingsProperty { return this._properties.characterEdge; } + public get characterEdgeColor(): SubtitleSettingsProperty { + return this._properties.characterEdgeColor; + } + public get backgroundColor(): SubtitleSettingsProperty { return this._properties.backgroundColor; }